@ai-zen/agents-host 0.1.0-alpha.2 → 0.1.0-alpha.4

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 (42) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/dist/app.d.ts +0 -5
  3. package/dist/app.js +3 -9
  4. package/dist/config.d.ts +3 -2
  5. package/dist/config.js +30 -4
  6. package/dist/handlers/configHandlers.d.ts +1 -3
  7. package/dist/handlers/conversationHandlers.d.ts +0 -2
  8. package/dist/handlers/conversationHandlers.js +2 -16
  9. package/dist/handlers/hostHandlers.d.ts +4 -5
  10. package/dist/handlers/hostHandlers.js +3 -21
  11. package/dist/handlers/index.d.ts +2 -4
  12. package/dist/handlers/index.js +0 -1
  13. package/dist/handlers/noticeHandlers.d.ts +0 -8
  14. package/dist/handlers/noticeHandlers.js +0 -10
  15. package/dist/i18n/en.d.ts +0 -168
  16. package/dist/i18n/en.js +0 -171
  17. package/dist/i18n/zh.d.ts +0 -168
  18. package/dist/i18n/zh.js +0 -169
  19. package/dist/index.d.ts +1 -0
  20. package/dist/net/WsHub.d.ts +1 -2
  21. package/dist/net/WsHub.js +0 -2
  22. package/dist/services/AutoNaming.d.ts +0 -5
  23. package/dist/services/AutoNaming.js +0 -18
  24. package/dist/services/ConfigService.d.ts +2 -2
  25. package/dist/services/ConfigService.js +11 -20
  26. package/dist/services/DiscoveryService.d.ts +10 -2
  27. package/dist/services/DiscoveryService.js +10 -2
  28. package/dist/services/ModelService.d.ts +1 -3
  29. package/dist/services/ModelService.js +0 -4
  30. package/dist/services/QuestionService.d.ts +0 -7
  31. package/dist/services/QuestionService.js +0 -15
  32. package/dist/storage/ConversationRepository.d.ts +0 -3
  33. package/dist/storage/ConversationRepository.js +0 -12
  34. package/dist/storage/QuestionRepository.d.ts +0 -1
  35. package/dist/storage/QuestionRepository.js +0 -4
  36. package/dist/storage/types.d.ts +0 -2
  37. package/dist/wire/methods.d.ts +4 -52
  38. package/dist/wire/methods.js +0 -5
  39. package/dist/wire/states.d.ts +5 -12
  40. package/package.json +4 -3
  41. package/dist/handlers/capabilities.d.ts +0 -26
  42. package/dist/handlers/capabilities.js +0 -138
@@ -12,7 +12,7 @@
12
12
  * 默认项指向被删的那个模型时要改指或清空,不留悬空引用。
13
13
  */
14
14
  import type { AgentRepository } from "@ai-zen/agents-sdk";
15
- import type { AppConfig, ConfigManager, Endpoint, ImageModel, Model, ReasoningPreset, ReasoningPresets } from "@ai-zen/agents-sdk";
15
+ import type { AppConfig, ConfigManager, Endpoint, Model, ReasoningPreset, ReasoningPresets } from "@ai-zen/agents-sdk";
16
16
  import type { ModelCreateParams, ModelCreateResult, ModelDeleteImageParams, ModelDeleteImageResult, ModelDeleteParams, ModelDeleteResult, ModelListImagesResult, ModelListParams, ModelListResult, ModelRestoreFactoryParams, ModelRestoreFactoryResult, ModelSaveImageParams, ModelSaveImageResult, ModelUpdateParams, ModelUpdateResult, ModelView, ProblemFact } from "../wire/index.js";
17
17
  /** 模型服务的依赖;由单根组装后注入 */
