@keyou007/agent-bot 0.1.24-alpha.5 → 0.1.24-alpha.6
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/CHANGELOG.md +26 -0
- package/README.md +27 -3
- package/README.zh.md +27 -3
- package/SECURITY.md +12 -0
- package/config.example.yaml +5 -0
- package/dist/cli/controlProtocol.js.map +1 -1
- package/dist/cli/serverStatus.js +1 -0
- package/dist/cli/serverStatus.js.map +1 -1
- package/dist/cli.js +6 -1
- package/dist/cli.js.map +1 -1
- package/dist/codex/CodexRuntime.js +202 -115
- package/dist/codex/CodexRuntime.js.map +1 -1
- package/dist/codex/ProviderSwitch.js +12 -13
- package/dist/codex/ProviderSwitch.js.map +1 -1
- package/dist/config/AgentExecutionDefaultsStore.js +4 -0
- package/dist/config/AgentExecutionDefaultsStore.js.map +1 -1
- package/dist/config/loadConfig.js +4 -0
- package/dist/config/loadConfig.js.map +1 -1
- package/dist/config/schema.js +3 -0
- package/dist/config/schema.js.map +1 -1
- package/dist/feishu/CardRenderer.js +66 -8
- package/dist/feishu/CardRenderer.js.map +1 -1
- package/dist/feishu/FeishuConnector.js +1 -0
- package/dist/feishu/FeishuConnector.js.map +1 -1
- package/dist/feishu/FeishuTurnPresenter.js +121 -17
- package/dist/feishu/FeishuTurnPresenter.js.map +1 -1
- package/dist/index.js +43 -6
- package/dist/index.js.map +1 -1
- package/dist/local-files/LocalFileViewerServer.js +51 -4
- package/dist/local-files/LocalFileViewerServer.js.map +1 -1
- package/dist/local-files/TurnPreviewPage.js +7 -2
- package/dist/local-files/TurnPreviewPage.js.map +1 -1
- package/dist/presentation/TurnStateReducer.js +41 -6
- package/dist/presentation/TurnStateReducer.js.map +1 -1
- package/dist/proxy/ProxySessionController.js +615 -214
- package/dist/proxy/ProxySessionController.js.map +1 -1
- package/dist/proxy/SessionOperationQueue.js +14 -0
- package/dist/proxy/SessionOperationQueue.js.map +1 -0
- package/dist/runtime/AcpRuntimeAdapter.js +4 -2
- package/dist/runtime/AcpRuntimeAdapter.js.map +1 -1
- package/dist/state/StateStore.js +22 -0
- package/dist/state/StateStore.js.map +1 -1
- package/dist/state/TurnPreviewJournal.js +19 -7
- package/dist/state/TurnPreviewJournal.js.map +1 -1
- package/dist/state/migrations.js +6 -0
- package/dist/state/migrations.js.map +1 -1
- package/dist/supervision/SafeRestartNotifier.js +1 -0
- package/dist/supervision/SafeRestartNotifier.js.map +1 -1
- package/dist/supervision/SafeRestartScheduler.js +19 -6
- package/dist/supervision/SafeRestartScheduler.js.map +1 -1
- package/dist/terminal/TerminalCards.js +13 -0
- package/dist/terminal/TerminalCards.js.map +1 -0
- package/dist/terminal/TerminalLinks.js +76 -0
- package/dist/terminal/TerminalLinks.js.map +1 -0
- package/dist/terminal/TerminalPage.js +212 -0
- package/dist/terminal/TerminalPage.js.map +1 -0
- package/dist/terminal/TerminalProcess.js +71 -0
- package/dist/terminal/TerminalProcess.js.map +1 -0
- package/dist/terminal/TerminalServer.js +639 -0
- package/dist/terminal/TerminalServer.js.map +1 -0
- package/docs/technical-reference.md +48 -0
- package/docs/technical-reference.zh.md +48 -0
- package/npm-shrinkwrap.json +55 -5
- package/package.json +11 -4
- package/skills/agent-bot/SKILL.md +9 -2
- package/src/cli/controlProtocol.ts +2 -1
- package/src/cli/serverStatus.ts +1 -0
- package/src/cli.ts +6 -1
- package/src/codex/CodexRuntime.ts +200 -123
- package/src/codex/ProviderSwitch.ts +11 -12
- package/src/config/AgentExecutionDefaultsStore.ts +2 -0
- package/src/config/loadConfig.ts +4 -0
- package/src/config/schema.ts +5 -1
- package/src/feishu/CardRenderer.ts +81 -8
- package/src/feishu/FeishuConnector.ts +1 -0
- package/src/feishu/FeishuTurnPresenter.ts +108 -16
- package/src/feishu/types.ts +1 -0
- package/src/index.ts +44 -7
- package/src/local-files/LocalFileViewerServer.ts +48 -4
- package/src/local-files/TurnPreviewPage.ts +7 -2
- package/src/presentation/TurnStateReducer.ts +46 -7
- package/src/presentation/turnViewTypes.ts +5 -0
- package/src/proxy/ProxySessionController.ts +625 -211
- package/src/proxy/SessionOperationQueue.ts +13 -0
- package/src/runtime/AcpRuntimeAdapter.ts +5 -3
- package/src/runtime/types.ts +8 -3
- package/src/state/StateStore.ts +38 -1
- package/src/state/TurnPreviewJournal.ts +19 -7
- package/src/state/migrations.ts +6 -0
- package/src/supervision/SafeRestartNotifier.ts +1 -0
- package/src/supervision/SafeRestartScheduler.ts +18 -6
- package/src/terminal/TerminalCards.ts +18 -0
- package/src/terminal/TerminalLinks.ts +61 -0
- package/src/terminal/TerminalPage.ts +213 -0
- package/src/terminal/TerminalProcess.ts +71 -0
- package/src/terminal/TerminalServer.ts +513 -0
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
|
+
import { approvalActivityId } from "../presentation/TurnStateReducer.js";
|
|
2
3
|
import path from "node:path";
|
|
3
4
|
import { truncateMiddle, truncateText } from "../utils/markdown.js";
|
|
4
5
|
import { localCardImage } from "./LocalCardImage.js";
|
|
5
6
|
const EXECUTION_SETTING_EFFECTS = {
|
|
6
7
|
agent: "只影响新建任务,不切换当前任务。",
|
|
7
|
-
provider: "
|
|
8
|
+
provider: "只影响当前任务;运行中选择将在本轮结束后生效。",
|
|
8
9
|
model: "只影响当前任务,下一轮生效。",
|
|
9
10
|
thinking: "只影响当前任务,下一轮生效。",
|
|
10
11
|
permission: "只影响当前任务,下一轮生效。",
|
|
@@ -199,6 +200,9 @@ export class CardRenderer {
|
|
|
199
200
|
...(outputWasTruncated ? ["输出过长,已保留开头和结尾并截断中间内容。"] : []),
|
|
200
201
|
].join("\n")),
|
|
201
202
|
];
|
|
203
|
+
if (view.terminalUrl) {
|
|
204
|
+
elements.push(markdown(`[Open Terminal](${view.terminalUrl}) · 独立终端,需在本会话由所有者授权`));
|
|
205
|
+
}
|
|
202
206
|
if (view.status === "running" && view.jobId && view.contextKey) {
|
|
203
207
|
elements.push({
|
|
204
208
|
tag: "button",
|
|
@@ -234,6 +238,7 @@ export class CardRenderer {
|
|
|
234
238
|
`**思考强度 / 权限**:${inlineCode(view.currentEffort ?? "自动")} / ${inlineCode(permissionModeLabel(view.currentPermissionMode))}`,
|
|
235
239
|
]
|
|
236
240
|
: []),
|
|
241
|
+
...(view.pendingNotice ? [view.pendingNotice] : []),
|
|
237
242
|
...(view.notice ? [view.notice] : []),
|
|
238
243
|
...(view.warning ? [`**提示**:${escapeCardHtml(view.warning)}`] : []),
|
|
239
244
|
].join("\n")),
|
|
@@ -267,7 +272,8 @@ export class CardRenderer {
|
|
|
267
272
|
inlineCode(provider.id),
|
|
268
273
|
provider.isDefault ? " · 默认" : "",
|
|
269
274
|
].join(""),
|
|
270
|
-
current: provider.id === view.currentProvider,
|
|
275
|
+
current: provider.id === view.currentProvider && !view.pendingFailed,
|
|
276
|
+
currentLabel: view.pendingNotice ? "待生效" : undefined,
|
|
271
277
|
action: {
|
|
272
278
|
text: "Switch",
|
|
273
279
|
value: {
|
|
@@ -284,18 +290,24 @@ export class CardRenderer {
|
|
|
284
290
|
elements.push(markdown("当前运行时未返回可用模型。"));
|
|
285
291
|
}
|
|
286
292
|
else {
|
|
287
|
-
|
|
293
|
+
const page = paginateModels(view.models, view.currentModel, view.modelPage, {
|
|
294
|
+
action: "settings_tab_open", ...baseAction, tab: "model", provider: view.currentProvider ?? "",
|
|
295
|
+
});
|
|
296
|
+
elements.push(...page.models.map((model) => settingsOptionRow({
|
|
288
297
|
label: `${inlineCode(model.id)}${model.isDefault ? " · 默认" : ""}`,
|
|
289
|
-
current: model.id === view.currentModel,
|
|
298
|
+
current: model.id === view.currentModel && !view.pendingFailed,
|
|
299
|
+
currentLabel: view.pendingNotice ? "待生效" : undefined,
|
|
290
300
|
action: {
|
|
291
301
|
text: "Switch",
|
|
292
302
|
value: {
|
|
293
303
|
action: "settings_model_select",
|
|
294
304
|
...baseAction,
|
|
305
|
+
provider: view.currentProvider ?? "",
|
|
295
306
|
model: model.id,
|
|
296
307
|
},
|
|
297
308
|
},
|
|
298
309
|
})));
|
|
310
|
+
elements.push(...page.navigation);
|
|
299
311
|
}
|
|
300
312
|
}
|
|
301
313
|
else if (view.activeTab === "thinking") {
|
|
@@ -310,11 +322,13 @@ export class CardRenderer {
|
|
|
310
322
|
elements.push(...view.reasoningOptions.map((option) => settingsOptionRow({
|
|
311
323
|
label: inlineCode(option.value),
|
|
312
324
|
current: option.value === view.currentEffort,
|
|
325
|
+
currentLabel: view.pendingNotice ? "待生效" : undefined,
|
|
313
326
|
action: {
|
|
314
327
|
text: "Switch",
|
|
315
328
|
value: {
|
|
316
329
|
action: "settings_thinking_select",
|
|
317
330
|
...baseAction,
|
|
331
|
+
provider: view.currentProvider ?? "",
|
|
318
332
|
model: currentModel,
|
|
319
333
|
effort: option.value,
|
|
320
334
|
},
|
|
@@ -326,6 +340,7 @@ export class CardRenderer {
|
|
|
326
340
|
elements.push(...["auto", "confirm"].map((mode) => settingsOptionRow({
|
|
327
341
|
label: `${inlineCode(mode)} · ${permissionModeLabel(mode)}`,
|
|
328
342
|
current: mode === view.currentPermissionMode,
|
|
343
|
+
currentLabel: view.pendingNotice ? "待生效" : undefined,
|
|
329
344
|
action: {
|
|
330
345
|
text: "Switch",
|
|
331
346
|
value: {
|
|
@@ -337,7 +352,7 @@ export class CardRenderer {
|
|
|
337
352
|
})));
|
|
338
353
|
}
|
|
339
354
|
elements.push(markdown(`> ${EXECUTION_SETTING_EFFECTS[view.activeTab]}`));
|
|
340
|
-
return sectionCard("运行设置", elements, view.warning ? "orange" : view.notice ? "green" : "blue");
|
|
355
|
+
return sectionCard("运行设置", elements, view.warning || view.pendingFailed ? "orange" : view.notice ? "green" : "blue");
|
|
341
356
|
}
|
|
342
357
|
renderProviderSelector(view) {
|
|
343
358
|
const elements = [
|
|
@@ -470,7 +485,14 @@ export class CardRenderer {
|
|
|
470
485
|
elements.push(markdown("当前运行时未返回可用模型。"));
|
|
471
486
|
}
|
|
472
487
|
else {
|
|
473
|
-
|
|
488
|
+
const page = paginateModels(view.models, view.currentModel, view.modelPage, {
|
|
489
|
+
action: view.unifiedSettings ? "provider_model_open" : "model_open",
|
|
490
|
+
sessionId: view.sessionId,
|
|
491
|
+
contextKey: view.contextKey,
|
|
492
|
+
...(view.modelProvider ? { provider: view.modelProvider } : {}),
|
|
493
|
+
...(view.permissionMode ? { permissionMode: view.permissionMode } : {}),
|
|
494
|
+
});
|
|
495
|
+
elements.push(...page.models.map((model) => {
|
|
474
496
|
const isCurrent = model.id === view.currentModel;
|
|
475
497
|
return {
|
|
476
498
|
tag: "column_set",
|
|
@@ -506,6 +528,7 @@ export class CardRenderer {
|
|
|
506
528
|
],
|
|
507
529
|
};
|
|
508
530
|
}));
|
|
531
|
+
elements.push(...page.navigation);
|
|
509
532
|
}
|
|
510
533
|
if (view.unifiedSettings) {
|
|
511
534
|
elements.push({ tag: "hr" }, taskActionRow([{
|
|
@@ -665,6 +688,24 @@ export class CardRenderer {
|
|
|
665
688
|
}
|
|
666
689
|
return sectionCard("Agent Bot 更新提醒", elements, view.status === "completed" ? "green" : view.status === "cancelled" ? "grey" : "blue");
|
|
667
690
|
}
|
|
691
|
+
renderTerminalAuthorization(view) {
|
|
692
|
+
const action = (decision) => ({ action: "terminal_authorize", contextKey: view.contextKey, requestId: view.requestId, token: view.approvalToken, decision });
|
|
693
|
+
const elements = [markdown(`**目录**:${inlineCode(view.cwd)}\n**终端**:${inlineCode(view.reopenToken)}`)];
|
|
694
|
+
if (view.state === "pending") {
|
|
695
|
+
elements.push(markdown(`**验证码**:${inlineCode(view.code)}\n仅 AgentBot 所有者可授权。授权后,该浏览器可在本机执行任意命令,拥有 AgentBot 的系统用户权限。请核对网页验证码,仅批准本人发起的请求。5 分钟内有效。${view.recovery ? (view.shellStarted ? "恢复原 Shell,不创建新终端;授权后旧网页失去访问权限。拒绝不影响原终端。" : "继续打开同一个终端;授权后旧网页失去访问权限,Shell 在连接成功后启动。拒绝不影响原授权。") : "不执行原卡片命令。"}`), taskActionRow([{ text: "Allow", value: action("allow") }, { text: "Deny", type: "danger", value: action("deny") }, { text: "刷新", value: action("refresh") }]));
|
|
696
|
+
}
|
|
697
|
+
else if (view.state === "closed") {
|
|
698
|
+
elements.push(markdown(`**状态**:${view.message ? escapeCardHtml(view.message) : "已关闭"}\n原终端已结束时,请从命令卡片创建新终端。`));
|
|
699
|
+
}
|
|
700
|
+
else {
|
|
701
|
+
const waiting = view.state === "approved";
|
|
702
|
+
const label = waiting ? "打开终端" : "重新打开终端";
|
|
703
|
+
elements.push(markdown(`**状态**:${waiting ? "已授权,等待网页连接" : view.connected ? "已连接" : "网页已断开,Shell 仍在运行"}\n${waiting ? "请返回原网页连接;原网页已关闭时,点击下方“打开终端”。Shell 尚未启动。" : "点击下方“重新打开终端”恢复原 Shell。前台连接时不因空闲关闭;后台空闲 30 分钟或网页断开 3 分钟后会自动关闭 Shell,成功重连取消断开计时并重置空闲计时;“关闭终端”会中断其中的命令。"}`));
|
|
704
|
+
elements.push(markdown(`[${label}](${view.reopenUrl}) · 新网页需核对验证码重新授权${waiting ? ",连接成功后启动 Shell" : ",恢复原 Shell"}`));
|
|
705
|
+
elements.push(taskActionRow([{ text: "关闭终端", type: "danger", value: action("close") }, { text: "刷新", value: action("refresh") }]));
|
|
706
|
+
}
|
|
707
|
+
return sectionCard(view.state === "pending" ? "网页终端授权" : "网页终端管理", elements, view.state === "closed" ? "grey" : view.state === "pending" ? "orange" : "blue");
|
|
708
|
+
}
|
|
668
709
|
renderSafeRestartStatus(view) {
|
|
669
710
|
const actionable = view.phase !== "restarting" && view.phase !== "cancelled" && view.phase !== "superseded";
|
|
670
711
|
const countdown = view.phase === "countdown"
|
|
@@ -692,6 +733,7 @@ export class CardRenderer {
|
|
|
692
733
|
`**重启原因**:${inlineCode(view.reason)}`,
|
|
693
734
|
`**重启倒计时**:${countdown}`,
|
|
694
735
|
`**待投递结果**:${view.pendingFinalDeliveries} 条`,
|
|
736
|
+
...(view.activeTerminals ? [`**活动终端**:${view.activeTerminals} 个,请在网页或原会话的终端管理卡中关闭。ForceRestart 会中断终端。`] : []),
|
|
695
737
|
];
|
|
696
738
|
const elements = [markdown(lines.join("\n"))];
|
|
697
739
|
if (view.waitingTasks.length > 0) {
|
|
@@ -1396,6 +1438,10 @@ function renderApprovalElements(state, request) {
|
|
|
1396
1438
|
request.reason,
|
|
1397
1439
|
].filter(Boolean).join("\n")));
|
|
1398
1440
|
}
|
|
1441
|
+
if (request.automatic) {
|
|
1442
|
+
elements.push(markdown("自动执行模式:正在自动同意。"));
|
|
1443
|
+
return elements;
|
|
1444
|
+
}
|
|
1399
1445
|
elements.push({
|
|
1400
1446
|
tag: "column_set",
|
|
1401
1447
|
flex_mode: "flow",
|
|
@@ -1781,7 +1827,8 @@ function removeMarkdownBold(value) {
|
|
|
1781
1827
|
}
|
|
1782
1828
|
function turnActivities(state) {
|
|
1783
1829
|
if (state.activities?.length)
|
|
1784
|
-
return state.
|
|
1830
|
+
return state.approval
|
|
1831
|
+
? state.activities.filter((a) => a.id !== approvalActivityId(state.turnId, state.approval.id)) : state.activities;
|
|
1785
1832
|
const activities = [];
|
|
1786
1833
|
if (state.progressText) {
|
|
1787
1834
|
activities.push({ kind: "reasoning", id: "legacy-progress", text: state.progressText });
|
|
@@ -2334,6 +2381,17 @@ function acpPermissionOptionLabel(option) {
|
|
|
2334
2381
|
};
|
|
2335
2382
|
return labels[option.kind] ?? (/^[\x20-\x7E]+$/.test(option.name) ? option.name : "Select");
|
|
2336
2383
|
}
|
|
2384
|
+
const MODEL_PAGE_SIZE = 20;
|
|
2385
|
+
function paginateModels(models, currentModel, requestedPage, action) {
|
|
2386
|
+
const totalPages = Math.max(1, Math.ceil(models.length / MODEL_PAGE_SIZE));
|
|
2387
|
+
const currentPage = Math.floor(models.findIndex((model) => model.id === currentModel) / MODEL_PAGE_SIZE);
|
|
2388
|
+
const page = Math.max(0, Math.min(requestedPage ?? currentPage, totalPages - 1));
|
|
2389
|
+
const navigation = totalPages > 1 ? [taskActionRow([
|
|
2390
|
+
...(page > 0 ? [{ text: "上一页", value: { ...action, page: String(page - 1) } }] : []),
|
|
2391
|
+
...(page < totalPages - 1 ? [{ text: "下一页", value: { ...action, page: String(page + 1) } }] : []),
|
|
2392
|
+
], `第 ${page + 1}/${totalPages} 页 · 共 ${models.length} 个模型`)] : [];
|
|
2393
|
+
return { models: models.slice(page * MODEL_PAGE_SIZE, (page + 1) * MODEL_PAGE_SIZE), navigation };
|
|
2394
|
+
}
|
|
2337
2395
|
function settingsTabRow(activeTab, baseAction, showAgentTab, showRuntimeTabs) {
|
|
2338
2396
|
const tabs = [
|
|
2339
2397
|
...(showAgentTab ? [{ id: "agent", label: "Agent" }] : []),
|
|
@@ -2412,7 +2470,7 @@ function settingsOptionRow(input) {
|
|
|
2412
2470
|
tag: "column",
|
|
2413
2471
|
width: "auto",
|
|
2414
2472
|
vertical_align: "center",
|
|
2415
|
-
elements: input.current ? [markdown("
|
|
2473
|
+
elements: input.current ? [markdown(`✅ ${input.currentLabel ?? "当前"}`)] : [taskActionElement(input.action)],
|
|
2416
2474
|
},
|
|
2417
2475
|
],
|
|
2418
2476
|
};
|