superun-ai-cli 0.1.32 → 0.1.34

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.
Files changed (45) hide show
  1. package/README.en.md +2 -0
  2. package/README.md +24 -1
  3. package/dist/api/agent-friendly-api.d.ts +16 -0
  4. package/dist/api/agent-friendly-api.js +83 -0
  5. package/dist/api/agent-friendly-api.js.map +1 -0
  6. package/dist/commands/chat/agent-friendly.d.ts +4 -0
  7. package/dist/commands/chat/agent-friendly.js +97 -0
  8. package/dist/commands/chat/agent-friendly.js.map +1 -0
  9. package/dist/commands/chat/index.js +2 -0
  10. package/dist/commands/chat/index.js.map +1 -1
  11. package/dist/commands/chat/publish.js +7 -0
  12. package/dist/commands/chat/publish.js.map +1 -1
  13. package/dist/commands/shared.d.ts +4 -0
  14. package/dist/commands/shared.js +46 -28
  15. package/dist/commands/shared.js.map +1 -1
  16. package/dist/config/state-directory.d.ts +1 -0
  17. package/dist/config/state-directory.js +13 -0
  18. package/dist/config/state-directory.js.map +1 -0
  19. package/dist/conversation/agent-friendly-prompts.d.ts +11 -0
  20. package/dist/conversation/agent-friendly-prompts.js +57 -0
  21. package/dist/conversation/agent-friendly-prompts.js.map +1 -0
  22. package/dist/conversation/agent-friendly.d.ts +24 -0
  23. package/dist/conversation/agent-friendly.js +165 -0
  24. package/dist/conversation/agent-friendly.js.map +1 -0
  25. package/dist/interactions/draft-store.d.ts +8 -0
  26. package/dist/interactions/draft-store.js +163 -70
  27. package/dist/interactions/draft-store.js.map +1 -1
  28. package/dist/interactions/state-storage.d.ts +4 -0
  29. package/dist/interactions/state-storage.js +65 -0
  30. package/dist/interactions/state-storage.js.map +1 -0
  31. package/dist/output/exit-codes.d.ts +4 -0
  32. package/dist/output/exit-codes.js +4 -0
  33. package/dist/output/exit-codes.js.map +1 -1
  34. package/dist/program.js +4 -1
  35. package/dist/program.js.map +1 -1
  36. package/dist/session/binding.d.ts +6 -4
  37. package/dist/session/binding.js +68 -22
  38. package/dist/session/binding.js.map +1 -1
  39. package/dist/session/remember-worker.d.ts +1 -0
  40. package/dist/session/remember-worker.js +43 -0
  41. package/dist/session/remember-worker.js.map +1 -0
  42. package/dist/session/remember.d.ts +9 -0
  43. package/dist/session/remember.js +14 -0
  44. package/dist/session/remember.js.map +1 -0
  45. package/package.json +1 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state-directory.js","sourceRoot":"","sources":["../../src/config/state-directory.ts"],"names":[],"mappings":"AAAA,gDAAgD;AAChD,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACxD,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAEnD,MAAM,UAAU,cAAc,CAAC,IAAiC;IAC9D,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC;IACjD,IAAI,UAAU,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC,OAAO,EAAE,EAAE,wBAAwB,EAAE,IAAI,CAAC,CAAC;IACrF,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC;QAC/C,MAAM,IAAI,QAAQ,CAAC,kBAAkB,EAAE,uCAAuC,CAAC,CAAC;IAClF,OAAO,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,EAAE,IAAI,CAAC,CAAC;AAC3C,CAAC"}
