@keyou007/agent-bot 0.1.24-alpha.1 → 0.1.24-alpha.3
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 +94 -0
- package/README.md +33 -7
- package/README.zh.md +32 -7
- package/dist/acp/AcpJsonRpcConnection.js +3 -1
- package/dist/acp/AcpJsonRpcConnection.js.map +1 -1
- package/dist/cli/SelfUpdateRunner.js +2 -0
- package/dist/cli/SelfUpdateRunner.js.map +1 -1
- package/dist/cli/SelfUpdater.js +2 -0
- package/dist/cli/SelfUpdater.js.map +1 -1
- package/dist/codex/AppServerConnection.js +3 -1
- package/dist/codex/AppServerConnection.js.map +1 -1
- package/dist/codex/CodexEventMapper.js +41 -3
- package/dist/codex/CodexEventMapper.js.map +1 -1
- package/dist/codex/CodexRuntime.js +95 -3
- package/dist/codex/CodexRuntime.js.map +1 -1
- package/dist/commands/CommandRouter.js +5 -0
- package/dist/commands/CommandRouter.js.map +1 -1
- package/dist/feishu/CardRenderer.js +49 -23
- package/dist/feishu/CardRenderer.js.map +1 -1
- package/dist/feishu/FeishuConnector.js +2 -0
- package/dist/feishu/FeishuConnector.js.map +1 -1
- package/dist/feishu/FeishuMarkdown.js +70 -4
- package/dist/feishu/FeishuMarkdown.js.map +1 -1
- package/dist/feishu/FeishuMessageClient.js +44 -0
- package/dist/feishu/FeishuMessageClient.js.map +1 -1
- package/dist/feishu/FeishuTurnPresenter.js +114 -37
- package/dist/feishu/FeishuTurnPresenter.js.map +1 -1
- package/dist/feishu/RecentMessageContext.js +70 -0
- package/dist/feishu/RecentMessageContext.js.map +1 -0
- package/dist/index.js +62 -24
- package/dist/index.js.map +1 -1
- package/dist/local-files/DiagramPreview.js +171 -0
- package/dist/local-files/DiagramPreview.js.map +1 -0
- package/dist/local-files/LocalFileViewerServer.js +141 -3
- package/dist/local-files/LocalFileViewerServer.js.map +1 -1
- package/dist/local-files/PreviewSyntaxHighlight.js +57 -0
- package/dist/local-files/PreviewSyntaxHighlight.js.map +1 -0
- package/dist/local-files/TurnPreviewPage.js +499 -60
- package/dist/local-files/TurnPreviewPage.js.map +1 -1
- package/dist/presentation/OutboundRouter.js +18 -9
- package/dist/presentation/OutboundRouter.js.map +1 -1
- package/dist/presentation/TurnStateReducer.js +157 -8
- package/dist/presentation/TurnStateReducer.js.map +1 -1
- package/dist/presentation/turnReasoning.js +23 -0
- package/dist/presentation/turnReasoning.js.map +1 -0
- package/dist/proxy/ProxySessionController.js +461 -49
- package/dist/proxy/ProxySessionController.js.map +1 -1
- package/dist/state/StateStore.js +43 -2
- package/dist/state/StateStore.js.map +1 -1
- package/dist/state/TurnPreviewJournal.js +469 -0
- package/dist/state/TurnPreviewJournal.js.map +1 -0
- package/dist/state/migrations.js +10 -0
- package/dist/state/migrations.js.map +1 -1
- package/dist/updates/AutomaticUpdatePreparer.js +16 -7
- package/dist/updates/AutomaticUpdatePreparer.js.map +1 -1
- package/dist/updates/ManualUpdateController.js +102 -0
- package/dist/updates/ManualUpdateController.js.map +1 -0
- package/dist/updates/PublishedRelease.js +42 -4
- package/dist/updates/PublishedRelease.js.map +1 -1
- package/dist/utils/ProtocolLineWarning.js +15 -0
- package/dist/utils/ProtocolLineWarning.js.map +1 -0
- package/docs/technical-reference.md +21 -1
- package/docs/technical-reference.zh.md +21 -1
- package/npm-shrinkwrap.json +1401 -10
- package/package.json +3 -1
- package/skills/agent-bot/SKILL.md +9 -2
- package/src/acp/AcpJsonRpcConnection.ts +3 -1
- package/src/cli/SelfUpdateRunner.ts +3 -0
- package/src/cli/SelfUpdater.ts +2 -0
- package/src/codex/AppServerConnection.ts +3 -1
- package/src/codex/CodexEventMapper.ts +40 -3
- package/src/codex/CodexRuntime.ts +91 -4
- package/src/commands/CommandRouter.ts +4 -0
- package/src/commands/commandTypes.ts +1 -0
- package/src/feishu/CardRenderer.ts +47 -21
- package/src/feishu/FeishuConnector.ts +2 -0
- package/src/feishu/FeishuMarkdown.ts +69 -3
- package/src/feishu/FeishuMessageClient.ts +44 -0
- package/src/feishu/FeishuTurnPresenter.ts +107 -31
- package/src/feishu/RecentMessageContext.ts +90 -0
- package/src/feishu/types.ts +5 -0
- package/src/index.ts +62 -22
- package/src/local-files/DiagramPreview.ts +173 -0
- package/src/local-files/LocalFileViewerServer.ts +129 -2
- package/src/local-files/PreviewSyntaxHighlight.ts +58 -0
- package/src/local-files/TurnPreviewPage.ts +539 -57
- package/src/presentation/OutboundRouter.ts +25 -7
- package/src/presentation/TurnStateReducer.ts +153 -9
- package/src/presentation/turnReasoning.ts +21 -0
- package/src/presentation/turnViewTypes.ts +19 -1
- package/src/proxy/ProxySessionController.ts +453 -40
- package/src/runtime/types.ts +21 -0
- package/src/state/StateStore.ts +45 -2
- package/src/state/TurnPreviewJournal.ts +398 -0
- package/src/state/migrations.ts +10 -0
- package/src/updates/AutomaticUpdatePreparer.ts +21 -7
- package/src/updates/ManualUpdateController.ts +116 -0
- package/src/updates/PublishedRelease.ts +49 -3
- package/src/utils/ProtocolLineWarning.ts +13 -0
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { truncateText } from "../utils/markdown.js";
|
|
3
|
+
import { compareSemver } from "../cli/SelfUpdater.js";
|
|
4
|
+
import { CardRenderer } from "../feishu/CardRenderer.js";
|
|
5
|
+
import { publishedVersionSchema } from "./PublishedRelease.js";
|
|
6
|
+
export class ManualUpdateController {
|
|
7
|
+
options;
|
|
8
|
+
renderer = new CardRenderer();
|
|
9
|
+
selecting = false;
|
|
10
|
+
constructor(options) {
|
|
11
|
+
this.options = options;
|
|
12
|
+
}
|
|
13
|
+
async show(contextKey, userId) {
|
|
14
|
+
await this.options.outbound.sendText(contextKey, "正在检查正式版和 Alpha 版更新,请稍后。");
|
|
15
|
+
const [releases, support] = await Promise.all([
|
|
16
|
+
this.options.readReleases(),
|
|
17
|
+
this.options.checkSupport().then(() => undefined, (error) => String(error instanceof Error ? error.message : error)),
|
|
18
|
+
]);
|
|
19
|
+
const owner = this.options.ownerOpenId();
|
|
20
|
+
const notice = support
|
|
21
|
+
? `当前安装方式不支持在线更新:${truncateText(support, 600)}`
|
|
22
|
+
: !owner || userId !== owner
|
|
23
|
+
? "仅配置的机器人所有者可以执行更新。"
|
|
24
|
+
: this.selecting || this.options.hasPendingUpdate()
|
|
25
|
+
? "已有更新或重启正在进行,请稍后再检查。"
|
|
26
|
+
: undefined;
|
|
27
|
+
const now = this.options.now?.() ?? Date.now();
|
|
28
|
+
const bindings = [];
|
|
29
|
+
const actions = [];
|
|
30
|
+
const sections = [{ title: "当前版本", lines: [`${this.options.currentVersion}`] }];
|
|
31
|
+
for (const release of releases) {
|
|
32
|
+
const label = release.channel === "latest" ? "正式版" : "Alpha";
|
|
33
|
+
if (!release.version) {
|
|
34
|
+
sections.push({ title: label, lines: [`查询失败:${truncateText(release.error ?? "暂时无法获取版本", 300)}`] });
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
const version = publishedVersionSchema.parse(release.version);
|
|
38
|
+
const comparison = compareSemver(version, this.options.currentVersion);
|
|
39
|
+
sections.push({ title: `${label} ${version}`, lines: [
|
|
40
|
+
comparison > 0 ? "有新版本" : comparison === 0 ? "当前已安装" : "早于当前版本,不提供降级",
|
|
41
|
+
truncateText(release.notes ?? "暂无更新简介。", 2000),
|
|
42
|
+
`[完整更新日志](https://github.com/keyou/agent-bot/releases/tag/v${version})`,
|
|
43
|
+
] });
|
|
44
|
+
if (comparison > 0 && !notice) {
|
|
45
|
+
const token = randomUUID();
|
|
46
|
+
bindings.push({ token, value: { action: "agentbot_update_select", token, version, contextKey, owner: owner, createdAt: String(now) } });
|
|
47
|
+
actions.push({ text: `Update ${version}`, value: { action: "agentbot_update_select", token, contextKey } });
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
const summary = notice ?? (actions.length > 0
|
|
51
|
+
? "选择一个版本开始更新;等待任务与结果投递完成后重启,失败时尝试回滚。"
|
|
52
|
+
: releases.some((release) => !release.version)
|
|
53
|
+
? "部分版本查询失败,请稍后重新发送 /update。"
|
|
54
|
+
: "暂无高于当前版本的可用更新。");
|
|
55
|
+
sections.push({ title: "说明", lines: [summary] });
|
|
56
|
+
const messageId = await this.options.outbound.sendInteractiveCard(contextKey, this.renderer.renderSectionsCard("Agent Bot 更新", sections, actions));
|
|
57
|
+
if (messageId && bindings.length)
|
|
58
|
+
this.options.store.upsertCardActionBindings(messageId, bindings);
|
|
59
|
+
}
|
|
60
|
+
async select(action, replyTarget) {
|
|
61
|
+
const token = typeof action.value.token === "string" ? action.value.token : "";
|
|
62
|
+
const binding = action.messageId && token ? this.options.store.getCardActionBinding(action.messageId, token) : undefined;
|
|
63
|
+
const now = this.options.now?.() ?? Date.now();
|
|
64
|
+
const createdAt = Number(binding?.createdAt);
|
|
65
|
+
if (!binding || binding.action !== "agentbot_update_select" || binding.contextKey !== action.contextKey
|
|
66
|
+
|| !Number.isFinite(createdAt) || now - createdAt > 30 * 60_000
|
|
67
|
+
|| now < createdAt) {
|
|
68
|
+
throw new Error("更新卡片已失效,请重新发送 /update。");
|
|
69
|
+
}
|
|
70
|
+
if (!action.userId || action.userId !== binding.owner || action.userId !== this.options.ownerOpenId()) {
|
|
71
|
+
throw new Error("仅配置的机器人所有者可以执行更新。");
|
|
72
|
+
}
|
|
73
|
+
const version = publishedVersionSchema.parse(binding.version);
|
|
74
|
+
if (compareSemver(version, this.options.currentVersion) <= 0)
|
|
75
|
+
throw new Error("此版本无需更新,请重新发送 /update。");
|
|
76
|
+
if (this.selecting || this.options.hasPendingUpdate())
|
|
77
|
+
throw new Error("已有更新或重启正在进行,请勿重复操作。");
|
|
78
|
+
this.selecting = true;
|
|
79
|
+
try {
|
|
80
|
+
this.options.store.retainCardActionBindings(action.messageId, []);
|
|
81
|
+
await this.options.outbound.sendText(action.contextKey, `正在下载并校验 Agent Bot ${version},请稍后;完成后将安排安全更新。`);
|
|
82
|
+
await this.options.applyUpdate(version, action.contextKey, replyTarget);
|
|
83
|
+
await this.showResult(action, version, "更新已就绪,等待任务与结果投递完成后自动安装并重启。");
|
|
84
|
+
}
|
|
85
|
+
catch (error) {
|
|
86
|
+
await this.showResult(action, version, "更新未完成,当前服务继续运行。请重新发送 /update 后重试。");
|
|
87
|
+
throw error;
|
|
88
|
+
}
|
|
89
|
+
finally {
|
|
90
|
+
this.selecting = false;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
async showResult(action, version, status) {
|
|
94
|
+
try {
|
|
95
|
+
await this.options.outbound.updateInteractiveCard(action.contextKey, action.messageId, this.renderer.renderSectionsCard("Agent Bot 更新", [{ title: version, lines: [status] }]));
|
|
96
|
+
}
|
|
97
|
+
catch (error) {
|
|
98
|
+
this.options.logger.warn({ error, version }, "Failed to refresh the manual update card.");
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=ManualUpdateController.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ManualUpdateController.js","sourceRoot":"","sources":["../../src/updates/ManualUpdateController.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
1
2
|
import { z } from "zod";
|
|
2
3
|
import { AGENT_BOT_PACKAGE_NAME } from "../cli/SelfUpdater.js";
|
|
3
4
|
export const stableVersionSchema = z.string().regex(/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/u);
|
|
@@ -5,17 +6,54 @@ export async function readLatestStableVersion() {
|
|
|
5
6
|
const text = await fetchText(`https://registry.npmjs.org/${encodeURIComponent(AGENT_BOT_PACKAGE_NAME)}/latest`, 256_000);
|
|
6
7
|
return z.object({ version: stableVersionSchema }).parse(JSON.parse(text)).version;
|
|
7
8
|
}
|
|
9
|
+
export const publishedVersionSchema = z.string().regex(/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-alpha\.(0|[1-9]\d*))?$/u);
|
|
10
|
+
export async function readPublishedReleases() {
|
|
11
|
+
return Promise.all(["latest", "alpha"].map(async (channel) => {
|
|
12
|
+
let version;
|
|
13
|
+
try {
|
|
14
|
+
const text = await fetchText(`https://registry.npmjs.org/${encodeURIComponent(AGENT_BOT_PACKAGE_NAME)}/${channel}`, 256_000);
|
|
15
|
+
version = z.object({ version: channel === "latest" ? stableVersionSchema : publishedVersionSchema }).parse(JSON.parse(text)).version;
|
|
16
|
+
if (channel === "alpha" && !version.includes("-alpha."))
|
|
17
|
+
throw new Error("The alpha tag does not point to an Alpha release.");
|
|
18
|
+
}
|
|
19
|
+
catch (error) {
|
|
20
|
+
return { channel, error: error instanceof Error ? error.message : String(error) };
|
|
21
|
+
}
|
|
22
|
+
try {
|
|
23
|
+
return { channel, version, notes: await readReleaseNotes(version) };
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
return { channel, version, notes: `更新简介暂时无法读取。[查看更新日志](https://github.com/keyou/agent-bot/releases/tag/v${version})` };
|
|
27
|
+
}
|
|
28
|
+
}));
|
|
29
|
+
}
|
|
8
30
|
export async function readReleaseNotes(version) {
|
|
9
|
-
|
|
31
|
+
publishedVersionSchema.parse(version);
|
|
32
|
+
// Published tags are immutable; bundled translations can cover older releases.
|
|
33
|
+
const bundled = await readFile(new URL("../../CHANGELOG.md", import.meta.url), "utf8").catch(() => "");
|
|
34
|
+
const chinese = chineseReleaseNotes(releaseNotesSection(bundled, version) ?? "");
|
|
35
|
+
if (chinese)
|
|
36
|
+
return boundReleaseNotes(chinese, version);
|
|
10
37
|
const changelog = await fetchText(`https://raw.githubusercontent.com/keyou/agent-bot/v${version}/CHANGELOG.md`, 2_000_000);
|
|
11
38
|
return extractReleaseNotes(changelog, version);
|
|
12
39
|
}
|
|
13
40
|
export function extractReleaseNotes(changelog, version) {
|
|
14
|
-
const
|
|
15
|
-
const section = sections.find((value) => value.split(/\r?\n/u, 1)[0]?.startsWith(`[${version}]`));
|
|
16
|
-
const notes = section?.includes("\n") ? section.slice(section.indexOf("\n") + 1).trim() : undefined;
|
|
41
|
+
const notes = releaseNotesSection(changelog, version);
|
|
17
42
|
if (!notes)
|
|
18
43
|
throw new Error(`Release notes are unavailable for Agent Bot ${version}.`);
|
|
44
|
+
return boundReleaseNotes(chineseReleaseNotes(notes) ?? notes, version);
|
|
45
|
+
}
|
|
46
|
+
function releaseNotesSection(changelog, version) {
|
|
47
|
+
const sections = changelog.split(/^## /mu).slice(1);
|
|
48
|
+
const section = sections.find((value) => value.split(/\r?\n/u, 1)[0]?.startsWith(`[${version}]`));
|
|
49
|
+
return section?.includes("\n") ? section.slice(section.indexOf("\n") + 1).trim() : undefined;
|
|
50
|
+
}
|
|
51
|
+
function chineseReleaseNotes(notes) {
|
|
52
|
+
const sections = notes.split(/^###\s+/mu).slice(1);
|
|
53
|
+
const section = sections.find((value) => /^(?:中文|简体中文|Chinese|zh-CN)\s*$/iu.test(value.split(/\r?\n/u, 1)[0] ?? ""));
|
|
54
|
+
return section?.includes("\n") ? section.slice(section.indexOf("\n") + 1).trim() || undefined : undefined;
|
|
55
|
+
}
|
|
56
|
+
function boundReleaseNotes(notes, version) {
|
|
19
57
|
return notes.length > 4_000 ? `${notes.slice(0, 3_900)}\n\n[完整更新日志](https://github.com/keyou/agent-bot/releases/tag/v${version})` : notes;
|
|
20
58
|
}
|
|
21
59
|
async function fetchText(url, maxBytes) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PublishedRelease.js","sourceRoot":"","sources":["../../src/updates/PublishedRelease.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAE/D,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,6CAA6C,CAAC,CAAC;AAEnG,MAAM,CAAC,KAAK,UAAU,uBAAuB;IAC3C,MAAM,IAAI,GAAG,MAAM,SAAS,CAAC,8BAA8B,kBAAkB,CAAC,sBAAsB,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IACzH,OAAO,CAAC,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,mBAAmB,EAAE,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC;AACpF,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,OAAe;IACpD,
|
|
1
|
+
{"version":3,"file":"PublishedRelease.js","sourceRoot":"","sources":["../../src/updates/PublishedRelease.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAE/D,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,6CAA6C,CAAC,CAAC;AAEnG,MAAM,CAAC,KAAK,UAAU,uBAAuB;IAC3C,MAAM,IAAI,GAAG,MAAM,SAAS,CAAC,8BAA8B,kBAAkB,CAAC,sBAAsB,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IACzH,OAAO,CAAC,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,mBAAmB,EAAE,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC;AACpF,CAAC;AAED,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,sEAAsE,CAAC,CAAC;AAS/H,MAAM,CAAC,KAAK,UAAU,qBAAqB;IACzC,OAAO,OAAO,CAAC,GAAG,CAAE,CAAC,QAAQ,EAAE,OAAO,CAAW,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,EAA6B,EAAE;QACjG,IAAI,OAAe,CAAC;QACpB,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,SAAS,CAAC,8BAA8B,kBAAkB,CAAC,sBAAsB,CAAC,IAAI,OAAO,EAAE,EAAE,OAAO,CAAC,CAAC;YAC7H,OAAO,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,sBAAsB,EAAE,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC;YACrI,IAAI,OAAO,KAAK,OAAO,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC;gBAAE,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;QAChI,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;QACpF,CAAC;QACD,IAAI,CAAC;YACH,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC,OAAO,CAAC,EAAE,CAAC;QACtE,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,wEAAwE,OAAO,GAAG,EAAE,CAAC;QACzH,CAAC;IACH,CAAC,CAAC,CAAC,CAAC;AACN,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,OAAe;IACpD,sBAAsB,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACtC,+EAA+E;IAC/E,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,IAAI,GAAG,CAAC,oBAAoB,EAAE,OAAO,IAAI,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;IACvG,MAAM,OAAO,GAAG,mBAAmB,CAAC,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;IACjF,IAAI,OAAO;QAAE,OAAO,iBAAiB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IACxD,MAAM,SAAS,GAAG,MAAM,SAAS,CAC/B,sDAAsD,OAAO,eAAe,EAAE,SAAS,CACxF,CAAC;IACF,OAAO,mBAAmB,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;AACjD,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,SAAiB,EAAE,OAAe;IACpE,MAAM,KAAK,GAAG,mBAAmB,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IACtD,IAAI,CAAC,KAAK;QAAE,MAAM,IAAI,KAAK,CAAC,+CAA+C,OAAO,GAAG,CAAC,CAAC;IACvF,OAAO,iBAAiB,CAAC,mBAAmB,CAAC,KAAK,CAAC,IAAI,KAAK,EAAE,OAAO,CAAC,CAAC;AACzE,CAAC;AAED,SAAS,mBAAmB,CAAC,SAAiB,EAAE,OAAe;IAC7D,MAAM,QAAQ,GAAG,SAAS,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACpD,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,UAAU,CAAC,IAAI,OAAO,GAAG,CAAC,CAAC,CAAC;IAClG,OAAO,OAAO,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;AAC/F,CAAC;AAED,SAAS,mBAAmB,CAAC,KAAa;IACxC,MAAM,QAAQ,GAAG,KAAK,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACnD,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,kCAAkC,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IACrH,OAAO,OAAO,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC;AAC5G,CAAC;AAED,SAAS,iBAAiB,CAAC,KAAa,EAAE,OAAe;IACvD,OAAO,KAAK,CAAC,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,iEAAiE,OAAO,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC;AAC5I,CAAC;AAED,KAAK,UAAU,SAAS,CAAC,GAAW,EAAE,QAAgB;IACpD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IAC3E,IAAI,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,gCAAgC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC;IACxG,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;IACzC,MAAM,MAAM,GAAiB,EAAE,CAAC;IAChC,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,IAAI,CAAC;QACH,OAAO,IAAI,EAAE,CAAC;YACZ,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;YAC5C,IAAI,IAAI;gBAAE,OAAO,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;YACxD,IAAI,IAAI,KAAK,CAAC,UAAU,CAAC;YACzB,IAAI,IAAI,GAAG,QAAQ;gBAAE,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;YACjF,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACrB,CAAC;IACH,CAAC;YAAS,CAAC;QACT,MAAM,MAAM,CAAC,MAAM,EAAE,CAAC;IACxB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/** Invalid protocol output is diagnostic metadata, not a second full execution log. */
|
|
2
|
+
export class ProtocolLineWarning {
|
|
3
|
+
nextWarningAt = 0;
|
|
4
|
+
suppressed = 0;
|
|
5
|
+
warn(logger, line, message, now = Date.now()) {
|
|
6
|
+
if (now < this.nextWarningAt) {
|
|
7
|
+
this.suppressed++;
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
logger.warn({ line: line.slice(0, 2048), characters: line.length, suppressed: this.suppressed }, message);
|
|
11
|
+
this.suppressed = 0;
|
|
12
|
+
this.nextWarningAt = now + 10_000;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=ProtocolLineWarning.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ProtocolLineWarning.js","sourceRoot":"","sources":["../../src/utils/ProtocolLineWarning.ts"],"names":[],"mappings":"AAEA,uFAAuF;AACvF,MAAM,OAAO,mBAAmB;IACtB,aAAa,GAAG,CAAC,CAAC;IAClB,UAAU,GAAG,CAAC,CAAC;IACvB,IAAI,CAAC,MAAc,EAAE,IAAY,EAAE,OAAe,EAAE,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE;QAClE,IAAI,GAAG,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;YAAC,IAAI,CAAC,UAAU,EAAE,CAAC;YAAC,OAAO;QAAC,CAAC;QAC5D,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,UAAU,EAAE,IAAI,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,EAAE,OAAO,CAAC,CAAC;QAC1G,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC;QACpB,IAAI,CAAC,aAAa,GAAG,GAAG,GAAG,MAAM,CAAC;IACpC,CAAC;CACF"}
|
|
@@ -201,7 +201,17 @@ New viewer links use a `/preview/<short-token>?path=<absolute-path>` shape. Wind
|
|
|
201
201
|
|
|
202
202
|
`fileViewer` turns local non-image files and directories in final replies into signed, read-only HTTP links. The default `host: "127.0.0.1"` accepts connections only from the Agent Bot machine. With `0.0.0.0` or `::`, the server listens on every interface and automatically chooses a non-internal IPv4 link address in wired, Wi-Fi, other physical, then VPN order. Docker, Hyper-V, VMware, VirtualBox, WSL, loopback, and link-local interfaces are excluded; if no candidate remains, links fall back to loopback. `publicBaseUrl` has the highest priority and overrides automatic selection for domains, HTTPS reverse proxies, NAT, or port mappings. With `port: 0`, the first startup selects a free port and stores it in `<data>/file-viewer/port`; later restarts reuse it, while separate Profiles avoid a shared fixed port. The signing key is stored beside it as `secret`. File URLs can read only their signed absolute path. Directory URLs list direct children and allow downward navigation without exposing a parent-directory action. Text identity is detected from a content sample, and text pages preview the first 2 MiB with line anchors; images, PDFs, audio, and video use native browser previews; other binary files expose raw and download actions. Treat each signed URL as a bearer credential and do not share it publicly.
|
|
203
203
|
|
|
204
|
-
The same server provides signed Turn Preview URLs
|
|
204
|
+
The same server provides signed Turn Preview URLs. Complete execution records live beside SQLite in `turn-previews/<first two hash digits>/<SHA256(turnId)>.jsonl`, isolated by Profile. The two-digit hash buckets are created on demand (at most 256 directories); all reads and writes use this single layout. This is a presentation journal, never an agent/tool replay mechanism. Records are appended in 250 ms / 256 KiB batches; terminal states and safe shutdown flush, with fsync at critical boundaries. SQLite retains a bounded 80-activity card projection, routing/recovery metadata, Prompt, final response and the delivery ledger; ordinary writes coalesce over 750 ms. Full outputs/reasoning and unbounded timelines are excluded from new snapshots. Cumulative tool/progress/reasoning strings are fingerprinted and encoded as append or replacement records, avoiding duplicate streamed plus final output.
|
|
205
|
+
|
|
206
|
+
Preview reads byte-cursor batches and SSE sends changed activity summaries only. No viewer reads or rendering run when no page is open. Details load in full on expansion; up to four detail projections below 16 MiB are cached with a 60-second idle lifetime. Plain command output streams transfer suffixes; replacements and structured REPL results fall back to a full per-tool detail response. Terminal pages stop SSE; reconnects resume using Last-Event-ID. Incomplete final JSONL lines are ignored during reads and removed before appending after restart; malformed complete records or write failures are reported, not silently discarded. Legacy snapshots remain readable without a startup-wide migration or VACUUM. Existing database/WAL sizes do not automatically shrink. Back up SQLite and the journal directory together. Signed URLs remain Profile-specific bearer credentials governed by `fileViewer` reachability.
|
|
207
|
+
|
|
208
|
+
`/status` can generate a signed Preview link for an external Turn with no local snapshot. It records only the existing `turn_runtime_origins` locator; no session, chat binding, snapshot, or final-delivery record is created. The first signed page GET reads the selected Turn from its original runtime, using summary pagination plus that Turn’s full record; HEAD, detail and SSE requests do not initiate remote reads. Concurrent reads coalesce. Successful full details are stored only in the Preview journal; subsequent views reuse it. Metadata failures do not discard execution details, and current task model settings are not used to label historical execution. An Agent Bot snapshot arriving during the read takes precedence. Read failures return a retryable page without changing task state; unknown Turn IDs remain 404. This does not attach to externally running Turns.
|
|
209
|
+
|
|
210
|
+
Turn Preview uses the existing highlight.js dependency to highlight explicitly labelled Markdown fences server-side. It includes the common language set plus PowerShell, Dockerfile, and Windows batch, with `zsh` and `pwsh` aliases. Unknown languages, unlabelled blocks, parser failures, and blocks exceeding 64 KiB of UTF-8 source fall back to escaped, untruncated code. A 32-entry/1 MiB LRU cache avoids re-highlighting unchanged code on SSE snapshots. Colors are scoped to Markdown code blocks and follow the browser light/dark preference; Mermaid rendering and tool logs are unchanged.
|
|
211
|
+
|
|
212
|
+
Input attachments are stored as optional `promptImagePaths` on `TurnViewState` and `localImagePaths` on user activities, separate from bounded display text. Pending-Turn promotion, steering/reconciliation, queued starts, and snapshot recovery retain these paths. Preview resolves them through the existing signed file service with `raw=1`; missing files get a placeholder. The additive JSON fields require no database migration, and historical user activities without paths are not backfilled.
|
|
213
|
+
|
|
214
|
+
Turn Preview recognizes `mermaid` and `flowchart` fences in Prompt, Commentary, and answer Markdown. The browser lazy-loads the pinned Mermaid distribution from the same-origin `/assets/mermaid.js` endpoint (respecting `fileViewer.publicBaseUrl` prefixes), not a CDN. Strict security mode disables HTML labels and interactive callbacks; frontmatter/config directives and sources over 50,000 characters are rejected, and graphs are capped at 500 edges. Rendered SVG has active elements and external links removed; the existing viewer CSP remains unchanged. Each block defaults to Preview with width fitting, keeps its selected mode, fit/actual-size choice, and unchanged SVG across SSE updates, and shows escaped source when loading or rendering fails. SVG width is capped by both its viewBox width and its container width, preserving aspect ratio and avoiding enlargement. Narrow/touch screens cap the preview at 480 px or 55 svh (55 vh fallback); long diagrams scroll vertically. Actual size restores the viewBox width with block-local scrolling, while Fit resets the block scroll position. CSS sizing adapts to orientation changes without re-rendering Mermaid. Ordinary code blocks and tool output remain unchanged.
|
|
205
215
|
|
|
206
216
|
HTML text files (`.html` and `.htm`, case-insensitive) have preview/code modes. The preview iframe loads the signed file URL with `render=html`, streams the complete original document in its detected encoding, and carries a file-version query for live updates. Both the iframe and the response CSP use `sandbox allow-scripts` without `allow-same-origin`; the response sandbox also applies when the rendered URL is opened directly. Inline scripts/styles and embedded data/blob media are allowed, but external/local resource loading, network requests, forms, popups, and top-level navigation are not enabled. The outer viewer retains its own restrictive script policy, and raw/download responses are unchanged. Source remains escaped, syntax-highlighted where possible, limited to 2 MiB, and addressable with `#L<n>`.
|
|
207
217
|
|
|
@@ -211,6 +221,8 @@ HTML text files (`.html` and `.htm`, case-insensitive) have preview/code modes.
|
|
|
211
221
|
|
|
212
222
|
`/mute` and `/mute on` persist mention-only response mode for the current base group; `/mute off` disables it. The group timeline and every topic share this state. While muted, messages that do not mention the current bot are ignored before event claims, reactions, activity tracking, image downloads, command parsing, or Agent calls. The command that disables mute must itself mention the bot. Private chats do not support `/mute`.
|
|
213
223
|
|
|
224
|
+
Only groups explicitly enabled with `/mute` or `/mute on` supplement ordinary @-mention Prompts with recent human text and images. Topic requests read only that topic; ordinary group requests exclude topic messages. Reads are limited to two reverse-chronological pages of 30 messages, selecting up to 20 messages before the triggering mention, 16,000 text characters (2,000 per message), and six additional images, newest first. Bot messages, deleted messages, and later messages are excluded; non-image attachments and forwarded bundles are not expanded automatically. The original question remains the card Prompt. Included context is marked as reference data, not authorization. Successful submissions persist a bounded deduplication ledger scoped to the task, remote branch, and conversation. Scanning stops at the first message already submitted to that Agent conversation (either a direct Prompt or previously injected context): that message and all older messages are excluded, and no earlier page is requested. Queued-but-not-submitted context is deduplicated without becoming a stop boundary. `/mute off`, private chats, unmentioned messages, and slash/Shell commands do not trigger this read. Existing topic-root and explicit-reply handling remains unchanged. Reading requires the bot to have the relevant Feishu history/group-message/resource permissions; denied reads or image-download failures are reported without submitting an incomplete Prompt. This feature does not enable permissions automatically.
|
|
225
|
+
|
|
214
226
|
`feishu.groupNameFormat.project` and `projectless` control names created by NewGroup or ForkGroup for Project and Projectless tasks. Each template must contain exactly one `{taskname}` and may use these variables:
|
|
215
227
|
|
|
216
228
|
| Variable | Value |
|
|
@@ -295,6 +307,8 @@ Commands that can wait on App Server, Feishu, process control, or file transfer
|
|
|
295
307
|
|
|
296
308
|
Incoming Feishu rich-text `code_block` elements are converted to fenced Markdown with their language and original indentation preserved; `md` elements remain Markdown. The same conversion applies when rich-text messages are quoted or included in merged forwards. Rich-text images are downloaded into the inbound image cache and passed to the App Server as `localImage` inputs. An image-only message uses the default Prompt `请查看这张图片`. An ACP runtime that cannot accept image input returns an explicit error.
|
|
297
309
|
|
|
310
|
+
Reasoning Preview receives `item/reasoning/summaryTextDelta`, `item/reasoning/textDelta`, and authoritative `item/completed` reasoning arrays. Optional `TurnViewState.reasoningItems` stores complete summary/content sections separately, anchored to existing activity IDs; legacy `reasoning:*:<summaryIndex>` activities remain a summary fallback. Only summary deltas continue through the existing card progress path. Content and completion updates persist without scheduling card refreshes. Preview extracts the first explicit leading Markdown heading or standalone bold title into the disclosure header, removes only that title from the expanded text, and renders all supplied summary/content sections without field labels. Linked/image headings retain their original body markup to preserve navigation and attachments; untitled text remains intact. Heading detection parses only a candidate first line, not the full Markdown. Preview details use `reasoning:<itemId>` keys and revision-aware lazy loading. No database schema migration or remote history backfill is performed.
|
|
311
|
+
|
|
298
312
|
## Tasks, Projects, And External App Server Work
|
|
299
313
|
|
|
300
314
|
`/sessions` reads tasks through `thread/list` from every configured App Server Agent. For Codex, this includes tasks created by Codex Desktop, CLI, Agent Bot, or another App Server client under the same `CODEX_HOME`; other Agents expose their own task stores through the same protocol. Tasks are sorted globally before pagination: the current task first, then other active tasks, followed by idle tasks in descending last-activity order. The first ten global results determine page membership. Those visible tasks are then grouped by project in first-appearance order, with each project's tasks kept in descending activity order. Expanding a task directly shows the first 50 Unicode characters of its latest user Prompt without a field label, followed by its update time and action menu; runtime IDs, directory, loading state, and other status details remain in the dedicated Status view. `Previous` and `Next` replace the current card contents instead of appending more tasks, while preserving search terms and task numbers that match the displayed order.
|
|
@@ -395,6 +409,12 @@ The default target is `~/.agents/skills`. `AGENT_BOT_SKILLS_DIR` or `--target` s
|
|
|
395
409
|
|
|
396
410
|
## npm Package And Releases
|
|
397
411
|
|
|
412
|
+
### Manual update cards
|
|
413
|
+
|
|
414
|
+
`/update` queries npm `latest` and `alpha` concurrently with bounded responses/timeouts. Each channel fails independently; missing release notes fall back to the exact GitHub tag link. Only newer exact stable/Alpha SemVer values are selectable. Card-message-bound, owner-bound tokens expire after 30 minutes and are consumed together before preparation. Replayed, forwarded, expired, or non-owner selections cannot install a package. Manual and daily updates share a preparation guard and use a hidden child process for npm preparation; activation uses the existing safe-restart and rollback flow. The prepared plan persists the initiating chat/topic notification target for recovery. `updates.enabled` controls the daily monitor, not this explicit command.
|
|
415
|
+
|
|
416
|
+
|
|
417
|
+
|
|
398
418
|
The public package is `@keyou007/agent-bot`; its primary executable is `agentbot`. The deprecated `agent-bot` executable remains as a forwarding compatibility entry and prints a localized warning before each invocation. The package uses a `files` allowlist so runtime code, templates, the managed skill, source code, and user-facing documentation are published without tests or internal design plans.
|
|
399
419
|
|
|
400
420
|
`npm-shrinkwrap.json` is published with the CLI to keep transitive runtime dependencies reproducible. Direct runtime and development dependencies are also pinned to exact versions.
|
|
@@ -201,7 +201,17 @@ logging:
|
|
|
201
201
|
|
|
202
202
|
`fileViewer` 为最终回答中的本地非图片文件和目录生成带签名的只读 HTTP 链接。默认 `host: "127.0.0.1"`,只能从运行 Agent Bot 的机器访问。设为 `0.0.0.0` 或 `::` 时,服务会监听所有网卡,并从非内部 IPv4 地址中按有线、Wi-Fi、其他物理网卡、VPN 的顺序自动选择链接地址;Docker、Hyper-V、VMware、VirtualBox、WSL、回环和链路本地地址会被排除,没有候选地址时回退到本机环回地址。`publicBaseUrl` 的优先级最高,用于域名、HTTPS 反向代理、NAT 或端口映射。`port: 0` 会在第一次启动时选择空闲端口,并保存到 `<data>/file-viewer/port`,以后重启继续使用,同一机器上的多个 Profile 不会争用固定端口。签名密钥保存在同目录的 `secret` 文件中。文件 URL 只能读取签发时对应的绝对路径;目录 URL 会列出其直接子项并允许继续向下浏览,但不提供向父目录跳转。文本身份由内容采样识别,页面显示带行号的开头 2 MiB;图片、PDF、音视频使用浏览器原生预览,其他二进制文件提供原始打开和下载入口。签名 URL 是持有者凭证,不应公开分享。
|
|
203
203
|
|
|
204
|
-
|
|
204
|
+
Turn Preview 的完整执行记录保存在 SQLite 所在目录的 `turn-previews/<哈希前两位>/<SHA256(turnId)>.jsonl`,各 Profile 隔离。按需创建两位哈希子目录(最多 256 个),读写统一使用这一种目录布局。日志只用于展示,不会重放或重新执行 Agent/工具。普通记录按 250 ms 或 256 KiB 合并追加;完成、失败、取消和安全关闭会刷新,关键状态执行 fsync。SQLite 只保留最近 80 条有界卡片活动、路由和恢复信息、Prompt、最终回答及投递 ledger;普通更新合并为约 750 ms 一次。完整工具输出、思考和历史活动不再写回大快照。累计工具输出采用带指纹的追加/替换记录,避免 `A`、`B`、最终 `AB` 重复成 `ABAB`。
|
|
205
|
+
|
|
206
|
+
页面按字节游标分块读取日志,之后 SSE 只发送变化的活动摘要;没有打开页面时不运行 Preview 读取/渲染。折叠详情按需完整加载,小于 16 MiB 的详情投影最多缓存 4 个、空闲 60 秒释放。普通命令的流式输出按后缀传输;替换、REPL 结构化内容等回退为该工具的完整详情。终态页面停止订阅,重连使用 Last-Event-ID 游标接续。JSONL 不完整尾行读取时忽略,下次追加前截掉;完整行损坏或磁盘写失败会报错,不静默丢弃。旧快照继续支持,不在启动时迁移全库或 VACUUM;已有数据库/WAL 大小不会因此自动缩小。备份需包含数据库和 `turn-previews` 目录。签名 URL 仍是 Profile 级 bearer credential。
|
|
207
|
+
|
|
208
|
+
`/status` 可为尚无本地快照的外部轮次生成签名 Preview 链接,只保存已有的 `turn_runtime_origins` 定位信息,不创建任务、群绑定、快照或最终回复投递记录。首次签名页面 GET 从原 Agent 读取所选轮次,使用摘要分页和该轮完整记录;HEAD、详情及 SSE 请求不主动触发远端读取。并发读取合并,成功后的完整详情仅缓存到 Preview 日志,后续复用。任务元数据读取失败不丢弃执行详情,不以任务当前模型配置标记历史轮次。读取期间若出现真实 Agent Bot 快照,以该快照为准。失败页面支持刷新重试,不改变任务状态;未知轮次仍返回 404。这条路径不会接管外部正在执行的轮次。
|
|
209
|
+
|
|
210
|
+
Turn Preview 复用 highlight.js,在服务端高亮显式标注语言的 Markdown 代码块。支持常见语言集合,以及 PowerShell、Dockerfile、Windows batch 和 `zsh`、`pwsh` 别名。未标注、未知语言、解析失败或 UTF-8 源码超过 64 KiB 时回退到完整转义文本,不截断内容。32 项/1 MiB 的 LRU 缓存避免在 SSE 快照中重复高亮未变代码。配色仅作用于 Markdown 代码块并跟随系统浅色/深色偏好,Mermaid 渲染和工具日志保持不变。
|
|
211
|
+
|
|
212
|
+
输入附件路径分别保存在 `TurnViewState.promptImagePaths` 和用户活动的 `localImagePaths` 可选字段中,不混入受长度限制的文字。待启动轮次转为正式轮次、追加及重试、排队启动和快照恢复都会保留路径。Preview 通过现有签名文件服务加 `raw=1` 加载图片,文件缺失则显示占位提示。新增 JSON 字段不需要数据库迁移,也不会自动回填缺少路径的历史用户活动。
|
|
213
|
+
|
|
214
|
+
Turn Preview 支持在 Prompt、Commentary 和回答的 Markdown 中使用 `mermaid`、`flowchart` 代码块。浏览器按需从同源 `/assets/mermaid.js` 加载锁定版本的 Mermaid(支持 `fileViewer.publicBaseUrl` 路径前缀),不依赖 CDN。严格模式禁用 HTML 标签和交互回调;拒绝 frontmatter、配置指令和超过 50,000 字符的源码,最多 500 条边。生成的 SVG 还会移除可执行元素和外部链接,保留现有 CSP。图表块默认预览并按宽度适配,SSE 更新保留手动模式、「适应 / 原大」选择和未变化的 SVG;加载或渲染失败时显示转义后的源码。SVG 宽度不超过 viewBox 原宽度和容器宽度,保持比例且不放大小图。窄屏或触摸设备的预览高度最多为 480 px 或 55 svh(回退为 55 vh),长图纵向滚动;原大恢复 viewBox 宽度并在块内滚动,切回适应时重置块内滚动位置。CSS 自动适应横竖屏切换,无需重新渲染 Mermaid。普通代码块和工具输出保持不变。
|
|
205
215
|
|
|
206
216
|
HTML 文本文件(`.html`、`.htm`,不区分大小写)支持预览与代码模式。预览 iframe 使用带 `render=html` 的签名文件 URL,按检测到的编码流式加载完整原文,并携带文件版本参数用于实时刷新。iframe 与响应 CSP 都使用 `sandbox allow-scripts`,不授予 `allow-same-origin`;直接打开渲染 URL 时,响应级沙箱仍生效。允许内联脚本、样式及 data/blob 嵌入媒体,不开放外部或本地资源加载、网络请求、表单、弹窗和顶层跳转。外层页面保持原有脚本限制,原始文件与下载响应不变。源码仍经过转义、按需高亮,限制为开头 2 MiB,并支持 `#L<n>` 行号定位。
|
|
207
217
|
|
|
@@ -211,6 +221,8 @@ HTML 文本文件(`.html`、`.htm`,不区分大小写)支持预览与代
|
|
|
211
221
|
|
|
212
222
|
`/mute` 或 `/mute on` 会为当前基础群聊持久化仅 @ 响应模式,`/mute off` 会关闭。群正文及其所有话题共享该状态;静音期间未 @ 当前机器人的消息会在事件去重、reaction、活跃时间、图片下载、命令解析和 Agent 调用之前被忽略。关闭静音的命令本身也必须 @ 机器人。私聊不支持 `/mute`。
|
|
213
223
|
|
|
224
|
+
只有显式开启 `/mute` 或 `/mute on` 的群,普通 @ 提问才会自动补充近期成员文字和图片。话题内仅查询当前话题,普通群主会话排除其他话题消息。最多倒序读取 2 页、每页 30 条,从中选取本次 @ 之前最多 20 条消息;文字上限 16,000 字符、单条 2,000 字符,额外图片最多 6 张,优先最近内容。排除机器人、已删除及后续消息,不自动展开文件附件或合并转发。卡片 Prompt 保留原始提问,补充内容标记为参考资料而非操作授权。提交成功后按任务、远端分支和群/话题持久化有限的去重记录。从新到旧扫描,遇到第一条已提交给当前 Agent 会话的消息(普通提问或已补充的上下文)立即停止:不重复附带该消息,不提取更早内容,也不再请求更早一页。仅在队列中尚未提交的上下文只去重,不作为停止边界。`/mute off`、私聊、未 @ 消息、斜杠及 Shell 命令不触发补读;原有话题根消息和显式引用逻辑不变。机器人需要相应的飞书历史消息、群消息和资源权限;读取或图片下载失败会明确提示,不向 Agent 提交残缺请求,也不会自动开启权限。
|
|
225
|
+
|
|
214
226
|
`feishu.groupNameFormat.project` 和 `projectless` 分别控制 Project 与 Projectless 任务通过 NewGroup 或 ForkGroup 创建的群名。每个模板必须且只能包含一个 `{taskname}`,并可使用以下变量:
|
|
215
227
|
|
|
216
228
|
| 变量 | 内容 |
|
|
@@ -295,6 +307,8 @@ Fork 从未绑定过 Agent Bot 的任务前,Agent Bot 会先读取不含 Turns
|
|
|
295
307
|
|
|
296
308
|
接收飞书富文本时,`code_block` 节点会转换为带语言标记的 Markdown 代码块,并保留原始缩进;`md` 节点会继续保留 Markdown 格式。引用消息或合并转发中的富文本也使用相同转换。富文本图片会下载到输入图片缓存,并以 `localImage` 传给 App Server。纯图片消息使用默认 Prompt `请查看这张图片`。ACP Runtime 不支持图片输入时会明确报错。
|
|
297
309
|
|
|
310
|
+
思考 Preview 接收 `item/reasoning/summaryTextDelta`、`item/reasoning/textDelta` 和 `item/completed` 中的完整 reasoning 数组。可选的 `TurnViewState.reasoningItems` 独立保存完整摘要/正文及活动位置锚点,旧版 `reasoning:*:<summaryIndex>` 活动作为摘要回退。只有摘要 delta 继续进入原有卡片进度路径,正文和完成更新仅持久化、不触发卡片刷新。Preview 将首个明确的开头 Markdown 标题或独立加粗标题移到折叠栏,展开区只移除该标题,并直接呈现全部已有摘要/正文,不添加字段标签。带链接或图片的标题保留原有正文标记,避免丢失跳转或附件;无标题原文完整保留。标题识别只解析候选首行,不渲染全文。Preview 详情使用 `reasoning:<itemId>` 键和版本校验按需加载。不迁移数据库结构,也不自动回填远端历史。
|
|
311
|
+
|
|
298
312
|
## 任务、项目与外部 App Server 工作
|
|
299
313
|
|
|
300
314
|
`/sessions` 通过 `thread/list` 读取每个已配置 App Server Agent 的任务。对于 Codex,可发现同一 `CODEX_HOME` 下由 Codex Desktop、CLI、Agent Bot 或其他 App Server 客户端创建的任务;其他 Agent 通过同一协议暴露各自的任务存储。任务会在分页前进行全局排序:当前任务最优先,其次是其他活跃任务,其余任务按最后活跃时间倒序排列。全局前 10 个任务只用于确定当前页成员;展示时再按项目首次出现顺序聚拢,每个项目内部继续按活跃时间倒序。展开任务后会直接显示最后一个用户 Prompt 的前 50 个 Unicode 字符,不再显示字段标签,之后是更新时间和操作菜单;运行时任务 ID、目录、加载状态等详情统一留在专门的 Status 视图中。`Previous` 和 `Next` 会替换当前卡片内容而不是继续追加任务,同时保留搜索条件以及与展示顺序一致的任务序号。
|
|
@@ -395,6 +409,12 @@ agentbot skills uninstall
|
|
|
395
409
|
|
|
396
410
|
## npm 包与发布
|
|
397
411
|
|
|
412
|
+
### 手动更新卡片
|
|
413
|
+
|
|
414
|
+
`/update` 并发查询 npm 的 `latest` 与 `alpha`,限制响应大小和超时;两个渠道独立失败,简介读取失败时显示对应 GitHub tag 的日志链接。只允许更新到更高的正式版或 Alpha 精确版本。更新选择绑定卡片消息和所有者,30 分钟过期;准备更新前一次性消费该卡片的所有选择。拒绝重复、转发、过期和非所有者操作。手动更新与每日自动更新共享准备阶段互斥,在隐藏子进程中执行 npm 准备,激活复用安全重启与回滚。准备计划保存发起会话/话题通知目标,以便重启恢复。`updates.enabled` 仅控制每日检查,不控制此命令。
|
|
415
|
+
|
|
416
|
+
|
|
417
|
+
|
|
398
418
|
公开包名为 `@keyou007/agent-bot`,安装后的主命令为 `agentbot`。已弃用的 `agent-bot` 作为转发兼容入口暂时保留,每次调用前都会根据系统语言显示警告。包使用 `files` 白名单,只发布运行代码、模板、受管 Skill、源码和用户文档,不包含测试及内部设计计划。
|
|
399
419
|
|
|
400
420
|
CLI 随包发布 `npm-shrinkwrap.json`,以固定传递运行依赖;直接运行依赖和开发依赖也使用精确版本。
|