-
Notifications
You must be signed in to change notification settings - Fork 6
Template properties extraction #110
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 18 commits
1d357e4
1b42b8c
18944cf
827375c
7258cb1
403bcf2
646414a
e26e644
cf8fcb2
995dbc6
de7cf7b
7a0ecd1
0bee855
8e04c8b
d822d19
be5370f
5d26765
e6eae66
ec540f3
143ae73
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -30,6 +30,10 @@ export const PROJECT_GENERATION_WORKFLOW_INPUT_SCHEMA = WORKFLOW_TOOL_BASE_INPUT | |
| .string() | ||
| .optional() | ||
| .describe('Optional Salesforce login host URL (e.g., https://test.salesforce.com for sandbox)'), | ||
| templateProperties: z | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. in a separate PR I want to address the similarities (and differences) between
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To expand on the comment,
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yeah I think we're going to have to think holistically about state as the workflow grows - we have a lot of state which is transient and just a means to carry data from one node to the next and then we're done with it so we should have a strategy where we clear state when we are done with that part of the workflow - @khawkins we've discussed this briefly, might be worth a targeted convo as we're going to continually hit it with our various workflows as they grow |
||
| .record(z.string()) | ||
| .optional() | ||
| .describe('Custom template-specific properties required by the selected template'), | ||
| }); | ||
|
|
||
| export type ProjectGenerationWorkflowInput = z.infer< | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -52,12 +52,9 @@ export class SFMobileNativeProjectGenerationTool extends AbstractNativeProjectMa | |
|
|
||
| ${this.generateStepExecuteCliCommand(1, input)} | ||
|
|
||
| ${this.generateStepVerifyProjectStructure(2, input)} | ||
|
|
||
| ## Success Criteria | ||
|
|
||
| ✅ Project generated successfully from template "${input.selectedTemplate}" | ||
| ✅ Project structure verified | ||
| `; | ||
| } | ||
|
|
||
|
|
@@ -67,36 +64,27 @@ export class SFMobileNativeProjectGenerationTool extends AbstractNativeProjectMa | |
| ): string { | ||
| const platformLower = input.platform.toLowerCase(); | ||
|
|
||
| // Build template properties flags if they exist | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think @haifeng-li-at-salesforce has a PR that puts this behind a node tool (which is great!) but we'll need to reconcile with these changes |
||
| let templatePropertiesFlags = ''; | ||
| if (input.templateProperties && Object.keys(input.templateProperties).length > 0) { | ||
| const propertyFlags = Object.entries(input.templateProperties) | ||
| .map(([key, value]) => `--template-property-${key}="${value}"`) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Here we generate the shell command to run. Do we need to worry the command line to be valid in case value has special character for shell, like " here for the value?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @haifeng-li-at-salesforce is doing work to move this work into a node I wonder if that's a more appropriate place to do deterministic validation since we'll also have access to the shell result - what do you think @haifeng-li-at-salesforce ? seems like doing that work within the tool itself is not appropriate - can you add it to your pr when resolving to do some basic validation on the input? |
||
| .join(' '); | ||
| templatePropertiesFlags = ` ${propertyFlags}`; | ||
| } | ||
|
|
||
| return dedent` | ||
| ## Step ${stepNumber}: Execute Platform-Specific CLI Command | ||
|
|
||
| Generate the project using the Salesforce Mobile SDK CLI: | ||
|
|
||
| \`\`\`bash | ||
| sf mobilesdk ${platformLower} createwithtemplate --templatesource="${MOBILE_SDK_TEMPLATES_PATH}" --template="${input.selectedTemplate}" --appname="${input.projectName}" --packagename="${input.packageName}" --organization="${input.organization} --consumerkey="${input.connectedAppClientId}" --callbackurl="${input.connectedAppCallbackUri}" --loginserver="${input.loginHost}" | ||
| sf mobilesdk ${platformLower} createwithtemplate --templatesource="${MOBILE_SDK_TEMPLATES_PATH}" --template="${input.selectedTemplate}" --appname="${input.projectName}" --packagename="${input.packageName}" --organization="${input.organization} --consumerkey="${input.connectedAppClientId}" --callbackurl="${input.connectedAppCallbackUri}" --loginserver="${input.loginHost} ${templatePropertiesFlags}" | ||
| \`\`\` | ||
|
|
||
| **Expected Outcome**: A new ${input.platform} project directory named "${input.projectName}" will be created with the template structure. The output of the command will indicate the location of the bootconfig.plist file, take note of this for oauth configuration! | ||
jhorst11 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| NOTE: it is VERY IMPORTANT to use the above command EXACTLY to generate the project. Do not use any other configuration method to generate the project. If the above command fails do not try to generate the project using any other method. Instead report back error to the user. | ||
| `; | ||
| } | ||
|
|
||
| private generateStepVerifyProjectStructure( | ||
| stepNumber: number, | ||
| input: ProjectGenerationWorkflowInput | ||
| ): string { | ||
| return dedent` | ||
| ## Step ${stepNumber}: Verify Project Structure | ||
|
|
||
| Navigate to the project directory and verify the basic structure: | ||
|
|
||
| \`\`\`bash | ||
| cd "${input.projectName}" | ||
| ls -la | ||
| \`\`\` | ||
|
|
||
| **Expected Structure**: You should see platform-specific files and directories appropriate for ${input.platform} development. | ||
| `; | ||
| } | ||
| } | ||
This file was deleted.
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| /* | ||
| * Copyright (c) 2025, salesforce.com, inc. | ||
| * All rights reserved. | ||
| * SPDX-License-Identifier: MIT | ||
| * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT | ||
| */ | ||
|
|
||
| import z from 'zod'; | ||
| import { PLATFORM_ENUM, TEMPLATE_LIST_SCHEMA } from '../../../common/schemas.js'; | ||
| import { | ||
| WORKFLOW_TOOL_BASE_INPUT_SCHEMA, | ||
| MCP_WORKFLOW_TOOL_OUTPUT_SCHEMA, | ||
| WorkflowToolMetadata, | ||
| } from '@salesforce/magen-mcp-workflow'; | ||
|
|
||
| /** | ||
| * Template Selection Tool Input Schema | ||
| */ | ||
| export const TEMPLATE_SELECTION_WORKFLOW_INPUT_SCHEMA = WORKFLOW_TOOL_BASE_INPUT_SCHEMA.extend({ | ||
| platform: PLATFORM_ENUM, | ||
| templateOptions: TEMPLATE_LIST_SCHEMA.describe( | ||
| 'The template options from listtemplates command. Each template includes metadata with platform, displayName, and other descriptive information.' | ||
| ), | ||
| }); | ||
|
|
||
| export type TemplateSelectionWorkflowInput = z.infer< | ||
| typeof TEMPLATE_SELECTION_WORKFLOW_INPUT_SCHEMA | ||
| >; | ||
|
|
||
| export const TEMPLATE_SELECTION_WORKFLOW_RESULT_SCHEMA = z.object({ | ||
| selectedTemplate: z | ||
| .string() | ||
| .describe('The template path/name selected from the available templates'), | ||
| }); | ||
|
|
||
| /** | ||
| * Template Selection Tool Metadata | ||
| */ | ||
| export const TEMPLATE_SELECTION_TOOL: WorkflowToolMetadata< | ||
| typeof TEMPLATE_SELECTION_WORKFLOW_INPUT_SCHEMA, | ||
| typeof TEMPLATE_SELECTION_WORKFLOW_RESULT_SCHEMA | ||
| > = { | ||
| toolId: 'sfmobile-native-template-selection', | ||
| title: 'Salesforce Mobile Native Template Selection', | ||
| description: 'Guides LLM through template selection from available template options', | ||
| inputSchema: TEMPLATE_SELECTION_WORKFLOW_INPUT_SCHEMA, | ||
| outputSchema: MCP_WORKFLOW_TOOL_OUTPUT_SCHEMA, | ||
| resultSchema: TEMPLATE_SELECTION_WORKFLOW_RESULT_SCHEMA, | ||
| } as const; |
Uh oh!
There was an error while loading. Please reload this page.