Skip to content

Commit

Permalink
Merge pull request #39 from salesforcecli/wr/agentCreate
Browse files Browse the repository at this point in the history
Wr/agent create
  • Loading branch information
shetzel authored Dec 10, 2024
2 parents 3ad317d + dd387bc commit 4c2d6bc
Show file tree
Hide file tree
Showing 4 changed files with 395 additions and 48 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"@inquirer/select": "^4.0.1",
"@oclif/core": "^4",
"@oclif/multi-stage-output": "^0.7.12",
"@salesforce/agents": "^0.4.0",
"@salesforce/agents": "^0.4.2",
"@salesforce/core": "^8.8.0",
"@salesforce/kit": "^3.2.1",
"@salesforce/sf-plugins-core": "^12.1.0",
Expand Down
61 changes: 34 additions & 27 deletions src/commands/agent/create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
*/

import * as fs from 'node:fs';
import { SfCommand, Flags } from '@salesforce/sf-plugins-core';
import { Messages } from '@salesforce/core';
import { Duration, sleep } from '@salesforce/kit';
import { Lifecycle, Messages } from '@salesforce/core';
import { MultiStageOutput } from '@oclif/multi-stage-output';
import { colorize } from '@oclif/core/ux';
import { Agent, AgentCreateConfig, AgentCreateLifecycleStages } from '@salesforce/agents';

Messages.importMessagesDirectoryFromMetaUrl(import.meta.url);
const messages = Messages.loadMessages('@salesforce/plugin-agent', 'agent.create');
Expand All @@ -19,14 +20,11 @@ export type AgentCreateResult = {
errorMessage?: string;
};

// There is no API for this yet. It's being planned/built by the Agent Creator team.
// However, we could possibly use:
// /services/data/{api-version}/connect/attach-agent-topics

export default class AgentCreate extends SfCommand<AgentCreateResult> {
public static readonly summary = messages.getMessage('summary');
public static readonly description = messages.getMessage('description');
public static readonly examples = messages.getMessages('examples');
public static readonly requiresProject = true;
public static state = 'beta';

public static readonly flags = {
Expand All @@ -53,38 +51,47 @@ export default class AgentCreate extends SfCommand<AgentCreateResult> {
title: `Creating ${flags.name} Agent`,
stages: [
jsonParsingStage,
'Generating GenAiPlanner metadata',
'Creating agent in org',
'Retrieving agent metadata',
'Generating local metadata',
'Deploying metadata to org',
'Creating Agent in org',
'Retrieving Agent metadata',
],
});

mso.goto(jsonParsingStage);
await sleep(Duration.milliseconds(200));

mso.goto('Generating GenAiPlanner metadata');
await sleep(Duration.milliseconds(200));

mso.goto('Creating agent in org');

// POST to /services/data/{api-version}/connect/attach-agent-topics

// To simulate time spent on the server generating the spec.
await sleep(Duration.seconds(5));
const agentConfig = {
...(JSON.parse(fs.readFileSync(flags['job-spec'], 'utf8')) as AgentCreateConfig),
name: flags.name,
};

// @ts-expect-error not using async method in callback
Lifecycle.getInstance().on(AgentCreateLifecycleStages.CreatingLocally, () => mso.goto('Generating local metadata'));
Lifecycle.getInstance().on(AgentCreateLifecycleStages.DeployingMetadata, () =>
// @ts-expect-error not using async method in callback
mso.goto('Deploying metadata to org')
);
// @ts-expect-error not using async method in callback
Lifecycle.getInstance().on(AgentCreateLifecycleStages.CreatingRemotely, () => mso.goto('Creating Agent in org'));
Lifecycle.getInstance().on(AgentCreateLifecycleStages.RetrievingMetadata, () =>
// @ts-expect-error not using async method in callback
mso.goto('Retrieving Agent metadata')
);

mso.goto('Retrieving agent metadata');
await sleep(Duration.seconds(3));
const agent = new Agent(flags['target-org'].getConnection(flags['api-version']), this.project!);
const created = await agent.create(agentConfig);

mso.stop();

this.log(
colorize(
'green',
`Successfully created ${flags.name} in ${flags['target-org'].getUsername() ?? 'the target org'}.`
)
created.isSuccess
? colorize(
'green',
`Successfully created ${flags.name} in ${flags['target-org'].getUsername() ?? 'the target org'}.`
)
: colorize('red', `failed to create agent ${flags.name}: ${created.errorMessage ?? ''}`)
);
this.log(`Use ${colorize('dim', `sf org open agent --name ${flags.name}`)} to view the agent in the browser.`);

return { isSuccess: true };
return { isSuccess: created.isSuccess };
}
}
8 changes: 6 additions & 2 deletions src/commands/agent/generate/spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import ansis from 'ansis';
import select from '@inquirer/select';
import inquirerInput from '@inquirer/input';
import figures from '@inquirer/figures';
import { Agent, SfAgent } from '@salesforce/agents';
import { Agent, AgentCreateConfig, SfAgent } from '@salesforce/agents';

Messages.importMessagesDirectoryFromMetaUrl(import.meta.url);
const messages = Messages.loadMessages('@salesforce/plugin-agent', 'agent.generate.spec');
Expand Down Expand Up @@ -169,7 +169,11 @@ export default class AgentCreateSpec extends SfCommand<AgentCreateSpecResult> {
const filePath = join(flags['output-dir'], flags['file-name']);
writeFileSync(
filePath,
JSON.stringify({ type, role, companyName, companyDescription, companyWebsite, JobSpec: agentSpec }, null, 4)
JSON.stringify(
{ type, role, companyName, companyDescription, companyWebsite, jobSpec: agentSpec } as AgentCreateConfig,
null,
4
)
);

this.spinner.stop();
Expand Down
Loading

0 comments on commit 4c2d6bc

Please sign in to comment.