@oh-my-pi/pi-coding-agent 16.1.13 → 16.1.15
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 +48 -0
- package/dist/cli.js +5615 -2833
- package/dist/types/advisor/runtime.d.ts +3 -0
- package/dist/types/config/settings-schema.d.ts +64 -14
- package/dist/types/eval/__tests__/julia-prelude.test.d.ts +1 -0
- package/dist/types/eval/backend-helpers.d.ts +23 -0
- package/dist/types/eval/executor-base.d.ts +118 -0
- package/dist/types/eval/index.d.ts +2 -0
- package/dist/types/eval/jl/executor.d.ts +44 -0
- package/dist/types/eval/jl/index.d.ts +11 -0
- package/dist/types/eval/jl/kernel.d.ts +28 -0
- package/dist/types/eval/jl/prelude.d.ts +1 -0
- package/dist/types/eval/jl/runtime.d.ts +22 -0
- package/dist/types/eval/kernel-base.d.ts +105 -0
- package/dist/types/eval/py/kernel.d.ts +3 -61
- package/dist/types/eval/rb/executor.d.ts +77 -0
- package/dist/types/eval/rb/index.d.ts +11 -0
- package/dist/types/eval/rb/kernel.d.ts +31 -0
- package/dist/types/eval/rb/prelude.d.ts +1 -0
- package/dist/types/eval/rb/runtime.d.ts +23 -0
- package/dist/types/eval/runtime-env.d.ts +24 -0
- package/dist/types/eval/types.d.ts +3 -3
- package/dist/types/export/share.d.ts +8 -1
- package/dist/types/extensibility/extensions/runner.d.ts +2 -15
- package/dist/types/extensibility/hooks/loader.d.ts +1 -25
- package/dist/types/extensibility/session-handler-types.d.ts +23 -0
- package/dist/types/jsonrpc/message-framing.d.ts +35 -0
- package/dist/types/mcp/transports/stdio.d.ts +12 -1
- package/dist/types/mnemopi/embed-client.d.ts +7 -24
- package/dist/types/modes/components/chat-transcript-builder.d.ts +1 -1
- package/dist/types/modes/components/custom-editor.d.ts +11 -0
- package/dist/types/modes/components/selector-helpers.d.ts +53 -0
- package/dist/types/modes/components/status-line/context-thresholds.d.ts +4 -3
- package/dist/types/modes/components/status-line/types.d.ts +1 -0
- package/dist/types/modes/interactive-mode.d.ts +0 -2
- package/dist/types/modes/theme/theme.d.ts +8 -1
- package/dist/types/modes/types.d.ts +0 -2
- package/dist/types/modes/utils/copy-targets.d.ts +1 -1
- package/dist/types/modes/utils/interactive-context-helpers.d.ts +14 -0
- package/dist/types/modes/utils/transcript-render-helpers.d.ts +54 -0
- package/dist/types/sdk.d.ts +1 -1
- package/dist/types/secrets/obfuscator.d.ts +3 -3
- package/dist/types/session/agent-session.d.ts +2 -2
- package/dist/types/stt/asr-client.d.ts +3 -29
- package/dist/types/subprocess/worker-client.d.ts +149 -0
- package/dist/types/subprocess/worker-runtime.d.ts +107 -0
- package/dist/types/tiny/title-client.d.ts +14 -34
- package/dist/types/tools/eval-backends.d.ts +6 -3
- package/dist/types/tools/eval-render.d.ts +6 -5
- package/dist/types/tools/eval.d.ts +13 -15
- package/dist/types/tools/index.d.ts +3 -3
- package/dist/types/tts/tts-client.d.ts +3 -28
- package/dist/types/tui/code-cell.d.ts +7 -0
- package/dist/types/utils/file-display-mode.d.ts +1 -1
- package/dist/types/utils/shell-snapshot.d.ts +10 -0
- package/dist/types/web/parallel.d.ts +6 -0
- package/dist/types/web/search/providers/perplexity.d.ts +17 -3
- package/package.json +12 -12
- package/src/advisor/__tests__/advisor.test.ts +114 -0
- package/src/advisor/runtime.ts +129 -1
- package/src/config/model-registry.ts +12 -4
- package/src/config/settings-schema.ts +74 -18
- package/src/config/settings.ts +5 -0
- package/src/dap/client.ts +13 -107
- package/src/eval/__tests__/julia-prelude.test.ts +77 -0
- package/src/eval/backend-helpers.ts +48 -0
- package/src/eval/executor-base.ts +425 -0
- package/src/eval/index.ts +2 -0
- package/src/eval/jl/executor.ts +540 -0
- package/src/eval/jl/index.ts +54 -0
- package/src/eval/jl/kernel.ts +235 -0
- package/src/eval/jl/prelude.jl +930 -0
- package/src/eval/jl/prelude.ts +3 -0
- package/src/eval/jl/runner.jl +634 -0
- package/src/eval/jl/runtime.ts +118 -0
- package/src/eval/js/index.ts +3 -14
- package/src/eval/kernel-base.ts +569 -0
- package/src/eval/py/executor.ts +43 -252
- package/src/eval/py/index.ts +9 -20
- package/src/eval/py/kernel.ts +29 -544
- package/src/eval/rb/executor.ts +504 -0
- package/src/eval/rb/index.ts +54 -0
- package/src/eval/rb/kernel.ts +230 -0
- package/src/eval/rb/prelude.rb +721 -0
- package/src/eval/rb/prelude.ts +3 -0
- package/src/eval/rb/runner.rb +474 -0
- package/src/eval/rb/runtime.ts +132 -0
- package/src/eval/runtime-env.ts +104 -0
- package/src/eval/types.ts +3 -3
- package/src/exec/bash-executor.ts +44 -0
- package/src/export/share.ts +51 -28
- package/src/extensibility/extensions/runner.ts +4 -11
- package/src/extensibility/hooks/loader.ts +3 -21
- package/src/extensibility/session-handler-types.ts +21 -0
- package/src/internal-urls/docs-index.generated.txt +1 -1
- package/src/jsonrpc/message-framing.ts +142 -0
- package/src/lsp/client.ts +13 -109
- package/src/mcp/transports/stdio.ts +20 -4
- package/src/mnemopi/embed-client.ts +43 -198
- package/src/modes/components/agent-dashboard.ts +17 -40
- package/src/modes/components/chat-transcript-builder.ts +18 -102
- package/src/modes/components/custom-editor.test.ts +22 -0
- package/src/modes/components/custom-editor.ts +29 -1
- package/src/modes/components/extensions/extension-dashboard.ts +4 -13
- package/src/modes/components/extensions/extension-list.ts +16 -44
- package/src/modes/components/footer.ts +4 -3
- package/src/modes/components/history-search.ts +4 -16
- package/src/modes/components/selector-helpers.ts +129 -0
- package/src/modes/components/settings-selector.ts +7 -5
- package/src/modes/components/status-line/component.ts +5 -1
- package/src/modes/components/status-line/context-thresholds.ts +11 -3
- package/src/modes/components/status-line/segments.ts +1 -1
- package/src/modes/components/status-line/types.ts +1 -0
- package/src/modes/components/tree-selector.ts +13 -18
- package/src/modes/controllers/command-controller.ts +1 -0
- package/src/modes/controllers/event-controller.ts +3 -9
- package/src/modes/controllers/input-controller.ts +32 -54
- package/src/modes/interactive-mode.ts +5 -7
- package/src/modes/theme/theme.ts +35 -0
- package/src/modes/types.ts +0 -2
- package/src/modes/utils/copy-targets.ts +3 -2
- package/src/modes/utils/interactive-context-helpers.ts +27 -0
- package/src/modes/utils/transcript-render-helpers.ts +157 -0
- package/src/modes/utils/ui-helpers.ts +21 -126
- package/src/prompts/system/system-prompt.md +5 -5
- package/src/prompts/tools/bash.md +2 -3
- package/src/prompts/tools/eval.md +6 -4
- package/src/prompts/tools/find.md +0 -4
- package/src/prompts/tools/read.md +1 -2
- package/src/prompts/tools/replace.md +1 -1
- package/src/sdk.ts +13 -7
- package/src/secrets/obfuscator.ts +3 -9
- package/src/session/agent-session.ts +42 -9
- package/src/slash-commands/builtin-registry.ts +2 -1
- package/src/stt/asr-client.ts +35 -215
- package/src/stt/asr-worker.ts +29 -181
- package/src/subprocess/worker-client.ts +297 -0
- package/src/subprocess/worker-runtime.ts +277 -0
- package/src/task/executor.ts +4 -4
- package/src/tiny/title-client.ts +53 -219
- package/src/tiny/worker.ts +29 -180
- package/src/tools/eval-backends.ts +10 -3
- package/src/tools/eval-render.ts +17 -8
- package/src/tools/eval.ts +187 -22
- package/src/tools/index.ts +51 -28
- package/src/tts/tts-client.ts +38 -206
- package/src/tts/tts-worker.ts +23 -97
- package/src/tui/code-cell.ts +12 -1
- package/src/utils/file-display-mode.ts +2 -3
- package/src/utils/shell-snapshot.ts +63 -1
- package/src/web/parallel.ts +43 -42
- package/src/web/search/providers/parallel.ts +10 -99
- package/src/web/search/providers/perplexity.ts +18 -6
|
@@ -22,7 +22,7 @@ export type MessageBlock = ({ kind: "code" } & CodeBlock) | ({ kind: "quote" } &
|
|
|
22
22
|
export interface LastCommand {
|
|
23
23
|
kind: "bash" | "eval";
|
|
24
24
|
code: string;
|
|
25
|
-
/** Highlight language: "bash" for bash, "python"/"javascript"
|
|
25
|
+
/** Highlight language: "bash" for bash, or the resolved eval language ("python"/"javascript"/"ruby"/"julia"). */
|
|
26
26
|
language: string;
|
|
27
27
|
}
|
|
28
28
|
|
|
@@ -139,7 +139,8 @@ function extractEvalCode(args: unknown): { code: string; language: string } | un
|
|
|
139
139
|
if (typeof code !== "string" || code.length === 0) continue;
|
|
140
140
|
codeBlocks.push(code);
|
|
141
141
|
if (!languageResolved) {
|
|
142
|
-
|
|
142
|
+
const lang = (cell as { language?: unknown }).language;
|
|
143
|
+
language = lang === "js" ? "javascript" : lang === "rb" ? "ruby" : lang === "jl" ? "julia" : "python";
|
|
143
144
|
languageResolved = true;
|
|
144
145
|
}
|
|
145
146
|
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Small helpers over {@link InteractiveModeContext} shared between
|
|
3
|
+
* {@link UiHelpers} and the input/event controllers, so the live chat surfaces
|
|
4
|
+
* construct components and reset editor state identically.
|
|
5
|
+
*/
|
|
6
|
+
import type { AssistantMessage } from "@oh-my-pi/pi-ai";
|
|
7
|
+
import { AssistantMessageComponent } from "../components/assistant-message";
|
|
8
|
+
import type { InteractiveModeContext } from "../types";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Construct an {@link AssistantMessageComponent} wired to the live context's
|
|
12
|
+
* thinking/image settings. `message` is omitted for the streaming placeholder
|
|
13
|
+
* component and supplied when rendering a persisted turn.
|
|
14
|
+
*/
|
|
15
|
+
export function createAssistantMessageComponent(
|
|
16
|
+
ctx: InteractiveModeContext,
|
|
17
|
+
message?: AssistantMessage,
|
|
18
|
+
): AssistantMessageComponent {
|
|
19
|
+
return new AssistantMessageComponent(
|
|
20
|
+
message,
|
|
21
|
+
ctx.hideThinkingBlock,
|
|
22
|
+
() => ctx.ui.requestRender(),
|
|
23
|
+
ctx.viewSession.extensionRunner?.getAssistantThinkingRenderers(),
|
|
24
|
+
ctx.ui.imageBudget,
|
|
25
|
+
ctx.proseOnlyThinking,
|
|
26
|
+
);
|
|
27
|
+
}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Render helpers shared between the live transcript ({@link UiHelpers}) and the
|
|
3
|
+
* file/remote-backed {@link ChatTranscriptBuilder}. Both surfaces build the same
|
|
4
|
+
* transcript rows from persisted message entries; holding the row construction
|
|
5
|
+
* here keeps the two byte-for-byte identical.
|
|
6
|
+
*/
|
|
7
|
+
import type { AgentMessage } from "@oh-my-pi/pi-agent-core";
|
|
8
|
+
import { type Component, Text } from "@oh-my-pi/pi-tui";
|
|
9
|
+
import { formatBytes, formatDuration } from "@oh-my-pi/pi-utils";
|
|
10
|
+
import { type CustomMessage, type FileMentionMessage, isSilentAbort, resolveAbortLabel } from "../../session/messages";
|
|
11
|
+
import { createIrcMessageCard } from "../../tools/irc";
|
|
12
|
+
import { canonicalizeMessage } from "../../utils/thinking-display";
|
|
13
|
+
import { TranscriptBlock } from "../components/transcript-container";
|
|
14
|
+
import { theme } from "../theme/theme";
|
|
15
|
+
|
|
16
|
+
type CustomOrHookMessage = Extract<AgentMessage, { role: "custom" | "hookMessage" }>;
|
|
17
|
+
type AssistantAgentMessage = Extract<AgentMessage, { role: "assistant" }>;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Render an `async-result` custom message (a completed background bash/task job,
|
|
21
|
+
* or a batch of them) as a transcript block of one "Background job completed"
|
|
22
|
+
* row per job.
|
|
23
|
+
*/
|
|
24
|
+
export function buildAsyncResultBlock(message: CustomOrHookMessage): TranscriptBlock {
|
|
25
|
+
const details = (
|
|
26
|
+
message as CustomMessage<{
|
|
27
|
+
jobId?: string;
|
|
28
|
+
type?: "bash" | "task";
|
|
29
|
+
label?: string;
|
|
30
|
+
durationMs?: number;
|
|
31
|
+
jobs?: Array<{ jobId?: string; type?: "bash" | "task"; label?: string; durationMs?: number }>;
|
|
32
|
+
}>
|
|
33
|
+
).details;
|
|
34
|
+
const jobs =
|
|
35
|
+
details?.jobs && details.jobs.length > 0
|
|
36
|
+
? details.jobs
|
|
37
|
+
: [
|
|
38
|
+
{
|
|
39
|
+
jobId: details?.jobId,
|
|
40
|
+
type: details?.type,
|
|
41
|
+
label: details?.label,
|
|
42
|
+
durationMs: details?.durationMs,
|
|
43
|
+
},
|
|
44
|
+
];
|
|
45
|
+
const block = new TranscriptBlock();
|
|
46
|
+
for (const job of jobs) {
|
|
47
|
+
const jobId = job.jobId ?? "unknown";
|
|
48
|
+
const typeLabel = job.type ? `[${job.type}]` : "[job]";
|
|
49
|
+
const duration = typeof job.durationMs === "number" ? formatDuration(job.durationMs) : undefined;
|
|
50
|
+
const line = [
|
|
51
|
+
theme.fg("success", `${theme.status.done} Background job completed`),
|
|
52
|
+
theme.fg("dim", typeLabel),
|
|
53
|
+
theme.fg("accent", jobId),
|
|
54
|
+
duration ? theme.fg("dim", `(${duration})`) : undefined,
|
|
55
|
+
]
|
|
56
|
+
.filter(Boolean)
|
|
57
|
+
.join(" ");
|
|
58
|
+
block.addChild(new Text(line, 1, 0));
|
|
59
|
+
}
|
|
60
|
+
return block;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Render a live IRC traffic custom message (`irc:incoming` / `irc:autoreply` /
|
|
65
|
+
* `irc:relay`) as a transcript card. `getExpanded` supplies the live
|
|
66
|
+
* expanded-state getter for the cached card.
|
|
67
|
+
*/
|
|
68
|
+
export function buildIrcMessageCard(message: CustomOrHookMessage, getExpanded: () => boolean): Component {
|
|
69
|
+
const details = (
|
|
70
|
+
message as CustomMessage<{ from?: string; to?: string; message?: string; body?: string; replyTo?: string }>
|
|
71
|
+
).details;
|
|
72
|
+
const kind =
|
|
73
|
+
message.customType === "irc:incoming"
|
|
74
|
+
? ("incoming" as const)
|
|
75
|
+
: message.customType === "irc:autoreply"
|
|
76
|
+
? ("autoreply" as const)
|
|
77
|
+
: ("relay" as const);
|
|
78
|
+
return createIrcMessageCard(
|
|
79
|
+
{
|
|
80
|
+
kind,
|
|
81
|
+
from: details?.from,
|
|
82
|
+
to: details?.to,
|
|
83
|
+
body: kind === "incoming" ? details?.message : details?.body,
|
|
84
|
+
replyTo: details?.replyTo,
|
|
85
|
+
timestamp: message.timestamp,
|
|
86
|
+
},
|
|
87
|
+
getExpanded,
|
|
88
|
+
theme,
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Render a `fileMention` message's files as a transcript block of "Read <path>"
|
|
94
|
+
* rows. `indent` sets the left pad: the live chat renders within an outer gutter
|
|
95
|
+
* (0), the transcript viewer renders body rows without one so rows own their pad
|
|
96
|
+
* (1).
|
|
97
|
+
*/
|
|
98
|
+
export function buildFileMentionBlock(files: FileMentionMessage["files"], indent: number): TranscriptBlock {
|
|
99
|
+
const block = new TranscriptBlock();
|
|
100
|
+
for (const file of files) {
|
|
101
|
+
let suffix: string;
|
|
102
|
+
if (file.skippedReason === "tooLarge") {
|
|
103
|
+
const size = typeof file.byteSize === "number" ? formatBytes(file.byteSize) : "unknown size";
|
|
104
|
+
suffix = `(skipped: ${size})`;
|
|
105
|
+
} else {
|
|
106
|
+
suffix = file.image
|
|
107
|
+
? "(image)"
|
|
108
|
+
: file.lineCount === undefined
|
|
109
|
+
? "(unknown lines)"
|
|
110
|
+
: `(${file.lineCount} lines)`;
|
|
111
|
+
}
|
|
112
|
+
const text = `${theme.fg("dim", `${theme.tree.last} `)}${theme.fg("muted", "Read")} ${theme.fg(
|
|
113
|
+
"accent",
|
|
114
|
+
file.path,
|
|
115
|
+
)} ${theme.fg("dim", suffix)}`;
|
|
116
|
+
block.addChild(new Text(text, indent, 0));
|
|
117
|
+
}
|
|
118
|
+
return block;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Whether an assistant turn has visible text or thinking content (after
|
|
123
|
+
* canonicalization) — i.e. content that closes the current read-tool run.
|
|
124
|
+
*/
|
|
125
|
+
export function assistantHasVisibleContent(message: AssistantAgentMessage): boolean {
|
|
126
|
+
return message.content.some(
|
|
127
|
+
content =>
|
|
128
|
+
(content.type === "text" && canonicalizeMessage(content.text)) ||
|
|
129
|
+
(content.type === "thinking" && canonicalizeMessage(content.thinking)),
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Normalize raw tool-call arguments to a plain record, collapsing non-object or
|
|
135
|
+
* array values to an empty object.
|
|
136
|
+
*/
|
|
137
|
+
export function normalizeToolArgs(args: unknown): Record<string, unknown> {
|
|
138
|
+
return args && typeof args === "object" && !Array.isArray(args) ? (args as Record<string, unknown>) : {};
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Resolve the inline error label, if any, for a turn-ending assistant message.
|
|
143
|
+
* Silent aborts yield no label. `retryAttempt` tunes the abort label wording.
|
|
144
|
+
*/
|
|
145
|
+
export function resolveAssistantErrorMessage(
|
|
146
|
+
message: AssistantAgentMessage,
|
|
147
|
+
retryAttempt = 0,
|
|
148
|
+
): { hasErrorStop: boolean; errorMessage: string | null } {
|
|
149
|
+
const isAbortedSilently = message.stopReason === "aborted" && isSilentAbort(message.errorMessage);
|
|
150
|
+
const hasErrorStop = !isAbortedSilently && (message.stopReason === "aborted" || message.stopReason === "error");
|
|
151
|
+
const errorMessage = hasErrorStop
|
|
152
|
+
? message.stopReason === "aborted"
|
|
153
|
+
? resolveAbortLabel(message.errorMessage, retryAttempt)
|
|
154
|
+
: message.errorMessage || "Error"
|
|
155
|
+
: null;
|
|
156
|
+
return { hasErrorStop, errorMessage };
|
|
157
|
+
}
|
|
@@ -39,16 +39,20 @@ import type { CompactionQueuedMessage, InteractiveModeContext } from "../../mode
|
|
|
39
39
|
import {
|
|
40
40
|
BACKGROUND_TAN_DISPATCH_MESSAGE_TYPE,
|
|
41
41
|
type CustomMessage,
|
|
42
|
-
isSilentAbort,
|
|
43
42
|
LSP_LATE_DIAGNOSTIC_MESSAGE_TYPE,
|
|
44
|
-
resolveAbortLabel,
|
|
45
43
|
SKILL_PROMPT_MESSAGE_TYPE,
|
|
46
44
|
type SkillPromptDetails,
|
|
47
45
|
} from "../../session/messages";
|
|
48
46
|
import type { SessionContext } from "../../session/session-context";
|
|
49
|
-
import {
|
|
50
|
-
import {
|
|
51
|
-
|
|
47
|
+
import { createAssistantMessageComponent } from "./interactive-context-helpers";
|
|
48
|
+
import {
|
|
49
|
+
assistantHasVisibleContent,
|
|
50
|
+
buildAsyncResultBlock,
|
|
51
|
+
buildFileMentionBlock,
|
|
52
|
+
buildIrcMessageCard,
|
|
53
|
+
normalizeToolArgs,
|
|
54
|
+
resolveAssistantErrorMessage,
|
|
55
|
+
} from "./transcript-render-helpers";
|
|
52
56
|
|
|
53
57
|
type TextBlock = { type: "text"; text: string };
|
|
54
58
|
interface RenderInitialMessagesOptions {
|
|
@@ -143,47 +147,7 @@ export class UiHelpers {
|
|
|
143
147
|
case "custom": {
|
|
144
148
|
if (message.display) {
|
|
145
149
|
if (message.customType === "async-result") {
|
|
146
|
-
|
|
147
|
-
message as CustomMessage<{
|
|
148
|
-
jobId?: string;
|
|
149
|
-
type?: "bash" | "task";
|
|
150
|
-
label?: string;
|
|
151
|
-
durationMs?: number;
|
|
152
|
-
jobs?: Array<{
|
|
153
|
-
jobId?: string;
|
|
154
|
-
type?: "bash" | "task";
|
|
155
|
-
label?: string;
|
|
156
|
-
durationMs?: number;
|
|
157
|
-
}>;
|
|
158
|
-
}>
|
|
159
|
-
).details;
|
|
160
|
-
const jobs =
|
|
161
|
-
details?.jobs && details.jobs.length > 0
|
|
162
|
-
? details.jobs
|
|
163
|
-
: [
|
|
164
|
-
{
|
|
165
|
-
jobId: details?.jobId,
|
|
166
|
-
type: details?.type,
|
|
167
|
-
label: details?.label,
|
|
168
|
-
durationMs: details?.durationMs,
|
|
169
|
-
},
|
|
170
|
-
];
|
|
171
|
-
const block = new TranscriptBlock();
|
|
172
|
-
for (const job of jobs) {
|
|
173
|
-
const jobId = job.jobId ?? "unknown";
|
|
174
|
-
const typeLabel = job.type ? `[${job.type}]` : "[job]";
|
|
175
|
-
const duration = typeof job.durationMs === "number" ? formatDuration(job.durationMs) : undefined;
|
|
176
|
-
const line = [
|
|
177
|
-
theme.fg("success", `${theme.status.done} Background job completed`),
|
|
178
|
-
theme.fg("dim", typeLabel),
|
|
179
|
-
theme.fg("accent", jobId),
|
|
180
|
-
duration ? theme.fg("dim", `(${duration})`) : undefined,
|
|
181
|
-
]
|
|
182
|
-
.filter(Boolean)
|
|
183
|
-
.join(" ");
|
|
184
|
-
block.addChild(new Text(line, 1, 0));
|
|
185
|
-
}
|
|
186
|
-
this.ctx.chatContainer.addChild(block);
|
|
150
|
+
this.ctx.chatContainer.addChild(buildAsyncResultBlock(message));
|
|
187
151
|
break;
|
|
188
152
|
}
|
|
189
153
|
if (message.customType === LSP_LATE_DIAGNOSTIC_MESSAGE_TYPE) {
|
|
@@ -213,33 +177,7 @@ export class UiHelpers {
|
|
|
213
177
|
message.customType === "irc:autoreply" ||
|
|
214
178
|
message.customType === "irc:relay"
|
|
215
179
|
) {
|
|
216
|
-
const
|
|
217
|
-
message as CustomMessage<{
|
|
218
|
-
from?: string;
|
|
219
|
-
to?: string;
|
|
220
|
-
message?: string;
|
|
221
|
-
body?: string;
|
|
222
|
-
replyTo?: string;
|
|
223
|
-
}>
|
|
224
|
-
).details;
|
|
225
|
-
const kind =
|
|
226
|
-
message.customType === "irc:incoming"
|
|
227
|
-
? ("incoming" as const)
|
|
228
|
-
: message.customType === "irc:autoreply"
|
|
229
|
-
? ("autoreply" as const)
|
|
230
|
-
: ("relay" as const);
|
|
231
|
-
const card = createIrcMessageCard(
|
|
232
|
-
{
|
|
233
|
-
kind,
|
|
234
|
-
from: details?.from,
|
|
235
|
-
to: details?.to,
|
|
236
|
-
body: kind === "incoming" ? details?.message : details?.body,
|
|
237
|
-
replyTo: details?.replyTo,
|
|
238
|
-
timestamp: message.timestamp,
|
|
239
|
-
},
|
|
240
|
-
() => this.ctx.toolOutputExpanded,
|
|
241
|
-
theme,
|
|
242
|
-
);
|
|
180
|
+
const card = buildIrcMessageCard(message, () => this.ctx.toolOutputExpanded);
|
|
243
181
|
this.ctx.chatContainer.addChild(card);
|
|
244
182
|
return [card];
|
|
245
183
|
}
|
|
@@ -284,25 +222,7 @@ export class UiHelpers {
|
|
|
284
222
|
}
|
|
285
223
|
case "fileMention": {
|
|
286
224
|
// Render compact file mention display
|
|
287
|
-
const block =
|
|
288
|
-
for (const file of message.files) {
|
|
289
|
-
let suffix: string;
|
|
290
|
-
if (file.skippedReason === "tooLarge") {
|
|
291
|
-
const size = typeof file.byteSize === "number" ? formatBytes(file.byteSize) : "unknown size";
|
|
292
|
-
suffix = `(skipped: ${size})`;
|
|
293
|
-
} else {
|
|
294
|
-
suffix = file.image
|
|
295
|
-
? "(image)"
|
|
296
|
-
: file.lineCount === undefined
|
|
297
|
-
? "(unknown lines)"
|
|
298
|
-
: `(${file.lineCount} lines)`;
|
|
299
|
-
}
|
|
300
|
-
const text = `${theme.fg("dim", `${theme.tree.last} `)}${theme.fg("muted", "Read")} ${theme.fg(
|
|
301
|
-
"accent",
|
|
302
|
-
file.path,
|
|
303
|
-
)} ${theme.fg("dim", suffix)}`;
|
|
304
|
-
block.addChild(new Text(text, 0, 0));
|
|
305
|
-
}
|
|
225
|
+
const block = buildFileMentionBlock(message.files, 0);
|
|
306
226
|
if (block.children.length > 0) this.ctx.chatContainer.addChild(block);
|
|
307
227
|
break;
|
|
308
228
|
}
|
|
@@ -326,14 +246,7 @@ export class UiHelpers {
|
|
|
326
246
|
break;
|
|
327
247
|
}
|
|
328
248
|
case "assistant": {
|
|
329
|
-
const assistantComponent =
|
|
330
|
-
message,
|
|
331
|
-
this.ctx.hideThinkingBlock,
|
|
332
|
-
() => this.ctx.ui.requestRender(),
|
|
333
|
-
this.ctx.viewSession.extensionRunner?.getAssistantThinkingRenderers(),
|
|
334
|
-
this.ctx.ui.imageBudget,
|
|
335
|
-
this.ctx.proseOnlyThinking,
|
|
336
|
-
);
|
|
249
|
+
const assistantComponent = createAssistantMessageComponent(this.ctx, message);
|
|
337
250
|
this.ctx.chatContainer.addChild(assistantComponent);
|
|
338
251
|
break;
|
|
339
252
|
}
|
|
@@ -425,11 +338,7 @@ export class UiHelpers {
|
|
|
425
338
|
this.ctx.lastAssistantUsage = usage;
|
|
426
339
|
}
|
|
427
340
|
}
|
|
428
|
-
const hasVisibleAssistantContent = message
|
|
429
|
-
content =>
|
|
430
|
-
(content.type === "text" && canonicalizeMessage(content.text)) ||
|
|
431
|
-
(content.type === "thinking" && canonicalizeMessage(content.thinking)),
|
|
432
|
-
);
|
|
341
|
+
const hasVisibleAssistantContent = assistantHasVisibleContent(message);
|
|
433
342
|
if (hasVisibleAssistantContent) {
|
|
434
343
|
// Rebuild reconstructs immutable history; seal (not finalize) so the
|
|
435
344
|
// group freezes even if a read's result was never persisted —
|
|
@@ -438,14 +347,10 @@ export class UiHelpers {
|
|
|
438
347
|
readGroup?.seal();
|
|
439
348
|
readGroup = null;
|
|
440
349
|
}
|
|
441
|
-
const
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
? message.stopReason === "aborted"
|
|
446
|
-
? resolveAbortLabel(message.errorMessage, this.ctx.viewSession.retryAttempt)
|
|
447
|
-
: message.errorMessage || "Error"
|
|
448
|
-
: null;
|
|
350
|
+
const { hasErrorStop, errorMessage } = resolveAssistantErrorMessage(
|
|
351
|
+
message,
|
|
352
|
+
this.ctx.viewSession.retryAttempt,
|
|
353
|
+
);
|
|
449
354
|
|
|
450
355
|
// Render tool call components
|
|
451
356
|
for (const content of message.content) {
|
|
@@ -474,10 +379,7 @@ export class UiHelpers {
|
|
|
474
379
|
content.id,
|
|
475
380
|
);
|
|
476
381
|
} else {
|
|
477
|
-
const normalizedArgs =
|
|
478
|
-
content.arguments && typeof content.arguments === "object" && !Array.isArray(content.arguments)
|
|
479
|
-
? (content.arguments as Record<string, unknown>)
|
|
480
|
-
: {};
|
|
382
|
+
const normalizedArgs = normalizeToolArgs(content.arguments);
|
|
481
383
|
readToolCallArgs.set(content.id, normalizedArgs);
|
|
482
384
|
if (assistantComponent) {
|
|
483
385
|
readToolCallAssistantComponents.set(content.id, assistantComponent);
|
|
@@ -647,10 +549,7 @@ export class UiHelpers {
|
|
|
647
549
|
}
|
|
648
550
|
|
|
649
551
|
clearEditor(): void {
|
|
650
|
-
this.ctx.editor.
|
|
651
|
-
this.ctx.pendingImages = [];
|
|
652
|
-
this.ctx.pendingImageLinks = [];
|
|
653
|
-
this.ctx.editor.imageLinks = undefined;
|
|
552
|
+
this.ctx.editor.clearDraft();
|
|
654
553
|
this.ctx.ui.requestRender();
|
|
655
554
|
}
|
|
656
555
|
|
|
@@ -719,11 +618,7 @@ export class UiHelpers {
|
|
|
719
618
|
queueCompactionMessage(text: string, mode: "steer" | "followUp", images?: ImageContent[]): void {
|
|
720
619
|
const queuedImages = images && images.length > 0 ? images : undefined;
|
|
721
620
|
this.ctx.compactionQueuedMessages.push({ text, mode, images: queuedImages } as CompactionQueuedMessage);
|
|
722
|
-
this.ctx.editor.
|
|
723
|
-
this.ctx.editor.setText("");
|
|
724
|
-
this.ctx.editor.imageLinks = undefined;
|
|
725
|
-
this.ctx.pendingImages = [];
|
|
726
|
-
this.ctx.pendingImageLinks = [];
|
|
621
|
+
this.ctx.editor.clearDraft(text);
|
|
727
622
|
this.ctx.updatePendingMessagesDisplay();
|
|
728
623
|
this.ctx.showStatus(
|
|
729
624
|
queuedImages ? "Queued message with image for after compaction" : "Queued message for after compaction",
|
|
@@ -101,12 +101,12 @@ Use tools whenever they improve correctness, completeness, or grounding.
|
|
|
101
101
|
{{#if secretsEnabled}}- Redacted `#XXXX#` tokens in output are opaque strings.{{/if}}
|
|
102
102
|
{{#has tools "inspect_image"}}- Image tasks: prefer `{{toolRefs.inspect_image}}` over `{{toolRefs.read}}` to spare session context.{{/has}}
|
|
103
103
|
|
|
104
|
-
# Specialized
|
|
104
|
+
# Specialized Tools
|
|
105
105
|
You MUST use the specialized tool over its shell equivalent:
|
|
106
|
-
{{#has tools "read"}}- File or directory reads → `{{toolRefs.read}}
|
|
107
|
-
{{#has tools "edit"}}- Surgical edits → `{{toolRefs.edit}}
|
|
108
|
-
{{#has tools "write"}}- Create or overwrite → `{{toolRefs.write}}
|
|
109
|
-
{{#has tools "lsp"}}- Code intelligence → `{{toolRefs.lsp}}
|
|
106
|
+
{{#has tools "read"}}- File or directory reads → `{{toolRefs.read}}` (a directory path lists entries).{{/has}}
|
|
107
|
+
{{#has tools "edit"}}- Surgical edits → `{{toolRefs.edit}}`.{{/has}}
|
|
108
|
+
{{#has tools "write"}}- Create or overwrite → `{{toolRefs.write}}`.{{/has}}
|
|
109
|
+
{{#has tools "lsp"}}- Code intelligence → `{{toolRefs.lsp}}`.{{/has}}
|
|
110
110
|
{{#has tools "search"}}- Regex search → `{{toolRefs.search}}`, not `grep`, `rg`, or `awk`.{{/has}}
|
|
111
111
|
{{#has tools "find"}}- Globbing → `{{toolRefs.find}}`, not `ls **/*.ext` or `fd`.{{/has}}
|
|
112
112
|
{{#has tools "eval"}}- Quick compute → `{{toolRefs.eval}}`; you SHOULD go step by step.{{/has}}
|
|
@@ -14,9 +14,8 @@ Runs bash in a shell session — terminal ops: git, bun, cargo, python.
|
|
|
14
14
|
</instruction>
|
|
15
15
|
|
|
16
16
|
<critical>
|
|
17
|
-
- NEVER shell out to
|
|
18
|
-
-
|
|
19
|
-
- Pipelines that COMPUTE a new fact are correct bash: `wc -l`, `sort | uniq -c`, `comm`, `cut`, `diff a b`, `shasum`. Litmus: produces a count, frequency table, set difference, or checksum no tool returns → bash. Merely moves or trims bytes a tool can fetch → use the tool.
|
|
17
|
+
- NEVER shell out to search content or files: `grep/rg` → `search`.
|
|
18
|
+
- Avoid head/tail/redirections: stderr already merged; long output auto-truncated, FULL capture kept at `artifact://<id>`.
|
|
20
19
|
</critical>
|
|
21
20
|
|
|
22
21
|
<output>
|
|
@@ -5,7 +5,7 @@ Cells run in array order. State persists per language across cells, tool calls,
|
|
|
5
5
|
|
|
6
6
|
Cell fields:
|
|
7
7
|
|
|
8
|
-
- `language` — {{#if py}}`"py"` IPython kernel{{/if}}{{#ifAll py js}}, {{/ifAll}}{{#if js}}`"js"` persistent JavaScript VM{{/if}}.
|
|
8
|
+
- `language` — {{#if py}}`"py"` IPython kernel{{/if}}{{#ifAll py js}}, {{/ifAll}}{{#if js}}`"js"` persistent JavaScript VM{{/if}}{{#if rb}}{{#ifAny py js}}, {{/ifAny}}`"rb"` persistent Ruby kernel{{/if}}{{#if jl}}{{#ifAny py js rb}}, {{/ifAny}}`"jl"` persistent Julia kernel{{/if}}.
|
|
9
9
|
- `code` — cell body, verbatim. Newlines/quotes JSON-encoded; no fences, no headers.
|
|
10
10
|
- `title` (optional) — short transcript label (e.g. `"imports"`).
|
|
11
11
|
- `timeout` (optional) — per-cell seconds. Raise only for heavy compute or long non-agent tool calls.
|
|
@@ -13,11 +13,13 @@ Cell fields:
|
|
|
13
13
|
|
|
14
14
|
Work incrementally — one logical step per cell (imports, define, test, use), many small cells per call; workflow notes in the assistant message or `title`, never in cell code.
|
|
15
15
|
{{#if py}}Live event loop: use top-level `await` directly; `asyncio.run(…)` raises "cannot be called from a running event loop".{{/if}}
|
|
16
|
+
{{#if rb}}Ruby: synchronous; helper options are keyword args (e.g. `tree(".", max_depth: 2)`); the last expression auto-displays unless it is `nil`, an assignment, or a definition (like IRB).{{/if}}
|
|
17
|
+
{{#if jl}}Julia: synchronous; helper options are standard keyword args (e.g. `tree(max_depth=2)`); the last expression auto-displays unless it is an assignment or a definition (like the Julia REPL).{{/if}}
|
|
16
18
|
Errors name the failing cell ("Cell 3 failed") — resubmit the fixed cell + any remaining.
|
|
17
19
|
</instruction>
|
|
18
20
|
|
|
19
21
|
<prelude>
|
|
20
|
-
{{#ifAll py js}}Same helpers + arg order, both runtimes. Python: sync, options = trailing kwargs. JS: async/`await`able, options = ONE trailing object literal, never positional (extras throw).{{else}}{{#if py}}Sync; options = trailing kwargs.{{/if}}{{#if js}}Async/`await`able; options = ONE trailing object literal, never positional (extras throw).{{/if}}{{/ifAll}}
|
|
22
|
+
{{#ifAll py js}}Same helpers + arg order, both runtimes. Python: sync, options = trailing kwargs. JS: async/`await`able, options = ONE trailing object literal, never positional (extras throw).{{else}}{{#if py}}Sync; options = trailing kwargs.{{/if}}{{#if js}}Async/`await`able; options = ONE trailing object literal, never positional (extras throw).{{/if}}{{/ifAll}}{{#if rb}} Ruby: sync, options = trailing keyword args.{{/if}}{{#if jl}} Julia: sync, options = trailing keyword args.{{/if}}
|
|
21
23
|
```
|
|
22
24
|
display(value) → None
|
|
23
25
|
Cell output; figures/images/dataframes shown natively.
|
|
@@ -55,13 +57,13 @@ log(message) → None
|
|
|
55
57
|
phase(title) → None
|
|
56
58
|
Phase grouping subsequent status lines.
|
|
57
59
|
budget → per-turn token budget
|
|
58
|
-
{{#if py}}`budget.total` (ceiling or None), `budget.spent()`, `budget.remaining()` (math.inf when no ceiling), `budget.hard`.{{/if}}{{#if js}}`await budget.total()` (ceiling or null), `await budget.spent()`, `await budget.remaining()` (Infinity when no ceiling), `await budget.hard()`.{{/if}} Ceiling: `+Nk` (advisory) or `+Nk!`/Goal Mode (hard — `agent()` won't spawn past it); spend still tracked.
|
|
60
|
+
{{#if py}}`budget.total` (ceiling or None), `budget.spent()`, `budget.remaining()` (math.inf when no ceiling), `budget.hard`.{{/if}}{{#if js}}`await budget.total()` (ceiling or null), `await budget.spent()`, `await budget.remaining()` (Infinity when no ceiling), `await budget.hard()`.{{/if}}{{#if rb}} Ruby: `budget.total` (ceiling or nil), `budget.spent`, `budget.remaining` (Float::INFINITY when no ceiling), `budget.hard`.{{/if}}{{#if jl}} Julia: `budget.total` (ceiling or nothing), `budget.spent()`, `budget.remaining()` (Inf when no ceiling), `budget.hard`.{{/if}} Ceiling: `+Nk` (advisory) or `+Nk!`/Goal Mode (hard — `agent()` won't spawn past it); spend still tracked.
|
|
59
61
|
```
|
|
60
62
|
</prelude>
|
|
61
63
|
{{#if spawns}}
|
|
62
64
|
<dag>
|
|
63
65
|
Pipe handles through stage helpers to build a dependency graph — acyclic waves:
|
|
64
|
-
- **Name nodes.** Capture each `agent(…, {{#if py}}return_handle=True{{/if}}{{#if js}}{ returnHandle: true }{{/if}})` result; carries `handle` (`agent://<id>`) + `output`.
|
|
66
|
+
- **Name nodes.** Capture each `agent(…, {{#if py}}return_handle=True{{/if}}{{#if js}}{ returnHandle: true }{{/if}}{{#if jl}}return_handle=true{{/if}})` result; carries `handle` (`agent://<id>`) + `output`.
|
|
65
67
|
- **Wire edges by reference.** Put an upstream node's `handle`/`output` in the dependent stage's prompt — large transcript never re-inlined. Bulk: `write("local://<name>.md", …)`, pass the URI.
|
|
66
68
|
- **`pipeline(items, *stages)` = staged waves**, barrier between stages (every item clears stage N before any enters N+1). **`parallel(thunks)` = one wave** of independent nodes.
|
|
67
69
|
- **Isolate failure.** A raising node re-raises the lowest-index error, aborts its wave; wrap risky nodes in try/except so a failure degrades only its dependent subtree, independent branches finish.
|
|
@@ -13,7 +13,3 @@ Matching paths sorted by mtime (newest first), grouped under `# <dir>/` headers
|
|
|
13
13
|
<avoid>
|
|
14
14
|
Open-ended searches needing multiple rounds of globbing/searching: you MUST use the Task tool instead.
|
|
15
15
|
</avoid>
|
|
16
|
-
|
|
17
|
-
<critical>
|
|
18
|
-
- You MUST use the built-in Find tool for every file-name lookup. NEVER shell out to `find`, `fd`, `locate`, `ls`, or `git ls-files` via Bash — they ignore `.gitignore`, blow past result limits, and waste tokens.
|
|
19
|
-
</critical>
|
|
@@ -70,7 +70,6 @@ For `.sqlite`, `.sqlite3`, `.db`, `.db3`:
|
|
|
70
70
|
All URI schemes take the same line selectors. `artifact://<id>` recovers full output a bash/eval/tool result spilled or truncated. `history://<agentId>` = agent transcript; bare `history://` lists agents.
|
|
71
71
|
|
|
72
72
|
<critical>
|
|
73
|
-
-
|
|
74
|
-
- Line ranges go in the selector (`path="src/foo.ts:50-200"`) — NEVER `sed -n`, `awk NR`, or `head`/`tail` pipelines.
|
|
73
|
+
- Line ranges go in the selector: `path="src/foo.ts:50-200"`.
|
|
75
74
|
- Summary footer names elided ranges? Re-issue ONLY those ranges. NEVER guess `..`/`…` content.
|
|
76
75
|
</critical>
|
|
@@ -25,5 +25,5 @@ For pattern-addressed bulk changes, bash is more efficient:
|
|
|
25
25
|
|Bulk replace across files|`sd 'pattern' 'replacement' **/*.ts`|
|
|
26
26
|
|
|
27
27
|
Use Replace when _content itself_ identifies location; use `ast_edit` for structure-aware codemods.
|
|
28
|
-
|
|
28
|
+
For in-place edits prefer this tool or `write` — you get a diff preview and fuzzy matching.
|
|
29
29
|
</bash-alternatives>
|
package/src/sdk.ts
CHANGED
|
@@ -46,7 +46,9 @@ import { Settings, type SkillsSettings } from "./config/settings";
|
|
|
46
46
|
import { CursorExecHandlers } from "./cursor";
|
|
47
47
|
import "./discovery";
|
|
48
48
|
import { initializeWithSettings } from "./discovery";
|
|
49
|
+
import { disposeAllJuliaKernelSessions, disposeJuliaKernelSessionsByOwner } from "./eval/jl/executor";
|
|
49
50
|
import { disposeAllKernelSessions, disposeKernelSessionsByOwner } from "./eval/py/executor";
|
|
51
|
+
import { disposeAllRubyKernelSessions, disposeRubyKernelSessionsByOwner } from "./eval/rb/executor";
|
|
50
52
|
import { defaultEvalSessionId } from "./eval/session-id";
|
|
51
53
|
import {
|
|
52
54
|
type CustomCommandsLoadResult,
|
|
@@ -472,7 +474,7 @@ export interface CreateAgentSessionOptions {
|
|
|
472
474
|
|
|
473
475
|
/** Enable LSP integration (tool, formatting, diagnostics, warmup). Default: true */
|
|
474
476
|
enableLsp?: boolean;
|
|
475
|
-
/** Skip
|
|
477
|
+
/** Skip subprocess-kernel availability checks and prelude warmup */
|
|
476
478
|
skipPythonPreflight?: boolean;
|
|
477
479
|
/** Tool names explicitly requested (enables disabled-by-default tools) */
|
|
478
480
|
toolNames?: string[];
|
|
@@ -866,12 +868,14 @@ function registerSshCleanup(): void {
|
|
|
866
868
|
postmortem.register("ssh-cleanup", cleanupSshResources);
|
|
867
869
|
}
|
|
868
870
|
|
|
869
|
-
let
|
|
871
|
+
let evalCleanupRegistered = false;
|
|
870
872
|
|
|
871
|
-
function
|
|
872
|
-
if (
|
|
873
|
-
|
|
873
|
+
function registerEvalCleanup(): void {
|
|
874
|
+
if (evalCleanupRegistered) return;
|
|
875
|
+
evalCleanupRegistered = true;
|
|
874
876
|
postmortem.register("python-cleanup", disposeAllKernelSessions);
|
|
877
|
+
postmortem.register("ruby-cleanup", disposeAllRubyKernelSessions);
|
|
878
|
+
postmortem.register("julia-cleanup", disposeAllJuliaKernelSessions);
|
|
875
879
|
}
|
|
876
880
|
|
|
877
881
|
function customToolToDefinition(tool: CustomTool): ToolDefinition {
|
|
@@ -1080,7 +1084,7 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
1080
1084
|
const eventBus = options.eventBus ?? new EventBus();
|
|
1081
1085
|
|
|
1082
1086
|
registerSshCleanup();
|
|
1083
|
-
|
|
1087
|
+
registerEvalCleanup();
|
|
1084
1088
|
|
|
1085
1089
|
// Pin authStorage to modelRegistry.authStorage: ModelRegistry.getApiKey() routes refresh
|
|
1086
1090
|
// failures through that instance, so any divergent storage handed to the bridge / mcpManager
|
|
@@ -2693,7 +2697,7 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
2693
2697
|
const originalDispose = session.dispose.bind(session);
|
|
2694
2698
|
session.dispose = async () => {
|
|
2695
2699
|
try {
|
|
2696
|
-
// Reject new session work (
|
|
2700
|
+
// Reject new session work (eval starts) the moment disposal
|
|
2697
2701
|
// begins — the lifecycle await below opens an async gap before
|
|
2698
2702
|
// AgentSession.dispose() would otherwise set its guards.
|
|
2699
2703
|
session.beginDispose();
|
|
@@ -2913,6 +2917,8 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
2913
2917
|
await asyncJobManager.dispose({ timeoutMs: 3_000 });
|
|
2914
2918
|
}
|
|
2915
2919
|
await disposeKernelSessionsByOwner(evalKernelOwnerId);
|
|
2920
|
+
await disposeRubyKernelSessionsByOwner(evalKernelOwnerId);
|
|
2921
|
+
await disposeJuliaKernelSessionsByOwner(evalKernelOwnerId);
|
|
2916
2922
|
if (ownsAuthStorage) authStorage.close();
|
|
2917
2923
|
}
|
|
2918
2924
|
} catch (cleanupError) {
|
|
@@ -259,9 +259,9 @@ export function deobfuscateAgentMessages(obfuscator: SecretObfuscator, messages:
|
|
|
259
259
|
}
|
|
260
260
|
|
|
261
261
|
/**
|
|
262
|
-
* Restore placeholders in assistant content: visible text
|
|
263
|
-
*
|
|
264
|
-
*
|
|
262
|
+
* Restore placeholders in assistant content: visible text and tool-call
|
|
263
|
+
* arguments/intent/rawBlock. Thinking and signatures are opaque
|
|
264
|
+
* provider-replay/hidden-reasoning data and pass through byte-identical.
|
|
265
265
|
*/
|
|
266
266
|
export function deobfuscateAssistantContent(
|
|
267
267
|
obfuscator: SecretObfuscator,
|
|
@@ -276,12 +276,6 @@ export function deobfuscateAssistantContent(
|
|
|
276
276
|
changed = true;
|
|
277
277
|
return { ...block, text };
|
|
278
278
|
}
|
|
279
|
-
if (block.type === "thinking") {
|
|
280
|
-
const thinking = obfuscator.deobfuscate(block.thinking);
|
|
281
|
-
if (thinking === block.thinking) return block;
|
|
282
|
-
changed = true;
|
|
283
|
-
return { ...block, thinking };
|
|
284
|
-
}
|
|
285
279
|
if (block.type === "toolCall") {
|
|
286
280
|
const args = deobfuscateToolArguments(obfuscator, block.arguments);
|
|
287
281
|
const intent = block.intent === undefined ? undefined : obfuscator.deobfuscate(block.intent);
|