@keyou007/agent-bot 0.1.24-alpha.8 → 0.1.25-alpha.0
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 +28 -0
- package/README.md +12 -6
- package/README.zh.md +12 -6
- package/dist/codex/CodexRuntime.js +141 -21
- package/dist/codex/CodexRuntime.js.map +1 -1
- package/dist/codex/ProviderSwitch.js +1 -1
- package/dist/codex/ProviderSwitch.js.map +1 -1
- package/dist/feishu/CardRenderer.js +10 -6
- package/dist/feishu/CardRenderer.js.map +1 -1
- package/dist/feishu/FeishuConnector.js +10 -3
- package/dist/feishu/FeishuConnector.js.map +1 -1
- package/dist/feishu/MergedForwardMessage.js +14 -11
- package/dist/feishu/MergedForwardMessage.js.map +1 -1
- package/dist/local-files/TurnPreviewPage.js +26 -10
- package/dist/local-files/TurnPreviewPage.js.map +1 -1
- package/dist/presentation/visibleTurnActivities.js +13 -0
- package/dist/presentation/visibleTurnActivities.js.map +1 -0
- package/dist/proxy/ProxySessionController.js +169 -92
- package/dist/proxy/ProxySessionController.js.map +1 -1
- package/dist/runtime/responseErrors.js +60 -0
- package/dist/runtime/responseErrors.js.map +1 -0
- package/docs/technical-reference.md +12 -2
- package/docs/technical-reference.zh.md +12 -2
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
- package/skills/agent-bot/SKILL.md +5 -1
- package/src/codex/CodexRuntime.ts +139 -20
- package/src/codex/ProviderSwitch.ts +1 -1
- package/src/feishu/CardRenderer.ts +10 -5
- package/src/feishu/FeishuConnector.ts +10 -3
- package/src/feishu/MergedForwardMessage.ts +14 -11
- package/src/feishu/types.ts +3 -0
- package/src/local-files/TurnPreviewPage.ts +25 -10
- package/src/presentation/visibleTurnActivities.ts +12 -0
- package/src/proxy/ProxySessionController.ts +175 -105
- package/src/runtime/responseErrors.ts +62 -0
- package/src/runtime/types.ts +7 -1
|
@@ -105,6 +105,7 @@ export function renderMergedForwardPrompt(
|
|
|
105
105
|
|
|
106
106
|
const senderLabels = new Map<string, string>();
|
|
107
107
|
const imageNumbers = new Map<string, number>();
|
|
108
|
+
const fileNumbers = new Map<string, number>();
|
|
108
109
|
const images: MergedForwardImageReference[] = [];
|
|
109
110
|
const files: MergedForwardFileReference[] = [];
|
|
110
111
|
let userIndex = 0;
|
|
@@ -126,22 +127,24 @@ export function renderMergedForwardPrompt(
|
|
|
126
127
|
const time = formatMessageTime(item.create_time);
|
|
127
128
|
const heading = [`消息 ${index + 1}`, senderLabel, time].filter(Boolean).join(" · ");
|
|
128
129
|
return `[${heading}]\n${renderMessageContent(item, (imageKey) => {
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
const referenceKey = `${messageId}:${imageKey}`;
|
|
132
|
-
let imageNumber = imageNumbers.get(referenceKey);
|
|
130
|
+
if (!imageKey) return "[图片]";
|
|
131
|
+
let imageNumber = imageNumbers.get(imageKey);
|
|
133
132
|
if (!imageNumber) {
|
|
134
133
|
imageNumber = images.length + 1;
|
|
135
|
-
imageNumbers.set(
|
|
136
|
-
|
|
134
|
+
imageNumbers.set(imageKey, imageNumber);
|
|
135
|
+
// Forwarded resources belong to the container, not the listed child IDs.
|
|
136
|
+
images.push({ messageId: parentMessageId, imageKey });
|
|
137
137
|
}
|
|
138
138
|
return `[图片 ${imageNumber}]`;
|
|
139
139
|
}, (fileKey, fileName) => {
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
140
|
+
if (!fileKey) return namedPlaceholder("文件", fileName);
|
|
141
|
+
let fileNumber = fileNumbers.get(fileKey);
|
|
142
|
+
if (!fileNumber) {
|
|
143
|
+
fileNumber = files.length + 1;
|
|
144
|
+
fileNumbers.set(fileKey, fileNumber);
|
|
145
|
+
files.push({ messageId: parentMessageId, fileKey, fileName: fileName || `file-${fileNumber}` });
|
|
146
|
+
}
|
|
147
|
+
return `[文件 ${fileNumber}:${files[fileNumber - 1]!.fileName}]`;
|
|
145
148
|
})}`;
|
|
146
149
|
});
|
|
147
150
|
const prompt = [
|
package/src/feishu/types.ts
CHANGED
|
@@ -9,6 +9,9 @@ export interface IncomingMessage {
|
|
|
9
9
|
messageId: string;
|
|
10
10
|
messageType?: string;
|
|
11
11
|
createdAt?: number;
|
|
12
|
+
/** SDK callback time, not WebSocket frame arrival time. */
|
|
13
|
+
receivedAt?: number;
|
|
14
|
+
eventId?: string;
|
|
12
15
|
contextKey: string;
|
|
13
16
|
chatId?: string;
|
|
14
17
|
chatType?: "p2p" | "group";
|
|
@@ -8,6 +8,8 @@ import type { ApprovalRequest, ToolState } from "../runtime/types.js";
|
|
|
8
8
|
import type { FileSummary, TurnActivity, TurnReasoningItem, TurnViewState, TurnViewStatus } from "../presentation/turnViewTypes.js";
|
|
9
9
|
import { displayFilePath, displayToolCommand, formatShellCommandForDisplay, toolStatusIcon } from "../feishu/CardRenderer.js";
|
|
10
10
|
import { turnReasoningItems } from "../presentation/turnReasoning.js";
|
|
11
|
+
import { visibleTurnActivities } from "../presentation/visibleTurnActivities.js";
|
|
12
|
+
import { displayRuntimeError } from "../runtime/responseErrors.js";
|
|
11
13
|
import { isFileUrl, rewriteMarkdownFileLinks } from "./MarkdownFileLinks.js";
|
|
12
14
|
|
|
13
15
|
const MARKDOWN = new MarkdownIt({
|
|
@@ -285,6 +287,10 @@ export const TURN_PREVIEW_CLIENT_SCRIPT = DIAGRAM_PREVIEW_CLIENT_SCRIPT + `(() =
|
|
|
285
287
|
};
|
|
286
288
|
const compatible = (current, next) => current.nodeType === next.nodeType && current.nodeName === next.nodeName;
|
|
287
289
|
const patchNode = (current, next) => {
|
|
290
|
+
if (!compatible(current, next)) {
|
|
291
|
+
current.replaceWith(next.cloneNode(true));
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
288
294
|
// Summary snapshots never own a detail body that has already been fetched.
|
|
289
295
|
if (current.nodeType === 1 && current.hasAttribute("data-detail-body") && next.hasAttribute("data-detail-body")) return;
|
|
290
296
|
if (current.isEqualNode(next)) return;
|
|
@@ -620,16 +626,19 @@ export function renderTurnPreviewPatch(
|
|
|
620
626
|
state: TurnViewState, changed: Set<string>, removed: Set<string>,
|
|
621
627
|
localFileUrl: (filePath: string) => string | undefined, language: TurnPreviewLanguage,
|
|
622
628
|
): TurnPreviewSnapshot & { removed: string[]; before: Record<string, string> } {
|
|
629
|
+
const visible = visibleTurnActivities(state);
|
|
630
|
+
const visibleIds = new Set(visible.map((activity) => activity.id));
|
|
631
|
+
const suppressed = state.activities.filter((activity) => !visibleIds.has(activity.id)).map((activity) => activity.id);
|
|
623
632
|
const partial = { ...state,
|
|
624
|
-
activities:
|
|
633
|
+
activities: visible.filter((a) => changed.has(a.id)),
|
|
625
634
|
reasoningItems: state.reasoningItems?.filter((r) => changed.has(`reasoning:${r.itemId}`)),
|
|
626
635
|
};
|
|
627
636
|
const order = [
|
|
628
637
|
...(state.reasoningItems ?? []).filter((r) => !r.afterActivityId).map((r) => `reasoning:${r.itemId}`),
|
|
629
|
-
...
|
|
638
|
+
...visible.flatMap((a) => [a.id, ...(state.reasoningItems ?? []).filter((r) => r.afterActivityId === a.id).map((r) => `reasoning:${r.itemId}`)]),
|
|
630
639
|
];
|
|
631
640
|
const before = Object.fromEntries(order.flatMap((id, i) => changed.has(id) && order[i + 1] ? [[id, order[i + 1]]] : []));
|
|
632
|
-
return { ...renderTurnPreviewSnapshot(partial, localFileUrl, language, { deferDetails: true }), removed: [...removed], before };
|
|
641
|
+
return { ...renderTurnPreviewSnapshot(partial, localFileUrl, language, { deferDetails: true }), removed: [...new Set([...removed, ...suppressed])], before };
|
|
633
642
|
}
|
|
634
643
|
|
|
635
644
|
export function renderTurnPreviewSnapshot(
|
|
@@ -645,7 +654,7 @@ export function renderTurnPreviewSnapshot(
|
|
|
645
654
|
return localFileUrl(path.resolve(state.projectCwd, filePath));
|
|
646
655
|
} : undefined;
|
|
647
656
|
const renderText = (value: string): string => renderMarkdown(value, state.projectCwd, localFileUrl, language);
|
|
648
|
-
const timeline = renderTimeline(state, renderText, resolveFileUrl, state.fullToolOutputs, state.fullToolErrors, language, state.projectCwd, options.deferDetails);
|
|
657
|
+
const timeline = renderTimeline({ ...state, activities: visibleTurnActivities(state) }, renderText, resolveFileUrl, state.fullToolOutputs, state.fullToolErrors, language, state.projectCwd, options.deferDetails);
|
|
649
658
|
const terminal = isTerminal(state.status);
|
|
650
659
|
const waitingForProgress = !terminal && !state.finalResponse && !state.assistantText
|
|
651
660
|
&& !state.error && !state.approval && state.status !== "waiting_for_approval"
|
|
@@ -666,7 +675,7 @@ export function renderTurnPreviewSnapshot(
|
|
|
666
675
|
`<section class="timeline" data-preview-key="timeline"${timelineContent ? "" : " hidden"}>${timelineContent}</section>`,
|
|
667
676
|
state.fileSummary.length > 0 ? renderFileSummary(state, language, resolveFileUrl, options.deferDetails) : "",
|
|
668
677
|
state.approval ? renderApprovalNotice(state.approval, renderText, language) : "",
|
|
669
|
-
state.error ? `<section class="result error-result" data-preview-key="error"><h2>${escapeHtml(labels.error)}</h2><pre>${escapeHtml(state.error)}</pre></section>` : "",
|
|
678
|
+
state.error ? `<section class="result error-result" data-preview-key="error"><h2>${escapeHtml(labels.error)}</h2><pre>${escapeHtml(displayRuntimeError(state.error))}</pre></section>` : "",
|
|
670
679
|
state.finalResponse
|
|
671
680
|
? renderFinalAnswer(state.finalResponse, state.turnId, renderText, language)
|
|
672
681
|
: state.assistantText
|
|
@@ -792,8 +801,12 @@ function renderReasoningItem(
|
|
|
792
801
|
deferDetails: boolean,
|
|
793
802
|
): string {
|
|
794
803
|
const presentation = reasoningPresentation(item);
|
|
795
|
-
|
|
804
|
+
const hasBody = presentation.sections.some((section) => section.parts.length > 0);
|
|
805
|
+
if (!presentation.title && !hasBody) return "";
|
|
796
806
|
const title = presentation.title ?? previewLabels(language).reasoning;
|
|
807
|
+
if (!hasBody) {
|
|
808
|
+
return `<article class="reasoning-step" data-activity-id="reasoning:${escapeAttribute(item.itemId)}"><div class="reasoning-header" title="${escapeAttribute(title)}"><span class="reasoning-title">💭 ${escapeHtml(title)}</span></div></article>`;
|
|
809
|
+
}
|
|
797
810
|
const lazy = deferDetails ? lazyDetailAttributes(`reasoning:${item.itemId}`, reasoningRevision(item, cwd)) : "";
|
|
798
811
|
const body = deferDetails ? lazyDetailBody() : renderReasoningBody(item, cwd, localFileUrl, language, presentation);
|
|
799
812
|
return `<details class="reasoning-step" data-activity-id="reasoning:${escapeAttribute(item.itemId)}"${lazy}><summary class="reasoning-header" title="${escapeAttribute(title)}"><span class="reasoning-title">💭 ${escapeHtml(title)}</span></summary>${body}</details>`;
|
|
@@ -831,7 +844,7 @@ function renderActivity(
|
|
|
831
844
|
switch (activity.kind) {
|
|
832
845
|
case "assistant":
|
|
833
846
|
if (activity.id.startsWith("commentary:runtime-error:")) {
|
|
834
|
-
return `<article class="activity message runtime-error" data-activity="${escapeAttribute(activity.id)}"><pre>${escapeHtml(activity.text)}</pre></article>`;
|
|
847
|
+
return `<article class="activity message runtime-error" data-activity="${escapeAttribute(activity.id)}"><pre>${escapeHtml(displayRuntimeError(activity.text))}</pre></article>`;
|
|
835
848
|
}
|
|
836
849
|
return renderMessageActivity(activity.id, activity.text, "commentary", renderText);
|
|
837
850
|
case "user":
|
|
@@ -1163,9 +1176,11 @@ export function renderTurnPreviewDetail(
|
|
|
1163
1176
|
}
|
|
1164
1177
|
if (key.startsWith("reasoning:")) {
|
|
1165
1178
|
const item = turnReasoningItems(state).find((item) => `reasoning:${item.itemId}` === key);
|
|
1166
|
-
if (!item
|
|
1179
|
+
if (!item) return undefined;
|
|
1180
|
+
const presentation = reasoningPresentation(item);
|
|
1181
|
+
if (!presentation.sections.some((section) => section.parts.length > 0)) return undefined;
|
|
1167
1182
|
return { key, revision: reasoningRevision(item, state.projectCwd),
|
|
1168
|
-
content: renderReasoningBody(item, state.projectCwd, localFileUrl, language) };
|
|
1183
|
+
content: renderReasoningBody(item, state.projectCwd, localFileUrl, language, presentation) };
|
|
1169
1184
|
}
|
|
1170
1185
|
const activity = state.activities?.find((item) => item.kind === "tool" && `tool:${item.id}` === key);
|
|
1171
1186
|
if (activity?.kind !== "tool") return undefined;
|
|
@@ -1334,7 +1349,7 @@ main { max-width: 1320px; margin: 0 auto; padding: 0 20px 40px; }
|
|
|
1334
1349
|
.markdown > :first-child { margin-top: 0; }
|
|
1335
1350
|
.markdown > :last-child { margin-bottom: 0; }
|
|
1336
1351
|
.reasoning-step { margin:8px 0; border:1px solid var(--line); border-radius:7px; min-width:0; }
|
|
1337
|
-
.reasoning-header {
|
|
1352
|
+
.reasoning-header { display:flex; align-items:center; gap:8px; min-height:32px; padding:8px 10px; color:var(--muted); }
|
|
1338
1353
|
.reasoning-title { min-width:0; flex:1; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
|
|
1339
1354
|
.reasoning-section { margin:0 10px 10px; max-height:30em; overflow:auto; overflow-wrap:anywhere; }
|
|
1340
1355
|
.reasoning-part + .reasoning-part { border-top:1px solid var(--line); padding-top:8px; }
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { RUNTIME_WARNING_PREFIXES, sameRuntimeError } from "../runtime/responseErrors.js";
|
|
2
|
+
import type { TurnActivity, TurnViewState } from "./turnViewTypes.js";
|
|
3
|
+
|
|
4
|
+
export function visibleTurnActivities(state: TurnViewState): TurnActivity[] {
|
|
5
|
+
if (state.status !== "failed" || !state.error) return state.activities;
|
|
6
|
+
return state.activities.filter((activity) => {
|
|
7
|
+
if (activity.id !== `commentary:runtime-error:${state.turnId}`
|
|
8
|
+
|| (activity.kind !== "assistant" && activity.kind !== "reasoning")) return true;
|
|
9
|
+
const prefix = RUNTIME_WARNING_PREFIXES.find((value) => activity.text.startsWith(value));
|
|
10
|
+
return !sameRuntimeError(prefix ? activity.text.slice(prefix.length) : activity.text, state.error!);
|
|
11
|
+
});
|
|
12
|
+
}
|