@keyou007/agent-bot 0.1.10 → 0.1.12

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 (121) hide show
  1. package/.env.example +1 -1
  2. package/CHANGELOG.md +25 -0
  3. package/README.md +55 -43
  4. package/README.zh.md +55 -43
  5. package/assets/agent-bot-logo.png +0 -0
  6. package/config.example.yaml +11 -1
  7. package/dist/acp/AcpSessionManager.js +78 -46
  8. package/dist/acp/AcpSessionManager.js.map +1 -1
  9. package/dist/cli/FeishuAppConfiguration.js +1 -1
  10. package/dist/cli/FeishuAppConfiguration.js.map +1 -1
  11. package/dist/cli/FeishuAppRegistration.js +2 -2
  12. package/dist/cli/FeishuAppRegistration.js.map +1 -1
  13. package/dist/cli/Initializer.js +1 -1
  14. package/dist/cli/Initializer.js.map +1 -1
  15. package/dist/cli/ServerStarter.js +7 -2
  16. package/dist/cli/ServerStarter.js.map +1 -1
  17. package/dist/cli/controlProtocol.js.map +1 -1
  18. package/dist/cli/help.js +20 -16
  19. package/dist/cli/help.js.map +1 -1
  20. package/dist/cli/taskGroupOptions.js +95 -0
  21. package/dist/cli/taskGroupOptions.js.map +1 -0
  22. package/dist/cli.js +74 -2
  23. package/dist/cli.js.map +1 -1
  24. package/dist/codex/AppServerConnection.js +15 -1
  25. package/dist/codex/AppServerConnection.js.map +1 -1
  26. package/dist/codex/CodexLocalActivityDetector.js +4 -1
  27. package/dist/codex/CodexLocalActivityDetector.js.map +1 -1
  28. package/dist/codex/CodexProcessManager.js +1 -0
  29. package/dist/codex/CodexProcessManager.js.map +1 -1
  30. package/dist/codex/CodexRuntime.js +112 -11
  31. package/dist/codex/CodexRuntime.js.map +1 -1
  32. package/dist/commands/CommandRouter.js +64 -49
  33. package/dist/commands/CommandRouter.js.map +1 -1
  34. package/dist/config/loadConfig.js +11 -1
  35. package/dist/config/loadConfig.js.map +1 -1
  36. package/dist/config/schema.js +6 -1
  37. package/dist/config/schema.js.map +1 -1
  38. package/dist/console/ConsoleConnector.js +1 -1
  39. package/dist/console/ConsoleConnector.js.map +1 -1
  40. package/dist/console/ConsoleTurnPresenter.js +15 -8
  41. package/dist/console/ConsoleTurnPresenter.js.map +1 -1
  42. package/dist/deprecated-cli.js +5 -0
  43. package/dist/deprecated-cli.js.map +1 -0
  44. package/dist/feishu/CardRenderer.js +350 -15
  45. package/dist/feishu/CardRenderer.js.map +1 -1
  46. package/dist/feishu/FeishuMessageClient.js +51 -5
  47. package/dist/feishu/FeishuMessageClient.js.map +1 -1
  48. package/dist/feishu/FeishuTurnPresenter.js +17 -8
  49. package/dist/feishu/FeishuTurnPresenter.js.map +1 -1
  50. package/dist/feishu/transport.js +1 -1
  51. package/dist/feishu/transport.js.map +1 -1
  52. package/dist/index.js +38 -19
  53. package/dist/index.js.map +1 -1
  54. package/dist/presentation/OutboundRouter.js +2 -2
  55. package/dist/presentation/OutboundRouter.js.map +1 -1
  56. package/dist/presentation/TurnStateReducer.js +2 -1
  57. package/dist/presentation/TurnStateReducer.js.map +1 -1
  58. package/dist/proxy/ProxySessionController.js +665 -225
  59. package/dist/proxy/ProxySessionController.js.map +1 -1
  60. package/dist/runtime/AcpRuntimeAdapter.js +1 -0
  61. package/dist/runtime/AcpRuntimeAdapter.js.map +1 -1
  62. package/dist/runtime/AgentRuntimeRegistry.js +7 -4
  63. package/dist/runtime/AgentRuntimeRegistry.js.map +1 -1
  64. package/dist/runtime/createAgentRuntimeRegistry.js +22 -0
  65. package/dist/runtime/createAgentRuntimeRegistry.js.map +1 -0
  66. package/dist/startup/SessionMetadataHydrator.js +2 -2
  67. package/dist/startup/SessionMetadataHydrator.js.map +1 -1
  68. package/dist/startup/StartupNotifier.js +1 -0
  69. package/dist/startup/StartupNotifier.js.map +1 -1
  70. package/dist/state/StateStore.js +21 -15
  71. package/dist/state/StateStore.js.map +1 -1
  72. package/dist/supervision/SafeRestartScheduler.js +5 -0
  73. package/dist/supervision/SafeRestartScheduler.js.map +1 -1
  74. package/dist/supervision/systemEnvironment.js +129 -0
  75. package/dist/supervision/systemEnvironment.js.map +1 -0
  76. package/dist/supervisor.js +13 -1
  77. package/dist/supervisor.js.map +1 -1
  78. package/docs/technical-reference.md +35 -21
  79. package/docs/technical-reference.zh.md +35 -21
  80. package/npm-shrinkwrap.json +4 -3
  81. package/package.json +4 -2
  82. package/skills/agent-bot/SKILL.md +73 -30
  83. package/src/acp/AcpSessionManager.ts +73 -54
  84. package/src/cli/FeishuAppConfiguration.ts +2 -2
  85. package/src/cli/FeishuAppRegistration.ts +4 -4
  86. package/src/cli/Initializer.ts +2 -2
  87. package/src/cli/ServerStarter.ts +8 -3
  88. package/src/cli/controlProtocol.ts +21 -1
  89. package/src/cli/help.ts +20 -16
  90. package/src/cli/taskGroupOptions.ts +149 -0
  91. package/src/cli.ts +98 -4
  92. package/src/codex/AppServerConnection.ts +21 -1
  93. package/src/codex/CodexLocalActivityDetector.ts +8 -1
  94. package/src/codex/CodexProcessManager.ts +1 -0
  95. package/src/codex/CodexRuntime.ts +137 -15
  96. package/src/commands/CommandRouter.ts +71 -49
  97. package/src/commands/commandTypes.ts +6 -11
  98. package/src/config/loadConfig.ts +11 -1
  99. package/src/config/schema.ts +7 -1
  100. package/src/console/ConsoleConnector.ts +1 -1
  101. package/src/console/ConsoleTurnPresenter.ts +21 -8
  102. package/src/deprecated-cli.ts +9 -0
  103. package/src/feishu/CardRenderer.ts +423 -15
  104. package/src/feishu/FeishuMessageClient.ts +66 -3
  105. package/src/feishu/FeishuTurnPresenter.ts +22 -3
  106. package/src/feishu/transport.ts +1 -1
  107. package/src/index.ts +54 -24
  108. package/src/presentation/OutboundRouter.ts +15 -3
  109. package/src/presentation/TurnStateReducer.ts +2 -0
  110. package/src/presentation/turnViewTypes.ts +1 -0
  111. package/src/proxy/ProxySessionController.ts +870 -228
  112. package/src/runtime/AcpRuntimeAdapter.ts +1 -0
  113. package/src/runtime/AgentRuntimeRegistry.ts +7 -6
  114. package/src/runtime/createAgentRuntimeRegistry.ts +25 -0
  115. package/src/runtime/types.ts +18 -0
  116. package/src/startup/SessionMetadataHydrator.ts +2 -2
  117. package/src/startup/StartupNotifier.ts +1 -0
  118. package/src/state/StateStore.ts +29 -15
  119. package/src/supervision/SafeRestartScheduler.ts +5 -0
  120. package/src/supervision/systemEnvironment.ts +174 -0
  121. package/src/supervisor.ts +12 -1