18
18
  export interface ModelServiceOptions {
@@ -25,8 +25,6 @@ export interface ModelServiceOptions {
25
25
  export declare function findEndpoint(config: AppConfig, endpointId: string): Endpoint | undefined;
26
26
  /** 按 id 找模型 */
27
27
  export declare function findModel(config: AppConfig, modelId: string): Model | undefined;
28
- /** 按 id 找图片模型 */
29
- export declare function findImageModel(config: AppConfig, imageModelId: string): ImageModel | undefined;
30
28
  /**
31
29
  * 这个模型现在能不能用;能用回 `null`,不能用回一条带原因的事实(F-B5:藏着不如说清楚)。
32
30
  *
@@ -68,10 +68,6 @@ export function findEndpoint(config, endpointId) {
68
68
  export function findModel(config, modelId) {
69
69
  return config.models.find((model) => model.id === modelId);
70
70
  }
71
- /** 按 id 找图片模型 */
72
- export function findImageModel(config, imageModelId) {
73
- return (config.imageModels ?? []).find((model) => model.id === imageModelId);
74
- }
75
71
  /**
76
72
  * 这个模型现在能不能用;能用回 `null`,不能用回一条带原因的事实(F-B5:藏着不如说清楚)。
77
73
  *
@@ -158,13 +158,6 @@ export declare class QuestionService {
158
158
  * 第 3、4 两步都在写状态之前返回,所以「答不下去」不会把问题弄成一个半答的中间态。
159
159
  */
160
160
  answer(params: QuestionAnswerParams, context?: QuestionAnswerContext): Promise<QuestionAnswerResult>;
161
- /**
162
- * 显式取消一个问题(生命周期里的 `cancelled`)。
163
- *
164
- * 只有调用方明确要关掉时才用(例如对话被删、工作流换了方向)。没有任何自动取消的路径 ——
165
- * 越线拒绝之后问题要继续挂着(D23),所以「答不下去」与「关掉它」是两件事。
166
- */
167
- cancel(questionId: string, language?: Language): Promise<QuestionView>;
168
161
  /**
169
162
  * 答完之后接着往下走:交接(D22)。
170
163
  *
@@ -328,21 +328,6 @@ export class QuestionService {
328
328
  const effects = await this.applyEffects({ kind, value, handoffMode, conversationId, data: payload.data }, language);
329
329
  return { question: view, effects };
330
330
  }
331
- /**
332
- * 显式取消一个问题(生命周期里的 `cancelled`)。
333
- *
334
- * 只有调用方明确要关掉时才用(例如对话被删、工作流换了方向)。没有任何自动取消的路径 ——
335
- * 越线拒绝之后问题要继续挂着(D23),所以「答不下去」与「关掉它」是两件事。
336
- */
337
- async cancel(questionId, language = DEFAULT_LANGUAGE) {
338
- const question = await this.requireQuestion(questionId);
339
- const cancelledAt = this.now();
340
- await this.questions.update(question.id, { state: "cancelled", updatedAt: cancelledAt });
341
- const row = await this.questions.get(question.id);
342
- const view = toView(row ?? question, language);
343
- this.emit?.("question", { question: view, at: iso(cancelledAt) });
344
- return view;
345
- }
346
331
  /**
347
332
  * 答完之后接着往下走:交接(D22)。
348
333
  *
@@ -40,8 +40,6 @@ export declare class ConversationRepository {
40
40
  setModel(id: string, modelId: string, updatedAt: number): Promise<number>;
41
41
  /** 写这段会话的思考档位;`null` 表示回到「跟随助手定义」 */
42
42
  setThinkingLevel(id: string, thinkingLevel: string | null, updatedAt: number): Promise<number>;
43
- /** 只推进修改时间(新增消息等结构变化后调用) */
44
- touch(id: string, updatedAt: number): Promise<number>;
45
43
  /** 硬删对话(PRD D17),消息与素材行随之级联删除 */
46
44
  delete(id: string): Promise<number>;
47
45
  /**
@@ -51,5 +49,4 @@ export declare class ConversationRepository {
51
49
  * 也省掉维护第二张 FTS 表。
52
50
  */
53
51
  searchByName(keyword: string, workspaceId: string | undefined, limit: number): Promise<Conversation[]>;
54
- countByWorkspace(workspaceId: string): Promise<number>;
55
52
  }
@@ -87,14 +87,6 @@ export class ConversationRepository {
87
87
  const result = await this.db.run("UPDATE conversations SET thinkingLevel = ?, updatedAt = ? WHERE id = ?", [thinkingLevel, updatedAt, id]);
88
88
  return result.changes;
89
89
  }
90
- /** 只推进修改时间(新增消息等结构变化后调用) */
91
- async touch(id, updatedAt) {
92
- const result = await this.db.run("UPDATE conversations SET updatedAt = ? WHERE id = ?", [
93
- updatedAt,
94
- id,
95
- ]);
96
- return result.changes;
97
- }
98
90
  /** 硬删对话(PRD D17),消息与素材行随之级联删除 */
99
91
  async delete(id) {
100
92
  const result = await this.db.run("DELETE FROM conversations WHERE id = ?", [id]);
@@ -121,8 +113,4 @@ export class ConversationRepository {
121
113
  LIMIT ?`, [workspaceId, pattern, limit]);
122
114
  return rows.map(toConversation);
123
115
  }
124
- async countByWorkspace(workspaceId) {
125
- const row = await this.db.get("SELECT count(*) AS n FROM conversations WHERE workspaceId = ?", [workspaceId]);
126
- return row?.n ?? 0;
127
- }
128
116
  }
@@ -30,5 +30,4 @@ export declare class QuestionRepository {
30
30
  * (例如只改 state 时不会把已有的 answer 抹掉)。
31
31
  */
32
32
  update(id: string, patch: QuestionPatch): Promise<number>;
33
- delete(id: string): Promise<number>;
34
33
  }
@@ -89,8 +89,4 @@ export class QuestionRepository {
89
89
  const result = await this.db.run(`UPDATE questions SET ${assignments.join(", ")} WHERE id = ?`, params);
90
90
  return result.changes;
91
91
  }
92
- async delete(id) {
93
- const result = await this.db.run("DELETE FROM questions WHERE id = ?", [id]);
94
- return result.changes;
95
- }
96
92
  }
@@ -12,8 +12,6 @@
12
12
  * 收敛成 core 的枚举发生在服务层。
13
13
  */
14
14
  import type { AgentNS } from "@ai-zen/agents-core";
15
- /** 消息角色,取值与 core 的 `AgentNS.Role` 对齐 */
16
- export type MessageRole = "system" | "user" | "assistant" | "tool" | "function" | "unknown";
17
15
  /** 消息状态,取值与 core 的 `AgentNS.MessageStatus` 对齐 */
18
16
  export type MessageStatus = "pending" | "writing" | "completed" | "error" | "aborted" | "unknown";
19
17
  export interface WorkspaceRow {
@@ -28,27 +28,6 @@ export interface ClientInfo {
28
28
  /** 运行平台(可选,仅供展示) */
29
29
  platform?: string;
30
30
  }
31
- /**
32
- * 能力清单里的一项(PRD F-E5 帮助由能力清单渲染、F-E6 阻塞是能力属性、F-F9 二次确认)。
33
- *
34
- * `id` 用 PRD 的能力编号(如 `F-C8`),因为那份清单是「要为用户做到什么」的唯一真相;
35
- * 客户端据此接线,不必再维护第三份清单。
36
- */
37
- export interface CapabilityView {
38
- /** 稳定能力编号(PRD §4 的编号,如 `F-C8`) */
39
- id: string;
40
- domain: MethodDomain;
41
- title: LocalizedText;
42
- description: LocalizedText;
43
- /** 对应的方法名;纯事实类能力(如生成六态)没有方法,为空 */
44
- method: MethodName | null;
45
- /** 执行期间会阻塞对话(PRD F-E6:界面要能显示「正在执行什么」) */
46
- blocking: boolean;
47
- /** 有不可撤销的后果(PRD F-F9:需要二次确认) */
48
- destructive: boolean;
49
- }
50
- /** 方法的域(方法名的第一段) */
51
- export type MethodDomain = "host" | "workspace" | "conversation" | "message" | "question" | "notice" | "config" | "agent" | "model" | "asset" | "completion" | "handoff" | "search";
52
31
  /**
53
32
  * 一次删除的代价(PRD D11「删前明说代价」/ D17「先警告」/ F-F9「二次确认」)。
54
33
  *
@@ -87,7 +66,8 @@ export interface HostHelloParams {
87
66
  *
88
67
  * 除了握手成功本身,还把「这条连接以后说哪种语言」「宿主是什么版本」「有哪些能力」
89
68
  * 一次给全:客户端连上就能把界面语言定下来(D8)。能力只给 id 列表(R57):握手这一帧
90
- * 要小,完整清单(标题、说明、阻塞与不可撤销)走 `host.capabilities`,那一份按连接语言渲染。
69
+ * 要小,完整清单(编号、域、方法名、阻塞与不可撤销)走 `host.capabilities` —— 清单里没有
70
+ * 文案,与语言无关。
91
71
  */
92
72
  export interface HostHelloResult {
93
73
  /** 这条连接协商出的语言;后续这条连接上的文案都按它渲染 */
@@ -96,12 +76,6 @@ export interface HostHelloResult {
96
76
  protocolVersion: string;
97
77
  /** 宿主进程启动时间 */
98
78
  startedAt: string;
99
- /**
100
- * 能力 id 列表(PRD F-E5 / R57)
101
- *
102
- * 每一串就是 `host.capabilities` 里那一项 `CapabilityView.id`,顺序与那份清单一致。
103
- */
104
- capabilities: string[];
105
79
  /** 附件上限等客户端要先知道的事实(PRD D5) */
106
80
  limits: TransferLimits;
107
81
  }
@@ -149,21 +123,6 @@ export interface HostShutdownParams {
149
123
  export interface HostShutdownResult {
150
124
  accepted: boolean;
151
125
  }
152
- /** `capabilities` 出参(PRD F-E5:帮助与指令菜单都从这一份渲染) */
153
- export interface HostCapabilitiesResult {
154
- capabilities: CapabilityView[];
155
- }
156
- /**
157
- * `host.reload` 能重载的范围(PRD F-E1 命令清单里的「重载」)。
158
- *
159
- * 每一档对应「哪一类能力要重新装配」:改的是磁盘上的东西(配置文件 / 助手定义 / 技能目录 /
160
- * MCP 文件),所以重载不写盘,只让宿主重新读一遍。不给 `scope` 表示全部。
161
- */
162
- export type HostReloadScope = "config" | "agents" | "tools" | "skills" | "mcp";
163
- /** `host.reload` 入参:只重载某一类能力,或全部(不给) */
164
- export interface HostReloadParams {
165
- scope?: HostReloadScope;
166
- }
167
126
  /**
168
127
  * `host.reload` 出参:与 `config.patch` 同一份形状(`config` + `applied`)。
169
128
  *
@@ -1570,11 +1529,6 @@ export interface MethodMap {
1570
1529
  params: HostShutdownParams;
1571
1530
  result: HostShutdownResult;
1572
1531
  };
1573
- /** F-E5 / F-E6 / F-F9:帮助由能力清单渲染;阻塞与不可撤销是能力属性。 */
1574
- "host.capabilities": {
1575
- params: NoParams;
1576
- result: HostCapabilitiesResult;
1577
- };
1578
1532
  /**
1579
1533
  * F-E1:命令清单里的「重载」在宿主这一侧的动作。
1580
1534
  *
@@ -1582,7 +1536,7 @@ export interface MethodMap {
1582
1536
  * 手改了磁盘上的助手定义 / 技能目录 / MCP 文件之后不必重启。
1583
1537
  */
1584
1538
  "host.reload": {
1585
- params: HostReloadParams;
1539
+ params: NoParams;
1586
1540
  result: HostReloadResult;
1587
1541
  };
1588
1542
  /** D8 / F-E4:`/lang` 是连接级动作,语言挂在连接上、断开即忘。 */
@@ -1889,8 +1843,6 @@ export type MethodResult<M extends MethodName> = MethodMap[M]["result"];
1889
1843
  * 测试里做 `Exclude<MethodName, (typeof METHOD_NAMES)[number]>` 时,漏掉的名字会留在
1890
1844
  * 那个差集里而不是被抹成 `never`。
1891
1845
  */
1892
- export declare const METHOD_NAMES: readonly ["host.hello", "host.version", "host.upgrade", "host.shutdown", "host.capabilities", "host.reload", "host.setLanguage", "workspace.list", "workspace.create", "workspace.get", "workspace.rename", "workspace.remove", "conversation.list", "conversation.create", "conversation.get", "conversation.state", "conversation.rename", "conversation.pin", "conversation.delete", "conversation.send", "conversation.abort", "conversation.revert", "conversation.setModel", "conversation.setThinking", "conversation.transient", "message.list", "question.list", "question.answer", "notice.list", "notice.dismiss", "notice.clear", "config.get", "config.patch", "config.setDefaults", "config.getDiscovery", "config.saveMcp", "config.deleteMcp", "config.saveEndpoint", "config.deleteEndpoint", "agent.list", "agent.get", "agent.create", "agent.update", "agent.delete", "agent.setModel", "agent.setThinking", "agent.restoreFactory", "model.list", "model.listImages", "model.create", "model.update", "model.delete", "model.restoreFactory", "model.saveImage", "model.deleteImage", "asset.begin", "asset.end", "asset.get", "completion.files", "handoff.start", "handoff.listDocuments", "search.conversations", "search.messages"];
1846
+ export declare const METHOD_NAMES: readonly ["host.hello", "host.version", "host.upgrade", "host.shutdown", "host.reload", "host.setLanguage", "workspace.list", "workspace.create", "workspace.get", "workspace.rename", "workspace.remove", "conversation.list", "conversation.create", "conversation.get", "conversation.state", "conversation.rename", "conversation.pin", "conversation.delete", "conversation.send", "conversation.abort", "conversation.revert", "conversation.setModel", "conversation.setThinking", "conversation.transient", "message.list", "question.list", "question.answer", "notice.list", "notice.dismiss", "notice.clear", "config.get", "config.patch", "config.setDefaults", "config.getDiscovery", "config.saveMcp", "config.deleteMcp", "config.saveEndpoint", "config.deleteEndpoint", "agent.list", "agent.get", "agent.create", "agent.update", "agent.delete", "agent.setModel", "agent.setThinking", "agent.restoreFactory", "model.list", "model.listImages", "model.create", "model.update", "model.delete", "model.restoreFactory", "model.saveImage", "model.deleteImage", "asset.begin", "asset.end", "asset.get", "completion.files", "handoff.start", "handoff.listDocuments", "search.conversations", "search.messages"];
1893
1847
  /** 运行时判断一个字符串是不是已知方法名 */
1894
1848
  export declare function isMethodName(value: unknown): value is MethodName;
1895
- /** 方法名属于哪个域(`conversation.send` → `conversation`) */
1896
- export declare function methodDomain(method: MethodName): MethodDomain;
@@ -29,7 +29,6 @@ export const METHOD_NAMES = [
29
29
  "host.version",
30
30
  "host.upgrade",
31
31
  "host.shutdown",
32
- "host.capabilities",
33
32
  "host.reload",
34
33
  "host.setLanguage",
35
34
  "workspace.list",
@@ -93,7 +92,3 @@ export const METHOD_NAMES = [
93
92
  export function isMethodName(value) {
94
93
  return typeof value === "string" && METHOD_NAMES.includes(value);
95
94
  }
96
- /** 方法名属于哪个域(`conversation.send` → `conversation`) */
97
- export function methodDomain(method) {
98
- return method.slice(0, method.indexOf("."));
99
- }
@@ -29,7 +29,7 @@ import type { MessageKey } from "../i18n/index.js";
29
29
  * 「界面显示」「客户端重排」「换个语言连回来重渲染」三种需要。
30
30
  */
31
31
  export interface LocalizedText {
32
- /** 稳定码(如 `notice.settingsSaved`、`tool.failed`),与文案键分开,便于客户端分支 */
32
+ /** 稳定码(如 `notice.settingsApplied`、`tool.failed`),与文案键分开,便于客户端分支 */
33
33
  code: string;
34
34
  /** 文案键(`i18n` 的键空间) */
35
35
  messageKey: MessageKey;
@@ -347,8 +347,6 @@ export interface LocalSectionExtensions {
347
347
  * ```
348
348
  */
349
349
  export type LocalMessageContentSection = AgentNS.MessageContentSection & LocalSectionExtensions;
350
- /** 带本地扩展的正文:字符串原样,数组里的每一段可能带 `__` 字段 */
351
- export type LocalMessageContent = string | LocalMessageContentSection[];
352
350
  /**
353
351
  * 一个内容段里的素材 id(没有这个扩展字段时为空)。
354
352
  *
@@ -410,14 +408,16 @@ export interface AttachmentOutcome {
410
408
  problem: ProblemFact | null;
411
409
  }
412
410
  /**
413
- * 状态栏每一块的事实。块名固定,块内结构按块名不同而不同(判别式联合)。
411
+ * 状态栏每一块的事实。块 id 固定,块内结构按 id 不同而不同(判别式联合)。
414
412
  *
415
413
  * 这样的好处是:宿主给的是可排版的块,客户端决定摆哪几块、摆在哪(PRD F-I6 /
416
414
  * 「宿主给能力、客户端给交互」),双方都不需要解析一整行字符串。
415
+ *
416
+ * **块名(助手 / 模型 / 上下文 …)不在这里**:那是界面的词汇,归客户端 —— 同一块在
417
+ * 不同界面上叫法可能不同,也可能干脆不显示名字。宿主只给 id 与 facts。
417
418
  */
418
419
  export type StatusBlock = {
419
420
  id: "agent";
420
- label: LocalizedText;
421
421
  /**
422
422
  * 助手块的三个事实。
423
423
  *
@@ -432,33 +432,26 @@ export type StatusBlock = {
432
432
  };
433
433
  } | {
434
434
  id: "model";
435
- label: LocalizedText;
436
435
  facts: ModelState;
437
436
  } | {
438
437
  id: "thinking";
439
- label: LocalizedText;
440
438
  facts: ThinkingState;
441
439
  } | {
442
440
  id: "context";
443
- label: LocalizedText;
444
441
  facts: ContextState;
445
442
  } | {
446
443
  id: "usage";
447
- label: LocalizedText;
448
444
  facts: UsageSnapshot;
449
445
  } | {
450
446
  id: "cwd";
451
- label: LocalizedText;
452
447
  facts: FolderFact;
453
448
  } | {
454
449
  id: "tools";
455
- label: LocalizedText;
456
450
  facts: {
457
451
  running: RunningTool[];
458
452
  };
459
453
  } | {
460
454
  id: "subagents";
461
- label: LocalizedText;
462
455
  facts: {
463
456
  items: SubAgentSnapshot[];
464
457
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-zen/agents-host",
3
- "version": "0.1.0-alpha.2",
3
+ "version": "0.1.0-alpha.4",
4
4
  "description": "AI-Zen Agents Host — session/workspace service shared by CLI and Desktop",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -40,7 +40,7 @@
40
40
  "license": "MIT",
41
41
  "dependencies": {
42
42
  "@ai-zen/agents-core": "^4.6.0-alpha.0",
43
- "@ai-zen/agents-sdk": "^1.2.0-alpha.1",
43
+ "@ai-zen/agents-sdk": "^1.2.0-alpha.2",
44
44
  "ws": "^8.22.2"
45
45
  },
46
46
  "devDependencies": {
@@ -61,6 +61,7 @@
61
61
  "build": "tsc",
62
62
  "pretest": "tsc --noEmit -p tsconfig.test.json",
63
63
  "test": "vitest run",
64
- "test:all": "npm run pretest && vitest run && npm run build"
64
+ "test:all": "npm run pretest && vitest run && npm run build && vitest run --config vitest.e2e.config.ts",
65
+ "test:e2e": "npm run pretest && vitest run --config vitest.e2e.config.ts"
65
66
  }
66
67
  }
@@ -1,26 +0,0 @@
1
- /**
2
- * 能力清单(PRD F-E5 / F-E6 / F-F9,裁定 R6)。
3
- *
4
- * 清单是「帮助页与指令菜单渲染用的那一份真相」,所以它必须与契约同步:每一项对应
5
- * `MethodMap` 里的一个方法名,编号取 PRD §4 那一行的能力号(`wire/methods.ts` 里每个方法
6
- * 的注释就写着自己的编号)。没有编号的方法用契约注释里记的那条决定编号(`workspace.*` 是
7
- * `D9`/`D10`/`D11`:PRD §4 当初没给项目单列能力行),不另编一个。
8
- *
9
- * 三件事刻意分开:
10
- * - **标题与说明**:`LocalizedText`,按连接语言渲染(D8),文案键在 `i18n/`;
11
- * - **`blocking`**:执行期间会不会占住这段对话(F-E6 让界面显示「正在执行什么」);
12
- * - **`destructive`**:有不可撤销的后果(F-F9 的二次确认)。
13
- *
14
- * 编号撞车的场合(几个方法服务同一条能力,例如 `config.saveEndpoint` / `config.deleteEndpoint`
15
- * 都属于 F-F2)用 `<编号>#<动作>` 做 id:编号仍是 PRD 的那个,id 保持唯一,客户端可以按 id 存
16
- * 展开状态。顺序与 `METHOD_NAMES` 一致,帮助页读起来就是「按域分组的办法清单」。
17
- */
18
- import type { Language } from "../i18n/index.js";
19
- import type { CapabilityView } from "../wire/index.js";
20
- /**
21
- * 造能力清单。
22
- *
23
- * 默认语言渲染一份:`host.hello` 与 `host.capabilities` 的出参都要能在不知道收件人语言时
24
- * 先给出形状,客户端按自己的语言用 `messageKey` + `params` 重渲染(D8 的同一套口径)。
25
- */
26
- export declare function createCapabilities(language?: Language): CapabilityView[];
@@ -1,138 +0,0 @@
1
- /**
2
- * 能力清单(PRD F-E5 / F-E6 / F-F9,裁定 R6)。
3
- *
4
- * 清单是「帮助页与指令菜单渲染用的那一份真相」,所以它必须与契约同步:每一项对应
5
- * `MethodMap` 里的一个方法名,编号取 PRD §4 那一行的能力号(`wire/methods.ts` 里每个方法
6
- * 的注释就写着自己的编号)。没有编号的方法用契约注释里记的那条决定编号(`workspace.*` 是
7
- * `D9`/`D10`/`D11`:PRD §4 当初没给项目单列能力行),不另编一个。
8
- *
9
- * 三件事刻意分开:
10
- * - **标题与说明**:`LocalizedText`,按连接语言渲染(D8),文案键在 `i18n/`;
11
- * - **`blocking`**:执行期间会不会占住这段对话(F-E6 让界面显示「正在执行什么」);
12
- * - **`destructive`**:有不可撤销的后果(F-F9 的二次确认)。
13
- *
14
- * 编号撞车的场合(几个方法服务同一条能力,例如 `config.saveEndpoint` / `config.deleteEndpoint`
15
- * 都属于 F-F2)用 `<编号>#<动作>` 做 id:编号仍是 PRD 的那个,id 保持唯一,客户端可以按 id 存
16
- * 展开状态。顺序与 `METHOD_NAMES` 一致,帮助页读起来就是「按域分组的办法清单」。
17
- */
18
- import { DEFAULT_LANGUAGE, render } from "../i18n/index.js";
19
- import { methodDomain } from "../wire/index.js";
20
- /**
21
- * 清单本体:**每个方法一条**,且与 `METHOD_NAMES` 一一对应(用例会钉住这条)。
22
- *
23
- * `blocking` 只标「跑起来时这段对话不能发下一条」的那几个:一轮对话、交接回合、
24
- * 临时对话(它借的 Scope 与项目共用,跑的时候同样不能被打断)。
25
- * `destructive` 只标「做下去就回不来」的那几个:删项目 / 删对话 / 撤回 / 删端点 /
26
- * 删助手 / 删模型(含图片模型)/ 删 MCP 条目 / 恢复出厂。清通知不算:它清的是
27
- * 界面上的一条提示,为它弹二次确认反而是打扰。
28
- *
29
- * 两样东西刻意不在这份清单里(裁定 2026-11-13):
30
- * - `host.usage`:「按项目 / 整机」的用量聚合没有任何客户端消费,F-I5 的落点在
31
- * `conversation.state` 的 `usage`;
32
- * - `credential.*`:凭据由宿主自己管理(`agents-host token create|list|revoke`),
33
- * 客户端只有「连接管理 + 记住密码」,那里没有可渲染的能力。
34
- */
35
- const FACTS = [
36
- { method: "host.hello", prd: "F-A1", blocking: false, destructive: false },
37
- { method: "host.version", prd: "F-E3", blocking: false, destructive: false },
38
- { method: "host.upgrade", prd: "F-E3", blocking: false, destructive: false },
39
- { method: "host.shutdown", prd: "F-E1", blocking: false, destructive: false },
40
- { method: "host.capabilities", prd: "F-E5", blocking: false, destructive: false },
41
- { method: "host.reload", prd: "F-E1", blocking: false, destructive: false },
42
- { method: "host.setLanguage", prd: "F-E4", blocking: false, destructive: false },
43
- { method: "workspace.list", prd: "D9", blocking: false, destructive: false },
44
- { method: "workspace.create", prd: "D10", blocking: false, destructive: false },
45
- { method: "workspace.get", prd: "D9", blocking: false, destructive: false },
46
- { method: "workspace.rename", prd: "D9", blocking: false, destructive: false },
47
- { method: "workspace.remove", prd: "D11", blocking: false, destructive: true },
48
- { method: "conversation.list", prd: "F-C5", blocking: false, destructive: false },
49
- { method: "conversation.create", prd: "F-C7", blocking: false, destructive: false },
50
- { method: "conversation.get", prd: "F-A6", blocking: false, destructive: false },
51
- { method: "conversation.state", prd: "F-I3", blocking: false, destructive: false },
52
- { method: "conversation.rename", prd: "F-C3", blocking: false, destructive: false },
53
- { method: "conversation.pin", prd: "F-C5", blocking: false, destructive: false },
54
- { method: "conversation.delete", prd: "F-C10", blocking: false, destructive: true },
55
- { method: "conversation.send", prd: "F-C2", blocking: true, destructive: false },
56
- { method: "conversation.abort", prd: "F-E1", blocking: false, destructive: false },
57
- { method: "conversation.revert", prd: "F-C8", blocking: false, destructive: true },
58
- { method: "conversation.setModel", prd: "F-B4", blocking: false, destructive: false },
59
- { method: "conversation.setThinking", prd: "F-B6", blocking: false, destructive: false },
60
- { method: "conversation.transient", prd: "F-A2", blocking: true, destructive: false },
61
- { method: "message.list", prd: "F-I7", blocking: false, destructive: false },
62
- { method: "question.list", prd: "F-I9", blocking: false, destructive: false },
63
- { method: "question.answer", prd: "F-I9", blocking: false, destructive: false },
64
- { method: "notice.list", prd: "F-I8", blocking: false, destructive: false },
65
- { method: "notice.dismiss", prd: "F-I8", blocking: false, destructive: false },
66
- { method: "notice.clear", prd: "F-I8", blocking: false, destructive: false },
67
- { method: "config.get", prd: "F-F1", blocking: false, destructive: false },
68
- { method: "config.patch", prd: "F-F1", blocking: false, destructive: false },
69
- { method: "config.setDefaults", prd: "F-F7", blocking: false, destructive: false },
70
- { method: "config.getDiscovery", prd: "F-G1", blocking: false, destructive: false },
71
- { method: "config.saveMcp", prd: "F-F6", blocking: false, destructive: false },
72
- { method: "config.deleteMcp", prd: "F-G1", blocking: false, destructive: true },
73
- { method: "config.saveEndpoint", prd: "F-F2", blocking: false, destructive: false },
74
- { method: "config.deleteEndpoint", prd: "F-F2", blocking: false, destructive: true },
75
- { method: "agent.list", prd: "F-B2", blocking: false, destructive: false },
76
- { method: "agent.get", prd: "F-B2", blocking: false, destructive: false },
77
- { method: "agent.create", prd: "F-B2", blocking: false, destructive: false },
78
- { method: "agent.update", prd: "F-B2", blocking: false, destructive: false },
79
- { method: "agent.delete", prd: "F-F5", blocking: false, destructive: true },
80
- { method: "agent.setModel", prd: "F-B4", blocking: false, destructive: false },
81
- { method: "agent.setThinking", prd: "F-B6", blocking: false, destructive: false },
82
- { method: "agent.restoreFactory", prd: "F-F5", blocking: false, destructive: true },
83
- { method: "model.list", prd: "F-F3", blocking: false, destructive: false },
84
- { method: "model.listImages", prd: "F-F4", blocking: false, destructive: false },
85
- { method: "model.create", prd: "F-F3", blocking: false, destructive: false },
86
- { method: "model.update", prd: "F-F3", blocking: false, destructive: false },
87
- { method: "model.delete", prd: "F-F3", blocking: false, destructive: true },
88
- { method: "model.restoreFactory", prd: "F-F3", blocking: false, destructive: true },
89
- { method: "model.saveImage", prd: "F-F4", blocking: false, destructive: false },
90
- { method: "model.deleteImage", prd: "F-F4", blocking: false, destructive: true },
91
- { method: "asset.begin", prd: "F-H8", blocking: false, destructive: false },
92
- { method: "asset.end", prd: "F-H8", blocking: false, destructive: false },
93
- { method: "asset.get", prd: "F-H7", blocking: false, destructive: false },
94
- { method: "completion.files", prd: "F-H5", blocking: false, destructive: false },
95
- { method: "handoff.start", prd: "F-D5", blocking: true, destructive: false },
96
- { method: "handoff.listDocuments", prd: "F-D6", blocking: false, destructive: false },
97
- { method: "search.conversations", prd: "F-C6", blocking: false, destructive: false },
98
- { method: "search.messages", prd: "F-C6", blocking: false, destructive: false },
99
- ];
100
- /** 标题的文案键(`capability.<方法名>`) */
101
- function titleKey(method) {
102
- return `capability.${method}`;
103
- }
104
- /** 说明的文案键(`capability.<方法名>.detail`) */
105
- function detailKey(method) {
106
- return `capability.${method}.detail`;
107
- }
108
- /** 一句话:码 + 参数 + 按给定语言渲染的句子(存码不存句子,D8) */
109
- function text(key, language) {
110
- return { code: key, messageKey: key, params: {}, message: render(language, key) };
111
- }
112
- /** 动作名(`conversation.send` → `send`),编号撞车时用来给 id 去重 */
113
- function actionOf(method) {
114
- return method.slice(method.indexOf(".") + 1);
115
- }
116
- /**
117
- * 造能力清单。
118
- *
119
- * 默认语言渲染一份:`host.hello` 与 `host.capabilities` 的出参都要能在不知道收件人语言时
120
- * 先给出形状,客户端按自己的语言用 `messageKey` + `params` 重渲染(D8 的同一套口径)。
121
- */
122
- export function createCapabilities(language = DEFAULT_LANGUAGE) {
123
- const used = new Set();
124
- return FACTS.map((fact) => {
125
- // 同一个编号下的第二个及以后的方法:`<编号>#<动作>`
126
- const id = used.has(fact.prd) ? `${fact.prd}#${actionOf(fact.method)}` : fact.prd;
127
- used.add(fact.prd);
128
- return {
129
- id,
130
- domain: methodDomain(fact.method),
131
- title: text(titleKey(fact.method), language),
132
- description: text(detailKey(fact.method), language),
133
- method: fact.method,
134
- blocking: fact.blocking,
135
- destructive: fact.destructive,
136
- };
137
- });
138
- }