@@ -0,0 +1,11 @@
1
+ /** 与 Glow origin/pre 29112fe11d 同源的技能协议及两种完整接入指令。@author xiuyu.yi */
2
+ import type { ChatInput } from '../api/agent-command-api.js';
3
+ export type AgentFriendlyMethod = 'skill' | 'connector';
4
+ export declare const AGENT_FRIENDLY_DESCRIPTION = "\u8BA9\u4F60\u7684 AI \u5E94\u7528\u4F7F\u7528\u8FD9\u4E2A\u9879\u76EE\uFF0C\u53EF\u4EE5\u628A\u9879\u76EE\u8FDE\u63A5\u5230\u4F60\u6B63\u5728\u4F7F\u7528\u7684 AI \u5E94\u7528\uFF0C\u901A\u8FC7\u5BF9\u8BDD\u67E5\u8BE2\u6570\u636E\u3001\u4F7F\u7528\u9879\u76EE\u529F\u80FD\u3002";
5
+ export declare function agentFriendlyChat(sessionId: string): ChatInput;
6
+ export declare function agentFriendlyPrompt(method: AgentFriendlyMethod, connection: {
7
+ appName: string;
8
+ supabaseUrl: string;
9
+ anonKey: string;
10
+ manifestUrl: string;
11
+ }): string;
@@ -0,0 +1,57 @@
1
+ import { AGENT_FRIENDLY_SKILL_ID } from '../api/agent-friendly-api.js';
2
+ export const AGENT_FRIENDLY_DESCRIPTION = '让你的 AI 应用使用这个项目,可以把项目连接到你正在使用的 AI 应用,通过对话查询数据、使用项目功能。';
3
+ export function agentFriendlyChat(sessionId) {
4
+ return {
5
+ sessionId,
6
+ content: [
7
+ '<command-message>连接 AI 应用</command-message>',
8
+ `<command-name>${AGENT_FRIENDLY_SKILL_ID}</command-name>`,
9
+ '<command-args>请生成「连接 AI 应用」:按照该技能的 SOP 为当前项目准备技能和连接器两种接入方式,并在完成后将该技能状态更新为 ENABLED。</command-args>',
10
+ '<command-type>skill</command-type>',
11
+ ].join('\n'),
12
+ roundExtra: { special_skill_scope: 'official' },
13
+ businessParams: {
14
+ skill_display: {
15
+ skillId: AGENT_FRIENDLY_SKILL_ID,
16
+ name: '连接 AI 应用',
17
+ category: 'technical',
18
+ description: '连接常用的 AI 应用,并在其中使用 superun 部分功能、查询数据。',
19
+ },
20
+ },
21
+ };
22
+ }
23
+ const SKILL_PROMPT = '请把这个 superun 项目作为一个技能接入你当前所在的AI应用,并完成一次真实查询验证。\n\n请按顺序执行:\n1. 先确认当前应用支持安装或导入技能;如果不支持,请明确告诉我,不要声称已经接入。\n2. 确认本机有 Node.js 20 或更高版本,然后执行:\n{{installCommand}}\n3. 先检查项目是否已经存在:\n{{inspectCommand}}\n只有明确提示项目未注册或不存在时,才执行:\n{{initCommand}}\n不要重复初始化已有项目。\n4. 完成登录并刷新项目能力:\n{{loginCommand}}\n{{refreshCommand}}\n5. 从 {{skillUrl}} 下载技能说明,安装到当前应用的技能目录中。保留已有其他技能,不要覆盖无关文件。\n6. 按技能说明执行一次只读的真实项目查询。只有拿到真实结果后才告诉我接入成功;如果失败,请说明失败步骤和错误信息。';
24
+ const CONNECTOR_PROMPT = '请把这个 superun 项目接入你当前所在的智能体或 MCP 客户端,并用一次真实查询确认连接成功。先确认当前客户端支持运行本地 MCP 服务(stdio);如果不支持,请直接说明,不能假装接入成功。然后按以下步骤执行:\n\n1. 检查 Node.js 版本为 20 或更高,然后安装 CLI:\n{{installCommand}}\n\n2. 先检查这个项目是否已经注册:\n{{inspectCommand}}\n如果命令成功,复用现有项目配置,不要重复执行 init,以免覆盖已有设置。只有明确提示项目未注册或不存在时,才执行:\n{{initCommand}}\n初始化后再次运行上述 app show 命令,并记录返回的 id(如有)。\n\n3. 使用浏览器登录:\n{{loginCommand}}\n请让我在浏览器中完成授权,不要要求我在对话中粘贴 access token 或 refresh token。\n\n4. 优先使用当前客户端自带的 MCP 设置页面或命令。如果必须修改配置文件,先确认该客户端官方规定的配置位置和格式,再把下面的本地 MCP 服务参数合并进去;如果客户端使用 mcpServers 结构,可以直接采用下面的配置,否则请转换成作用相同的格式。必须保留已有的其他 MCP 服务,不要覆盖整个配置。如果 app show 返回 id,优先使用该 id 替换下方 args 中 --app 后的名称;如果当前客户端找不到 superun 命令,请先找到它的绝对路径再写入:\n{{mcpConfig}}\n\n5. 让客户端重新加载 MCP 服务并确认已经发现可用工具,然后实际调用 project_status,再执行一次只读项目查询。只有真实查询成功后,才告诉我配置完成;失败时请保留原配置并说明具体原因。不要开启不受限制的高权限模式。每次调用 call_function 前,先展示具体函数名和参数并等待我明确确认;只有确认后才将 userConfirmed 设为 true,未确认不得调用。';
25
+ /** 保留 Glow 的命令形状,转义项目名中的 Shell 特殊字符。 */
26
+ function shellName(name) {
27
+ return '"' + name.replace(/[\\"$`]/g, '\\$&') + '"';
28
+ }
29
+ export function agentFriendlyPrompt(method, connection) {
30
+ const { appName, supabaseUrl, anonKey, manifestUrl } = connection;
31
+ const app = `superun --app ${shellName(appName)} --env production`;
32
+ const login = `${app} login --browser`;
33
+ const refresh = `${app} app refresh`;
34
+ const serverName = `superun-${appName
35
+ .trim()
36
+ .replace(/[^a-zA-Z0-9._-]+/g, '-')
37
+ .replace(/^-+|-+$/g, '') || 'project'}`;
38
+ const values = {
39
+ installCommand: 'npm install -g superun-cli',
40
+ inspectCommand: `${app} app show`,
41
+ initCommand: `superun init --name ${shellName(appName)} --url ${supabaseUrl} --anon-key ${anonKey} --manifest ${manifestUrl} --environment production`,
42
+ loginCommand: method === 'skill' ? login : `${login}\n${refresh}`,
43
+ refreshCommand: refresh,
44
+ skillUrl: 'https://raw.githubusercontent.com/AiGuangInc/superun-cli/main/skills/superun/SKILL.md',
45
+ mcpConfig: JSON.stringify({
46
+ mcpServers: {
47
+ [serverName]: {
48
+ type: 'stdio',
49
+ command: 'superun',
50
+ args: ['--app', appName, '--env', 'production', 'mcp'],
51
+ },
52
+ },
53
+ }, null, 2),
54
+ };
55
+ return (method === 'skill' ? SKILL_PROMPT : CONNECTOR_PROMPT).replace(/{{(\w+)}}/g, (_, key) => values[key]);
56
+ }
57
+ //# sourceMappingURL=agent-friendly-prompts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-friendly-prompts.js","sourceRoot":"","sources":["../../src/conversation/agent-friendly-prompts.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AAGvE,MAAM,CAAC,MAAM,0BAA0B,GACrC,uDAAuD,CAAC;AAE1D,MAAM,UAAU,iBAAiB,CAAC,SAAiB;IACjD,OAAO;QACL,SAAS;QACT,OAAO,EAAE;YACP,6CAA6C;YAC7C,iBAAiB,uBAAuB,iBAAiB;YACzD,mGAAmG;YACnG,oCAAoC;SACrC,CAAC,IAAI,CAAC,IAAI,CAAC;QACZ,UAAU,EAAE,EAAE,mBAAmB,EAAE,UAAU,EAAE;QAC/C,cAAc,EAAE;YACd,aAAa,EAAE;gBACb,OAAO,EAAE,uBAAuB;gBAChC,IAAI,EAAE,UAAU;gBAChB,QAAQ,EAAE,WAAW;gBACrB,WAAW,EAAE,uCAAuC;aACrD;SACF;KACF,CAAC;AACJ,CAAC;AAED,MAAM,YAAY,GAChB,qaAAqa,CAAC;AACxa,MAAM,gBAAgB,GACpB,02BAA02B,CAAC;AAE72B,wCAAwC;AACxC,SAAS,SAAS,CAAC,IAAY;IAC7B,OAAO,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,MAAM,CAAC,GAAG,GAAG,CAAC;AACtD,CAAC;AAED,MAAM,UAAU,mBAAmB,CACjC,MAA2B,EAC3B,UAKC;IAED,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,WAAW,EAAE,GAAG,UAAU,CAAC;IAClE,MAAM,GAAG,GAAG,iBAAiB,SAAS,CAAC,OAAO,CAAC,mBAAmB,CAAC;IACnE,MAAM,KAAK,GAAG,GAAG,GAAG,kBAAkB,CAAC;IACvC,MAAM,OAAO,GAAG,GAAG,GAAG,cAAc,CAAC;IACrC,MAAM,UAAU,GAAG,WACjB,OAAO;SACJ,IAAI,EAAE;SACN,OAAO,CAAC,mBAAmB,EAAE,GAAG,CAAC;SACjC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,IAAI,SAChC,EAAE,CAAC;IACH,MAAM,MAAM,GAA2B;QACrC,cAAc,EAAE,4BAA4B;QAC5C,cAAc,EAAE,GAAG,GAAG,WAAW;QACjC,WAAW,EAAE,uBAAuB,SAAS,CAAC,OAAO,CAAC,UAAU,WAAW,eAAe,OAAO,eAAe,WAAW,2BAA2B;QACtJ,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,KAAK,OAAO,EAAE;QACjE,cAAc,EAAE,OAAO;QACvB,QAAQ,EAAE,uFAAuF;QACjG,SAAS,EAAE,IAAI,CAAC,SAAS,CACvB;YACE,UAAU,EAAE;gBACV,CAAC,UAAU,CAAC,EAAE;oBACZ,IAAI,EAAE,OAAO;oBACb,OAAO,EAAE,SAAS;oBAClB,IAAI,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,KAAK,CAAC;iBACvD;aACF;SACF,EACD,IAAI,EACJ,CAAC,CACF;KACF,CAAC;IACF,OAAO,CAAC,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,OAAO,CACnE,YAAY,EACZ,CAAC,CAAC,EAAE,GAAW,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAE,CACjC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,24 @@
1
+ /** Agent 友好的独立结果与引导,不改变普通会话的状态判断。@author xiuyu.yi */
2
+ import type { CreationResult } from '../contracts/cli-output.js';
3
+ import type { SessionView } from '../contracts/node-wire.js';
4
+ import type { CreationRuntime } from '../runtime.js';
5
+ import { AgentFriendlyApi } from '../api/agent-friendly-api.js';
6
+ import { type AgentFriendlyMethod } from './agent-friendly-prompts.js';
7
+ export type AgentFriendlyResult = CreationResult & {
8
+ agentFriendly: {
9
+ stage: 'GENERATING' | 'NOT_READY' | 'READY' | 'INSTRUCTIONS';
10
+ method?: AgentFriendlyMethod;
11
+ prompt?: string;
12
+ methods?: Array<{
13
+ value: AgentFriendlyMethod;
14
+ label: string;
15
+ description: string;
16
+ }>;
17
+ };
18
+ };
19
+ export declare function isAgentFriendlyRound(view: SessionView): boolean;
20
+ export declare function agentFriendlyGuidance(service: CreationRuntime, result: AgentFriendlyResult): AgentFriendlyResult;
21
+ export declare function agentFriendlyNotReady(sessionId: string, notice: string): AgentFriendlyResult;
22
+ export declare function readyAgentFriendly(service: CreationRuntime, api: AgentFriendlyApi, view: SessionView, method?: AgentFriendlyMethod): Promise<AgentFriendlyResult>;
23
+ /** 只包装新命令的等待结果,普通 chat state/wait 保持原有行为。 */
24
+ export declare function projectAgentFriendlyGeneration(service: CreationRuntime, api: AgentFriendlyApi, view: SessionView): Promise<AgentFriendlyResult>;
@@ -0,0 +1,165 @@
1
+ import { AGENT_FRIENDLY_SKILL_ID, LEGACY_AGENT_FRIENDLY_SKILL_ID, AgentFriendlyApi, } from '../api/agent-friendly-api.js';
2
+ import { currentRound, roundMessage } from './round-selector.js';
3
+ import { resolveState } from './state-resolver.js';
4
+ import { collectInteractions } from '../interactions/registry.js';
5
+ import { object, text } from '../contracts/value.js';
6
+ import { COMMAND_NAME } from '../config/constants.js';
7
+ import { agentFriendlyPrompt } from './agent-friendly-prompts.js';
8
+ export function isAgentFriendlyRound(view) {
9
+ return !!currentRound(view)?.userItems.some((item) => [AGENT_FRIENDLY_SKILL_ID, LEGACY_AGENT_FRIENDLY_SKILL_ID].includes(text(object(item.payload.skillDisplay).skillId) ?? ''));
10
+ }
11
+ export function agentFriendlyGuidance(service, result) {
12
+ const command = [
13
+ COMMAND_NAME,
14
+ '--endpoint',
15
+ service.client.config.endpoint,
16
+ '--locale',
17
+ service.client.config.locale,
18
+ 'chat',
19
+ 'agent-friendly',
20
+ ];
21
+ const { stage, method } = result.agentFriendly;
22
+ let actions;
23
+ if (result.interactions.length) {
24
+ // 沿用真实服务端提问和回复命令;回答后回到只读接入查询,不再发生成消息。
25
+ actions = service.withGuidance(result).nextActions.map((action) => ({
26
+ ...action,
27
+ instruction: `${action.instruction} 当前仍在准备 Agent 友好接入能力。回答并处理当前问题后,执行 ${[...command, '--status', '--', result.sessionId].join(' ')} 继续本次流程,不重新生成。`,
28
+ }));
29
+ }
30
+ else if (stage === 'READY') {
31
+ actions = (result.agentFriendly.methods ?? []).map((option) => ({
32
+ action: option.value === 'skill' ? 'SELECT_AGENT_FRIENDLY_SKILL' : 'SELECT_AGENT_FRIENDLY_CONNECTOR',
33
+ requiresUserInput: true,
34
+ instruction: '只询问一次“你希望通过哪种方式接入?”,展示 messages 中的两个选项及说明,支持原生选择题的宿主也可使用 agentFriendly.methods。等待用户选择,选择后执行对应命令。不要自动选择,不安装,不生成文件,不创建新会话。',
35
+ command: [...command, '--method', option.value, '--', result.sessionId],
36
+ }));
37
+ }
38
+ else if (stage === 'INSTRUCTIONS' && method) {
39
+ const display = '先展示 messages:在一个文本代码块中完整展示所选方式的接入原文,不摘要、不截断、不把命令中的 URL 改成 Markdown 链接、不生成文件。展示指令不等于执行安装,指令准备完成不等于已接入。随后原样展示以下引导,不改写标题、选项和说明:\n接下来,你可以直接回复我:\n\n- **接入当前会话**:我在当前会话中完成配置和查询验证。\n- **接入到新会话**:我新开一个会话,将完整指令交给它执行。\n- **接入其他 AI 应用**:复制上述完整指令,到目标应用中发送。';
40
+ const read = [...command, '--method', method, '--', result.sessionId];
41
+ actions = [
42
+ {
43
+ action: 'CONNECT_CURRENT_APP',
44
+ requiresUserInput: true,
45
+ command: read,
46
+ instruction: `${display} 用户明确选择“接入当前会话”后,由当前宿主 Agent 执行 messages 代码块中的完整指令(与 agentFriendly.prompt 相同),无需用户再复制发送;先检查宿主能力,浏览器登录由用户完成,拿到真实只读查询结果才可宣布成功。不要将安装指令发回 Superun 项目 chat。command 仅重新读取指令,不执行安装。`,
47
+ },
48
+ {
49
+ action: 'CONNECT_NEW_CONVERSATION',
50
+ requiresUserInput: true,
51
+ command: read,
52
+ instruction: `${display} 用户明确选择“接入到新会话”且宿主提供真实的新会话工具时,才把 messages 代码块中的所选完整指令交给新会话;不传当前研发历史或 PAT。没有该工具就说明不支持,让用户选择当前会话继续或自行复制。不能用 Superun 新建项目冒充宿主新会话。command 仅重新读取指令。`,
53
+ },
54
+ {
55
+ action: 'CONNECT_OTHER_AI_APP',
56
+ requiresUserInput: true,
57
+ command: read,
58
+ instruction: `${display} 用户选择“接入其他 AI 应用”后,提示复制当前完整指令,到目标应用发送;不自动在本机执行或创建会话。command 仅重新读取指令。`,
59
+ },
60
+ ];
61
+ }
62
+ else {
63
+ actions = [
64
+ {
65
+ action: stage === 'GENERATING' ? 'WAIT_AGENT_FRIENDLY' : 'QUERY_AGENT_FRIENDLY',
66
+ requiresUserInput: stage !== 'GENERATING',
67
+ instruction: stage === 'GENERATING'
68
+ ? '展示当前任务的实际进度,继续等待生成及后台任务收尾;不要重复发送生成消息,不提前询问接入方式或输出两套指令。'
69
+ : '如实展示当前未就绪的原因;此命令只查询状态,不重复生成,不声称已经开启或接入。',
70
+ command: [
71
+ ...command,
72
+ '--status',
73
+ ...(result.messageId ? ['--message-id', result.messageId] : []),
74
+ '--',
75
+ result.sessionId,
76
+ ],
77
+ },
78
+ ];
79
+ }
80
+ return { ...result, nextActions: actions };
81
+ }
82
+ export function agentFriendlyNotReady(sessionId, notice) {
83
+ return {
84
+ state: 'NEEDS_INPUT',
85
+ sessionId,
86
+ messages: [{ id: `${sessionId}:agent-friendly:notice`, role: 'assistant', text: notice }],
87
+ interactions: [],
88
+ progress: [],
89
+ agentFriendly: { stage: 'NOT_READY' },
90
+ };
91
+ }
92
+ export async function readyAgentFriendly(service, api, view, method) {
93
+ const sessionId = view.session.sessionId;
94
+ const connection = await api.connection(sessionId, text(view.session.sessionKey) ?? '');
95
+ const base = { sessionId, topic: view.session.topic, interactions: [], progress: [] };
96
+ if (!method)
97
+ return agentFriendlyGuidance(service, {
98
+ ...base,
99
+ state: 'NEEDS_SELECTION',
100
+ messages: [
101
+ {
102
+ id: `${sessionId}:agent-friendly:select`,
103
+ role: 'assistant',
104
+ text: '项目接入能力已准备好,你希望通过哪种方式接入?\n\n- **通过技能接入**:适合支持安装 Skill 的 AI 应用。\n- **通过连接器接入**:适合支持本地 MCP 的 AI 应用。',
105
+ },
106
+ ],
107
+ agentFriendly: {
108
+ stage: 'READY',
109
+ methods: [
110
+ { value: 'skill', label: '通过技能接入', description: '适合支持安装 Skill 的 AI 应用。' },
111
+ { value: 'connector', label: '通过连接器接入', description: '适合支持本地 MCP 的 AI 应用。' },
112
+ ],
113
+ },
114
+ });
115
+ const prompt = agentFriendlyPrompt(method, connection);
116
+ return agentFriendlyGuidance(service, {
117
+ ...base,
118
+ state: 'COMPLETED',
119
+ messages: [
120
+ {
121
+ id: `${sessionId}:agent-friendly:${method}`,
122
+ role: 'assistant',
123
+ text: `复制下面整段内容,发送到你要接入的 AI 应用。\n\n\`\`\`text\n${prompt}\n\`\`\``,
124
+ },
125
+ ],
126
+ agentFriendly: { stage: 'INSTRUCTIONS', method, prompt },
127
+ });
128
+ }
129
+ /** 只包装新命令的等待结果,普通 chat state/wait 保持原有行为。 */
130
+ export async function projectAgentFriendlyGeneration(service, api, view) {
131
+ const activeSubagentWork = await service.taskProgress.hasPendingSubagentWork(view.session.sessionId);
132
+ // 主会话和子任务都已结束且技能已开启时,直接交付;末尾回执无需再回溯审查/测试来源。
133
+ if (view.session.status === 3 && !activeSubagentWork && (await api.enabled(view.session.sessionId)))
134
+ return readyAgentFriendly(service, api, view);
135
+ const round = currentRound(view);
136
+ const businessType = roundMessage(view, round)?.roundExtra?.business_type;
137
+ const isReceipt = round?.meta?.subAgentReport ||
138
+ ['sub_agent_report', 'background_task_report'].includes(String(businessType));
139
+ let result;
140
+ if (isReceipt) {
141
+ // 本入口已确定是能力生成,回执只参与生命周期和真实提问,不触发审查/测试来源回溯。
142
+ const current = { ...view, activeSubagentWork };
143
+ result = resolveState(current, collectInteractions(current));
144
+ result.taskProgress = await service.taskProgress.read(current, [], result.interactions);
145
+ }
146
+ else
147
+ result = await service.inspect(view);
148
+ const featureSelection = result.state === 'NEEDS_INPUT' &&
149
+ result.interactions.length > 0 &&
150
+ result.interactions.every((item) => item.kind === 'SELECT_FEATURES') &&
151
+ result.taskProgress?.activeCount === 0;
152
+ if (result.state === 'COMPLETED' || featureSelection) {
153
+ if (await api.enabled(view.session.sessionId))
154
+ return readyAgentFriendly(service, api, view);
155
+ return agentFriendlyGuidance(service, agentFriendlyNotReady(view.session.sessionId, '本轮执行已结束,但尚未确认 Agent 友好技能已开启,请查询状态或查看本轮执行结果。'));
156
+ }
157
+ return agentFriendlyGuidance(service, {
158
+ ...result,
159
+ messages: result.interactions.length || !['RUNNING', 'QUEUED'].includes(result.state) ? result.messages : [],
160
+ agentFriendly: {
161
+ stage: ['RUNNING', 'QUEUED', 'NEEDS_INPUT'].includes(result.state) ? 'GENERATING' : 'NOT_READY',
162
+ },
163
+ });
164
+ }
165
+ //# sourceMappingURL=agent-friendly.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-friendly.js","sourceRoot":"","sources":["../../src/conversation/agent-friendly.ts"],"names":[],"mappings":"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"}
@@ -5,6 +5,14 @@ export declare class InteractionDraftStore {
5
5
  constructor(scope: string, root?: string);
6
6
  private path;
7
7
  read(key: string): Promise<unknown>;
8
+ private remove;
9
+ private close;
10
+ private writeFile;
11
+ private prepare;
12
+ private checkDirectory;
8
13
  write(key: string, value: unknown): Promise<void>;
14
+ private owner;
15
+ private alive;
16
+ private recoveryRequired;
9
17
  locked<T>(key: string, run: () => Promise<T>): Promise<T>;
10
18
  }
@@ -1,14 +1,17 @@
1
1
  /** 按环境和凭据隔离交互草稿,串行保存回答与创建进度。@author xiuyu.yi */
2
2
  import { createHash, randomUUID } from 'node:crypto';
3
3
  import { mkdir, open, readFile, rename, unlink } from 'node:fs/promises';
4
- import { homedir } from 'node:os';
5
- import { join } from 'node:path';
4
+ import { join, resolve } from 'node:path';
5
+ import { stateDirectory } from '../config/state-directory.js';
6
6
  import { CliError } from '../output/exit-codes.js';
7
+ import { filesystemCode, stateOperation, withStateCleanup } from './state-storage.js';
7
8
  export const fingerprint = (value) => createHash('sha256').update(JSON.stringify(value)).digest('hex');
9
+ // 同一进程同一目录只检查一次;实际操作仍处理权限变化与磁盘异常。
10
+ const checkedDirectories = new Map();
8
11
  export class InteractionDraftStore {
9
12
  scope;
10
13
  root;
11
- constructor(scope, root = join(homedir(), '.config/superun-ai-cli/interactions')) {
14
+ constructor(scope, root = stateDirectory('interactions')) {
12
15
  this.scope = scope;
13
16
  this.root = root;
14
17
  }
@@ -16,87 +19,177 @@ export class InteractionDraftStore {
16
19
  return join(this.root, this.scope, `${fingerprint(key)}.json`);
17
20
  }
18
21
  async read(key) {
22
+ const path = this.path(key);
23
+ const content = await stateOperation('read', path, async () => {
24
+ try {
25
+ return await readFile(path, 'utf8');
26
+ }
27
+ catch (error) {
28
+ if (filesystemCode(error) === 'ENOENT')
29
+ return undefined;
30
+ throw error;
31
+ }
32
+ });
33
+ if (content === undefined)
34
+ return undefined;
19
35
  try {
20
- return JSON.parse(await readFile(this.path(key), 'utf8'));
36
+ return JSON.parse(content);
21
37
  }
22
- catch (error) {
23
- if (error.code === 'ENOENT')
24
- return undefined;
25
- throw new CliError('PROTOCOL_ERROR', '交互草稿无法读取,请保留文件排查,勿重复创建');
38
+ catch {
39
+ throw new CliError('PROTOCOL_ERROR', '本地状态文件格式无效,请保留文件排查,勿重复创建', { path });
26
40
  }
27
41
  }
42
+ remove(path) {
43
+ return stateOperation('unlink', path, async () => {
44
+ try {
45
+ await unlink(path);
46
+ }
47
+ catch (error) {
48
+ if (filesystemCode(error) !== 'ENOENT')
49
+ throw error;
50
+ }
51
+ });
52
+ }
53
+ close(file, path) {
54
+ return stateOperation('close', path, () => file.close());
55
+ }
56
+ async writeFile(path, content) {
57
+ const file = await stateOperation('create', path, () => open(path, 'wx', 0o600));
58
+ await withStateCleanup(async () => {
59
+ await stateOperation('write', path, () => file.writeFile(content));
60
+ await stateOperation('fsync', path, () => file.sync());
61
+ }, [() => this.close(file, path)]);
62
+ }
63
+ prepare() {
64
+ const directory = resolve(this.root, this.scope);
65
+ let checked = checkedDirectories.get(directory);
66
+ if (!checked) {
67
+ checked = this.checkDirectory(directory).catch((error) => {
68
+ checkedDirectories.delete(directory);
69
+ throw error;
70
+ });
71
+ checkedDirectories.set(directory, checked);
72
+ }
73
+ return checked;
74
+ }
75
+ async checkDirectory(directory) {
76
+ await stateOperation('mkdir', directory, () => mkdir(directory, { recursive: true, mode: 0o700 }));
77
+ const temp = join(directory, `.state-probe-${randomUUID()}.tmp`);
78
+ const target = `${temp}.ready`;
79
+ // 检查失败最多留下诊断文件,不能先创建真实业务锁;清理失败保留路径。
80
+ await withStateCleanup(async () => {
81
+ await this.writeFile(temp, '{}');
82
+ await stateOperation('rename', temp, () => rename(temp, target));
83
+ // 同时验证覆盖已存在文件的原子改名,避免首次绑定成功、后续更新才失败。
84
+ await this.writeFile(temp, '{}');
85
+ await stateOperation('rename', temp, () => rename(temp, target));
86
+ }, [() => this.remove(temp), () => this.remove(target)]);
87
+ }
28
88
  async write(key, value) {
29
- await mkdir(join(this.root, this.scope), { recursive: true, mode: 0o700 });
89
+ await this.prepare();
30
90
  const path = this.path(key), temp = `${path}.${randomUUID()}.tmp`;
31
- const file = await open(temp, 'wx', 0o600);
32
- try {
33
- await file.writeFile(JSON.stringify(value));
34
- await file.sync();
35
- }
36
- finally {
37
- await file.close();
38
- }
39
- await rename(temp, path);
91
+ await withStateCleanup(async () => {
92
+ await this.writeFile(temp, JSON.stringify(value));
93
+ await stateOperation('rename', temp, () => rename(temp, path));
94
+ }, [() => this.remove(temp)]);
40
95
  }
41
- async locked(key, run) {
42
- await mkdir(join(this.root, this.scope), { recursive: true, mode: 0o700 });
43
- const path = `${this.path(key)}.lock`;
44
- // 不回收无法确认归属的锁。已退出进程的遗留锁可在下一次操作恢复。
45
- let lock;
46
- try {
47
- lock = await open(path, 'wx', 0o600);
48
- }
49
- catch (error) {
50
- if (error.code !== 'EEXIST')
51
- throw error;
52
- // 遗留锁回收也必须互斥,避免两个恢复进程误删对方刚取得的新锁。
53
- const recoveryPath = `${path}.recovery`;
54
- let recovery;
96
+ async owner(path) {
97
+ const content = await stateOperation('read-lock', path, async () => {
55
98
  try {
56
- recovery = await open(recoveryPath, 'wx', 0o600);
99
+ return await readFile(path, 'utf8');
57
100
  }
58
- catch {
59
- throw new CliError('AMBIGUOUS_INTERACTION', '交互锁正在恢复,请稍后查询状态');
101
+ catch (error) {
102
+ if (filesystemCode(error) === 'ENOENT')
103
+ throw new CliError('LOCAL_STATE_LOCKED', '本地状态锁已变化,请重新查询状态', { path });
104
+ throw error;
60
105
  }
106
+ });
107
+ const pid = Number(content);
108
+ return Number.isSafeInteger(pid) && pid > 0 ? pid : undefined;
109
+ }
110
+ async alive(pid, path) {
111
+ return stateOperation('check-lock-owner', path, async () => {
61
112
  try {
62
- let dead = false;
63
- try {
64
- const pid = Number(await readFile(path, 'utf8'));
65
- if (Number.isInteger(pid) && pid > 0) {
66
- try {
67
- process.kill(pid, 0);
68
- }
69
- catch (cause) {
70
- dead = cause.code === 'ESRCH';
71
- }
72
- }
73
- }
74
- catch {
75
- /* 未写完的锁不能抢占。 */
76
- }
77
- if (!dead)
78
- throw new CliError('AMBIGUOUS_INTERACTION', '当前交互正在处理,请稍后查询状态');
79
- await unlink(path);
113
+ process.kill(pid, 0);
114
+ return true;
115
+ }
116
+ catch (error) {
117
+ if (filesystemCode(error) === 'ESRCH')
118
+ return false;
119
+ throw error;
120
+ }
121
+ });
122
+ }
123
+ recoveryRequired(path, lockPid) {
124
+ return new CliError('LOCAL_STATE_RECOVERY_REQUIRED', '本地状态锁无法安全自动回收;请先确认没有写入进程,再备份并恢复所列锁文件,不要反复重试或按文件年龄强制删除', { path, lockPid });
125
+ }
126
+ async locked(key, run) {
127
+ await this.prepare();
128
+ const path = `${this.path(key)}.lock`;
129
+ let lock;
130
+ const acquire = () => open(path, 'wx', 0o600);
131
+ return withStateCleanup(async () => {
132
+ // 恢复分支清理失败时,外层仍会释放刚取得的业务锁。
133
+ await stateOperation('acquire-lock', path, async () => {
80
134
  try {
81
- lock = await open(path, 'wx', 0o600);
135
+ lock = await acquire();
136
+ return;
82
137
  }
83
- catch {
84
- throw new CliError('AMBIGUOUS_INTERACTION', '当前交互正在处理,请稍后查询状态');
138
+ catch (error) {
139
+ if (filesystemCode(error) !== 'EEXIST')
140
+ throw error;
85
141
  }
86
- }
87
- finally {
88
- await recovery.close();
89
- await unlink(recoveryPath);
90
- }
91
- }
92
- try {
93
- await lock.writeFile(String(process.pid));
94
- return await run();
95
- }
96
- finally {
97
- await lock.close();
98
- await unlink(path);
99
- }
142
+ const recoveryPath = `${path}.recovery`;
143
+ const recovery = await stateOperation('acquire-recovery-lock', recoveryPath, async () => {
144
+ try {
145
+ return await open(recoveryPath, 'wx', 0o600);
146
+ }
147
+ catch (error) {
148
+ if (filesystemCode(error) !== 'EEXIST')
149
+ throw error;
150
+ const pid = await this.owner(recoveryPath);
151
+ if (pid !== undefined && (await this.alive(pid, recoveryPath)))
152
+ throw new CliError('LOCAL_STATE_LOCKED', '本地状态锁正在恢复,请等待持有进程结束', {
153
+ path: recoveryPath,
154
+ lockPid: pid,
155
+ });
156
+ // 旧空锁或已退出恢复进程的锁无法凭年龄判断归属,必须显式维护。
157
+ throw this.recoveryRequired(recoveryPath, pid);
158
+ }
159
+ });
160
+ await withStateCleanup(async () => {
161
+ await stateOperation('write-lock-owner', recoveryPath, () => recovery.writeFile(String(process.pid)));
162
+ const pid = await this.owner(path);
163
+ if (pid === undefined)
164
+ throw this.recoveryRequired(path);
165
+ if (await this.alive(pid, path))
166
+ throw new CliError('LOCAL_STATE_LOCKED', '本地状态正在由其他进程更新,请等待该进程结束', {
167
+ path,
168
+ lockPid: pid,
169
+ });
170
+ await this.remove(path);
171
+ try {
172
+ lock = await acquire();
173
+ }
174
+ catch (error) {
175
+ if (filesystemCode(error) !== 'EEXIST')
176
+ throw error;
177
+ throw new CliError('LOCAL_STATE_LOCKED', '其他进程已取得本地状态锁,请稍后查询', { path });
178
+ }
179
+ }, [() => this.close(recovery, recoveryPath), () => this.remove(recoveryPath)]);
180
+ });
181
+ await stateOperation('write-lock-owner', path, () => lock.writeFile(String(process.pid)));
182
+ return run();
183
+ }, [
184
+ async () => {
185
+ if (lock)
186
+ await this.close(lock, path);
187
+ },
188
+ async () => {
189
+ if (lock)
190
+ await this.remove(path);
191
+ },
192
+ ]);
100
193
  }
101
194
  }
102
195
  //# sourceMappingURL=draft-store.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"draft-store.js","sourceRoot":"","sources":["../../src/interactions/draft-store.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"draft-store.js","sourceRoot":"","sources":["../../src/interactions/draft-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export declare function filesystemCode(error: unknown): string | undefined;
2
+ export declare function stateOperation<T>(operation: string, path: string, run: () => Promise<T>): Promise<T>;
3
+ /** 所有清理均尝试执行;清理异常不能覆盖首次异常。 */
4
+ export declare function withStateCleanup<T>(run: () => Promise<T>, cleanup: Array<() => Promise<unknown>>): Promise<T>;