@@ -3,9 +3,184 @@ import path from "node:path";
3
3
  import { truncateMiddle, truncateText } from "../utils/markdown.js";
4
4
  import { localCardImage } from "./LocalCardImage.js";
5
5
  export class CardRenderer {
6
+ renderExecutionSettings(view) {
7
+ const baseAction = {
8
+ contextKey: view.contextKey,
9
+ ...(view.sessionId ? { sessionId: view.sessionId } : {}),
10
+ };
11
+ const tabRow = settingsTabRow(view.activeTab, baseAction, view.agents.length > 1, view.runtimeSettingsAvailable);
12
+ const elements = [
13
+ markdown([
14
+ view.taskAgent
15
+ ? `**默认 Agent / 当前任务 Agent**:${inlineCode(view.currentAgent)} / ${inlineCode(view.taskAgent)}`
16
+ : `**默认 Agent**:${inlineCode(view.currentAgent)}`,
17
+ ...(view.runtimeSettingsAvailable
18
+ ? [
19
+ `**Provider / 模型**:${inlineCode(view.currentProvider ?? "Codex 默认")} / ${inlineCode(view.currentModel ?? "默认")}`,
20
+ `**思考强度 / 权限**:${inlineCode(view.currentEffort ?? "自动")} / ${inlineCode(permissionModeLabel(view.currentPermissionMode))}`,
21
+ ]
22
+ : []),
23
+ ...(view.notice ? [view.notice] : []),
24
+ ].join("\n")),
25
+ ...(tabRow ? [tabRow] : []),
26
+ { tag: "hr" },
27
+ ];
28
+ if (view.activeTab === "agent") {
29
+ elements.push(...view.agents.map((agent) => settingsOptionRow({
30
+ label: `${inlineCode(agent.name)} · ${escapeCardHtml(agent.title)}`,
31
+ current: agent.name === view.currentAgent,
32
+ action: {
33
+ text: "Switch",
34
+ value: {
35
+ action: "settings_agent_select",
36
+ ...baseAction,
37
+ agent: agent.name,
38
+ },
39
+ },
40
+ })));
41
+ }
42
+ else if (view.activeTab === "provider") {
43
+ if (!view.providerSupported) {
44
+ elements.push(markdown("当前运行时不支持 Provider 切换;其他设置仍可通过上方 tab 修改。"));
45
+ }
46
+ else if (view.providers.length === 0) {
47
+ elements.push(markdown("Codex 配置中没有可用的 Provider。"));
48
+ }
49
+ else {
50
+ elements.push(...view.providers.map((provider) => settingsOptionRow({
51
+ label: [
52
+ inlineCode(provider.id),
53
+ provider.displayName && provider.displayName !== provider.id
54
+ ? ` · ${escapeCardHtml(provider.displayName)}`
55
+ : "",
56
+ provider.isDefault ? " · 默认" : "",
57
+ ].join(""),
58
+ current: provider.id === view.currentProvider,
59
+ action: {
60
+ text: "Switch",
61
+ value: {
62
+ action: "settings_provider_select",
63
+ ...baseAction,
64
+ provider: provider.id,
65
+ },
66
+ },
67
+ })));
68
+ }
69
+ }
70
+ else if (view.activeTab === "model") {
71
+ if (view.models.length === 0) {
72
+ elements.push(markdown("当前运行时未返回可用模型。"));
73
+ }
74
+ else {
75
+ elements.push(...view.models.map((model) => settingsOptionRow({
76
+ label: `${inlineCode(model.id)}${model.isDefault ? " · 默认" : ""}`,
77
+ current: model.id === view.currentModel,
78
+ action: {
79
+ text: "Switch",
80
+ value: {
81
+ action: "settings_model_select",
82
+ ...baseAction,
83
+ model: model.id,
84
+ },
85
+ },
86
+ })));
87
+ }
88
+ }
89
+ else if (view.activeTab === "thinking") {
90
+ if (!view.currentModel) {
91
+ elements.push(markdown("请先选择模型。"));
92
+ }
93
+ else if (view.reasoningOptions.length === 0) {
94
+ elements.push(markdown("当前模型没有可配置的思考强度。"));
95
+ }
96
+ else {
97
+ const currentModel = view.currentModel;
98
+ elements.push(...view.reasoningOptions.map((option) => settingsOptionRow({
99
+ label: inlineCode(option.value),
100
+ current: option.value === view.currentEffort,
101
+ action: {
102
+ text: "Switch",
103
+ value: {
104
+ action: "settings_thinking_select",
105
+ ...baseAction,
106
+ model: currentModel,
107
+ effort: option.value,
108
+ },
109
+ },
110
+ })));
111
+ }
112
+ }
113
+ else {
114
+ elements.push(...["auto", "confirm"].map((mode) => settingsOptionRow({
115
+ label: `${inlineCode(mode)} · ${permissionModeLabel(mode)}`,
116
+ current: mode === view.currentPermissionMode,
117
+ action: {
118
+ text: "Switch",
119
+ value: {
120
+ action: "settings_permission_select",
121
+ ...baseAction,
122
+ permissionMode: mode,
123
+ },
124
+ },
125
+ })));
126
+ }
127
+ return sectionCard("运行设置", elements, view.notice ? "green" : "blue");
128
+ }
129
+ renderProviderSelector(view) {
130
+ const elements = [
131
+ markdown([
132
+ `**当前 Provider**:${inlineCode(view.currentProvider ?? "Codex 默认")}`,
133
+ `**模型 / 思考强度 / 权限**:${inlineCode(view.currentModel ?? "默认")} / ${inlineCode(view.reasoningEffort ?? "自动")} / ${inlineCode(permissionModeLabel(view.permissionMode))}`,
134
+ ...(view.notice ? [view.notice] : []),
135
+ ].join("\n")),
136
+ { tag: "hr" },
137
+ ];
138
+ if (view.providers.length === 0) {
139
+ elements.push(markdown("Codex 配置中没有可用的 Provider。"));
140
+ }
141
+ else {
142
+ elements.push(...view.providers.map((provider) => ({
143
+ tag: "column_set",
144
+ flex_mode: "none",
145
+ horizontal_spacing: "8px",
146
+ vertical_align: "center",
147
+ columns: [
148
+ {
149
+ tag: "column",
150
+ width: "weighted",
151
+ weight: 1,
152
+ vertical_align: "center",
153
+ elements: [markdown([
154
+ inlineCode(provider.id),
155
+ provider.displayName && provider.displayName !== provider.id ? ` · ${escapeCardHtml(provider.displayName)}` : "",
156
+ provider.isDefault ? " · 默认" : "",
157
+ provider.id === view.currentProvider ? " · ✅ 当前" : "",
158
+ ].join(""))],
159
+ },
160
+ {
161
+ tag: "column",
162
+ width: "auto",
163
+ vertical_align: "center",
164
+ elements: [taskActionElement({
165
+ text: provider.id === view.currentProvider ? "Configure" : "Select",
166
+ value: {
167
+ action: "provider_select",
168
+ sessionId: view.sessionId,
169
+ contextKey: view.contextKey,
170
+ provider: provider.id,
171
+ permissionMode: view.permissionMode,
172
+ },
173
+ })],
174
+ },
175
+ ],
176
+ })));
177
+ }
178
+ return sectionCard("Provider 设置", elements, view.notice ? "green" : "blue");
179
+ }
6
180
  renderReasoningSelector(view) {
7
181
  const elements = [
8
182
  markdown([
183
+ ...(view.modelProvider ? [`**Provider**:${inlineCode(view.modelProvider)}`] : []),
9
184
  `**模型**:${inlineCode(view.model)}`,
10
185
  `**当前思考模式**:${inlineCode(view.currentEffort ?? "默认")}`,
11
186
  ...(view.notice ? [view.notice] : []),
@@ -35,16 +210,18 @@ export class CardRenderer {
35
210
  tag: "column",
36
211
  width: "auto",
37
212
  vertical_align: "center",
38
- elements: isCurrent
213
+ elements: isCurrent && !view.unifiedSettings
39
214
  ? [markdown("✅ 当前")]
40
215
  : [taskActionElement({
41
- text: "Switch",
216
+ text: view.unifiedSettings ? (isCurrent ? "Continue" : "Select") : "Switch",
42
217
  value: {
43
- action: "reasoning_select",
218
+ action: view.unifiedSettings ? "provider_reasoning_select" : "reasoning_select",
44
219
  sessionId: view.sessionId,
45
220
  contextKey: view.contextKey,
221
+ ...(view.modelProvider ? { provider: view.modelProvider } : {}),
46
222
  model: view.model,
47
223
  effort: option.value,
224
+ ...(view.permissionMode ? { permissionMode: view.permissionMode } : {}),
48
225
  },
49
226
  })],
50
227
  },
@@ -55,9 +232,11 @@ export class CardRenderer {
55
232
  elements.push({ tag: "hr" }, taskActionRow([{
56
233
  text: "Back",
57
234
  value: {
58
- action: "model_open",
235
+ action: view.unifiedSettings ? "provider_model_open" : "model_open",
59
236
  sessionId: view.sessionId,
60
237
  contextKey: view.contextKey,
238
+ ...(view.modelProvider ? { provider: view.modelProvider } : {}),
239
+ ...(view.permissionMode ? { permissionMode: view.permissionMode } : {}),
61
240
  },
62
241
  }]));
63
242
  return sectionCard("思考模式", elements, view.notice ? "green" : "blue");
@@ -65,6 +244,7 @@ export class CardRenderer {
65
244
  renderModelSelector(view) {
66
245
  const elements = [
67
246
  markdown([
247
+ ...(view.modelProvider ? [`**Provider**:${inlineCode(view.modelProvider)}`] : []),
68
248
  `**当前模型**:${inlineCode(view.currentModel ?? "默认")}`,
69
249
  `**思考强度**:${inlineCode(view.reasoningEffort ?? "默认")}`,
70
250
  ...(view.notice ? [view.notice] : []),
@@ -94,15 +274,17 @@ export class CardRenderer {
94
274
  tag: "column",
95
275
  width: "auto",
96
276
  vertical_align: "center",
97
- elements: isCurrent
277
+ elements: isCurrent && !view.unifiedSettings
98
278
  ? [markdown("✅ 当前")]
99
279
  : [taskActionElement({
100
- text: "Switch",
280
+ text: view.unifiedSettings ? (isCurrent ? "Continue" : "Select") : "Switch",
101
281
  value: {
102
- action: "model_select",
282
+ action: view.unifiedSettings ? "provider_model_select" : "model_select",
103
283
  sessionId: view.sessionId,
104
284
  contextKey: view.contextKey,
285
+ ...(view.modelProvider ? { provider: view.modelProvider } : {}),
105
286
  model: model.id,
287
+ ...(view.permissionMode ? { permissionMode: view.permissionMode } : {}),
106
288
  },
107
289
  })],
108
290
  },
@@ -110,7 +292,73 @@ export class CardRenderer {
110
292
  };
111
293
  }));
112
294
  }
113
- return sectionCard("模型", elements, view.notice ? "green" : "blue");
295
+ if (view.unifiedSettings) {
296
+ elements.push({ tag: "hr" }, taskActionRow([{
297
+ text: "Back",
298
+ value: {
299
+ action: "provider_open",
300
+ sessionId: view.sessionId,
301
+ contextKey: view.contextKey,
302
+ },
303
+ }]));
304
+ }
305
+ return sectionCard(view.unifiedSettings ? "Provider 设置 · 模型" : "模型", elements, view.notice ? "green" : "blue");
306
+ }
307
+ renderPermissionSelector(view) {
308
+ const elements = [
309
+ markdown([
310
+ `**Provider**:${inlineCode(view.modelProvider)}`,
311
+ `**模型**:${inlineCode(view.model)}`,
312
+ `**思考强度**:${inlineCode(view.reasoningEffort)}`,
313
+ `**当前权限**:${inlineCode(permissionModeLabel(view.currentMode))}`,
314
+ ].join("\n")),
315
+ { tag: "hr" },
316
+ ...["auto", "confirm"].map((mode) => ({
317
+ tag: "column_set",
318
+ flex_mode: "none",
319
+ horizontal_spacing: "8px",
320
+ vertical_align: "center",
321
+ columns: [
322
+ {
323
+ tag: "column",
324
+ width: "weighted",
325
+ weight: 1,
326
+ vertical_align: "center",
327
+ elements: [markdown(`${inlineCode(mode)} · ${permissionModeLabel(mode)}`)],
328
+ },
329
+ {
330
+ tag: "column",
331
+ width: "auto",
332
+ vertical_align: "center",
333
+ elements: [taskActionElement({
334
+ text: mode === view.currentMode ? "Apply" : "Select",
335
+ value: {
336
+ action: "provider_permission_select",
337
+ sessionId: view.sessionId,
338
+ contextKey: view.contextKey,
339
+ provider: view.modelProvider,
340
+ model: view.model,
341
+ effort: view.reasoningEffort,
342
+ permissionMode: mode,
343
+ },
344
+ })],
345
+ },
346
+ ],
347
+ })),
348
+ { tag: "hr" },
349
+ taskActionRow([{
350
+ text: "Back",
351
+ value: {
352
+ action: "provider_reasoning_open",
353
+ sessionId: view.sessionId,
354
+ contextKey: view.contextKey,
355
+ provider: view.modelProvider,
356
+ model: view.model,
357
+ permissionMode: view.currentMode,
358
+ },
359
+ }]),
360
+ ];
361
+ return sectionCard("Provider 设置 · 权限", elements);
114
362
  }
115
363
  renderPromptQueue(view) {
116
364
  const elements = view.prompts.length === 0
@@ -228,14 +476,14 @@ export class CardRenderer {
228
476
  ? [
229
477
  `**当前任务**:${inlineCode(view.currentTask.title ?? view.currentTask.id)}`,
230
478
  workspaceLine,
231
- `**模型 / 思考强度 / 权限**:${inlineCode(view.currentTask.model ?? "默认")} / ${inlineCode(view.currentTask.reasoningEffort ?? "自动")} / ${inlineCode(permissionModeLabel(view.currentTask.permissionMode))}`,
479
+ `**Provider / 模型 / 思考强度 / 权限**:${inlineCode(view.currentTask.modelProvider ?? "Codex 默认")} / ${inlineCode(view.currentTask.model ?? "默认")} / ${inlineCode(view.currentTask.reasoningEffort ?? "自动")} / ${inlineCode(permissionModeLabel(view.currentTask.permissionMode))}`,
232
480
  `**任务状态 / Agent**:${persistedTaskStatus(view.currentTask.sessionStatus, view.currentTask.lastTurnStatus)} / ${inlineCode(view.currentTask.agentName)}`,
233
481
  `**任务 ID**:${inlineCode(view.currentTask.id)}`,
234
482
  ]
235
483
  : [
236
484
  "**当前任务**:无,下一条普通消息会创建新任务",
237
485
  workspaceLine,
238
- `**模型 / 思考强度 / 权限**:${inlineCode("默认")} / ${inlineCode("自动")} / ${inlineCode(permissionModeLabel())}`,
486
+ `**Provider / 模型 / 思考强度 / 权限**:${inlineCode("Codex 默认")} / ${inlineCode("默认")} / ${inlineCode("自动")} / ${inlineCode(permissionModeLabel())}`,
239
487
  `**默认 Agent**:${view.defaultAgentTitle} (${inlineCode(view.defaultAgentName)})`,
240
488
  ];
241
489
  lines.push(`**Agent Bot 版本**:${inlineCode(view.agentBotVersion)}`, `**服务状态 / 启动时间**:🟢 在线 / ${formatStartupTime(view.startedAt)}`, `**重启原因**:${inlineCode(view.restartReason)}`, "> 发送消息即可开始对话;发送 `/new` 创建新任务;发送 `/help` 查看帮助。");
@@ -491,17 +739,18 @@ function renderTurnElements(state, assistantTextMode) {
491
739
  elements.push(markdown(`**${heading}**\n${truncateText(state.assistantText, 3_000)}`));
492
740
  }
493
741
  if (elements.length === 0)
494
- elements.push(markdown(emptyTurnText(state.status)));
742
+ elements.push(markdown(emptyTurnText(state.status, state.agentLabel)));
495
743
  return elements;
496
744
  }
497
- function emptyTurnText(status) {
745
+ function emptyTurnText(status, agentLabel) {
746
+ const label = agentLabel?.trim().replace(/[\r\n]+/g, " ") || "Agent";
498
747
  if (status === "starting")
499
- return "正在连接 Codex…";
748
+ return `正在连接 ${label}…`;
500
749
  if (status === "completed")
501
750
  return "本轮已完成。";
502
751
  if (status === "cancelled")
503
752
  return "本轮已停止。";
504
- return "正在等待 Codex 返回进度…";
753
+ return `正在等待 ${label} 返回进度…`;
505
754
  }
506
755
  function planPanel(plan) {
507
756
  const completed = plan.filter((step) => step.status === "completed").length;
@@ -512,7 +761,7 @@ function planPanel(plan) {
512
761
  }
513
762
  function fileSummaryPanel(state) {
514
763
  return collapsiblePanel(`文件变更 · ${state.fileSummary.length}`, state.fileSummary
515
- .map((file) => `- ${displayFilePath(file.path, state.projectCwd)} +${file.additions ?? 0} -${file.deletions ?? 0}`)
764
+ .map((file) => `- ${escapeMarkdownFilePath(displayFilePath(file.path, state.projectCwd))} +${file.additions ?? 0} -${file.deletions ?? 0}`)
516
765
  .join("\n"), { elementId: "turn_files" });
517
766
  }
518
767
  function renderPlanStep(step) {
@@ -696,6 +945,9 @@ function displayFilePath(filePath, projectCwd) {
696
945
  && !relativePath.startsWith(`..${pathApi.sep}`));
697
946
  return isInsideProject ? relativePath || "." : absolutePath;
698
947
  }
948
+ function escapeMarkdownFilePath(filePath) {
949
+ return filePath.replaceAll("\\.", "\\\\.");
950
+ }
699
951
  function usesWindowsPaths(...values) {
700
952
  return values.some((value) => /^[A-Za-z]:[\\/]/.test(value) || /^\\\\/.test(value));
701
953
  }
@@ -888,6 +1140,89 @@ function acpPermissionOptionLabel(option) {
888
1140
  };
889
1141
  return labels[option.kind] ?? (/^[\x20-\x7E]+$/.test(option.name) ? option.name : "Select");
890
1142
  }
1143
+ function settingsTabRow(activeTab, baseAction, showAgentTab, showRuntimeTabs) {
1144
+ const tabs = [
1145
+ ...(showAgentTab ? [{ id: "agent", label: "Agent" }] : []),
1146
+ ...(showRuntimeTabs
1147
+ ? [
1148
+ { id: "provider", label: "Provider" },
1149
+ { id: "model", label: "Model" },
1150
+ { id: "thinking", label: "Thinking" },
1151
+ { id: "permission", label: "Permission" },
1152
+ ]
1153
+ : []),
1154
+ ];
1155
+ if (tabs.length === 0)
1156
+ return undefined;
1157
+ return {
1158
+ tag: "column_set",
1159
+ flex_mode: "none",
1160
+ horizontal_spacing: "2px",
1161
+ margin: "8px 0 0 0",
1162
+ columns: tabs.flatMap((tab, index) => [
1163
+ ...(index > 0
1164
+ ? [{
1165
+ tag: "column",
1166
+ width: "auto",
1167
+ vertical_align: "center",
1168
+ elements: [{ ...markdown("·"), text_align: "center", text_size: "notation" }],
1169
+ }]
1170
+ : []),
1171
+ {
1172
+ tag: "column",
1173
+ width: "auto",
1174
+ vertical_align: "center",
1175
+ elements: [settingsTabElement(tab.label, tab.id === activeTab, {
1176
+ action: "settings_tab_open",
1177
+ ...baseAction,
1178
+ tab: tab.id,
1179
+ })],
1180
+ },
1181
+ ]),
1182
+ };
1183
+ }
1184
+ function settingsTabElement(label, active, value) {
1185
+ if (active) {
1186
+ return {
1187
+ ...markdown(escapeCardHtml(label)),
1188
+ text_align: "center",
1189
+ text_size: "notation",
1190
+ };
1191
+ }
1192
+ const action = taskActionElement({ text: label, value });
1193
+ return {
1194
+ ...action,
1195
+ padding: "6px 0px",
1196
+ elements: action.elements.map((element) => ({
1197
+ ...element,
1198
+ text_align: "center",
1199
+ text_size: "notation",
1200
+ })),
1201
+ };
1202
+ }
1203
+ function settingsOptionRow(input) {
1204
+ return {
1205
+ tag: "column_set",
1206
+ flex_mode: "none",
1207
+ horizontal_spacing: "8px",
1208
+ vertical_align: "center",
1209
+ columns: [
1210
+ {
1211
+ tag: "column",
1212
+ width: "weighted",
1213
+ weight: 1,
1214
+ vertical_align: "center",
1215
+ elements: [markdown(input.label)],
1216
+ },
1217
+ {
1218
+ tag: "column",
1219
+ width: "auto",
1220
+ vertical_align: "center",
1221
+ elements: input.current ? [markdown("✅ 当前")] : [taskActionElement(input.action)],
1222
+ },
1223
+ ],
1224
+ };
1225
+ }
891
1226
  function taskActionRow(actions) {
892
1227
  return {
893
1228
  tag: "column_set",