@copado/agentia-cli 0.108.0-alpha.0 → 0.110.0-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +263 -188
- package/dist/commands/ai/session/list.d.ts +14 -0
- package/dist/commands/ai/session/list.js +46 -0
- package/dist/commands/ai/session/list.js.map +1 -0
- package/dist/commands/ai/session/start.d.ts +17 -0
- package/dist/commands/ai/session/start.js +60 -0
- package/dist/commands/ai/session/start.js.map +1 -0
- package/dist/commands/cicd/notification/configure.d.ts +1 -1
- package/dist/commands/cicd/work/deployment-step/create.d.ts +1 -1
- package/dist/commands/cicd/work/status.d.ts +5 -1
- package/dist/commands/cicd/work/status.js +41 -6
- package/dist/commands/cicd/work/status.js.map +1 -1
- package/dist/commands/testing/build/run.d.ts +1 -1
- package/dist/commands/testing/job/update.d.ts +1 -1
- package/dist/commands/testing/run.d.ts +1 -1
- package/dist/commands/testing/test/run.d.ts +1 -1
- package/dist/lib/ai-chat-session.d.ts +3 -0
- package/dist/lib/ai-chat-session.js +180 -64
- package/dist/lib/ai-chat-session.js.map +1 -1
- package/dist/lib/ai-gateway.d.ts +8 -1
- package/dist/lib/ai-gateway.js +34 -2
- package/dist/lib/ai-gateway.js.map +1 -1
- package/dist/lib/ai-session-banner.d.ts +5 -0
- package/dist/lib/ai-session-banner.js +20 -0
- package/dist/lib/ai-session-banner.js.map +1 -0
- package/dist/lib/ai-session-tui-blocks.d.ts +9 -0
- package/dist/lib/ai-session-tui-blocks.js +36 -0
- package/dist/lib/ai-session-tui-blocks.js.map +1 -0
- package/dist/lib/ai-session-tui-clipboard.d.ts +22 -0
- package/dist/lib/ai-session-tui-clipboard.js +78 -0
- package/dist/lib/ai-session-tui-clipboard.js.map +1 -0
- package/dist/lib/ai-session-tui-composer.d.ts +35 -0
- package/dist/lib/ai-session-tui-composer.js +96 -0
- package/dist/lib/ai-session-tui-composer.js.map +1 -0
- package/dist/lib/ai-session-tui-highlight.d.ts +11 -0
- package/dist/lib/ai-session-tui-highlight.js +310 -0
- package/dist/lib/ai-session-tui-highlight.js.map +1 -0
- package/dist/lib/ai-session-tui-keys.d.ts +42 -0
- package/dist/lib/ai-session-tui-keys.js +159 -0
- package/dist/lib/ai-session-tui-keys.js.map +1 -0
- package/dist/lib/ai-session-tui-mermaid-image.d.ts +43 -0
- package/dist/lib/ai-session-tui-mermaid-image.js +444 -0
- package/dist/lib/ai-session-tui-mermaid-image.js.map +1 -0
- package/dist/lib/ai-session-tui-mermaid-paint.d.ts +3 -0
- package/dist/lib/ai-session-tui-mermaid-paint.js +182 -0
- package/dist/lib/ai-session-tui-mermaid-paint.js.map +1 -0
- package/dist/lib/ai-session-tui-mermaid.d.ts +19 -0
- package/dist/lib/ai-session-tui-mermaid.js +158 -0
- package/dist/lib/ai-session-tui-mermaid.js.map +1 -0
- package/dist/lib/ai-session-tui-message.d.ts +9 -0
- package/dist/lib/ai-session-tui-message.js +24 -0
- package/dist/lib/ai-session-tui-message.js.map +1 -0
- package/dist/lib/ai-session-tui-scroll.d.ts +32 -0
- package/dist/lib/ai-session-tui-scroll.js +148 -0
- package/dist/lib/ai-session-tui-scroll.js.map +1 -0
- package/dist/lib/ai-session-tui-slash.d.ts +14 -0
- package/dist/lib/ai-session-tui-slash.js +53 -0
- package/dist/lib/ai-session-tui-slash.js.map +1 -0
- package/dist/lib/ai-session-tui-welcome.d.ts +12 -0
- package/dist/lib/ai-session-tui-welcome.js +33 -0
- package/dist/lib/ai-session-tui-welcome.js.map +1 -0
- package/dist/lib/ai-session-tui-wrap.d.ts +2 -0
- package/dist/lib/ai-session-tui-wrap.js +24 -0
- package/dist/lib/ai-session-tui-wrap.js.map +1 -0
- package/dist/lib/ai-session-tui.d.ts +7 -0
- package/dist/lib/ai-session-tui.js +859 -0
- package/dist/lib/ai-session-tui.js.map +1 -0
- package/dist/lib/ai-sessions.d.ts +17 -0
- package/dist/lib/ai-sessions.js +142 -0
- package/dist/lib/ai-sessions.js.map +1 -0
- package/dist/lib/ai-types.d.ts +19 -0
- package/dist/lib/ai-types.js +49 -1
- package/dist/lib/ai-types.js.map +1 -1
- package/dist/lib/format.d.ts +2 -0
- package/dist/lib/format.js +5 -2
- package/dist/lib/format.js.map +1 -1
- package/dist/lib/mcp/tools.d.ts +5 -2
- package/dist/lib/mcp/tools.js +20 -3
- package/dist/lib/mcp/tools.js.map +1 -1
- package/dist/lib/testing-flags.d.ts +1 -1
- package/dist/lib/work-branch-metadata.d.ts +11 -0
- package/dist/lib/work-branch-metadata.js +31 -0
- package/dist/lib/work-branch-metadata.js.map +1 -0
- package/dist/lib/work-types.d.ts +3 -0
- package/dist/lib/work-types.js +21 -0
- package/dist/lib/work-types.js.map +1 -1
- package/oclif.manifest.json +2418 -2260
- package/package.json +10 -1
- package/templates/skills/agentia-ai/SKILL.md +5 -5
- package/templates/skills/agentia-ai/references/ai-agents.md +18 -3
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { AgentiaCommand } from '../../../lib/agentia-command.js';
|
|
2
|
+
import { type AiDialogueSummary } from '../../../lib/ai-types.js';
|
|
3
|
+
import { type PaginatedListResult } from '../../../lib/list-pagination.js';
|
|
4
|
+
export default class AiSessionList extends AgentiaCommand {
|
|
5
|
+
static description: string;
|
|
6
|
+
static examples: string[];
|
|
7
|
+
static flags: {
|
|
8
|
+
'page-size': import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
|
|
9
|
+
workspace: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
|
+
cursor: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
|
+
timeout: import("@oclif/core/interfaces").OptionFlag<number | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
|
+
};
|
|
13
|
+
run(): Promise<PaginatedListResult<AiDialogueSummary>>;
|
|
14
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { Flags } from '@oclif/core';
|
|
2
|
+
import { AgentiaCommand } from '../../../lib/agentia-command.js';
|
|
3
|
+
import { aiConnectionFlags, aiGatewayCallOptions } from '../../../lib/ai-flags.js';
|
|
4
|
+
import { formatAiSessionTable, listAiSessions } from '../../../lib/ai-sessions.js';
|
|
5
|
+
import { AI_SESSION_LIST_DEFAULT_PAGE_SIZE } from '../../../lib/ai-types.js';
|
|
6
|
+
import { displayListPagination, LIST_PAGE_SIZE_MAX, LIST_PAGE_SIZE_MIN, listPaginationFlags, } from '../../../lib/list-pagination.js';
|
|
7
|
+
export default class AiSessionList extends AgentiaCommand {
|
|
8
|
+
static description = 'List Copado AI dialogue sessions';
|
|
9
|
+
static examples = [
|
|
10
|
+
'<%= config.bin %> <%= command.id %>',
|
|
11
|
+
'<%= config.bin %> <%= command.id %> --page-size 15',
|
|
12
|
+
'<%= config.bin %> <%= command.id %> --workspace 42d0b908-37b7-4565-9ec9-86eda40c9782 --json',
|
|
13
|
+
];
|
|
14
|
+
static flags = {
|
|
15
|
+
...aiConnectionFlags,
|
|
16
|
+
...listPaginationFlags,
|
|
17
|
+
'page-size': Flags.integer({
|
|
18
|
+
default: AI_SESSION_LIST_DEFAULT_PAGE_SIZE,
|
|
19
|
+
description: `Number of sessions to show (${LIST_PAGE_SIZE_MIN}-${LIST_PAGE_SIZE_MAX})`,
|
|
20
|
+
max: LIST_PAGE_SIZE_MAX,
|
|
21
|
+
min: LIST_PAGE_SIZE_MIN,
|
|
22
|
+
}),
|
|
23
|
+
workspace: Flags.string({
|
|
24
|
+
description: 'Copado AI workspace UUID to filter sessions',
|
|
25
|
+
}),
|
|
26
|
+
};
|
|
27
|
+
async run() {
|
|
28
|
+
const { flags } = await this.parse(AiSessionList);
|
|
29
|
+
const page = await this.withSpinner('Loading AI sessions', () => listAiSessions({
|
|
30
|
+
...aiGatewayCallOptions(flags),
|
|
31
|
+
cursor: flags.cursor,
|
|
32
|
+
pageSize: flags['page-size'],
|
|
33
|
+
workspace: flags.workspace,
|
|
34
|
+
}));
|
|
35
|
+
this.display(() => {
|
|
36
|
+
if (page.data.length === 0) {
|
|
37
|
+
this.log('No AI sessions found.');
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
this.log(formatAiSessionTable(page.data));
|
|
41
|
+
displayListPagination(this.log.bind(this), page);
|
|
42
|
+
});
|
|
43
|
+
return page;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=list.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list.js","sourceRoot":"","sources":["../../../../src/commands/ai/session/list.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,KAAK,EAAC,MAAM,aAAa,CAAA;AAEjC,OAAO,EAAC,cAAc,EAAC,MAAM,iCAAiC,CAAA;AAC9D,OAAO,EAAC,iBAAiB,EAAE,oBAAoB,EAAC,MAAM,0BAA0B,CAAA;AAChF,OAAO,EAAC,oBAAoB,EAAE,cAAc,EAAC,MAAM,6BAA6B,CAAA;AAChF,OAAO,EAAC,iCAAiC,EAAyB,MAAM,0BAA0B,CAAA;AAClG,OAAO,EACL,qBAAqB,EACrB,kBAAkB,EAClB,kBAAkB,EAClB,mBAAmB,GAEpB,MAAM,iCAAiC,CAAA;AAExC,MAAM,CAAC,OAAO,OAAO,aAAc,SAAQ,cAAc;IACvD,MAAM,CAAU,WAAW,GAAG,kCAAkC,CAAA;IAChE,MAAM,CAAU,QAAQ,GAAG;QACzB,qCAAqC;QACrC,oDAAoD;QACpD,6FAA6F;KAC9F,CAAA;IACD,MAAM,CAAU,KAAK,GAAG;QACtB,GAAG,iBAAiB;QACpB,GAAG,mBAAmB;QACtB,WAAW,EAAE,KAAK,CAAC,OAAO,CAAC;YACzB,OAAO,EAAE,iCAAiC;YAC1C,WAAW,EAAE,+BAA+B,kBAAkB,IAAI,kBAAkB,GAAG;YACvF,GAAG,EAAE,kBAAkB;YACvB,GAAG,EAAE,kBAAkB;SACxB,CAAC;QACF,SAAS,EAAE,KAAK,CAAC,MAAM,CAAC;YACtB,WAAW,EAAE,6CAA6C;SAC3D,CAAC;KACH,CAAA;IAEM,KAAK,CAAC,GAAG;QACd,MAAM,EAAC,KAAK,EAAC,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,CAAA;QAC/C,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,qBAAqB,EAAE,GAAG,EAAE,CAC9D,cAAc,CAAC;YACb,GAAG,oBAAoB,CAAC,KAAK,CAAC;YAC9B,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,QAAQ,EAAE,KAAK,CAAC,WAAW,CAAC;YAC5B,SAAS,EAAE,KAAK,CAAC,SAAS;SAC3B,CAAC,CACH,CAAA;QAED,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE;YAChB,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC3B,IAAI,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAA;gBACjC,OAAM;YACR,CAAC;YAED,IAAI,CAAC,GAAG,CAAC,oBAAoB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAA;YACzC,qBAAqB,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,CAAA;QAClD,CAAC,CAAC,CAAA;QAEF,OAAO,IAAI,CAAA;IACb,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { AgentiaCommand } from '../../../lib/agentia-command.js';
|
|
2
|
+
import { type AiChatSessionResult } from '../../../lib/ai-chat-session.js';
|
|
3
|
+
export default class AiSessionStart extends AgentiaCommand {
|
|
4
|
+
static description: string;
|
|
5
|
+
static enableJsonFlag: boolean;
|
|
6
|
+
static examples: string[];
|
|
7
|
+
static flags: {
|
|
8
|
+
'sf-org': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
9
|
+
'user-story': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
|
+
workspace: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
|
+
timeout: import("@oclif/core/interfaces").OptionFlag<number | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
|
+
agent: import("@oclif/core/interfaces").OptionFlag<"plan" | "build" | "test" | "release" | "operate" | "knowledge" | "orchestrate", import("@oclif/core/interfaces").CustomOptions>;
|
|
13
|
+
component: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
14
|
+
dialogue: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
15
|
+
};
|
|
16
|
+
run(): Promise<AiChatSessionResult>;
|
|
17
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { Flags } from '@oclif/core';
|
|
2
|
+
import { stdin as input } from 'node:process';
|
|
3
|
+
import { AgentiaCommand } from '../../../lib/agentia-command.js';
|
|
4
|
+
import { aiConnectionFlags, aiGatewayCallOptions } from '../../../lib/ai-flags.js';
|
|
5
|
+
import { runAiSessionTui } from '../../../lib/ai-session-tui.js';
|
|
6
|
+
import { AI_CHAT_AGENTS } from '../../../lib/ai-types.js';
|
|
7
|
+
export default class AiSessionStart extends AgentiaCommand {
|
|
8
|
+
static description = 'Start or resume an interactive Copado AI session';
|
|
9
|
+
static enableJsonFlag = false;
|
|
10
|
+
static examples = [
|
|
11
|
+
'<%= config.bin %> <%= command.id %>',
|
|
12
|
+
'<%= config.bin %> <%= command.id %> --dialogue 42d0b908-37b7-4565-9ec9-86eda40c9782',
|
|
13
|
+
'<%= config.bin %> <%= command.id %> --agent build --user-story US-1042',
|
|
14
|
+
];
|
|
15
|
+
static flags = {
|
|
16
|
+
agent: Flags.option({
|
|
17
|
+
default: 'orchestrate',
|
|
18
|
+
description: 'Copado AI agent to start on',
|
|
19
|
+
options: [...AI_CHAT_AGENTS],
|
|
20
|
+
})(),
|
|
21
|
+
component: Flags.string({
|
|
22
|
+
description: 'Metadata component name prepended to the first prompt as context',
|
|
23
|
+
}),
|
|
24
|
+
dialogue: Flags.string({
|
|
25
|
+
description: 'Copado AI dialogue UUID to resume',
|
|
26
|
+
}),
|
|
27
|
+
...aiConnectionFlags,
|
|
28
|
+
'sf-org': Flags.string({
|
|
29
|
+
description: 'Salesforce org or environment name prepended to the first prompt as context',
|
|
30
|
+
}),
|
|
31
|
+
'user-story': Flags.string({
|
|
32
|
+
description: 'Copado user story id prepended to the first prompt as context',
|
|
33
|
+
}),
|
|
34
|
+
workspace: Flags.string({
|
|
35
|
+
description: 'Override the workspace UUID from auth or AGENTIA_AI_WORKSPACE; omit to use that default',
|
|
36
|
+
}),
|
|
37
|
+
};
|
|
38
|
+
async run() {
|
|
39
|
+
const { flags } = await this.parse(AiSessionStart);
|
|
40
|
+
if (!input.isTTY) {
|
|
41
|
+
this.error('AI session start requires an interactive terminal. Use `agentia ai agent ask` for headless prompts.', {
|
|
42
|
+
exit: 2,
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
const options = {
|
|
46
|
+
agent: flags.agent,
|
|
47
|
+
component: flags.component,
|
|
48
|
+
dialogue: flags.dialogue,
|
|
49
|
+
loadHistory: true,
|
|
50
|
+
sameSessionAgentSwitch: true,
|
|
51
|
+
sessionCommands: true,
|
|
52
|
+
...aiGatewayCallOptions(flags),
|
|
53
|
+
sfOrg: flags['sf-org'],
|
|
54
|
+
userStory: flags['user-story'],
|
|
55
|
+
workspace: flags.workspace,
|
|
56
|
+
};
|
|
57
|
+
return runAiSessionTui(options);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=start.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"start.js","sourceRoot":"","sources":["../../../../src/commands/ai/session/start.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,KAAK,EAAC,MAAM,aAAa,CAAA;AACjC,OAAO,EAAC,KAAK,IAAI,KAAK,EAAC,MAAM,cAAc,CAAA;AAE3C,OAAO,EAAC,cAAc,EAAC,MAAM,iCAAiC,CAAA;AAE9D,OAAO,EAAC,iBAAiB,EAAE,oBAAoB,EAAC,MAAM,0BAA0B,CAAA;AAChF,OAAO,EAAC,eAAe,EAAC,MAAM,gCAAgC,CAAA;AAC9D,OAAO,EAAC,cAAc,EAAe,MAAM,0BAA0B,CAAA;AAErE,MAAM,CAAC,OAAO,OAAO,cAAe,SAAQ,cAAc;IACxD,MAAM,CAAU,WAAW,GAAG,kDAAkD,CAAA;IAChF,MAAM,CAAU,cAAc,GAAG,KAAK,CAAA;IACtC,MAAM,CAAU,QAAQ,GAAG;QACzB,qCAAqC;QACrC,qFAAqF;QACrF,wEAAwE;KACzE,CAAA;IACD,MAAM,CAAU,KAAK,GAAG;QACtB,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC;YAClB,OAAO,EAAE,aAAa;YACtB,WAAW,EAAE,6BAA6B;YAC1C,OAAO,EAAE,CAAC,GAAG,cAAc,CAAC;SAC7B,CAAC,EAAE;QACJ,SAAS,EAAE,KAAK,CAAC,MAAM,CAAC;YACtB,WAAW,EAAE,kEAAkE;SAChF,CAAC;QACF,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC;YACrB,WAAW,EAAE,mCAAmC;SACjD,CAAC;QACF,GAAG,iBAAiB;QACpB,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC;YACrB,WAAW,EAAE,6EAA6E;SAC3F,CAAC;QACF,YAAY,EAAE,KAAK,CAAC,MAAM,CAAC;YACzB,WAAW,EAAE,+DAA+D;SAC7E,CAAC;QACF,SAAS,EAAE,KAAK,CAAC,MAAM,CAAC;YACtB,WAAW,EAAE,yFAAyF;SACvG,CAAC;KACH,CAAA;IAEM,KAAK,CAAC,GAAG;QACd,MAAM,EAAC,KAAK,EAAC,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,CAAA;QAEhD,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;YACjB,IAAI,CAAC,KAAK,CAAC,qGAAqG,EAAE;gBAChH,IAAI,EAAE,CAAC;aACR,CAAC,CAAA;QACJ,CAAC;QAED,MAAM,OAAO,GAAyB;YACpC,KAAK,EAAE,KAAK,CAAC,KAAgB;YAC7B,SAAS,EAAE,KAAK,CAAC,SAAS;YAC1B,QAAQ,EAAE,KAAK,CAAC,QAAQ;YACxB,WAAW,EAAE,IAAI;YACjB,sBAAsB,EAAE,IAAI;YAC5B,eAAe,EAAE,IAAI;YACrB,GAAG,oBAAoB,CAAC,KAAK,CAAC;YAC9B,KAAK,EAAE,KAAK,CAAC,QAAQ,CAAC;YACtB,SAAS,EAAE,KAAK,CAAC,YAAY,CAAC;YAC9B,SAAS,EAAE,KAAK,CAAC,SAAS;SAC3B,CAAA;QAED,OAAO,eAAe,CAAC,OAAO,CAAC,CAAA;IACjC,CAAC"}
|
|
@@ -8,7 +8,7 @@ export default class NotificationConfigure extends AgentiaCommand {
|
|
|
8
8
|
'destination-type': import("@oclif/core/interfaces").OptionFlag<"user" | "channel", import("@oclif/core/interfaces").CustomOptions>;
|
|
9
9
|
event: import("@oclif/core/interfaces").OptionFlag<"Promotion_Success" | "Promotion_Failed" | "Promotion_Conflict" | "Failed_Promotion_Creation" | "Deploy_Success" | "Deploy_Failed" | "Commit_Failed" | "Successful_Snapshot" | "Failed_Snapshot" | "ManualTask_Assigned" | "Test_Success" | "Test_Failed" | "Test_Cancelled" | "Test_Not Started" | "Quality_Gate_Success" | "Quality_Gate_Failed" | "Quality_Gate_Cancelled" | "Quality_Gate_Not Started" | "Create_Package_Success" | "Create_Package_Failure" | "Generate_Package_Version_Success" | "Generate_Package_Version_Failure" | "Import_Package_Success" | "Import_Package_Failure" | "Publish_Package_Success" | "Publish_Package_Failure", import("@oclif/core/interfaces").CustomOptions>;
|
|
10
10
|
'pipeline-id': import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
|
-
subscription: import("@oclif/core/interfaces").OptionFlag<"
|
|
11
|
+
subscription: import("@oclif/core/interfaces").OptionFlag<"all" | "user", import("@oclif/core/interfaces").CustomOptions>;
|
|
12
12
|
};
|
|
13
13
|
run(): Promise<ConfigureNotificationResult>;
|
|
14
14
|
}
|
|
@@ -15,7 +15,7 @@ export default class WorkDeploymentStepCreate extends AgentiaCommand {
|
|
|
15
15
|
'custom-step-api-name': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
16
16
|
'data-set-id': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
17
17
|
'data-template-id': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
18
|
-
environment: import("@oclif/core/interfaces").OptionFlag<"
|
|
18
|
+
environment: import("@oclif/core/interfaces").OptionFlag<"both" | "source" | "destination" | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
19
19
|
'flow-name': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
20
20
|
'function-name': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
21
21
|
instructions: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { AgentiaCommand } from '../../../lib/agentia-command.js';
|
|
2
|
+
import { type WorkBranchMetadataResult } from '../../../lib/work-branch-metadata.js';
|
|
2
3
|
import { type HeadlessWorkStatusResult } from '../../../lib/work-types.js';
|
|
3
4
|
export default class WorkStatus extends AgentiaCommand {
|
|
4
5
|
static args: {
|
|
@@ -6,5 +7,8 @@ export default class WorkStatus extends AgentiaCommand {
|
|
|
6
7
|
};
|
|
7
8
|
static description: string;
|
|
8
9
|
static examples: string[];
|
|
9
|
-
|
|
10
|
+
static flags: {
|
|
11
|
+
'metadata-list-only': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
12
|
+
};
|
|
13
|
+
run(): Promise<HeadlessWorkStatusResult | WorkBranchMetadataResult>;
|
|
10
14
|
}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { Args } from '@oclif/core';
|
|
1
|
+
import { Args, Flags } from '@oclif/core';
|
|
2
2
|
import { AgentiaCommand } from '../../../lib/agentia-command.js';
|
|
3
3
|
import { CicdGateway } from '../../../lib/cicd-gateway.js';
|
|
4
|
-
import { readLastWorkItem } from '../../../lib/defaults-store.js';
|
|
5
|
-
import {
|
|
4
|
+
import { readLastBaseBranch, readLastWorkItem } from '../../../lib/defaults-store.js';
|
|
5
|
+
import { resolveWorkBranchMetadata } from '../../../lib/work-branch-metadata.js';
|
|
6
|
+
import { formatWorkBranchMetadata, formatWorkStatus, workStatusEndpoint, } from '../../../lib/work-types.js';
|
|
6
7
|
export default class WorkStatus extends AgentiaCommand {
|
|
7
8
|
static args = {
|
|
8
9
|
id: Args.string({
|
|
@@ -11,18 +12,50 @@ export default class WorkStatus extends AgentiaCommand {
|
|
|
11
12
|
}),
|
|
12
13
|
};
|
|
13
14
|
static description = [
|
|
14
|
-
'Get status for a work item, including related job executions.',
|
|
15
|
+
'Get status for a work item, including related job executions and local branch metadata.',
|
|
15
16
|
'Uses the given user story ID/name, or the last work item from `agentia cicd work set`.',
|
|
17
|
+
'Use --metadata-list-only to retrieve only local branch metadata without an API call.',
|
|
16
18
|
].join(' ');
|
|
17
19
|
static examples = [
|
|
18
20
|
'<%= config.bin %> <%= command.id %>',
|
|
19
21
|
'<%= config.bin %> <%= command.id %> US-0001',
|
|
20
22
|
'<%= config.bin %> <%= command.id %> a0SKC000000CmZ2AU --json',
|
|
23
|
+
'<%= config.bin %> <%= command.id %> --metadata-list-only',
|
|
21
24
|
];
|
|
25
|
+
static flags = {
|
|
26
|
+
'metadata-list-only': Flags.boolean({
|
|
27
|
+
default: false,
|
|
28
|
+
description: 'Return only local branch metadata without calling the CICD API',
|
|
29
|
+
}),
|
|
30
|
+
};
|
|
22
31
|
async run() {
|
|
23
|
-
const { args } = await this.parse(WorkStatus);
|
|
32
|
+
const { args, flags } = await this.parse(WorkStatus);
|
|
24
33
|
const workItem = args.id?.trim() || (await readLastWorkItem());
|
|
25
|
-
if (workItem === undefined || workItem.length === 0) {
|
|
34
|
+
if (!flags['metadata-list-only'] && (workItem === undefined || workItem.length === 0)) {
|
|
35
|
+
this.error('No work item specified and no last work item recorded.', {
|
|
36
|
+
exit: 1,
|
|
37
|
+
suggestions: [
|
|
38
|
+
`${this.config.bin} cicd work status <id-or-name>`,
|
|
39
|
+
`${this.config.bin} cicd work set <id-or-name>`,
|
|
40
|
+
],
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
const baseRef = (await readLastBaseBranch())?.trim();
|
|
44
|
+
if (!baseRef) {
|
|
45
|
+
this.error('No base branch recorded for the active work item.', {
|
|
46
|
+
exit: 1,
|
|
47
|
+
suggestions: [`${this.config.bin} cicd work set <id-or-name>`],
|
|
48
|
+
});
|
|
49
|
+
throw new Error('Unreachable after command error.');
|
|
50
|
+
}
|
|
51
|
+
const branchMetadata = await resolveWorkBranchMetadata(baseRef);
|
|
52
|
+
if (flags['metadata-list-only']) {
|
|
53
|
+
this.display(() => {
|
|
54
|
+
this.log(formatWorkBranchMetadata(branchMetadata));
|
|
55
|
+
});
|
|
56
|
+
return branchMetadata;
|
|
57
|
+
}
|
|
58
|
+
if (!workItem) {
|
|
26
59
|
this.error('No work item specified and no last work item recorded.', {
|
|
27
60
|
exit: 1,
|
|
28
61
|
suggestions: [
|
|
@@ -30,11 +63,13 @@ export default class WorkStatus extends AgentiaCommand {
|
|
|
30
63
|
`${this.config.bin} cicd work set <id-or-name>`,
|
|
31
64
|
],
|
|
32
65
|
});
|
|
66
|
+
throw new Error('Unreachable after command error.');
|
|
33
67
|
}
|
|
34
68
|
const result = await this.withSpinner(`Fetching status for ${workItem}`, () => CicdGateway.call({
|
|
35
69
|
endpoint: workStatusEndpoint(workItem),
|
|
36
70
|
method: 'GET',
|
|
37
71
|
}));
|
|
72
|
+
result.branchMetadata = branchMetadata;
|
|
38
73
|
this.display(() => {
|
|
39
74
|
this.log(formatWorkStatus(result));
|
|
40
75
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"status.js","sourceRoot":"","sources":["../../../../src/commands/cicd/work/status.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,IAAI,EAAC,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"status.js","sourceRoot":"","sources":["../../../../src/commands/cicd/work/status.ts"],"names":[],"mappings":"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"}
|
|
@@ -14,7 +14,7 @@ export default class TestingBuildRun extends AgentiaCommand {
|
|
|
14
14
|
exclude: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
15
15
|
include: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
16
16
|
param: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
17
|
-
record: import("@oclif/core/interfaces").OptionFlag<"none" | "
|
|
17
|
+
record: import("@oclif/core/interfaces").OptionFlag<"none" | "all" | "failed" | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
18
18
|
'rerun-failed': import("@oclif/core/interfaces").OptionFlag<number | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
19
19
|
'rerun-failed-from-latest': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
20
20
|
tag: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
@@ -21,7 +21,7 @@ export default class TestingJobUpdate extends AgentiaCommand {
|
|
|
21
21
|
'screen-height': import("@oclif/core/interfaces").OptionFlag<number | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
22
22
|
'screen-width': import("@oclif/core/interfaces").OptionFlag<number | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
23
23
|
'show-video-params': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
24
|
-
'suite-type': import("@oclif/core/interfaces").OptionFlag<"default" | "bitbar" | "browserstack" | "browserstackdesktop" | "lambdatest" | "lambdatestdesktop" | "
|
|
24
|
+
'suite-type': import("@oclif/core/interfaces").OptionFlag<"default" | "mobile" | "bitbar" | "browserstack" | "browserstackdesktop" | "lambdatest" | "lambdatestdesktop" | "paceconnectmobile" | "privatemobile" | "rpa" | "selenese" | "zap" | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
25
25
|
timeout: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
26
26
|
'git-branch': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
27
27
|
'git-domain-credential': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
@@ -14,7 +14,7 @@ export default class TestingRun extends AgentiaCommand {
|
|
|
14
14
|
exclude: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
15
15
|
include: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
16
16
|
param: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
17
|
-
record: import("@oclif/core/interfaces").OptionFlag<"none" | "
|
|
17
|
+
record: import("@oclif/core/interfaces").OptionFlag<"none" | "all" | "failed" | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
18
18
|
'rerun-failed': import("@oclif/core/interfaces").OptionFlag<number | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
19
19
|
'rerun-failed-from-latest': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
20
20
|
tag: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
@@ -20,7 +20,7 @@ export default class TestingTestRun extends AgentiaCommand {
|
|
|
20
20
|
exclude: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
21
21
|
include: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
22
22
|
param: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
23
|
-
record: import("@oclif/core/interfaces").OptionFlag<"none" | "
|
|
23
|
+
record: import("@oclif/core/interfaces").OptionFlag<"none" | "all" | "failed" | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
24
24
|
'rerun-failed': import("@oclif/core/interfaces").OptionFlag<number | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
25
25
|
'rerun-failed-from-latest': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
26
26
|
tag: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
@@ -3,6 +3,9 @@ import { type AiAgent, type AiContextOptions } from './ai-types.js';
|
|
|
3
3
|
export type AiChatSessionOptions = AiConnectionOverrides & AiContextOptions & {
|
|
4
4
|
agent: AiAgent;
|
|
5
5
|
dialogue?: string;
|
|
6
|
+
loadHistory?: boolean;
|
|
7
|
+
sameSessionAgentSwitch?: boolean;
|
|
8
|
+
sessionCommands?: boolean;
|
|
6
9
|
timeoutMs?: number;
|
|
7
10
|
};
|
|
8
11
|
export type AiChatSessionResult = {
|
|
@@ -3,8 +3,9 @@ import { createInterface } from 'node:readline';
|
|
|
3
3
|
import { v4 as uuidv4 } from 'uuid';
|
|
4
4
|
import { AiGateway } from './ai-gateway.js';
|
|
5
5
|
import { bootstrapAiDialogue } from './ai-operations.js';
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
6
|
+
import { formatAiSessionTable, listAiSessions, pickSessionFromList } from './ai-sessions.js';
|
|
7
|
+
import { formatAiTerminalMessage, renderMarkdown, StreamingMarkdownRenderer, streamSupportsColor, } from './ai-terminal-renderer.js';
|
|
8
|
+
import { agentForAssistantId, AI_CHAT_AGENTS, AI_SESSION_LIST_DEFAULT_PAGE_SIZE, assistantIdForAgent, dialogueAssistantId, dialogueMessageText, enrichAiPrompt, } from './ai-types.js';
|
|
8
9
|
function writeLine(stream, value = '') {
|
|
9
10
|
stream.write(`${value}\n`);
|
|
10
11
|
}
|
|
@@ -38,7 +39,11 @@ function isGracefulReadlineClose(error) {
|
|
|
38
39
|
function errorMessage(error) {
|
|
39
40
|
return error instanceof Error ? error.message : String(error);
|
|
40
41
|
}
|
|
41
|
-
function renderHelp(output) {
|
|
42
|
+
function renderHelp(output, sessionCommands) {
|
|
43
|
+
if (sessionCommands) {
|
|
44
|
+
writeLine(output, `Commands: /help, /session, /${AI_CHAT_AGENTS.join(', /')}, /clear, /exit`);
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
42
47
|
writeLine(output, `Commands: /help, /clear, /agent <${AI_CHAT_AGENTS.join('|')}>, /exit`);
|
|
43
48
|
}
|
|
44
49
|
function normalizeAgent(value) {
|
|
@@ -47,10 +52,34 @@ function normalizeAgent(value) {
|
|
|
47
52
|
}
|
|
48
53
|
return undefined;
|
|
49
54
|
}
|
|
55
|
+
function slashAgent(line) {
|
|
56
|
+
if (!line.startsWith('/'))
|
|
57
|
+
return undefined;
|
|
58
|
+
return normalizeAgent(line.slice(1));
|
|
59
|
+
}
|
|
60
|
+
function renderHistory(output, dialogue, colors) {
|
|
61
|
+
const messages = dialogue.messages ?? [];
|
|
62
|
+
if (messages.length === 0)
|
|
63
|
+
return;
|
|
64
|
+
writeLine(output, 'Previous messages:');
|
|
65
|
+
for (const message of messages) {
|
|
66
|
+
const role = message.role === 'human' ? 'You' : 'Agent';
|
|
67
|
+
const text = dialogueMessageText(message);
|
|
68
|
+
writeLine(output, `${role}:`);
|
|
69
|
+
if (text.length > 0)
|
|
70
|
+
writeLine(output, renderMarkdown(text, { colors }));
|
|
71
|
+
writeLine(output);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
50
74
|
export async function runAiChatSession(options, io = defaultChatIo()) {
|
|
51
75
|
let { agent } = options;
|
|
52
76
|
let bootstrap = await bootstrapAiDialogue({ ...options, agent, kind: 'chat' });
|
|
53
77
|
let turns = 0;
|
|
78
|
+
let listedSessions = [];
|
|
79
|
+
let pendingSessionPick = false;
|
|
80
|
+
const sessionCommands = options.sessionCommands === true;
|
|
81
|
+
const sameSessionAgentSwitch = options.sameSessionAgentSwitch === true;
|
|
82
|
+
const loadHistory = options.loadHistory === true;
|
|
54
83
|
const stderrColors = streamSupportsColor(io.error);
|
|
55
84
|
const stdoutColors = streamSupportsColor(io.output);
|
|
56
85
|
const rl = createInterface({
|
|
@@ -61,75 +90,162 @@ export async function runAiChatSession(options, io = defaultChatIo()) {
|
|
|
61
90
|
const close = () => {
|
|
62
91
|
rl.close();
|
|
63
92
|
};
|
|
93
|
+
const switchAgent = async (nextAgent) => {
|
|
94
|
+
agent = nextAgent;
|
|
95
|
+
if (sameSessionAgentSwitch) {
|
|
96
|
+
writeLine(io.output, `Using ${agent} agent on session ${bootstrap.dialogue.id}`);
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
bootstrap = await bootstrapAiDialogue({ ...options, agent, dialogue: undefined, kind: 'chat' });
|
|
100
|
+
writeLine(io.output, `Switched to ${agent} agent. Dialogue: ${bootstrap.dialogue.id}`);
|
|
101
|
+
};
|
|
102
|
+
const openSession = async (dialogue) => {
|
|
103
|
+
const nextAgent = agentForAssistantId(dialogueAssistantId(dialogue));
|
|
104
|
+
if (nextAgent !== undefined)
|
|
105
|
+
agent = nextAgent;
|
|
106
|
+
bootstrap = { assistantId: assistantIdForAgent(agent), dialogue };
|
|
107
|
+
writeLine(io.output, `${agent} Agent chat`);
|
|
108
|
+
writeLine(io.output, `Dialogue: ${bootstrap.dialogue.id}`);
|
|
109
|
+
if (loadHistory)
|
|
110
|
+
renderHistory(io.output, dialogue, stdoutColors);
|
|
111
|
+
};
|
|
112
|
+
const listAndPromptSessions = async () => {
|
|
113
|
+
const page = await listAiSessions({ ...options, pageSize: AI_SESSION_LIST_DEFAULT_PAGE_SIZE });
|
|
114
|
+
listedSessions = page.data;
|
|
115
|
+
if (listedSessions.length === 0) {
|
|
116
|
+
writeLine(io.output, 'No AI sessions found.');
|
|
117
|
+
pendingSessionPick = false;
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
writeLine(io.output, formatAiSessionTable(listedSessions));
|
|
121
|
+
writeLine(io.output, 'Enter a number or session id to switch, or /cancel.');
|
|
122
|
+
pendingSessionPick = true;
|
|
123
|
+
};
|
|
124
|
+
const selectSession = async (selection) => {
|
|
125
|
+
const picked = pickSessionFromList(selection, listedSessions);
|
|
126
|
+
if (picked === undefined) {
|
|
127
|
+
writeLine(io.error, 'Unknown session. Use a list number or a dialogue UUID.');
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
const dialogue = await AiGateway.getDialogue(picked.id, options);
|
|
131
|
+
pendingSessionPick = false;
|
|
132
|
+
await openSession(dialogue);
|
|
133
|
+
};
|
|
134
|
+
const handleSessionCommand = async (line) => {
|
|
135
|
+
if (!sessionCommands)
|
|
136
|
+
return false;
|
|
137
|
+
if ((line === '/cancel' || line === 'cancel') && pendingSessionPick) {
|
|
138
|
+
pendingSessionPick = false;
|
|
139
|
+
writeLine(io.output, 'Session switch cancelled.');
|
|
140
|
+
return true;
|
|
141
|
+
}
|
|
142
|
+
if (pendingSessionPick && !line.startsWith('/')) {
|
|
143
|
+
await selectSession(line);
|
|
144
|
+
return true;
|
|
145
|
+
}
|
|
146
|
+
if (line === '/session') {
|
|
147
|
+
await listAndPromptSessions();
|
|
148
|
+
return true;
|
|
149
|
+
}
|
|
150
|
+
if (line.startsWith('/session ')) {
|
|
151
|
+
const selection = line.slice('/session '.length).trim();
|
|
152
|
+
if (listedSessions.length === 0) {
|
|
153
|
+
const page = await listAiSessions({ ...options, pageSize: AI_SESSION_LIST_DEFAULT_PAGE_SIZE });
|
|
154
|
+
listedSessions = page.data;
|
|
155
|
+
}
|
|
156
|
+
await selectSession(selection);
|
|
157
|
+
return true;
|
|
158
|
+
}
|
|
159
|
+
return false;
|
|
160
|
+
};
|
|
161
|
+
const handleCommand = async (line) => {
|
|
162
|
+
if (line.length === 0)
|
|
163
|
+
return 'continue';
|
|
164
|
+
if (line === '/exit' || line === 'exit' || line === 'quit')
|
|
165
|
+
return 'exit';
|
|
166
|
+
if (line === '/help') {
|
|
167
|
+
renderHelp(io.output, sessionCommands);
|
|
168
|
+
return 'continue';
|
|
169
|
+
}
|
|
170
|
+
if (await handleSessionCommand(line))
|
|
171
|
+
return 'continue';
|
|
172
|
+
if (line === '/clear') {
|
|
173
|
+
bootstrap = await bootstrapAiDialogue({ ...options, agent, dialogue: undefined, kind: 'chat' });
|
|
174
|
+
pendingSessionPick = false;
|
|
175
|
+
writeLine(io.output, `Started new dialogue: ${bootstrap.dialogue.id}`);
|
|
176
|
+
return 'continue';
|
|
177
|
+
}
|
|
178
|
+
const shortcutAgent = sessionCommands ? slashAgent(line) : undefined;
|
|
179
|
+
if (shortcutAgent !== undefined) {
|
|
180
|
+
await switchAgent(shortcutAgent);
|
|
181
|
+
return 'continue';
|
|
182
|
+
}
|
|
183
|
+
if (line.startsWith('/agent ')) {
|
|
184
|
+
const nextAgent = normalizeAgent(line.slice('/agent '.length).trim());
|
|
185
|
+
if (nextAgent === undefined) {
|
|
186
|
+
writeLine(io.error, `Unknown agent. Use ${AI_CHAT_AGENTS.join(', ')}.`);
|
|
187
|
+
return 'continue';
|
|
188
|
+
}
|
|
189
|
+
await switchAgent(nextAgent);
|
|
190
|
+
return 'continue';
|
|
191
|
+
}
|
|
192
|
+
return 'prompt';
|
|
193
|
+
};
|
|
194
|
+
const sendTurn = async (line) => {
|
|
195
|
+
const requestId = uuidv4();
|
|
196
|
+
let completed = false;
|
|
197
|
+
const renderer = new StreamingMarkdownRenderer({ colors: stdoutColors });
|
|
198
|
+
const prompt = enrichAiPrompt(line, {
|
|
199
|
+
component: options.component,
|
|
200
|
+
sfOrg: options.sfOrg,
|
|
201
|
+
userStory: options.userStory,
|
|
202
|
+
workItem: options.workItem,
|
|
203
|
+
});
|
|
204
|
+
try {
|
|
205
|
+
await AiGateway.sendMessage(bootstrap.dialogue.id, {
|
|
206
|
+
assistantId: assistantIdForAgent(agent),
|
|
207
|
+
'dev_context': null,
|
|
208
|
+
integrations: null,
|
|
209
|
+
prompt,
|
|
210
|
+
'request_id': requestId,
|
|
211
|
+
'system_prompt': null,
|
|
212
|
+
}, options, (chunk) => {
|
|
213
|
+
if (chunk.type === 'token' && typeof chunk.content === 'string')
|
|
214
|
+
renderer.write(io.output, chunk.content);
|
|
215
|
+
if ((chunk.type === 'status' || chunk.type === 'warning') && typeof chunk.content === 'string') {
|
|
216
|
+
const kind = chunk.type === 'warning' ? 'warning' : 'status';
|
|
217
|
+
writeLine(io.error, formatAiTerminalMessage(chunk.content, kind, { colors: stderrColors }));
|
|
218
|
+
}
|
|
219
|
+
if (chunk.type === 'error' && typeof chunk.content === 'string') {
|
|
220
|
+
throw new Error(chunk.content);
|
|
221
|
+
}
|
|
222
|
+
if (chunk.type === 'done' || chunk.type === 'performance' || chunk.type === 'stream_complete')
|
|
223
|
+
completed = true;
|
|
224
|
+
});
|
|
225
|
+
renderer.finish(io.output);
|
|
226
|
+
if (!completed)
|
|
227
|
+
throw new Error('AI stream ended before stream_complete. Response may be incomplete.');
|
|
228
|
+
turns += 1;
|
|
229
|
+
}
|
|
230
|
+
catch (error) {
|
|
231
|
+
writeLine(io.error, `AI turn failed: ${errorMessage(error)}`);
|
|
232
|
+
}
|
|
233
|
+
};
|
|
64
234
|
process.once('SIGINT', close);
|
|
65
235
|
try {
|
|
66
236
|
writeLine(io.output, `${agent} Agent chat`);
|
|
67
237
|
writeLine(io.output, `Dialogue: ${bootstrap.dialogue.id}`);
|
|
68
|
-
renderHelp(io.output);
|
|
238
|
+
renderHelp(io.output, sessionCommands);
|
|
239
|
+
if (loadHistory)
|
|
240
|
+
renderHistory(io.output, bootstrap.dialogue, stdoutColors);
|
|
69
241
|
while (true) {
|
|
70
242
|
const line = (await question(rl, '> ')).trim();
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
if (line === '/exit' || line === 'exit' || line === 'quit')
|
|
243
|
+
const action = await handleCommand(line);
|
|
244
|
+
if (action === 'exit')
|
|
74
245
|
break;
|
|
75
|
-
if (
|
|
76
|
-
renderHelp(io.output);
|
|
77
|
-
continue;
|
|
78
|
-
}
|
|
79
|
-
if (line === '/clear') {
|
|
80
|
-
bootstrap = await bootstrapAiDialogue({ ...options, agent, dialogue: undefined, kind: 'chat' });
|
|
81
|
-
writeLine(io.output, `Started new dialogue: ${bootstrap.dialogue.id}`);
|
|
82
|
-
continue;
|
|
83
|
-
}
|
|
84
|
-
if (line.startsWith('/agent ')) {
|
|
85
|
-
const nextAgent = normalizeAgent(line.slice('/agent '.length).trim());
|
|
86
|
-
if (nextAgent === undefined) {
|
|
87
|
-
writeLine(io.error, `Unknown agent. Use ${AI_CHAT_AGENTS.join(', ')}.`);
|
|
88
|
-
continue;
|
|
89
|
-
}
|
|
90
|
-
agent = nextAgent;
|
|
91
|
-
bootstrap = await bootstrapAiDialogue({ ...options, agent, dialogue: undefined, kind: 'chat' });
|
|
92
|
-
writeLine(io.output, `Switched to ${agent} agent. Dialogue: ${bootstrap.dialogue.id}`);
|
|
246
|
+
if (action === 'continue')
|
|
93
247
|
continue;
|
|
94
|
-
|
|
95
|
-
const requestId = uuidv4();
|
|
96
|
-
let completed = false;
|
|
97
|
-
const renderer = new StreamingMarkdownRenderer({ colors: stdoutColors });
|
|
98
|
-
const prompt = enrichAiPrompt(line, {
|
|
99
|
-
component: options.component,
|
|
100
|
-
sfOrg: options.sfOrg,
|
|
101
|
-
userStory: options.userStory,
|
|
102
|
-
workItem: options.workItem,
|
|
103
|
-
});
|
|
104
|
-
try {
|
|
105
|
-
await AiGateway.sendMessage(bootstrap.dialogue.id, {
|
|
106
|
-
assistantId: assistantIdForAgent(agent),
|
|
107
|
-
'dev_context': null,
|
|
108
|
-
integrations: null,
|
|
109
|
-
prompt,
|
|
110
|
-
'request_id': requestId,
|
|
111
|
-
'system_prompt': null,
|
|
112
|
-
}, options, (chunk) => {
|
|
113
|
-
if (chunk.type === 'token' && typeof chunk.content === 'string')
|
|
114
|
-
renderer.write(io.output, chunk.content);
|
|
115
|
-
if ((chunk.type === 'status' || chunk.type === 'warning') && typeof chunk.content === 'string') {
|
|
116
|
-
const kind = chunk.type === 'warning' ? 'warning' : 'status';
|
|
117
|
-
writeLine(io.error, formatAiTerminalMessage(chunk.content, kind, { colors: stderrColors }));
|
|
118
|
-
}
|
|
119
|
-
if (chunk.type === 'error' && typeof chunk.content === 'string') {
|
|
120
|
-
throw new Error(chunk.content);
|
|
121
|
-
}
|
|
122
|
-
if (chunk.type === 'done' || chunk.type === 'performance' || chunk.type === 'stream_complete')
|
|
123
|
-
completed = true;
|
|
124
|
-
});
|
|
125
|
-
renderer.finish(io.output);
|
|
126
|
-
if (!completed)
|
|
127
|
-
throw new Error('AI stream ended before stream_complete. Response may be incomplete.');
|
|
128
|
-
turns += 1;
|
|
129
|
-
}
|
|
130
|
-
catch (error) {
|
|
131
|
-
writeLine(io.error, `AI turn failed: ${errorMessage(error)}`);
|
|
132
|
-
}
|
|
248
|
+
await sendTurn(line);
|
|
133
249
|
}
|
|
134
250
|
}
|
|
135
251
|
catch (error) {
|