@astralyn/pi 1.4.5 → 1.4.7
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 +42 -0
- package/dist/bundle/chunks/chunk-FODCTZXW.js +230 -0
- package/dist/bundle/chunks/{chunk-I5S7H7GA.js → chunk-FYKNSJG6.js} +1 -1
- package/dist/bundle/chunks/{chunk-AXFWZIHH.js → chunk-MG5XDTXV.js} +1 -1
- package/dist/bundle/chunks/{chunk-ALHAFUHP.js → chunk-PU2IWWXV.js} +1 -1
- package/dist/bundle/chunks/{chunk-5M3YJ54Z.js → chunk-RO2VH6UZ.js} +1 -1
- package/dist/bundle/chunks/chunk-YJTSOLP2.js +1499 -0
- package/dist/bundle/chunks/{cli-FH77R7JR.js → cli-MEL7SGJD.js} +1 -1
- package/dist/bundle/chunks/{execute-GMFGC27P.js → execute-4CWRNHPO.js} +1 -1
- package/dist/bundle/chunks/{runtime-R5CMHJ5P.js → runtime-R3X67XMR.js} +1 -1
- package/dist/bundle/chunks/{virtual-modules-6FUV7ZDV.js → virtual-modules-PKEOKGYI.js} +1 -1
- package/dist/bundle/cli.js +1 -1
- package/dist/bundle/index.js +1 -1
- package/dist/bundle/rpc-entry.js +1 -1
- package/dist/core/agent-session.d.ts +0 -3
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +0 -4
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/extensions/index.d.ts +1 -1
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/isolated-session.d.ts +23 -0
- package/dist/core/isolated-session.d.ts.map +1 -0
- package/dist/core/isolated-session.js +55 -0
- package/dist/core/isolated-session.js.map +1 -0
- package/dist/core/package-manager.d.ts +7 -1
- package/dist/core/package-manager.d.ts.map +1 -1
- package/dist/core/package-manager.js +72 -1
- package/dist/core/package-manager.js.map +1 -1
- package/dist/core/resource-loader.d.ts +1 -0
- package/dist/core/resource-loader.d.ts.map +1 -1
- package/dist/core/resource-loader.js +23 -7
- package/dist/core/resource-loader.js.map +1 -1
- package/dist/core/settings-manager.d.ts +4 -2
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +11 -0
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/settings-schema.d.ts +7 -0
- package/dist/core/settings-schema.d.ts.map +1 -1
- package/dist/core/settings-schema.js +6 -0
- package/dist/core/settings-schema.js.map +1 -1
- package/dist/core/skills.d.ts +10 -0
- package/dist/core/skills.d.ts.map +1 -1
- package/dist/core/skills.js +23 -0
- package/dist/core/skills.js.map +1 -1
- package/dist/core/tasks/codec.d.ts +12 -0
- package/dist/core/tasks/codec.d.ts.map +1 -0
- package/dist/core/tasks/codec.js +139 -0
- package/dist/core/tasks/codec.js.map +1 -0
- package/dist/core/tasks/delivery.d.ts +11 -4
- package/dist/core/tasks/delivery.d.ts.map +1 -1
- package/dist/core/tasks/delivery.js +9 -9
- package/dist/core/tasks/delivery.js.map +1 -1
- package/dist/core/tasks/execution.d.ts +71 -0
- package/dist/core/tasks/execution.d.ts.map +1 -0
- package/dist/core/tasks/execution.js +292 -0
- package/dist/core/tasks/execution.js.map +1 -0
- package/dist/core/tasks/format.d.ts +0 -2
- package/dist/core/tasks/format.d.ts.map +1 -1
- package/dist/core/tasks/format.js +1 -16
- package/dist/core/tasks/format.js.map +1 -1
- package/dist/core/tasks/limits.d.ts +12 -1
- package/dist/core/tasks/limits.d.ts.map +1 -1
- package/dist/core/tasks/limits.js +20 -1
- package/dist/core/tasks/limits.js.map +1 -1
- package/dist/core/tasks/output.d.ts +17 -17
- package/dist/core/tasks/output.d.ts.map +1 -1
- package/dist/core/tasks/output.js +72 -69
- package/dist/core/tasks/output.js.map +1 -1
- package/dist/core/tasks/presentation.d.ts +14 -5
- package/dist/core/tasks/presentation.d.ts.map +1 -1
- package/dist/core/tasks/presentation.js +56 -185
- package/dist/core/tasks/presentation.js.map +1 -1
- package/dist/core/tasks/record.d.ts +45 -0
- package/dist/core/tasks/record.d.ts.map +1 -0
- package/dist/core/tasks/record.js +80 -0
- package/dist/core/tasks/record.js.map +1 -0
- package/dist/core/tasks/runtime.d.ts +22 -22
- package/dist/core/tasks/runtime.d.ts.map +1 -1
- package/dist/core/tasks/runtime.js +170 -343
- package/dist/core/tasks/runtime.js.map +1 -1
- package/dist/core/tasks/scheduler.d.ts +16 -0
- package/dist/core/tasks/scheduler.d.ts.map +1 -0
- package/dist/core/tasks/scheduler.js +42 -0
- package/dist/core/tasks/scheduler.js.map +1 -0
- package/dist/core/tasks/session.d.ts +1 -1
- package/dist/core/tasks/session.d.ts.map +1 -1
- package/dist/core/tasks/session.js +22 -35
- package/dist/core/tasks/session.js.map +1 -1
- package/dist/core/tasks/store.d.ts +18 -25
- package/dist/core/tasks/store.d.ts.map +1 -1
- package/dist/core/tasks/store.js +45 -43
- package/dist/core/tasks/store.js.map +1 -1
- package/dist/core/tasks/types.d.ts +159 -70
- package/dist/core/tasks/types.d.ts.map +1 -1
- package/dist/core/tasks/types.js +3 -9
- package/dist/core/tasks/types.js.map +1 -1
- package/dist/core/tools/shell-execution.d.ts +8 -7
- package/dist/core/tools/shell-execution.d.ts.map +1 -1
- package/dist/core/tools/shell-execution.js +19 -27
- package/dist/core/tools/shell-execution.js.map +1 -1
- package/dist/core/tools/shell-tool.d.ts.map +1 -1
- package/dist/core/tools/shell-tool.js +42 -47
- package/dist/core/tools/shell-tool.js.map +1 -1
- package/dist/core/usage-totals.d.ts +4 -3
- package/dist/core/usage-totals.d.ts.map +1 -1
- package/dist/core/usage-totals.js +32 -8
- package/dist/core/usage-totals.js.map +1 -1
- package/dist/extensions/agent/activity.d.ts +4 -4
- package/dist/extensions/agent/activity.d.ts.map +1 -1
- package/dist/extensions/agent/activity.js +15 -24
- package/dist/extensions/agent/activity.js.map +1 -1
- package/dist/extensions/agent/index.d.ts +2 -11
- package/dist/extensions/agent/index.d.ts.map +1 -1
- package/dist/extensions/agent/index.js +3 -88
- package/dist/extensions/agent/index.js.map +1 -1
- package/dist/extensions/agent/progress.d.ts +31 -0
- package/dist/extensions/agent/progress.d.ts.map +1 -0
- package/dist/extensions/agent/progress.js +135 -0
- package/dist/extensions/agent/progress.js.map +1 -0
- package/dist/extensions/agent/render.d.ts.map +1 -1
- package/dist/extensions/agent/render.js +8 -17
- package/dist/extensions/agent/render.js.map +1 -1
- package/dist/extensions/agent/report.d.ts +9 -0
- package/dist/extensions/agent/report.d.ts.map +1 -0
- package/dist/extensions/agent/report.js +40 -0
- package/dist/extensions/agent/report.js.map +1 -0
- package/dist/extensions/agent/settings-panel.d.ts +43 -0
- package/dist/extensions/agent/settings-panel.d.ts.map +1 -0
- package/dist/extensions/agent/settings-panel.js +125 -0
- package/dist/extensions/agent/settings-panel.js.map +1 -0
- package/dist/extensions/agent/settings.d.ts +1 -1
- package/dist/extensions/agent/settings.d.ts.map +1 -1
- package/dist/extensions/agent/settings.js +101 -83
- package/dist/extensions/agent/settings.js.map +1 -1
- package/dist/extensions/agent/tool.d.ts +13 -0
- package/dist/extensions/agent/tool.d.ts.map +1 -0
- package/dist/extensions/agent/tool.js +88 -0
- package/dist/extensions/agent/tool.js.map +1 -0
- package/dist/extensions/agent/types.d.ts +19 -21
- package/dist/extensions/agent/types.d.ts.map +1 -1
- package/dist/extensions/agent/types.js +2 -10
- package/dist/extensions/agent/types.js.map +1 -1
- package/dist/extensions/agent/worker.d.ts +16 -0
- package/dist/extensions/agent/worker.d.ts.map +1 -0
- package/dist/extensions/agent/worker.js +66 -0
- package/dist/extensions/agent/worker.js.map +1 -0
- package/dist/extensions/btw/agent.d.ts +1 -1
- package/dist/extensions/btw/agent.d.ts.map +1 -1
- package/dist/extensions/btw/agent.js +3 -20
- package/dist/extensions/btw/agent.js.map +1 -1
- package/dist/extensions/cached-compaction/index.d.ts.map +1 -1
- package/dist/extensions/cached-compaction/index.js +3 -22
- package/dist/extensions/cached-compaction/index.js.map +1 -1
- package/dist/extensions/cached-compaction/render.d.ts +1 -0
- package/dist/extensions/cached-compaction/render.d.ts.map +1 -1
- package/dist/extensions/cached-compaction/render.js +42 -14
- package/dist/extensions/cached-compaction/render.js.map +1 -1
- package/dist/extensions/deepwiki/client.d.ts.map +1 -1
- package/dist/extensions/deepwiki/client.js +6 -78
- package/dist/extensions/deepwiki/client.js.map +1 -1
- package/dist/extensions/deepwiki/transport.d.ts +3 -0
- package/dist/extensions/deepwiki/transport.d.ts.map +1 -0
- package/dist/extensions/deepwiki/transport.js +96 -0
- package/dist/extensions/deepwiki/transport.js.map +1 -0
- package/dist/extensions/provider/ui/builtin-data.d.ts +3 -3
- package/dist/extensions/provider/ui/builtin-data.d.ts.map +1 -1
- package/dist/extensions/provider/ui/builtin-data.js.map +1 -1
- package/dist/extensions/provider/ui/compat.d.ts +3 -3
- package/dist/extensions/provider/ui/compat.d.ts.map +1 -1
- package/dist/extensions/provider/ui/compat.js.map +1 -1
- package/dist/extensions/provider/ui/controls.d.ts +2 -2
- package/dist/extensions/provider/ui/controls.d.ts.map +1 -1
- package/dist/extensions/provider/ui/controls.js.map +1 -1
- package/dist/extensions/provider/ui/dialogs.d.ts +3 -3
- package/dist/extensions/provider/ui/dialogs.d.ts.map +1 -1
- package/dist/extensions/provider/ui/dialogs.js.map +1 -1
- package/dist/extensions/provider/ui/dictionary.d.ts +2 -2
- package/dist/extensions/provider/ui/dictionary.d.ts.map +1 -1
- package/dist/extensions/provider/ui/dictionary.js.map +1 -1
- package/dist/extensions/provider/ui/editor.d.ts.map +1 -1
- package/dist/extensions/provider/ui/editor.js +1 -3
- package/dist/extensions/provider/ui/editor.js.map +1 -1
- package/dist/extensions/provider/ui/fetch-models.d.ts +2 -2
- package/dist/extensions/provider/ui/fetch-models.d.ts.map +1 -1
- package/dist/extensions/provider/ui/fetch-models.js.map +1 -1
- package/dist/extensions/provider/ui/model-fields.d.ts +2 -2
- package/dist/extensions/provider/ui/model-fields.d.ts.map +1 -1
- package/dist/extensions/provider/ui/model-fields.js.map +1 -1
- package/dist/extensions/provider/ui/model-options.d.ts +6 -6
- package/dist/extensions/provider/ui/model-options.d.ts.map +1 -1
- package/dist/extensions/provider/ui/model-options.js.map +1 -1
- package/dist/extensions/provider/ui/pane.d.ts +21 -12
- package/dist/extensions/provider/ui/pane.d.ts.map +1 -1
- package/dist/extensions/provider/ui/pane.js.map +1 -1
- package/dist/extensions/provider/ui/provider-fields.d.ts +3 -3
- package/dist/extensions/provider/ui/provider-fields.d.ts.map +1 -1
- package/dist/extensions/provider/ui/provider-fields.js.map +1 -1
- package/dist/extensions/provider/ui/thinking-map.d.ts +2 -2
- package/dist/extensions/provider/ui/thinking-map.d.ts.map +1 -1
- package/dist/extensions/provider/ui/thinking-map.js.map +1 -1
- package/dist/extensions/run-summary/format.js +1 -1
- package/dist/extensions/run-summary/format.js.map +1 -1
- package/dist/extensions/statusline/usage.d.ts.map +1 -1
- package/dist/extensions/statusline/usage.js +2 -6
- package/dist/extensions/statusline/usage.js.map +1 -1
- package/dist/extensions/tasks/tool/actions.d.ts +1 -1
- package/dist/extensions/tasks/tool/actions.d.ts.map +1 -1
- package/dist/extensions/tasks/tool/actions.js +50 -115
- package/dist/extensions/tasks/tool/actions.js.map +1 -1
- package/dist/extensions/tasks/tool/constants.d.ts +1 -6
- package/dist/extensions/tasks/tool/constants.d.ts.map +1 -1
- package/dist/extensions/tasks/tool/constants.js +1 -6
- package/dist/extensions/tasks/tool/constants.js.map +1 -1
- package/dist/extensions/tasks/tool/schema.d.ts +0 -3
- package/dist/extensions/tasks/tool/schema.d.ts.map +1 -1
- package/dist/extensions/tasks/tool/schema.js +5 -14
- package/dist/extensions/tasks/tool/schema.js.map +1 -1
- package/dist/extensions/tasks/tool/types.d.ts +2 -8
- package/dist/extensions/tasks/tool/types.d.ts.map +1 -1
- package/dist/extensions/tasks/tool/types.js +0 -2
- package/dist/extensions/tasks/tool/types.js.map +1 -1
- package/dist/extensions/tasks/tool.d.ts.map +1 -1
- package/dist/extensions/tasks/tool.js +2 -2
- package/dist/extensions/tasks/tool.js.map +1 -1
- package/dist/extensions/tasks/ui/completion-render.d.ts.map +1 -1
- package/dist/extensions/tasks/ui/completion-render.js +46 -47
- package/dist/extensions/tasks/ui/completion-render.js.map +1 -1
- package/dist/extensions/tasks/ui/inspector.d.ts +5 -3
- package/dist/extensions/tasks/ui/inspector.d.ts.map +1 -1
- package/dist/extensions/tasks/ui/inspector.js +18 -6
- package/dist/extensions/tasks/ui/inspector.js.map +1 -1
- package/dist/extensions/tasks/ui/layout.d.ts +7 -7
- package/dist/extensions/tasks/ui/layout.d.ts.map +1 -1
- package/dist/extensions/tasks/ui/layout.js +118 -84
- package/dist/extensions/tasks/ui/layout.js.map +1 -1
- package/dist/extensions/tasks/ui/list.d.ts.map +1 -1
- package/dist/extensions/tasks/ui/list.js +45 -31
- package/dist/extensions/tasks/ui/list.js.map +1 -1
- package/dist/extensions/tasks/ui/manager.d.ts +16 -7
- package/dist/extensions/tasks/ui/manager.d.ts.map +1 -1
- package/dist/extensions/tasks/ui/manager.js +167 -129
- package/dist/extensions/tasks/ui/manager.js.map +1 -1
- package/dist/extensions/tasks/ui/model.d.ts +29 -0
- package/dist/extensions/tasks/ui/model.d.ts.map +1 -1
- package/dist/extensions/tasks/ui/model.js +16 -1
- package/dist/extensions/tasks/ui/model.js.map +1 -1
- package/dist/extensions/tasks/ui/render.d.ts +1 -1
- package/dist/extensions/tasks/ui/render.d.ts.map +1 -1
- package/dist/extensions/tasks/ui/render.js +12 -9
- package/dist/extensions/tasks/ui/render.js.map +1 -1
- package/dist/extensions/tasks/ui/status.d.ts +15 -0
- package/dist/extensions/tasks/ui/status.d.ts.map +1 -0
- package/dist/extensions/tasks/ui/status.js +16 -0
- package/dist/extensions/tasks/ui/status.js.map +1 -0
- package/dist/extensions/tasks/ui/tree.js +1 -1
- package/dist/extensions/tasks/ui/tree.js.map +1 -1
- package/dist/extensions/tasks/ui/views.d.ts +10 -5
- package/dist/extensions/tasks/ui/views.d.ts.map +1 -1
- package/dist/extensions/tasks/ui/views.js +61 -36
- package/dist/extensions/tasks/ui/views.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/modes/interactive/components/config-selector.d.ts +14 -1
- package/dist/modes/interactive/components/config-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/config-selector.js +258 -7
- package/dist/modes/interactive/components/config-selector.js.map +1 -1
- package/dist/modes/interactive/components/keybinding-hints.d.ts.map +1 -1
- package/dist/modes/interactive/components/keybinding-hints.js +2 -1
- package/dist/modes/interactive/components/keybinding-hints.js.map +1 -1
- package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/model-selector.js +7 -4
- package/dist/modes/interactive/components/model-selector.js.map +1 -1
- package/dist/modes/interactive/components/status-marker.d.ts +2 -1
- package/dist/modes/interactive/components/status-marker.d.ts.map +1 -1
- package/dist/modes/interactive/components/status-marker.js +0 -1
- package/dist/modes/interactive/components/status-marker.js.map +1 -1
- package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/thinking-selector.js +10 -3
- package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +7 -1
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/utils/duration.d.ts +3 -0
- package/dist/utils/duration.d.ts.map +1 -0
- package/dist/utils/duration.js +17 -0
- package/dist/utils/duration.js.map +1 -0
- package/dist/utils/number.d.ts +3 -0
- package/dist/utils/number.d.ts.map +1 -0
- package/dist/utils/number.js +5 -0
- package/dist/utils/number.js.map +1 -0
- package/docs/bundled/extensions/agent.md +14 -12
- package/docs/bundled/extensions/cached-compaction.md +13 -4
- package/docs/bundled/extensions/deepwiki.md +3 -1
- package/docs/bundled/extensions/statusline.md +1 -1
- package/docs/bundled/tasks.md +15 -14
- package/docs/extensions.md +26 -10
- package/docs/packages.md +5 -3
- package/docs/sdk.md +3 -3
- package/docs/session-format.md +28 -24
- package/docs/settings.md +11 -0
- package/docs/skills.md +23 -0
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
- package/schemas/settings.schema.json +36 -0
- package/dist/bundle/chunks/chunk-FSJ45CRP.js +0 -229
- package/dist/bundle/chunks/chunk-W3FIUMGM.js +0 -1501
- package/dist/core/tasks/history.d.ts +0 -4
- package/dist/core/tasks/history.d.ts.map +0 -1
- package/dist/core/tasks/history.js +0 -131
- package/dist/core/tasks/history.js.map +0 -1
- package/dist/extensions/agent/runner.d.ts +0 -24
- package/dist/extensions/agent/runner.d.ts.map +0 -1
- package/dist/extensions/agent/runner.js +0 -274
- package/dist/extensions/agent/runner.js.map +0 -1
- package/dist/extensions/deepwiki/http.d.ts +0 -13
- package/dist/extensions/deepwiki/http.d.ts.map +0 -1
- package/dist/extensions/deepwiki/http.js +0 -88
- package/dist/extensions/deepwiki/http.js.map +0 -1
- package/dist/extensions/tasks/ui/task-view.d.ts +0 -13
- package/dist/extensions/tasks/ui/task-view.d.ts.map +0 -1
- package/dist/extensions/tasks/ui/task-view.js +0 -20
- package/dist/extensions/tasks/ui/task-view.js.map +0 -1
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { createIsolatedSession } from "../../core/isolated-session.js";
|
|
2
|
+
import { clipText } from "./activity.js";
|
|
3
|
+
import { AgentProgress, finalAssistantText } from "./progress.js";
|
|
4
|
+
import { finalReport } from "./report.js";
|
|
5
|
+
const WORKER_TOOLS = ["read", "bash", "edit", "write"];
|
|
6
|
+
function workerPrompt(base) {
|
|
7
|
+
return [
|
|
8
|
+
base,
|
|
9
|
+
"You are an Agent completing one delegated task in an isolated session. The first user message is the complete briefing from your caller. You cannot see the caller's conversation or ask it questions. If the briefing is ambiguous, choose a reasonable interpretation within scope and report it; stop only when ambiguity blocks meaningful progress.",
|
|
10
|
+
"Use the assigned working directory and stay within the requested scope. Complete the task fully without expanding it. If the briefing asks only for investigation, do not modify files. Use read for known paths and bash for discovery, search, and shell commands. Prefer editing existing files; create new files only when the task requires them, and never create documentation or report files unless explicitly requested. Do not delegate or start background work. Run required commands in the foreground and wait for them.",
|
|
11
|
+
"Your final message is the only output returned to the caller. Lead with the outcome, then include essential findings, files changed if any, verification actually run and its result, and blockers or remaining risks. Cite workspace-relative paths with line numbers when useful. Respect any length limit in the briefing and omit process narration.",
|
|
12
|
+
]
|
|
13
|
+
.filter((part) => Boolean(part?.trim()))
|
|
14
|
+
.join("\n\n");
|
|
15
|
+
}
|
|
16
|
+
/** Run one delegated task in an isolated session and settle it with a self-contained report. */
|
|
17
|
+
export async function runWorker(control, request) {
|
|
18
|
+
const { signal } = control;
|
|
19
|
+
const progress = new AgentProgress(control);
|
|
20
|
+
let session;
|
|
21
|
+
let unsubscribe;
|
|
22
|
+
const abort = () => {
|
|
23
|
+
void session?.abort().catch(() => { });
|
|
24
|
+
};
|
|
25
|
+
signal.addEventListener("abort", abort, { once: true });
|
|
26
|
+
try {
|
|
27
|
+
session = await createIsolatedSession({
|
|
28
|
+
cwd: request.cwd,
|
|
29
|
+
model: request.model,
|
|
30
|
+
thinkingLevel: request.thinking,
|
|
31
|
+
modelRuntime: request.modelRuntime,
|
|
32
|
+
projectTrusted: request.projectTrusted,
|
|
33
|
+
systemPrompt: workerPrompt,
|
|
34
|
+
tools: WORKER_TOOLS,
|
|
35
|
+
signal,
|
|
36
|
+
});
|
|
37
|
+
const worker = session;
|
|
38
|
+
unsubscribe = worker.subscribe((event) => {
|
|
39
|
+
// Cancellation during prompt preflight can precede the run's own abort controller.
|
|
40
|
+
if (event.type === "agent_start" && signal.aborted)
|
|
41
|
+
abort();
|
|
42
|
+
else
|
|
43
|
+
progress.handle(event);
|
|
44
|
+
});
|
|
45
|
+
progress.publish();
|
|
46
|
+
control.accept();
|
|
47
|
+
signal.throwIfAborted();
|
|
48
|
+
await worker.prompt(request.prompt, { expandPromptTemplates: false });
|
|
49
|
+
const { status, error } = progress.outcome();
|
|
50
|
+
return progress.complete(status, error, await finalReport(control, finalAssistantText(worker.messages), error));
|
|
51
|
+
}
|
|
52
|
+
catch (error) {
|
|
53
|
+
const status = signal.aborted ? "cancelled" : "failed";
|
|
54
|
+
const reason = status === "cancelled"
|
|
55
|
+
? "Agent cancelled."
|
|
56
|
+
: clipText(error instanceof Error ? error.message : String(error), 4096);
|
|
57
|
+
const report = session ? finalAssistantText(session.messages) : "";
|
|
58
|
+
return progress.complete(status, reason, await finalReport(control, report, reason));
|
|
59
|
+
}
|
|
60
|
+
finally {
|
|
61
|
+
signal.removeEventListener("abort", abort);
|
|
62
|
+
unsubscribe?.();
|
|
63
|
+
session?.dispose();
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=worker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worker.js","sourceRoot":"","sources":["../../../src/extensions/agent/worker.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ThinkingLevel } from \"@earendil-works/pi-agent-core\";\nimport type { Model } from \"@earendil-works/pi-ai/compat\";\nimport type { AgentSession } from \"../../core/agent-session.ts\";\nimport { createIsolatedSession } from \"../../core/isolated-session.ts\";\nimport type { ModelRuntime } from \"../../core/model-runtime.ts\";\nimport type { TaskCompletion, TaskControl } from \"../../core/tasks/types.ts\";\nimport { clipText } from \"./activity.ts\";\nimport { AgentProgress, finalAssistantText } from \"./progress.ts\";\nimport { finalReport } from \"./report.ts\";\nimport type { AgentToolDetails } from \"./types.ts\";\n\nconst WORKER_TOOLS = [\"read\", \"bash\", \"edit\", \"write\"];\n\nexport interface AgentRequest {\n\tprompt: string;\n\tcwd: string;\n\tmodel: Model<any>;\n\tthinking: ThinkingLevel;\n\tmodelRuntime: ModelRuntime;\n\tprojectTrusted: boolean;\n}\n\nfunction workerPrompt(base: string | undefined): string {\n\treturn [\n\t\tbase,\n\t\t\"You are an Agent completing one delegated task in an isolated session. The first user message is the complete briefing from your caller. You cannot see the caller's conversation or ask it questions. If the briefing is ambiguous, choose a reasonable interpretation within scope and report it; stop only when ambiguity blocks meaningful progress.\",\n\t\t\"Use the assigned working directory and stay within the requested scope. Complete the task fully without expanding it. If the briefing asks only for investigation, do not modify files. Use read for known paths and bash for discovery, search, and shell commands. Prefer editing existing files; create new files only when the task requires them, and never create documentation or report files unless explicitly requested. Do not delegate or start background work. Run required commands in the foreground and wait for them.\",\n\t\t\"Your final message is the only output returned to the caller. Lead with the outcome, then include essential findings, files changed if any, verification actually run and its result, and blockers or remaining risks. Cite workspace-relative paths with line numbers when useful. Respect any length limit in the briefing and omit process narration.\",\n\t]\n\t\t.filter((part): part is string => Boolean(part?.trim()))\n\t\t.join(\"\\n\\n\");\n}\n\n/** Run one delegated task in an isolated session and settle it with a self-contained report. */\nexport async function runWorker(\n\tcontrol: TaskControl<AgentToolDetails>,\n\trequest: AgentRequest,\n): Promise<TaskCompletion<AgentToolDetails>> {\n\tconst { signal } = control;\n\tconst progress = new AgentProgress(control);\n\tlet session: AgentSession | undefined;\n\tlet unsubscribe: (() => void) | undefined;\n\tconst abort = () => {\n\t\tvoid session?.abort().catch(() => {});\n\t};\n\tsignal.addEventListener(\"abort\", abort, { once: true });\n\ttry {\n\t\tsession = await createIsolatedSession({\n\t\t\tcwd: request.cwd,\n\t\t\tmodel: request.model,\n\t\t\tthinkingLevel: request.thinking,\n\t\t\tmodelRuntime: request.modelRuntime,\n\t\t\tprojectTrusted: request.projectTrusted,\n\t\t\tsystemPrompt: workerPrompt,\n\t\t\ttools: WORKER_TOOLS,\n\t\t\tsignal,\n\t\t});\n\t\tconst worker = session;\n\t\tunsubscribe = worker.subscribe((event) => {\n\t\t\t// Cancellation during prompt preflight can precede the run's own abort controller.\n\t\t\tif (event.type === \"agent_start\" && signal.aborted) abort();\n\t\t\telse progress.handle(event);\n\t\t});\n\t\tprogress.publish();\n\t\tcontrol.accept();\n\t\tsignal.throwIfAborted();\n\t\tawait worker.prompt(request.prompt, { expandPromptTemplates: false });\n\t\tconst { status, error } = progress.outcome();\n\t\treturn progress.complete(status, error, await finalReport(control, finalAssistantText(worker.messages), error));\n\t} catch (error) {\n\t\tconst status = signal.aborted ? \"cancelled\" : \"failed\";\n\t\tconst reason =\n\t\t\tstatus === \"cancelled\"\n\t\t\t\t? \"Agent cancelled.\"\n\t\t\t\t: clipText(error instanceof Error ? error.message : String(error), 4096);\n\t\tconst report = session ? finalAssistantText(session.messages) : \"\";\n\t\treturn progress.complete(status, reason, await finalReport(control, report, reason));\n\t} finally {\n\t\tsignal.removeEventListener(\"abort\", abort);\n\t\tunsubscribe?.();\n\t\tsession?.dispose();\n\t}\n}\n"]}
|
|
@@ -20,7 +20,7 @@ export interface BtwConversationState {
|
|
|
20
20
|
/** An in-memory native Agent. No SessionManager, real tool executors, or main-agent signal. */
|
|
21
21
|
export declare class BtwAgent implements BtwConversationState {
|
|
22
22
|
readonly turns: BtwTurn[];
|
|
23
|
-
|
|
23
|
+
usage: Usage;
|
|
24
24
|
latestCacheHitPercent: number | undefined;
|
|
25
25
|
blockedTools: number;
|
|
26
26
|
private readonly agent;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../../src/extensions/btw/agent.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAA6B,MAAM,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAGtF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;
|
|
1
|
+
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../../src/extensions/btw/agent.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAA6B,MAAM,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAGtF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AAatE,MAAM,WAAW,OAAO;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,WAAW,GAAG,YAAY,GAAG,MAAM,GAAG,WAAW,GAAG,OAAO,CAAC;IACpE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,oBAAoB;IACpC,IAAI,EAAE,OAAO,CAAC;IACd,KAAK,EAAE,SAAS,OAAO,EAAE,CAAC;IAC1B,KAAK,EAAE,KAAK,CAAC;IACb,qBAAqB,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1C,YAAY,EAAE,MAAM,CAAC;CACrB;AAaD,+FAA+F;AAC/F,qBAAa,QAAS,YAAW,oBAAoB;IACpD,QAAQ,CAAC,KAAK,EAAE,OAAO,EAAE,CAAM;IAC/B,KAAK,QAAgB;IACrB,qBAAqB,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1C,YAAY,SAAK;IACjB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAQ;IAC9B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAa;IACzC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAa;IACtC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,MAAM,CAAC,CAAiB;IAChC,OAAO,CAAC,QAAQ,CAAS;gBAEb,QAAQ,EAAE,eAAe,EAAE,OAAO,EAAE,IAAI,CAAC,MAAM,EAAE,cAAc,CAAC,EAAE,QAAQ,EAAE,MAAM,IAAI;IAyDlG,IAAI,IAAI,IAAI,OAAO,CAElB;IAED,OAAO,CAAC,QAAQ;IAahB,oGAAoG;IACpG,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG;QAAE,UAAU,EAAE,OAAO,CAAC,IAAI,CAAC,CAAA;KAAE;YAqBhE,WAAW;IAsBzB,MAAM,IAAI,IAAI;IAOd,OAAO,IAAI,IAAI;IAUf,OAAO,CAAC,IAAI;IAeZ,OAAO,CAAC,WAAW;IAsCnB,OAAO,CAAC,YAAY;CAkBpB"}
|
|
@@ -1,18 +1,9 @@
|
|
|
1
1
|
import { Agent, } from "@earendil-works/pi-agent-core";
|
|
2
2
|
import { normalizeContext } from "@earendil-works/pi-ai";
|
|
3
3
|
import { estimateContextTokens } from "@earendil-works/pi-ai/utils/estimate";
|
|
4
|
+
import { cacheHitPercent, combineUsage, emptyUsage } from "../../core/usage-totals.js";
|
|
4
5
|
import { MAX_DISPLAY_CHARS, MAX_MODEL_STEPS, MAX_OUTPUT_RESERVE_TOKENS, MAX_QUESTION_CHARS, MAX_QUESTIONS, MAX_RESPONSE_CHARS, TOOL_DENIAL, } from "./constants.js";
|
|
5
6
|
import { createBtwMessages } from "./snapshot.js";
|
|
6
|
-
function emptyUsage() {
|
|
7
|
-
return {
|
|
8
|
-
input: 0,
|
|
9
|
-
output: 0,
|
|
10
|
-
cacheRead: 0,
|
|
11
|
-
cacheWrite: 0,
|
|
12
|
-
totalTokens: 0,
|
|
13
|
-
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
|
|
14
|
-
};
|
|
15
|
-
}
|
|
16
7
|
function displayText(text) {
|
|
17
8
|
return text.length <= MAX_DISPLAY_CHARS ? text : `${text.slice(0, MAX_DISPLAY_CHARS)}\n\n[Display truncated]`;
|
|
18
9
|
}
|
|
@@ -186,16 +177,8 @@ export class BtwAgent {
|
|
|
186
177
|
? part.thinking.length
|
|
187
178
|
: JSON.stringify(part.arguments).length), 0);
|
|
188
179
|
this.blockedTools += message.content.filter((part) => part.type === "toolCall").length;
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
this.latestCacheHitPercent =
|
|
192
|
-
(usage.cacheRead > 0 || usage.cacheWrite > 0) && promptTokens > 0
|
|
193
|
-
? (usage.cacheRead / promptTokens) * 100
|
|
194
|
-
: undefined;
|
|
195
|
-
for (const key of ["input", "output", "cacheRead", "cacheWrite", "totalTokens"])
|
|
196
|
-
this.usage[key] += usage[key];
|
|
197
|
-
for (const key of ["input", "output", "cacheRead", "cacheWrite", "total"])
|
|
198
|
-
this.usage.cost[key] += usage.cost[key];
|
|
180
|
+
this.latestCacheHitPercent = cacheHitPercent(message.usage);
|
|
181
|
+
this.usage = combineUsage(this.usage, message.usage);
|
|
199
182
|
if (message.stopReason === "error" || message.stopReason === "aborted") {
|
|
200
183
|
turn.status = message.stopReason === "aborted" ? "cancelled" : "error";
|
|
201
184
|
turn.notice ??=
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent.js","sourceRoot":"","sources":["../../../src/extensions/btw/agent.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\tAgent,\n\ttype AgentEvent,\n\ttype AgentMessage,\n\ttype AgentTool,\n\ttype AgentTurnDecision,\n} from \"@earendil-works/pi-agent-core\";\nimport type { AssistantMessage, Message, Models, Usage } from \"@earendil-works/pi-ai\";\nimport { normalizeContext } from \"@earendil-works/pi-ai\";\nimport { estimateContextTokens } from \"@earendil-works/pi-ai/utils/estimate\";\nimport type { ContextSnapshot } from \"../../core/extensions/index.ts\";\nimport {\n\tMAX_DISPLAY_CHARS,\n\tMAX_MODEL_STEPS,\n\tMAX_OUTPUT_RESERVE_TOKENS,\n\tMAX_QUESTION_CHARS,\n\tMAX_QUESTIONS,\n\tMAX_RESPONSE_CHARS,\n\tTOOL_DENIAL,\n} from \"./constants.ts\";\nimport { createBtwMessages } from \"./snapshot.ts\";\n\nexport interface BtwTurn {\n\tquestion: string;\n\tanswer: string;\n\tthinking: string;\n\tstatus: \"streaming\" | \"cancelling\" | \"done\" | \"cancelled\" | \"error\";\n\tnotice?: string;\n\tstartedAt: number;\n\telapsedMs: number;\n\tfirstAnswerMs?: number;\n}\n\nexport interface BtwConversationState {\n\tbusy: boolean;\n\tturns: readonly BtwTurn[];\n\tusage: Usage;\n\tlatestCacheHitPercent: number | undefined;\n\tblockedTools: number;\n}\n\ninterface ActiveQuestion {\n\tturn: BtwTurn;\n\tsteps: number;\n\tcompletedAnswer: string;\n\tresponseChars: number;\n}\n\nfunction emptyUsage(): Usage {\n\treturn {\n\t\tinput: 0,\n\t\toutput: 0,\n\t\tcacheRead: 0,\n\t\tcacheWrite: 0,\n\t\ttotalTokens: 0,\n\t\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n\t};\n}\n\nfunction displayText(text: string): string {\n\treturn text.length <= MAX_DISPLAY_CHARS ? text : `${text.slice(0, MAX_DISPLAY_CHARS)}\\n\\n[Display truncated]`;\n}\n\n/** An in-memory native Agent. No SessionManager, real tool executors, or main-agent signal. */\nexport class BtwAgent implements BtwConversationState {\n\treadonly turns: BtwTurn[] = [];\n\treadonly usage = emptyUsage();\n\tlatestCacheHitPercent: number | undefined;\n\tblockedTools = 0;\n\tprivate readonly agent: Agent;\n\tprivate readonly unsubscribe: () => void;\n\tprivate readonly onChange: () => void;\n\tprivate readonly inputBudget: number;\n\tprivate active?: ActiveQuestion;\n\tprivate disposed = false;\n\n\tconstructor(snapshot: ContextSnapshot, runtime: Pick<Models, \"streamSimple\">, onChange: () => void) {\n\t\tthis.onChange = onChange;\n\t\tconst outputReserve = Math.min(\n\t\t\tMAX_OUTPUT_RESERVE_TOKENS,\n\t\t\tsnapshot.model.maxTokens,\n\t\t\tMath.max(1024, Math.floor(snapshot.model.contextWindow / 8)),\n\t\t);\n\t\t// Leave room for the answer and estimation error; never trim the inherited prefix.\n\t\tthis.inputBudget = snapshot.model.contextWindow - outputReserve - 4096;\n\t\tconst tools: AgentTool[] = snapshot.tools.map((tool) => ({\n\t\t\t...structuredClone(tool),\n\t\t\tlabel: tool.name,\n\t\t\texecute: async () => {\n\t\t\t\t// Defense in depth: these objects never receive an original execute function.\n\t\t\t\tthrow new Error(TOOL_DENIAL);\n\t\t\t},\n\t\t}));\n\t\tthis.agent = new Agent({\n\t\t\tinitialState: {\n\t\t\t\tmodel: snapshot.model,\n\t\t\t\tthinkingLevel: snapshot.thinkingLevel,\n\t\t\t\tsystemPrompt: snapshot.systemPrompt,\n\t\t\t\ttools,\n\t\t\t\tmessages: createBtwMessages(snapshot),\n\t\t\t},\n\t\t\tsessionId: snapshot.streamOptions.sessionId ?? snapshot.sessionId,\n\t\t\ttransport: snapshot.streamOptions.transport,\n\t\t\tthinkingBudgets: snapshot.streamOptions.thinkingBudgets,\n\t\t\tmaxRetryDelayMs: snapshot.streamOptions.maxRetryDelayMs,\n\t\t\tonPayload: snapshot.streamOptions.onPayload,\n\t\t\tonResponse: snapshot.streamOptions.onResponse,\n\t\t\tstreamFn: (model, context, options) =>\n\t\t\t\t// Keep the parent's generation settings as well as its message prefix.\n\t\t\t\t// The model's native output ceiling and our response-size guard still bound output.\n\t\t\t\truntime.streamSimple(model, context, { ...snapshot.streamOptions, ...options }),\n\t\t\tbeforeToolCall: async () => ({ block: true, reason: TOOL_DENIAL }),\n\t\t\tfinishTurn: ({ message, toolResults, context }): AgentTurnDecision | undefined => {\n\t\t\t\tconst question = this.active;\n\t\t\t\t// Error and aborted responses are hard exits; the step budget only counts answered turns.\n\t\t\t\tif (!question || this.disposed || message.stopReason === \"error\" || message.stopReason === \"aborted\")\n\t\t\t\t\treturn undefined;\n\t\t\t\tquestion.steps++;\n\t\t\t\tif (!toolResults.length) return undefined;\n\t\t\t\tif (question.steps >= MAX_MODEL_STEPS || !this.fits(context.messages)) {\n\t\t\t\t\tquestion.turn.status = \"error\";\n\t\t\t\t\tquestion.turn.notice =\n\t\t\t\t\t\tquestion.steps >= MAX_MODEL_STEPS\n\t\t\t\t\t\t\t? \"Stopped after repeated tool requests. BTW can only answer from its snapshot.\"\n\t\t\t\t\t\t\t: \"Context limit reached. Reopen /btw for a new conversation.\";\n\t\t\t\t\treturn { action: \"end\" };\n\t\t\t\t}\n\t\t\t\treturn undefined;\n\t\t\t},\n\t\t});\n\t\tthis.unsubscribe = this.agent.subscribe((event) => this.handleEvent(event));\n\t}\n\n\tget busy(): boolean {\n\t\treturn this.active !== undefined;\n\t}\n\n\tprivate validate(text: string): string | undefined {\n\t\tif (this.disposed) return \"This BTW conversation is closed.\";\n\t\tif (this.busy) return \"BTW is still answering. Your question is kept in the editor.\";\n\t\tif (this.turns.length >= MAX_QUESTIONS) return \"BTW conversation limit reached. Reopen /btw to start a new one.\";\n\t\tif (text.length > MAX_QUESTION_CHARS)\n\t\t\treturn `BTW questions are limited to ${MAX_QUESTION_CHARS.toLocaleString()} characters.`;\n\t\tconst question: AgentMessage = { role: \"user\", content: text, timestamp: Date.now() };\n\t\tif (!this.fits([...this.agent.state.messages, question])) {\n\t\t\treturn \"Not enough context space for this BTW question. Compact the main conversation, then reopen /btw.\";\n\t\t}\n\t\treturn undefined;\n\t}\n\n\t/** Accept synchronously so a rejected question stays in the editor, outside both agents' queues. */\n\tstartQuestion(text: string): { error: string } | { completion: Promise<void> } {\n\t\tconst error = this.validate(text);\n\t\tif (error) return { error };\n\t\tconst question: ActiveQuestion = {\n\t\t\tturn: {\n\t\t\t\tquestion: text,\n\t\t\t\tanswer: \"\",\n\t\t\t\tthinking: \"\",\n\t\t\t\tstatus: \"streaming\",\n\t\t\t\tstartedAt: Date.now(),\n\t\t\t\telapsedMs: 0,\n\t\t\t},\n\t\t\tsteps: 0,\n\t\t\tcompletedAnswer: \"\",\n\t\t\tresponseChars: 0,\n\t\t};\n\t\tthis.active = question;\n\t\tthis.turns.push(question.turn);\n\t\treturn { completion: this.runQuestion(question) };\n\t}\n\n\tprivate async runQuestion({ turn }: ActiveQuestion): Promise<void> {\n\t\ttry {\n\t\t\tthis.onChange();\n\t\t\tawait this.agent.prompt(turn.question);\n\t\t\tif (turn.status === \"streaming\") {\n\t\t\t\tturn.status = \"done\";\n\t\t\t\tif (!turn.answer) turn.notice = \"The model returned no answer text.\";\n\t\t\t} else if (turn.status === \"cancelling\") {\n\t\t\t\tturn.status = \"cancelled\";\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tturn.status = \"error\";\n\t\t\tturn.notice = displayText(error instanceof Error ? error.message : String(error));\n\t\t} finally {\n\t\t\t// Cancellation remains busy until the native Agent has fully settled.\n\t\t\tthis.active = undefined;\n\t\t\tturn.elapsedMs = Date.now() - turn.startedAt;\n\t\t\tif (this.disposed) this.agent.reset();\n\t\t\telse this.onChange();\n\t\t}\n\t}\n\n\tcancel(): void {\n\t\tif (!this.active || this.disposed) return;\n\t\tthis.active.turn.status = \"cancelling\";\n\t\tthis.agent.abort();\n\t\tthis.onChange();\n\t}\n\n\tdispose(): void {\n\t\tif (this.disposed) return;\n\t\tthis.disposed = true;\n\t\tthis.unsubscribe();\n\t\tthis.agent.abort();\n\t\tthis.turns.length = 0;\n\t\tif (!this.busy) this.agent.reset();\n\t\t// sessionId is cache affinity shared with main. Never clean up its provider resources here.\n\t}\n\n\tprivate fits(messages: AgentMessage[]): boolean {\n\t\treturn (\n\t\t\testimateContextTokens(\n\t\t\t\tnormalizeContext({\n\t\t\t\t\tsystemPrompt: this.agent.state.systemPrompt,\n\t\t\t\t\ttools: this.agent.state.tools,\n\t\t\t\t\tmessages: messages.filter(\n\t\t\t\t\t\t(message): message is Message =>\n\t\t\t\t\t\t\tmessage.role === \"user\" || message.role === \"assistant\" || message.role === \"toolResult\",\n\t\t\t\t\t),\n\t\t\t\t}),\n\t\t\t).tokens < this.inputBudget\n\t\t);\n\t}\n\n\tprivate handleEvent(event: AgentEvent): void {\n\t\tconst question = this.active;\n\t\tif (\n\t\t\tthis.disposed ||\n\t\t\t!question ||\n\t\t\t(event.type !== \"message_update\" && event.type !== \"message_end\") ||\n\t\t\tevent.message.role !== \"assistant\"\n\t\t)\n\t\t\treturn;\n\t\tconst { turn } = question;\n\t\tconst message = event.message;\n\t\tthis.updateAnswer(question, message);\n\t\tif (event.type === \"message_end\") {\n\t\t\tquestion.completedAnswer = turn.answer;\n\t\t\tquestion.responseChars += message.content.reduce(\n\t\t\t\t(sum, part) =>\n\t\t\t\t\tsum +\n\t\t\t\t\t(part.type === \"text\"\n\t\t\t\t\t\t? part.text.length\n\t\t\t\t\t\t: part.type === \"thinking\"\n\t\t\t\t\t\t\t? part.thinking.length\n\t\t\t\t\t\t\t: JSON.stringify(part.arguments).length),\n\t\t\t\t0,\n\t\t\t);\n\t\t\tthis.blockedTools += message.content.filter((part) => part.type === \"toolCall\").length;\n\t\t\tconst usage = message.usage;\n\t\t\tconst promptTokens = usage.input + usage.cacheRead + usage.cacheWrite;\n\t\t\tthis.latestCacheHitPercent =\n\t\t\t\t(usage.cacheRead > 0 || usage.cacheWrite > 0) && promptTokens > 0\n\t\t\t\t\t? (usage.cacheRead / promptTokens) * 100\n\t\t\t\t\t: undefined;\n\t\t\tfor (const key of [\"input\", \"output\", \"cacheRead\", \"cacheWrite\", \"totalTokens\"] as const)\n\t\t\t\tthis.usage[key] += usage[key];\n\t\t\tfor (const key of [\"input\", \"output\", \"cacheRead\", \"cacheWrite\", \"total\"] as const)\n\t\t\t\tthis.usage.cost[key] += usage.cost[key];\n\t\t\tif (message.stopReason === \"error\" || message.stopReason === \"aborted\") {\n\t\t\t\tturn.status = message.stopReason === \"aborted\" ? \"cancelled\" : \"error\";\n\t\t\t\tturn.notice ??=\n\t\t\t\t\tmessage.stopReason === \"aborted\"\n\t\t\t\t\t\t? \"Stopped. You can ask another question.\"\n\t\t\t\t\t\t: displayText(message.errorMessage ?? \"The request failed.\");\n\t\t\t}\n\t\t}\n\t\tthis.onChange();\n\t}\n\n\tprivate updateAnswer(question: ActiveQuestion, message: AssistantMessage): void {\n\t\tconst { turn } = question;\n\t\tconst text = message.content\n\t\t\t.filter((part) => part.type === \"text\")\n\t\t\t.map((part) => part.text)\n\t\t\t.join(\"\");\n\t\tconst thinking = message.content\n\t\t\t.filter((part) => part.type === \"thinking\")\n\t\t\t.map((part) => part.thinking)\n\t\t\t.join(\"\");\n\t\tif (text && turn.firstAnswerMs === undefined) turn.firstAnswerMs = Date.now() - turn.startedAt;\n\t\tturn.answer = displayText([question.completedAnswer, text].filter(Boolean).join(\"\\n\\n\"));\n\t\tturn.thinking = thinking.slice(-2000);\n\t\tif (question.responseChars + JSON.stringify(message.content).length > MAX_RESPONSE_CHARS) {\n\t\t\tturn.notice = \"Stopped at the BTW response size limit. You can ask a shorter follow-up.\";\n\t\t\tthis.agent.abort();\n\t\t}\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"agent.js","sourceRoot":"","sources":["../../../src/extensions/btw/agent.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\tAgent,\n\ttype AgentEvent,\n\ttype AgentMessage,\n\ttype AgentTool,\n\ttype AgentTurnDecision,\n} from \"@earendil-works/pi-agent-core\";\nimport type { AssistantMessage, Message, Models, Usage } from \"@earendil-works/pi-ai\";\nimport { normalizeContext } from \"@earendil-works/pi-ai\";\nimport { estimateContextTokens } from \"@earendil-works/pi-ai/utils/estimate\";\nimport type { ContextSnapshot } from \"../../core/extensions/index.ts\";\nimport { cacheHitPercent, combineUsage, emptyUsage } from \"../../core/usage-totals.ts\";\nimport {\n\tMAX_DISPLAY_CHARS,\n\tMAX_MODEL_STEPS,\n\tMAX_OUTPUT_RESERVE_TOKENS,\n\tMAX_QUESTION_CHARS,\n\tMAX_QUESTIONS,\n\tMAX_RESPONSE_CHARS,\n\tTOOL_DENIAL,\n} from \"./constants.ts\";\nimport { createBtwMessages } from \"./snapshot.ts\";\n\nexport interface BtwTurn {\n\tquestion: string;\n\tanswer: string;\n\tthinking: string;\n\tstatus: \"streaming\" | \"cancelling\" | \"done\" | \"cancelled\" | \"error\";\n\tnotice?: string;\n\tstartedAt: number;\n\telapsedMs: number;\n\tfirstAnswerMs?: number;\n}\n\nexport interface BtwConversationState {\n\tbusy: boolean;\n\tturns: readonly BtwTurn[];\n\tusage: Usage;\n\tlatestCacheHitPercent: number | undefined;\n\tblockedTools: number;\n}\n\ninterface ActiveQuestion {\n\tturn: BtwTurn;\n\tsteps: number;\n\tcompletedAnswer: string;\n\tresponseChars: number;\n}\n\nfunction displayText(text: string): string {\n\treturn text.length <= MAX_DISPLAY_CHARS ? text : `${text.slice(0, MAX_DISPLAY_CHARS)}\\n\\n[Display truncated]`;\n}\n\n/** An in-memory native Agent. No SessionManager, real tool executors, or main-agent signal. */\nexport class BtwAgent implements BtwConversationState {\n\treadonly turns: BtwTurn[] = [];\n\tusage = emptyUsage();\n\tlatestCacheHitPercent: number | undefined;\n\tblockedTools = 0;\n\tprivate readonly agent: Agent;\n\tprivate readonly unsubscribe: () => void;\n\tprivate readonly onChange: () => void;\n\tprivate readonly inputBudget: number;\n\tprivate active?: ActiveQuestion;\n\tprivate disposed = false;\n\n\tconstructor(snapshot: ContextSnapshot, runtime: Pick<Models, \"streamSimple\">, onChange: () => void) {\n\t\tthis.onChange = onChange;\n\t\tconst outputReserve = Math.min(\n\t\t\tMAX_OUTPUT_RESERVE_TOKENS,\n\t\t\tsnapshot.model.maxTokens,\n\t\t\tMath.max(1024, Math.floor(snapshot.model.contextWindow / 8)),\n\t\t);\n\t\t// Leave room for the answer and estimation error; never trim the inherited prefix.\n\t\tthis.inputBudget = snapshot.model.contextWindow - outputReserve - 4096;\n\t\tconst tools: AgentTool[] = snapshot.tools.map((tool) => ({\n\t\t\t...structuredClone(tool),\n\t\t\tlabel: tool.name,\n\t\t\texecute: async () => {\n\t\t\t\t// Defense in depth: these objects never receive an original execute function.\n\t\t\t\tthrow new Error(TOOL_DENIAL);\n\t\t\t},\n\t\t}));\n\t\tthis.agent = new Agent({\n\t\t\tinitialState: {\n\t\t\t\tmodel: snapshot.model,\n\t\t\t\tthinkingLevel: snapshot.thinkingLevel,\n\t\t\t\tsystemPrompt: snapshot.systemPrompt,\n\t\t\t\ttools,\n\t\t\t\tmessages: createBtwMessages(snapshot),\n\t\t\t},\n\t\t\tsessionId: snapshot.streamOptions.sessionId ?? snapshot.sessionId,\n\t\t\ttransport: snapshot.streamOptions.transport,\n\t\t\tthinkingBudgets: snapshot.streamOptions.thinkingBudgets,\n\t\t\tmaxRetryDelayMs: snapshot.streamOptions.maxRetryDelayMs,\n\t\t\tonPayload: snapshot.streamOptions.onPayload,\n\t\t\tonResponse: snapshot.streamOptions.onResponse,\n\t\t\tstreamFn: (model, context, options) =>\n\t\t\t\t// Keep the parent's generation settings as well as its message prefix.\n\t\t\t\t// The model's native output ceiling and our response-size guard still bound output.\n\t\t\t\truntime.streamSimple(model, context, { ...snapshot.streamOptions, ...options }),\n\t\t\tbeforeToolCall: async () => ({ block: true, reason: TOOL_DENIAL }),\n\t\t\tfinishTurn: ({ message, toolResults, context }): AgentTurnDecision | undefined => {\n\t\t\t\tconst question = this.active;\n\t\t\t\t// Error and aborted responses are hard exits; the step budget only counts answered turns.\n\t\t\t\tif (!question || this.disposed || message.stopReason === \"error\" || message.stopReason === \"aborted\")\n\t\t\t\t\treturn undefined;\n\t\t\t\tquestion.steps++;\n\t\t\t\tif (!toolResults.length) return undefined;\n\t\t\t\tif (question.steps >= MAX_MODEL_STEPS || !this.fits(context.messages)) {\n\t\t\t\t\tquestion.turn.status = \"error\";\n\t\t\t\t\tquestion.turn.notice =\n\t\t\t\t\t\tquestion.steps >= MAX_MODEL_STEPS\n\t\t\t\t\t\t\t? \"Stopped after repeated tool requests. BTW can only answer from its snapshot.\"\n\t\t\t\t\t\t\t: \"Context limit reached. Reopen /btw for a new conversation.\";\n\t\t\t\t\treturn { action: \"end\" };\n\t\t\t\t}\n\t\t\t\treturn undefined;\n\t\t\t},\n\t\t});\n\t\tthis.unsubscribe = this.agent.subscribe((event) => this.handleEvent(event));\n\t}\n\n\tget busy(): boolean {\n\t\treturn this.active !== undefined;\n\t}\n\n\tprivate validate(text: string): string | undefined {\n\t\tif (this.disposed) return \"This BTW conversation is closed.\";\n\t\tif (this.busy) return \"BTW is still answering. Your question is kept in the editor.\";\n\t\tif (this.turns.length >= MAX_QUESTIONS) return \"BTW conversation limit reached. Reopen /btw to start a new one.\";\n\t\tif (text.length > MAX_QUESTION_CHARS)\n\t\t\treturn `BTW questions are limited to ${MAX_QUESTION_CHARS.toLocaleString()} characters.`;\n\t\tconst question: AgentMessage = { role: \"user\", content: text, timestamp: Date.now() };\n\t\tif (!this.fits([...this.agent.state.messages, question])) {\n\t\t\treturn \"Not enough context space for this BTW question. Compact the main conversation, then reopen /btw.\";\n\t\t}\n\t\treturn undefined;\n\t}\n\n\t/** Accept synchronously so a rejected question stays in the editor, outside both agents' queues. */\n\tstartQuestion(text: string): { error: string } | { completion: Promise<void> } {\n\t\tconst error = this.validate(text);\n\t\tif (error) return { error };\n\t\tconst question: ActiveQuestion = {\n\t\t\tturn: {\n\t\t\t\tquestion: text,\n\t\t\t\tanswer: \"\",\n\t\t\t\tthinking: \"\",\n\t\t\t\tstatus: \"streaming\",\n\t\t\t\tstartedAt: Date.now(),\n\t\t\t\telapsedMs: 0,\n\t\t\t},\n\t\t\tsteps: 0,\n\t\t\tcompletedAnswer: \"\",\n\t\t\tresponseChars: 0,\n\t\t};\n\t\tthis.active = question;\n\t\tthis.turns.push(question.turn);\n\t\treturn { completion: this.runQuestion(question) };\n\t}\n\n\tprivate async runQuestion({ turn }: ActiveQuestion): Promise<void> {\n\t\ttry {\n\t\t\tthis.onChange();\n\t\t\tawait this.agent.prompt(turn.question);\n\t\t\tif (turn.status === \"streaming\") {\n\t\t\t\tturn.status = \"done\";\n\t\t\t\tif (!turn.answer) turn.notice = \"The model returned no answer text.\";\n\t\t\t} else if (turn.status === \"cancelling\") {\n\t\t\t\tturn.status = \"cancelled\";\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tturn.status = \"error\";\n\t\t\tturn.notice = displayText(error instanceof Error ? error.message : String(error));\n\t\t} finally {\n\t\t\t// Cancellation remains busy until the native Agent has fully settled.\n\t\t\tthis.active = undefined;\n\t\t\tturn.elapsedMs = Date.now() - turn.startedAt;\n\t\t\tif (this.disposed) this.agent.reset();\n\t\t\telse this.onChange();\n\t\t}\n\t}\n\n\tcancel(): void {\n\t\tif (!this.active || this.disposed) return;\n\t\tthis.active.turn.status = \"cancelling\";\n\t\tthis.agent.abort();\n\t\tthis.onChange();\n\t}\n\n\tdispose(): void {\n\t\tif (this.disposed) return;\n\t\tthis.disposed = true;\n\t\tthis.unsubscribe();\n\t\tthis.agent.abort();\n\t\tthis.turns.length = 0;\n\t\tif (!this.busy) this.agent.reset();\n\t\t// sessionId is cache affinity shared with main. Never clean up its provider resources here.\n\t}\n\n\tprivate fits(messages: AgentMessage[]): boolean {\n\t\treturn (\n\t\t\testimateContextTokens(\n\t\t\t\tnormalizeContext({\n\t\t\t\t\tsystemPrompt: this.agent.state.systemPrompt,\n\t\t\t\t\ttools: this.agent.state.tools,\n\t\t\t\t\tmessages: messages.filter(\n\t\t\t\t\t\t(message): message is Message =>\n\t\t\t\t\t\t\tmessage.role === \"user\" || message.role === \"assistant\" || message.role === \"toolResult\",\n\t\t\t\t\t),\n\t\t\t\t}),\n\t\t\t).tokens < this.inputBudget\n\t\t);\n\t}\n\n\tprivate handleEvent(event: AgentEvent): void {\n\t\tconst question = this.active;\n\t\tif (\n\t\t\tthis.disposed ||\n\t\t\t!question ||\n\t\t\t(event.type !== \"message_update\" && event.type !== \"message_end\") ||\n\t\t\tevent.message.role !== \"assistant\"\n\t\t)\n\t\t\treturn;\n\t\tconst { turn } = question;\n\t\tconst message = event.message;\n\t\tthis.updateAnswer(question, message);\n\t\tif (event.type === \"message_end\") {\n\t\t\tquestion.completedAnswer = turn.answer;\n\t\t\tquestion.responseChars += message.content.reduce(\n\t\t\t\t(sum, part) =>\n\t\t\t\t\tsum +\n\t\t\t\t\t(part.type === \"text\"\n\t\t\t\t\t\t? part.text.length\n\t\t\t\t\t\t: part.type === \"thinking\"\n\t\t\t\t\t\t\t? part.thinking.length\n\t\t\t\t\t\t\t: JSON.stringify(part.arguments).length),\n\t\t\t\t0,\n\t\t\t);\n\t\t\tthis.blockedTools += message.content.filter((part) => part.type === \"toolCall\").length;\n\t\t\tthis.latestCacheHitPercent = cacheHitPercent(message.usage);\n\t\t\tthis.usage = combineUsage(this.usage, message.usage);\n\t\t\tif (message.stopReason === \"error\" || message.stopReason === \"aborted\") {\n\t\t\t\tturn.status = message.stopReason === \"aborted\" ? \"cancelled\" : \"error\";\n\t\t\t\tturn.notice ??=\n\t\t\t\t\tmessage.stopReason === \"aborted\"\n\t\t\t\t\t\t? \"Stopped. You can ask another question.\"\n\t\t\t\t\t\t: displayText(message.errorMessage ?? \"The request failed.\");\n\t\t\t}\n\t\t}\n\t\tthis.onChange();\n\t}\n\n\tprivate updateAnswer(question: ActiveQuestion, message: AssistantMessage): void {\n\t\tconst { turn } = question;\n\t\tconst text = message.content\n\t\t\t.filter((part) => part.type === \"text\")\n\t\t\t.map((part) => part.text)\n\t\t\t.join(\"\");\n\t\tconst thinking = message.content\n\t\t\t.filter((part) => part.type === \"thinking\")\n\t\t\t.map((part) => part.thinking)\n\t\t\t.join(\"\");\n\t\tif (text && turn.firstAnswerMs === undefined) turn.firstAnswerMs = Date.now() - turn.startedAt;\n\t\tturn.answer = displayText([question.completedAnswer, text].filter(Boolean).join(\"\\n\\n\"));\n\t\tturn.thinking = thinking.slice(-2000);\n\t\tif (question.responseChars + JSON.stringify(message.content).length > MAX_RESPONSE_CHARS) {\n\t\t\tturn.notice = \"Stopped at the BTW response size limit. You can ask a shorter follow-up.\";\n\t\t\tthis.agent.abort();\n\t\t}\n\t}\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/extensions/cached-compaction/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AAMnE,MAAM,CAAC,OAAO,UAAU,gBAAgB,CAAC,EAAE,EAAE,YAAY,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/extensions/cached-compaction/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AAMnE,MAAM,CAAC,OAAO,UAAU,gBAAgB,CAAC,EAAE,EAAE,YAAY,GAAG,IAAI,CAkE/D"}
|
|
@@ -3,8 +3,8 @@ import { renderCachedCompactionEntry } from "./render.js";
|
|
|
3
3
|
import { checkpointSummary, keptStart, summaryInstruction } from "./summary.js";
|
|
4
4
|
const CARD_TYPE = "cached-compaction";
|
|
5
5
|
export default function cachedCompaction(pi) {
|
|
6
|
+
/** Card for the summary returned to the current compaction; every compaction starts by clearing it. */
|
|
6
7
|
let completed;
|
|
7
|
-
let pendingCard;
|
|
8
8
|
pi.registerEntryRenderer(CARD_TYPE, renderCachedCompactionEntry);
|
|
9
9
|
pi.on("session_before_compact", async (event, ctx) => {
|
|
10
10
|
completed = undefined;
|
|
@@ -63,29 +63,10 @@ export default function cachedCompaction(pi) {
|
|
|
63
63
|
}
|
|
64
64
|
});
|
|
65
65
|
pi.on("session_compact", (event) => {
|
|
66
|
-
if (!event.fromExtension || !completed)
|
|
67
|
-
return;
|
|
68
66
|
const card = completed;
|
|
69
67
|
completed = undefined;
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
if (pendingCard !== card)
|
|
73
|
-
return;
|
|
74
|
-
pendingCard = undefined;
|
|
75
|
-
try {
|
|
76
|
-
pi.appendEntry(CARD_TYPE, card);
|
|
77
|
-
}
|
|
78
|
-
catch {
|
|
79
|
-
// The session may be disposed before the deferred card is appended.
|
|
80
|
-
}
|
|
81
|
-
}, 0);
|
|
82
|
-
});
|
|
83
|
-
pi.on("session_compact_failed", () => {
|
|
84
|
-
completed = undefined;
|
|
85
|
-
});
|
|
86
|
-
pi.on("session_shutdown", () => {
|
|
87
|
-
completed = undefined;
|
|
88
|
-
pendingCard = undefined;
|
|
68
|
+
if (event.fromExtension && card)
|
|
69
|
+
pi.appendEntry(CARD_TYPE, card);
|
|
89
70
|
});
|
|
90
71
|
}
|
|
91
72
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/extensions/cached-compaction/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAEpD,OAAO,EAA6B,2BAA2B,EAAE,MAAM,aAAa,CAAC;AACrF,OAAO,EAAE,iBAAiB,EAAE,SAAS,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAEhF,MAAM,SAAS,GAAG,mBAAmB,CAAC;AAEtC,MAAM,CAAC,OAAO,UAAU,gBAAgB,CAAC,EAAgB;IACxD,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/extensions/cached-compaction/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { contentText } from \"@earendil-works/pi-ai\";\nimport type { ExtensionAPI } from \"../../core/extensions/types.ts\";\nimport { type CachedCompactionCard, renderCachedCompactionEntry } from \"./render.ts\";\nimport { checkpointSummary, keptStart, summaryInstruction } from \"./summary.ts\";\n\nconst CARD_TYPE = \"cached-compaction\";\n\nexport default function cachedCompaction(pi: ExtensionAPI): void {\n\t/** Card for the summary returned to the current compaction; every compaction starts by clearing it. */\n\tlet completed: CachedCompactionCard | undefined;\n\n\tpi.registerEntryRenderer(CARD_TYPE, renderCachedCompactionEntry);\n\n\tpi.on(\"session_before_compact\", async (event, ctx) => {\n\t\tcompleted = undefined;\n\t\tif (event.reason === \"overflow\") return;\n\t\tconst startedAt = Date.now();\n\t\ttry {\n\t\t\tconst snapshot = await ctx.getContextSnapshot();\n\t\t\tconst kept = keptStart(event.branchEntries, event.preparation.firstKeptEntryId, snapshot.messages);\n\t\t\tif (!kept) return;\n\t\t\tconst response = await ctx.modelRegistry\n\t\t\t\t.streamSimple(\n\t\t\t\t\tsnapshot.model,\n\t\t\t\t\t{\n\t\t\t\t\t\tmessages: [\n\t\t\t\t\t\t\t...snapshot.messages,\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\trole: \"user\",\n\t\t\t\t\t\t\t\tcontent: [{ type: \"text\", text: summaryInstruction(kept, event.customInstructions) }],\n\t\t\t\t\t\t\t\ttimestamp: Date.now(),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t],\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\t...snapshot.streamOptions,\n\t\t\t\t\t\treasoning: snapshot.thinkingLevel === \"off\" ? undefined : snapshot.thinkingLevel,\n\t\t\t\t\t\tsignal: event.signal,\n\t\t\t\t\t},\n\t\t\t\t)\n\t\t\t\t.result();\n\t\t\tif (response.stopReason === \"aborted\") return { cancel: true };\n\t\t\tif (response.stopReason !== \"stop\" || response.content.some((block) => block.type === \"toolCall\")) return;\n\t\t\tconst text = contentText(response.content).trim();\n\t\t\tif (!text) return;\n\t\t\tconst checkpoint = checkpointSummary(text, event.preparation.fileOps, event.branchEntries);\n\t\t\tcompleted = {\n\t\t\t\treason: event.reason,\n\t\t\t\tcacheRead: response.usage.cacheRead,\n\t\t\t\tinput: response.usage.input,\n\t\t\t\tcacheWrite: response.usage.cacheWrite,\n\t\t\t\toutput: response.usage.output,\n\t\t\t\tdurationMs: Date.now() - startedAt,\n\t\t\t};\n\t\t\treturn {\n\t\t\t\tcompaction: {\n\t\t\t\t\tsummary: checkpoint.summary,\n\t\t\t\t\tfirstKeptEntryId: event.preparation.firstKeptEntryId,\n\t\t\t\t\ttokensBefore: event.preparation.tokensBefore,\n\t\t\t\t\tusage: response.usage,\n\t\t\t\t\tdetails: checkpoint.details,\n\t\t\t\t},\n\t\t\t};\n\t\t} catch {\n\t\t\treturn event.signal.aborted ? { cancel: true } : undefined;\n\t\t}\n\t});\n\n\tpi.on(\"session_compact\", (event) => {\n\t\tconst card = completed;\n\t\tcompleted = undefined;\n\t\tif (event.fromExtension && card) pi.appendEntry(CARD_TYPE, card);\n\t});\n}\n"]}
|
|
@@ -7,5 +7,6 @@ export interface CachedCompactionCard {
|
|
|
7
7
|
output: number;
|
|
8
8
|
durationMs: number;
|
|
9
9
|
}
|
|
10
|
+
/** A footnote to the native compaction summary above it, expanding with it. */
|
|
10
11
|
export declare const renderCachedCompactionEntry: EntryRenderer<CachedCompactionCard>;
|
|
11
12
|
//# sourceMappingURL=render.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../../src/extensions/cached-compaction/render.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;
|
|
1
|
+
{"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../../src/extensions/cached-compaction/render.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAMpE,MAAM,WAAW,oBAAoB;IACpC,MAAM,EAAE,QAAQ,GAAG,WAAW,CAAC;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;CACnB;AAqBD,+EAA+E;AAC/E,eAAO,MAAM,2BAA2B,EAAE,aAAa,CAAC,oBAAoB,CAmB3E,CAAC"}
|
|
@@ -1,19 +1,47 @@
|
|
|
1
1
|
import { Text } from "@earendil-works/pi-tui";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
2
|
+
import { cacheHitPercent } from "../../core/usage-totals.js";
|
|
3
|
+
import { formatTokens } from "../../modes/interactive/components/footer.js";
|
|
4
|
+
import { formatDuration } from "../../utils/duration.js";
|
|
5
|
+
/** Cache reuse is why this path exists, so its rate is the one colored segment. */
|
|
6
|
+
function hitRate(card, theme) {
|
|
7
|
+
const percent = cacheHitPercent(card);
|
|
8
|
+
if (percent === undefined)
|
|
9
|
+
return undefined;
|
|
10
|
+
return theme.fg(percent >= 80 ? "success" : percent < 50 ? "warning" : "dim", `CH ${percent.toFixed(1)}%`);
|
|
11
|
+
}
|
|
12
|
+
/** The prompt split by how the provider billed it; parts it did not use are left out. */
|
|
13
|
+
function promptBreakdown(card) {
|
|
14
|
+
const total = card.input + card.cacheRead + card.cacheWrite;
|
|
15
|
+
if (total === 0)
|
|
16
|
+
return undefined;
|
|
17
|
+
const parts = [
|
|
18
|
+
card.cacheRead > 0 ? `R${formatTokens(card.cacheRead)} cached` : undefined,
|
|
19
|
+
card.cacheWrite > 0 ? `W${formatTokens(card.cacheWrite)} written` : undefined,
|
|
20
|
+
card.input > 0 ? `↑${formatTokens(card.input)} uncached` : undefined,
|
|
21
|
+
];
|
|
22
|
+
return `Prompt ${formatTokens(total)} = ${parts.filter(Boolean).join(" + ")}`;
|
|
8
23
|
}
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
24
|
+
/** A footnote to the native compaction summary above it, expanding with it. */
|
|
25
|
+
export const renderCachedCompactionEntry = (entry, { expanded }, theme) => {
|
|
26
|
+
const card = entry.data;
|
|
27
|
+
if (!card)
|
|
12
28
|
return undefined;
|
|
13
|
-
const
|
|
14
|
-
const
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
|
|
29
|
+
const dim = (text) => theme.fg("dim", text);
|
|
30
|
+
const reason = card.reason === "manual" ? "manual" : "auto";
|
|
31
|
+
const head = [
|
|
32
|
+
dim("From cache"),
|
|
33
|
+
expanded || reason === "auto" ? dim(reason) : undefined,
|
|
34
|
+
hitRate(card, theme),
|
|
35
|
+
expanded ? undefined : dim(`↓${formatTokens(card.output)}`),
|
|
36
|
+
dim(formatDuration(card.durationMs)),
|
|
37
|
+
];
|
|
38
|
+
const lines = [head.filter(Boolean).join(dim(" · "))];
|
|
39
|
+
if (expanded) {
|
|
40
|
+
const breakdown = promptBreakdown(card);
|
|
41
|
+
if (breakdown)
|
|
42
|
+
lines.push(dim(breakdown));
|
|
43
|
+
lines.push(dim(`Output ↓${formatTokens(card.output)}`));
|
|
44
|
+
}
|
|
45
|
+
return new Text(lines.join("\n"), 1, 0);
|
|
18
46
|
};
|
|
19
47
|
//# sourceMappingURL=render.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"render.js","sourceRoot":"","sources":["../../../src/extensions/cached-compaction/render.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"render.js","sourceRoot":"","sources":["../../../src/extensions/cached-compaction/render.ts"],"names":[],"mappings":"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","sourcesContent":["import { Text } from \"@earendil-works/pi-tui\";\nimport type { EntryRenderer } from \"../../core/extensions/types.ts\";\nimport { cacheHitPercent } from \"../../core/usage-totals.ts\";\nimport { formatTokens } from \"../../modes/interactive/components/footer.ts\";\nimport type { Theme } from \"../../modes/interactive/theme/theme.ts\";\nimport { formatDuration } from \"../../utils/duration.ts\";\n\nexport interface CachedCompactionCard {\n\treason: \"manual\" | \"threshold\";\n\tcacheRead: number;\n\tinput: number;\n\tcacheWrite: number;\n\toutput: number;\n\tdurationMs: number;\n}\n\n/** Cache reuse is why this path exists, so its rate is the one colored segment. */\nfunction hitRate(card: CachedCompactionCard, theme: Theme): string | undefined {\n\tconst percent = cacheHitPercent(card);\n\tif (percent === undefined) return undefined;\n\treturn theme.fg(percent >= 80 ? \"success\" : percent < 50 ? \"warning\" : \"dim\", `CH ${percent.toFixed(1)}%`);\n}\n\n/** The prompt split by how the provider billed it; parts it did not use are left out. */\nfunction promptBreakdown(card: CachedCompactionCard): string | undefined {\n\tconst total = card.input + card.cacheRead + card.cacheWrite;\n\tif (total === 0) return undefined;\n\tconst parts = [\n\t\tcard.cacheRead > 0 ? `R${formatTokens(card.cacheRead)} cached` : undefined,\n\t\tcard.cacheWrite > 0 ? `W${formatTokens(card.cacheWrite)} written` : undefined,\n\t\tcard.input > 0 ? `↑${formatTokens(card.input)} uncached` : undefined,\n\t];\n\treturn `Prompt ${formatTokens(total)} = ${parts.filter(Boolean).join(\" + \")}`;\n}\n\n/** A footnote to the native compaction summary above it, expanding with it. */\nexport const renderCachedCompactionEntry: EntryRenderer<CachedCompactionCard> = (entry, { expanded }, theme) => {\n\tconst card = entry.data;\n\tif (!card) return undefined;\n\tconst dim = (text: string) => theme.fg(\"dim\", text);\n\tconst reason = card.reason === \"manual\" ? \"manual\" : \"auto\";\n\tconst head = [\n\t\tdim(\"From cache\"),\n\t\texpanded || reason === \"auto\" ? dim(reason) : undefined,\n\t\thitRate(card, theme),\n\t\texpanded ? undefined : dim(`↓${formatTokens(card.output)}`),\n\t\tdim(formatDuration(card.durationMs)),\n\t];\n\tconst lines = [head.filter(Boolean).join(dim(\" · \"))];\n\tif (expanded) {\n\t\tconst breakdown = promptBreakdown(card);\n\t\tif (breakdown) lines.push(dim(breakdown));\n\t\tlines.push(dim(`Output ↓${formatTokens(card.output)}`));\n\t}\n\treturn new Text(lines.join(\"\\n\"), 1, 0);\n};\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../src/extensions/deepwiki/client.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,cAAc,EAA2B,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../src/extensions/deepwiki/client.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,cAAc,EAA2B,MAAM,aAAa,CAAC;AAO3E,KAAK,gBAAgB,GAAG,qBAAqB,GAAG,oBAAoB,GAAG,cAAc,CAAC;AAEtF,MAAM,WAAW,gBAAgB;IAChC,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACnB;AA2ED,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAE/D;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAE1D;AAmBD,wBAAsB,YAAY,CAAC,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,WAAW,GAAG,SAAS,GAAG,OAAO,CAAC,gBAAgB,CAAC,CA8BrH"}
|
|
@@ -1,14 +1,9 @@
|
|
|
1
1
|
import { PAGE_HEADER_RE } from "./contents.js";
|
|
2
|
-
import { fetchWithRetry } from "./http.js";
|
|
3
2
|
import { normalizeDeepWikiParams } from "./schema.js";
|
|
4
|
-
|
|
5
|
-
const MCP_PROTOCOL_VERSION = "2024-11-05";
|
|
6
|
-
const REQUEST_TIMEOUT_MS = 45_000;
|
|
3
|
+
import { callDeepWikiTool } from "./transport.js";
|
|
7
4
|
const CACHE_TTL_MS = 10 * 60_000;
|
|
8
5
|
/** Long-lived process guard: entries are only otherwise dropped on re-read after expiry. */
|
|
9
6
|
const MAX_CACHE_ENTRIES = 50;
|
|
10
|
-
/** Transient-failure retries (network blips, 5xx, 429). Aborts/timeouts are not retried. */
|
|
11
|
-
const MAX_RETRIES = 2;
|
|
12
7
|
const responseCache = new Map();
|
|
13
8
|
function toolNameForAction(action) {
|
|
14
9
|
if (action === "structure")
|
|
@@ -38,47 +33,6 @@ function cloneResponse(response, cacheHit) {
|
|
|
38
33
|
cacheHit,
|
|
39
34
|
};
|
|
40
35
|
}
|
|
41
|
-
function truncate(text, maxLength = 500) {
|
|
42
|
-
if (text.length <= maxLength)
|
|
43
|
-
return text;
|
|
44
|
-
return `${text.slice(0, maxLength - 3)}...`;
|
|
45
|
-
}
|
|
46
|
-
function parseJson(text) {
|
|
47
|
-
try {
|
|
48
|
-
return JSON.parse(text);
|
|
49
|
-
}
|
|
50
|
-
catch (error) {
|
|
51
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
52
|
-
throw new Error(`DeepWiki returned invalid JSON: ${message}`);
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
function parseSse(text) {
|
|
56
|
-
const blocks = text.split(/\r?\n\r?\n/);
|
|
57
|
-
let fallback;
|
|
58
|
-
for (const block of blocks) {
|
|
59
|
-
const dataLines = block
|
|
60
|
-
.split(/\r?\n/)
|
|
61
|
-
.filter((line) => line.startsWith("data:"))
|
|
62
|
-
.map((line) => line.slice(5).replace(/^ /, ""));
|
|
63
|
-
if (dataLines.length === 0)
|
|
64
|
-
continue;
|
|
65
|
-
const data = dataLines.join("\n").trim();
|
|
66
|
-
if (!data || data === "[DONE]")
|
|
67
|
-
continue;
|
|
68
|
-
const envelope = parseJson(data);
|
|
69
|
-
if (envelope.error || envelope.result !== undefined)
|
|
70
|
-
return envelope;
|
|
71
|
-
fallback = envelope;
|
|
72
|
-
}
|
|
73
|
-
if (fallback)
|
|
74
|
-
return fallback;
|
|
75
|
-
throw new Error("DeepWiki returned an empty event stream");
|
|
76
|
-
}
|
|
77
|
-
function parseEnvelope(text, contentType) {
|
|
78
|
-
if (contentType?.includes("text/event-stream"))
|
|
79
|
-
return parseSse(text);
|
|
80
|
-
return parseJson(text);
|
|
81
|
-
}
|
|
82
36
|
function extractStructuredResult(result) {
|
|
83
37
|
if (!result.structuredContent || typeof result.structuredContent !== "object")
|
|
84
38
|
return undefined;
|
|
@@ -150,50 +104,24 @@ export async function callDeepWiki(params, signal) {
|
|
|
150
104
|
if (cached)
|
|
151
105
|
responseCache.delete(key);
|
|
152
106
|
const toolName = toolNameForAction(normalizedParams.action);
|
|
153
|
-
const
|
|
154
|
-
jsonrpc: "2.0",
|
|
155
|
-
id: 1,
|
|
156
|
-
method: "tools/call",
|
|
157
|
-
params: {
|
|
158
|
-
name: toolName,
|
|
159
|
-
arguments: argumentsForParams(normalizedParams),
|
|
160
|
-
},
|
|
161
|
-
});
|
|
162
|
-
// Timeout + bounded transient retry live in this extension's http.ts; non-retryable
|
|
163
|
-
// statuses come back here for the domain-specific HTTP error below.
|
|
164
|
-
const { response, text } = await fetchWithRetry(DEEPWIKI_MCP_URL, {
|
|
165
|
-
method: "POST",
|
|
166
|
-
headers: {
|
|
167
|
-
Accept: "application/json, text/event-stream",
|
|
168
|
-
"Content-Type": "application/json",
|
|
169
|
-
"MCP-Protocol-Version": MCP_PROTOCOL_VERSION,
|
|
170
|
-
},
|
|
171
|
-
body: bodyJson,
|
|
172
|
-
}, { timeoutMs: REQUEST_TIMEOUT_MS, retries: MAX_RETRIES, signal, label: "DeepWiki" });
|
|
107
|
+
const result = await callDeepWikiTool(toolName, argumentsForParams(normalizedParams), signal);
|
|
173
108
|
signal?.throwIfAborted();
|
|
174
|
-
|
|
175
|
-
throw new Error(`DeepWiki HTTP ${response.status}: ${truncate(text)}`);
|
|
176
|
-
}
|
|
177
|
-
const envelope = parseEnvelope(text, response.headers.get("content-type"));
|
|
178
|
-
if (envelope.error) {
|
|
179
|
-
throw new Error(envelope.error.message ?? `DeepWiki JSON-RPC error ${envelope.error.code ?? "unknown"}`);
|
|
180
|
-
}
|
|
181
|
-
const resultText = extractToolText(envelope.result);
|
|
109
|
+
const resultText = extractToolText(result);
|
|
182
110
|
const pageTitles = extractPageTitles(toolName, resultText);
|
|
183
|
-
const
|
|
111
|
+
const response = {
|
|
184
112
|
toolName,
|
|
185
113
|
text: resultText,
|
|
186
114
|
outputLength: resultText.length,
|
|
187
115
|
...(pageTitles.length ? { pageTitles } : {}),
|
|
188
116
|
};
|
|
189
117
|
signal?.throwIfAborted();
|
|
190
|
-
responseCache.set(key, { expiresAt: Date.now() + CACHE_TTL_MS, response: cloneResponse(
|
|
118
|
+
responseCache.set(key, { expiresAt: Date.now() + CACHE_TTL_MS, response: cloneResponse(response, false) });
|
|
191
119
|
while (responseCache.size > MAX_CACHE_ENTRIES) {
|
|
192
120
|
const oldest = responseCache.keys().next().value;
|
|
193
121
|
if (oldest === undefined)
|
|
194
122
|
break;
|
|
195
123
|
responseCache.delete(oldest);
|
|
196
124
|
}
|
|
197
|
-
return
|
|
125
|
+
return response;
|
|
198
126
|
}
|
|
199
127
|
//# sourceMappingURL=client.js.map
|