@code-yeongyu/senpi 2026.8.27 → 2026.8.28
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 +21 -0
- package/dist/core/credential-accounts.d.ts +31 -0
- package/dist/core/credential-accounts.d.ts.map +1 -0
- package/dist/core/credential-accounts.js +125 -0
- package/dist/core/credential-accounts.js.map +1 -0
- package/dist/core/extensions/builtin/account/index.d.ts +9 -0
- package/dist/core/extensions/builtin/account/index.d.ts.map +1 -0
- package/dist/core/extensions/builtin/account/index.js +69 -0
- package/dist/core/extensions/builtin/account/index.js.map +1 -0
- package/dist/core/extensions/builtin/imagegen/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/imagegen/index.js +10 -3
- package/dist/core/extensions/builtin/imagegen/index.js.map +1 -1
- package/dist/core/extensions/builtin/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/index.js +4 -0
- package/dist/core/extensions/builtin/index.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +12 -1
- package/dist/main.js.map +1 -1
- package/dist/modes/app-server/server/account.d.ts.map +1 -1
- package/dist/modes/app-server/server/account.js +5 -5
- package/dist/modes/app-server/server/account.js.map +1 -1
- package/dist/modes/interactive/components/footer.d.ts +11 -3
- package/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/dist/modes/interactive/components/footer.js +31 -1
- package/dist/modes/interactive/components/footer.js.map +1 -1
- package/dist/modes/interactive/grok/chrome.d.ts +4 -4
- package/dist/modes/interactive/grok/chrome.d.ts.map +1 -1
- package/dist/modes/interactive/grok/chrome.js.map +1 -1
- package/dist/modes/interactive/grok/footer.d.ts +3 -3
- package/dist/modes/interactive/grok/footer.d.ts.map +1 -1
- package/dist/modes/interactive/grok/footer.js.map +1 -1
- package/dist/modes/interactive/interactive-host-runtime.d.ts +16 -1
- package/dist/modes/interactive/interactive-host-runtime.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-host-runtime.js +36 -9
- package/dist/modes/interactive/interactive-host-runtime.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +19 -13
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/rpc/connection-handler.d.ts.map +1 -1
- package/dist/modes/rpc/connection-handler.js +12 -5
- package/dist/modes/rpc/connection-handler.js.map +1 -1
- package/dist/modes/rpc/rpc-client.d.ts +16 -3
- package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-client.js +43 -5
- package/dist/modes/rpc/rpc-client.js.map +1 -1
- package/dist/modes/rpc/rpc-types.d.ts +4 -1
- package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-types.js.map +1 -1
- package/dist/modes/rpc/session-command-router.d.ts.map +1 -1
- package/dist/modes/rpc/session-command-router.js +12 -4
- package/dist/modes/rpc/session-command-router.js.map +1 -1
- package/dist/modes/rpc/session-registry.d.ts +9 -0
- package/dist/modes/rpc/session-registry.d.ts.map +1 -1
- package/dist/modes/rpc/session-registry.js +31 -3
- package/dist/modes/rpc/session-registry.js.map +1 -1
- package/docs/providers.md +48 -0
- package/docs/rpc.md +6 -4
- package/node_modules/@code-yeongyu/senpi-codemode/CHANGELOG.md +14 -0
- package/node_modules/@code-yeongyu/senpi-codemode/package.json +4 -4
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/context-manager.ts +13 -1
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/inline-worker.ts +15 -1
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/py/transport.ts +14 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/edit.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/edit.js +20 -4
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/edit.js.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/index.d.ts +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/index.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/index.js.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/post-mutate.d.ts +21 -0
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/post-mutate.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/post-mutate.js +27 -0
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/post-mutate.js.map +1 -0
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/tool-context.d.ts +24 -0
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/tool-context.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/tool-context.js.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/write.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/write.js +7 -2
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/write.js.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/package.json +3 -3
- package/node_modules/@earendil-works/pi-ai/dist/auth/credential-store.d.ts +2 -1
- package/node_modules/@earendil-works/pi-ai/dist/auth/credential-store.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/auth/credential-store.js +2 -1
- package/node_modules/@earendil-works/pi-ai/dist/auth/credential-store.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/auth/types.d.ts +3 -2
- package/node_modules/@earendil-works/pi-ai/dist/auth/types.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/auth/types.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/.manifest.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/alibaba-token-plan.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/fireworks.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/github-copilot.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/nvidia.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/openai-codex.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/openai.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/openrouter.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/qwen-token-plan-cn.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/qwen-token-plan.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/together.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/vercel-ai-gateway.json +1 -1
- package/node_modules/@earendil-works/pi-ai/package.json +2 -2
- package/node_modules/@earendil-works/pi-pty/package.json +1 -1
- package/node_modules/@earendil-works/pi-telemetry/package.json +1 -1
- package/node_modules/@earendil-works/pi-tui/package.json +1 -1
- package/package.json +7 -7
|
@@ -1,4 +1,7 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
1
2
|
import { isAbsolute, relative, resolve, sep } from "node:path";
|
|
3
|
+
import { rendezvousOrder } from "@earendil-works/pi-ai/auth/pool/select";
|
|
4
|
+
import { listSlots } from "@earendil-works/pi-ai/auth/pool/slots";
|
|
2
5
|
import { truncateToWidth, visibleWidth } from "@earendil-works/pi-tui";
|
|
3
6
|
import { theme } from "../theme/theme.js";
|
|
4
7
|
import { planFooterLayout } from "./footer-layout.js";
|
|
@@ -34,6 +37,22 @@ export function formatTokens(count) {
|
|
|
34
37
|
return `${trim1(n / 1_000_000_000)}B`;
|
|
35
38
|
return `${Math.round(n / 1_000_000_000)}B`;
|
|
36
39
|
}
|
|
40
|
+
/**
|
|
41
|
+
* Mirrors the provider-shown-only-when->1 rule for accounts: the active account
|
|
42
|
+
* name appears only when the provider actually pools more than one slot. The
|
|
43
|
+
* pick shown is the pin when present, else the session's HRW winner - the same
|
|
44
|
+
* hash the rotation engine uses, so the footer names the slot that will serve.
|
|
45
|
+
*/
|
|
46
|
+
export function accountFooterSuffix(credential, sessionId) {
|
|
47
|
+
const slots = listSlots(credential);
|
|
48
|
+
if (slots.length < 2)
|
|
49
|
+
return "";
|
|
50
|
+
const pinned = Object.entries(credential ?? {}).find(([key]) => key === "pinned")?.[1];
|
|
51
|
+
if (typeof pinned === "string" && slots.some((slot) => slot.name === pinned))
|
|
52
|
+
return `@${pinned}`;
|
|
53
|
+
const winner = rendezvousOrder(sessionId, slots, (input) => createHash("sha256").update(input).digest().readBigUInt64BE(0))[0];
|
|
54
|
+
return winner === undefined ? "" : `@${winner.name}`;
|
|
55
|
+
}
|
|
37
56
|
/** Format with up to 1 decimal place, dropping trailing `.0`. */
|
|
38
57
|
function trim1(n) {
|
|
39
58
|
const s = n.toFixed(1);
|
|
@@ -165,7 +184,18 @@ export class FooterComponent {
|
|
|
165
184
|
minimalRight = thinkingLevel === "off" ? `${minimalRight}:off` : `${minimalRight}:${thinkingLevel}`;
|
|
166
185
|
}
|
|
167
186
|
const minimal = { plain: minimalRight, colored: colorRightSide(minimalRight) };
|
|
168
|
-
|
|
187
|
+
let accountSuffix = "";
|
|
188
|
+
if (state.model) {
|
|
189
|
+
try {
|
|
190
|
+
accountSuffix = accountFooterSuffix(this.session.modelRegistry.authStorage.get(state.model.provider), this.session.sessionManager.getSessionId());
|
|
191
|
+
}
|
|
192
|
+
catch {
|
|
193
|
+
// The footer must render even when credential storage is unreadable.
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
const providerPrefix = (this.footerData.getAvailableProviderCount() > 1 || accountSuffix !== "") && state.model
|
|
197
|
+
? `(${state.model.provider}${accountSuffix}) `
|
|
198
|
+
: "";
|
|
169
199
|
const full = providerPrefix
|
|
170
200
|
? { plain: `${providerPrefix}${minimalRight}`, colored: colorRightSide(`${providerPrefix}${minimalRight}`) }
|
|
171
201
|
: undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"footer.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/footer.ts"],"names":[],"mappings":"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","sourcesContent":["import { isAbsolute, relative, resolve, sep } from \"node:path\";\nimport { type Component, truncateToWidth, visibleWidth } from \"@earendil-works/pi-tui\";\nimport type { AgentSession } from \"../../../core/agent-session.ts\";\nimport type { ReadonlyFooterDataProvider } from \"../../../core/footer-data-provider.ts\";\nimport { theme } from \"../theme/theme.ts\";\nimport { type FooterSegment, planFooterLayout } from \"./footer-layout.ts\";\n\nconst FAST_MODE_INDICATOR = \"\\u26a1 \";\n\n/**\n * Sanitize text for display in a single-line status.\n * Removes newlines, tabs, carriage returns, and other control characters.\n */\nfunction sanitizeStatusText(text: string): string {\n\t// Replace newlines, tabs, carriage returns with space, then collapse multiple spaces\n\treturn text\n\t\t.replace(/[\\r\\n\\t]/g, \" \")\n\t\t.replace(/ +/g, \" \")\n\t\t.trim();\n}\n\n/**\n * Format token counts for footer display using oh-my-pi-style K/M/B abbreviation.\n * Examples: \"999\", \"6.8K\", \"546K\", \"1M\", \"1.5M\", \"2B\".\n */\nexport function formatTokens(count: number): string {\n\tconst n = Math.round(count);\n\tif (n < 1_000) return n.toString();\n\tif (n < 10_000) return `${trim1(n / 1_000)}K`;\n\tif (n < 1_000_000) return `${Math.round(n / 1_000)}K`;\n\tif (n < 10_000_000) return `${trim1(n / 1_000_000)}M`;\n\tif (n < 1_000_000_000) return `${Math.round(n / 1_000_000)}M`;\n\tif (n < 10_000_000_000) return `${trim1(n / 1_000_000_000)}B`;\n\treturn `${Math.round(n / 1_000_000_000)}B`;\n}\n\n/** Format with up to 1 decimal place, dropping trailing `.0`. */\nfunction trim1(n: number): string {\n\tconst s = n.toFixed(1);\n\treturn s.endsWith(\".0\") ? s.slice(0, -2) : s;\n}\n\nexport function formatCwdForFooter(cwd: string, home: string | undefined): string {\n\tif (!home) return cwd;\n\n\tconst resolvedCwd = resolve(cwd);\n\tconst resolvedHome = resolve(home);\n\tconst relativeToHome = relative(resolvedHome, resolvedCwd);\n\tconst isInsideHome =\n\t\trelativeToHome === \"\" ||\n\t\t(relativeToHome !== \"..\" && !relativeToHome.startsWith(`..${sep}`) && !isAbsolute(relativeToHome));\n\n\tif (!isInsideHome) return cwd;\n\treturn relativeToHome === \"\" ? \"~\" : `~${sep}${relativeToHome}`;\n}\n\n/**\n * Color the right side of the footer: (provider) muted, model accent, :thinking dim.\n * The text is the plain (uncolored) right-aligned segment from the layout pass.\n */\nfunction colorRightSide(text: string): string {\n\tif (!text) return \"\";\n\tconst providerMatch = text.match(/^\\(([^)]+)\\) (.*)$/);\n\tconst afterProvider = providerMatch ? providerMatch[2] : text;\n\tconst providerPrefix = providerMatch ? theme.fg(\"muted\", `(${providerMatch[1]}) `) : \"\";\n\tconst fastPrefix = afterProvider.startsWith(FAST_MODE_INDICATOR) ? theme.fg(\"warning\", FAST_MODE_INDICATOR) : \"\";\n\tconst body = fastPrefix ? afterProvider.slice(FAST_MODE_INDICATOR.length) : afterProvider;\n\tconst thinkingMatch = body.match(/^(.+):([^:]+)$/);\n\tif (!thinkingMatch) return providerPrefix + fastPrefix + theme.fg(\"accent\", body);\n\treturn `${providerPrefix}${fastPrefix}${theme.fg(\"accent\", thinkingMatch[1])}${theme.fg(\"dim\", `:${thinkingMatch[2]}`)}`;\n}\n\n/**\n * Footer component that shows pwd, token stats, and context usage.\n * Computes token/context stats from session, gets git branch and extension statuses from provider.\n */\nexport class FooterComponent implements Component {\n\tprivate session: AgentSession;\n\tprivate footerData: ReadonlyFooterDataProvider;\n\tprivate autoCompactEnabled = true;\n\n\tconstructor(session: AgentSession, footerData: ReadonlyFooterDataProvider) {\n\t\tthis.session = session;\n\t\tthis.footerData = footerData;\n\t}\n\n\tsetSession(session: AgentSession): void {\n\t\tthis.session = session;\n\t}\n\n\tsetAutoCompactEnabled(enabled: boolean): void {\n\t\tthis.autoCompactEnabled = enabled;\n\t}\n\n\t/**\n\t * No-op: git branch caching now handled by provider.\n\t * Kept for compatibility with existing call sites in interactive-mode.\n\t */\n\tinvalidate(): void {\n\t\t// No-op: git branch is cached/invalidated by provider\n\t}\n\n\t/**\n\t * Clean up resources.\n\t * Git watcher cleanup now handled by provider.\n\t */\n\tdispose(): void {\n\t\t// Git watcher cleanup handled by provider\n\t}\n\n\trender(width: number): string[] {\n\t\tconst state = this.session.state;\n\n\t\t// O(1) running totals maintained by SessionManager (identical to summing\n\t\t// usage over all entries; totals are not branch-scoped).\n\t\tconst usageTotals = this.session.sessionManager.getUsageTotals();\n\t\tconst totalCacheRead = usageTotals.cacheRead;\n\t\tconst totalCacheWrite = usageTotals.cacheWrite;\n\t\tconst totalCost = usageTotals.cost;\n\t\tconst latestCacheHitRate = usageTotals.latestCacheHitRate;\n\n\t\t// Calculate context usage from session (handles compaction correctly).\n\t\t// After compaction, tokens are unknown until the next LLM response.\n\t\tconst contextUsage = this.session.getContextUsage();\n\t\tconst contextWindow = contextUsage?.contextWindow ?? state.model?.contextWindow ?? 0;\n\t\tconst contextPercentValue = contextUsage?.percent ?? 0;\n\t\tconst contextPercent = contextUsage?.percent !== null ? contextPercentValue.toFixed(1) : \"?\";\n\t\tconst contextTokens =\n\t\t\ttypeof contextUsage?.tokens === \"number\"\n\t\t\t\t? formatTokens(contextUsage.tokens)\n\t\t\t\t: typeof contextUsage?.percent === \"number\"\n\t\t\t\t\t? formatTokens(Math.round((contextWindow * contextUsage.percent) / 100))\n\t\t\t\t\t: \"?\";\n\n\t\t// Segments in priority order: anchors (pwd, branch, context) and the model\n\t\t// label always stay; middle stats elide from the right when space runs out.\n\t\t// The width ladder itself lives in ./footer-layout.ts.\n\t\tconst separator = \" • \";\n\t\tconst sepColored = theme.fg(\"borderMuted\", separator);\n\t\tconst pwdRaw = formatCwdForFooter(\n\t\t\tthis.session.sessionManager.getCwd(),\n\t\t\tprocess.env.HOME || process.env.USERPROFILE,\n\t\t);\n\t\tconst branch = this.footerData.getGitBranch();\n\t\tconst sessionName = this.session.sessionManager.getSessionName();\n\n\t\tconst anchor: [FooterSegment, ...FooterSegment[]] = [{ plain: pwdRaw, colored: theme.fg(\"accent\", pwdRaw) }];\n\t\tif (branch) anchor.push({ plain: branch, colored: theme.fg(\"warning\", branch) });\n\t\tconst pwdIndex = 0;\n\n\t\tconst dim = (plain: string): FooterSegment => ({ plain, colored: theme.fg(\"dim\", plain) });\n\t\tconst middle: FooterSegment[] = [];\n\t\tif (sessionName) middle.push({ plain: sessionName, colored: theme.fg(\"muted\", sessionName) });\n\t\tif ((totalCacheRead > 0 || totalCacheWrite > 0) && latestCacheHitRate !== undefined && latestCacheHitRate >= 10) {\n\t\t\tmiddle.push(dim(`CH${latestCacheHitRate.toFixed(1)}%`));\n\t\t}\n\n\t\t// Kimi Coding is subscription-backed despite using API-key authentication.\n\t\tconst usingSubscription = state.model\n\t\t\t? state.model.provider === \"kimi-coding\" || this.session.modelRuntime.isUsingSubscription(state.model.provider)\n\t\t\t: false;\n\t\tif (totalCost || usingSubscription) {\n\t\t\tconst costStr = `$${totalCost.toFixed(3)}${usingSubscription ? \" (sub)\" : \"\"}`;\n\t\t\tmiddle.push({ plain: costStr, colored: theme.fg(\"success\", costStr) });\n\t\t}\n\n\t\tconst autoIndicator = this.autoCompactEnabled ? \" (auto)\" : \"\";\n\t\tconst ctxDisplay =\n\t\t\tcontextPercent === \"?\"\n\t\t\t\t? `${contextTokens}/${formatTokens(contextWindow)} (?)${autoIndicator}`\n\t\t\t\t: `${contextTokens}/${formatTokens(contextWindow)} (${contextPercent}%)${autoIndicator}`;\n\t\tconst ctxColored =\n\t\t\tcontextPercentValue > 90\n\t\t\t\t? theme.fg(\"error\", ctxDisplay)\n\t\t\t\t: contextPercentValue > 70\n\t\t\t\t\t? theme.fg(\"warning\", ctxDisplay)\n\t\t\t\t\t: theme.fg(\"muted\", ctxDisplay);\n\t\tconst tail: FooterSegment = { plain: ctxDisplay, colored: ctxColored };\n\n\t\t// Model label pinned to the right edge; the provider prefix stays only when\n\t\t// the full line fits.\n\t\tconst modelName = state.model?.id || \"no-model\";\n\t\tconst fastIndicator = this.session.isFastModeActive() ? FAST_MODE_INDICATOR : \"\";\n\t\tlet minimalRight = `${fastIndicator}${modelName}`;\n\t\tif (state.model?.reasoning) {\n\t\t\tconst thinkingLevel = state.thinkingLevel || \"off\";\n\t\t\tminimalRight = thinkingLevel === \"off\" ? `${minimalRight}:off` : `${minimalRight}:${thinkingLevel}`;\n\t\t}\n\t\tconst minimal: FooterSegment = { plain: minimalRight, colored: colorRightSide(minimalRight) };\n\t\tconst providerPrefix =\n\t\t\tthis.footerData.getAvailableProviderCount() > 1 && state.model ? `(${state.model.provider}) ` : \"\";\n\t\tconst full: FooterSegment | undefined = providerPrefix\n\t\t\t? { plain: `${providerPrefix}${minimalRight}`, colored: colorRightSide(`${providerPrefix}${minimalRight}`) }\n\t\t\t: undefined;\n\n\t\tconst marker: FooterSegment = { plain: \"…\", colored: theme.fg(\"dim\", \"…\") };\n\t\tconst plan = planFooterLayout({\n\t\t\twidth,\n\t\t\tanchor,\n\t\t\tpwdIndex,\n\t\t\tmiddle,\n\t\t\ttail,\n\t\t\tright: { minimal, full },\n\t\t\tseparator,\n\t\t\tminPadding: 2,\n\t\t\tellipsisMarker: marker,\n\t\t});\n\n\t\tconst joinSegments = (segments: readonly FooterSegment[]): { colored: string; width: number } => ({\n\t\t\tcolored: segments.map((segment) => segment.colored).join(sepColored),\n\t\t\twidth: visibleWidth(segments.map((segment) => segment.plain).join(separator)),\n\t\t});\n\n\t\tlet left: { colored: string; width: number };\n\t\tlet right: FooterSegment;\n\t\tif (plan.kind === \"full\") {\n\t\t\tright = plan.useFullRight && full ? full : minimal;\n\t\t\tleft = joinSegments([...anchor, ...middle, tail]);\n\t\t} else if (plan.kind === \"middle-elided\") {\n\t\t\tright = plan.useFullRight && full ? full : minimal;\n\t\t\tconst segments = [...anchor, ...middle.slice(0, plan.keptMiddleCount)];\n\t\t\tif (plan.showMarker) segments.push(marker);\n\t\t\tsegments.push(tail);\n\t\t\tleft = joinSegments(segments);\n\t\t} else if (plan.kind === \"pwd-elided\") {\n\t\t\tright = plan.useFullRight && full ? full : minimal;\n\t\t\tconst segments: FooterSegment[] = [\n\t\t\t\t...anchor.map((segment, index) =>\n\t\t\t\t\tindex === pwdIndex ? { plain: plan.pwdPlain, colored: theme.fg(\"accent\", plan.pwdPlain) } : segment,\n\t\t\t\t),\n\t\t\t\t...middle.slice(0, plan.keptMiddleCount),\n\t\t\t];\n\t\t\tif (plan.showMarker) segments.push(marker);\n\t\t\tsegments.push(tail);\n\t\t\tleft = joinSegments(segments);\n\t\t} else if (plan.kind === \"left-elided\") {\n\t\t\tright = minimal;\n\t\t\tleft = { colored: theme.fg(\"muted\", plan.leftPlain), width: visibleWidth(plan.leftPlain) };\n\t\t} else {\n\t\t\tleft = { colored: \"\", width: 0 };\n\t\t\tright = { plain: plan.rightPlain, colored: colorRightSide(plan.rightPlain) };\n\t\t}\n\n\t\tconst rightWidth = visibleWidth(right.plain);\n\t\tconst padding = \" \".repeat(Math.max(0, width - left.width - rightWidth));\n\t\tconst lines = [left.colored + padding + right.colored];\n\n\t\t// Add extension statuses on a single line, sorted by key alphabetically\n\t\tconst extensionStatuses = this.footerData.getExtensionStatuses();\n\t\tif (extensionStatuses.size > 0) {\n\t\t\tconst sortedStatuses = Array.from(extensionStatuses.entries())\n\t\t\t\t.sort(([a], [b]) => a.localeCompare(b))\n\t\t\t\t.map(([, text]) => sanitizeStatusText(text));\n\t\t\tconst statusLine = sortedStatuses.join(\" \");\n\t\t\t// Truncate to terminal width with dim ellipsis for consistency with footer style\n\t\t\tlines.push(truncateToWidth(statusLine, width, theme.fg(\"dim\", \"...\")));\n\t\t}\n\n\t\treturn lines;\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"footer.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/footer.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash } from \"node:crypto\";\nimport { isAbsolute, relative, resolve, sep } from \"node:path\";\nimport type { Credential } from \"@earendil-works/pi-ai\";\nimport { rendezvousOrder } from \"@earendil-works/pi-ai/auth/pool/select\";\nimport { listSlots } from \"@earendil-works/pi-ai/auth/pool/slots\";\nimport { type Component, truncateToWidth, visibleWidth } from \"@earendil-works/pi-tui\";\nimport type { ReadonlyFooterDataProvider } from \"../../../core/footer-data-provider.ts\";\nimport type { InteractiveSession } from \"../interactive-host-runtime.ts\";\nimport { theme } from \"../theme/theme.ts\";\nimport { type FooterSegment, planFooterLayout } from \"./footer-layout.ts\";\n\nconst FAST_MODE_INDICATOR = \"\\u26a1 \";\n\n/**\n * Sanitize text for display in a single-line status.\n * Removes newlines, tabs, carriage returns, and other control characters.\n */\nfunction sanitizeStatusText(text: string): string {\n\t// Replace newlines, tabs, carriage returns with space, then collapse multiple spaces\n\treturn text\n\t\t.replace(/[\\r\\n\\t]/g, \" \")\n\t\t.replace(/ +/g, \" \")\n\t\t.trim();\n}\n\n/**\n * Format token counts for footer display using oh-my-pi-style K/M/B abbreviation.\n * Examples: \"999\", \"6.8K\", \"546K\", \"1M\", \"1.5M\", \"2B\".\n */\nexport function formatTokens(count: number): string {\n\tconst n = Math.round(count);\n\tif (n < 1_000) return n.toString();\n\tif (n < 10_000) return `${trim1(n / 1_000)}K`;\n\tif (n < 1_000_000) return `${Math.round(n / 1_000)}K`;\n\tif (n < 10_000_000) return `${trim1(n / 1_000_000)}M`;\n\tif (n < 1_000_000_000) return `${Math.round(n / 1_000_000)}M`;\n\tif (n < 10_000_000_000) return `${trim1(n / 1_000_000_000)}B`;\n\treturn `${Math.round(n / 1_000_000_000)}B`;\n}\n\n/**\n * Mirrors the provider-shown-only-when->1 rule for accounts: the active account\n * name appears only when the provider actually pools more than one slot. The\n * pick shown is the pin when present, else the session's HRW winner - the same\n * hash the rotation engine uses, so the footer names the slot that will serve.\n */\nexport function accountFooterSuffix(credential: Credential | undefined, sessionId: string): string {\n\tconst slots = listSlots(credential);\n\tif (slots.length < 2) return \"\";\n\tconst pinned = Object.entries(credential ?? {}).find(([key]) => key === \"pinned\")?.[1];\n\tif (typeof pinned === \"string\" && slots.some((slot) => slot.name === pinned)) return `@${pinned}`;\n\tconst winner = rendezvousOrder(sessionId, slots, (input) =>\n\t\tcreateHash(\"sha256\").update(input).digest().readBigUInt64BE(0),\n\t)[0];\n\treturn winner === undefined ? \"\" : `@${winner.name}`;\n}\n\n/** Format with up to 1 decimal place, dropping trailing `.0`. */\nfunction trim1(n: number): string {\n\tconst s = n.toFixed(1);\n\treturn s.endsWith(\".0\") ? s.slice(0, -2) : s;\n}\n\nexport function formatCwdForFooter(cwd: string, home: string | undefined): string {\n\tif (!home) return cwd;\n\n\tconst resolvedCwd = resolve(cwd);\n\tconst resolvedHome = resolve(home);\n\tconst relativeToHome = relative(resolvedHome, resolvedCwd);\n\tconst isInsideHome =\n\t\trelativeToHome === \"\" ||\n\t\t(relativeToHome !== \"..\" && !relativeToHome.startsWith(`..${sep}`) && !isAbsolute(relativeToHome));\n\n\tif (!isInsideHome) return cwd;\n\treturn relativeToHome === \"\" ? \"~\" : `~${sep}${relativeToHome}`;\n}\n\n/**\n * Color the right side of the footer: (provider) muted, model accent, :thinking dim.\n * The text is the plain (uncolored) right-aligned segment from the layout pass.\n */\nfunction colorRightSide(text: string): string {\n\tif (!text) return \"\";\n\tconst providerMatch = text.match(/^\\(([^)]+)\\) (.*)$/);\n\tconst afterProvider = providerMatch ? providerMatch[2] : text;\n\tconst providerPrefix = providerMatch ? theme.fg(\"muted\", `(${providerMatch[1]}) `) : \"\";\n\tconst fastPrefix = afterProvider.startsWith(FAST_MODE_INDICATOR) ? theme.fg(\"warning\", FAST_MODE_INDICATOR) : \"\";\n\tconst body = fastPrefix ? afterProvider.slice(FAST_MODE_INDICATOR.length) : afterProvider;\n\tconst thinkingMatch = body.match(/^(.+):([^:]+)$/);\n\tif (!thinkingMatch) return providerPrefix + fastPrefix + theme.fg(\"accent\", body);\n\treturn `${providerPrefix}${fastPrefix}${theme.fg(\"accent\", thinkingMatch[1])}${theme.fg(\"dim\", `:${thinkingMatch[2]}`)}`;\n}\n\n/**\n * Footer component that shows pwd, token stats, and context usage.\n * Computes token/context stats from session, gets git branch and extension statuses from provider.\n */\nexport class FooterComponent implements Component {\n\tprivate session: InteractiveSession;\n\tprivate footerData: ReadonlyFooterDataProvider;\n\tprivate autoCompactEnabled = true;\n\n\tconstructor(session: InteractiveSession, footerData: ReadonlyFooterDataProvider) {\n\t\tthis.session = session;\n\t\tthis.footerData = footerData;\n\t}\n\n\tsetSession(session: InteractiveSession): void {\n\t\tthis.session = session;\n\t}\n\n\tsetAutoCompactEnabled(enabled: boolean): void {\n\t\tthis.autoCompactEnabled = enabled;\n\t}\n\n\t/**\n\t * No-op: git branch caching now handled by provider.\n\t * Kept for compatibility with existing call sites in interactive-mode.\n\t */\n\tinvalidate(): void {\n\t\t// No-op: git branch is cached/invalidated by provider\n\t}\n\n\t/**\n\t * Clean up resources.\n\t * Git watcher cleanup now handled by provider.\n\t */\n\tdispose(): void {\n\t\t// Git watcher cleanup handled by provider\n\t}\n\n\trender(width: number): string[] {\n\t\tconst state = this.session.state;\n\n\t\t// O(1) running totals maintained by SessionManager (identical to summing\n\t\t// usage over all entries; totals are not branch-scoped).\n\t\tconst usageTotals = this.session.sessionManager.getUsageTotals();\n\t\tconst totalCacheRead = usageTotals.cacheRead;\n\t\tconst totalCacheWrite = usageTotals.cacheWrite;\n\t\tconst totalCost = usageTotals.cost;\n\t\tconst latestCacheHitRate = usageTotals.latestCacheHitRate;\n\n\t\t// Calculate context usage from session (handles compaction correctly).\n\t\t// After compaction, tokens are unknown until the next LLM response.\n\t\tconst contextUsage = this.session.getContextUsage();\n\t\tconst contextWindow = contextUsage?.contextWindow ?? state.model?.contextWindow ?? 0;\n\t\tconst contextPercentValue = contextUsage?.percent ?? 0;\n\t\tconst contextPercent = contextUsage?.percent !== null ? contextPercentValue.toFixed(1) : \"?\";\n\t\tconst contextTokens =\n\t\t\ttypeof contextUsage?.tokens === \"number\"\n\t\t\t\t? formatTokens(contextUsage.tokens)\n\t\t\t\t: typeof contextUsage?.percent === \"number\"\n\t\t\t\t\t? formatTokens(Math.round((contextWindow * contextUsage.percent) / 100))\n\t\t\t\t\t: \"?\";\n\n\t\t// Segments in priority order: anchors (pwd, branch, context) and the model\n\t\t// label always stay; middle stats elide from the right when space runs out.\n\t\t// The width ladder itself lives in ./footer-layout.ts.\n\t\tconst separator = \" • \";\n\t\tconst sepColored = theme.fg(\"borderMuted\", separator);\n\t\tconst pwdRaw = formatCwdForFooter(\n\t\t\tthis.session.sessionManager.getCwd(),\n\t\t\tprocess.env.HOME || process.env.USERPROFILE,\n\t\t);\n\t\tconst branch = this.footerData.getGitBranch();\n\t\tconst sessionName = this.session.sessionManager.getSessionName();\n\n\t\tconst anchor: [FooterSegment, ...FooterSegment[]] = [{ plain: pwdRaw, colored: theme.fg(\"accent\", pwdRaw) }];\n\t\tif (branch) anchor.push({ plain: branch, colored: theme.fg(\"warning\", branch) });\n\t\tconst pwdIndex = 0;\n\n\t\tconst dim = (plain: string): FooterSegment => ({ plain, colored: theme.fg(\"dim\", plain) });\n\t\tconst middle: FooterSegment[] = [];\n\t\tif (sessionName) middle.push({ plain: sessionName, colored: theme.fg(\"muted\", sessionName) });\n\t\tif ((totalCacheRead > 0 || totalCacheWrite > 0) && latestCacheHitRate !== undefined && latestCacheHitRate >= 10) {\n\t\t\tmiddle.push(dim(`CH${latestCacheHitRate.toFixed(1)}%`));\n\t\t}\n\n\t\t// Kimi Coding is subscription-backed despite using API-key authentication.\n\t\tconst usingSubscription = state.model\n\t\t\t? state.model.provider === \"kimi-coding\" || this.session.modelRuntime.isUsingSubscription(state.model.provider)\n\t\t\t: false;\n\t\tif (totalCost || usingSubscription) {\n\t\t\tconst costStr = `$${totalCost.toFixed(3)}${usingSubscription ? \" (sub)\" : \"\"}`;\n\t\t\tmiddle.push({ plain: costStr, colored: theme.fg(\"success\", costStr) });\n\t\t}\n\n\t\tconst autoIndicator = this.autoCompactEnabled ? \" (auto)\" : \"\";\n\t\tconst ctxDisplay =\n\t\t\tcontextPercent === \"?\"\n\t\t\t\t? `${contextTokens}/${formatTokens(contextWindow)} (?)${autoIndicator}`\n\t\t\t\t: `${contextTokens}/${formatTokens(contextWindow)} (${contextPercent}%)${autoIndicator}`;\n\t\tconst ctxColored =\n\t\t\tcontextPercentValue > 90\n\t\t\t\t? theme.fg(\"error\", ctxDisplay)\n\t\t\t\t: contextPercentValue > 70\n\t\t\t\t\t? theme.fg(\"warning\", ctxDisplay)\n\t\t\t\t\t: theme.fg(\"muted\", ctxDisplay);\n\t\tconst tail: FooterSegment = { plain: ctxDisplay, colored: ctxColored };\n\n\t\t// Model label pinned to the right edge; the provider prefix stays only when\n\t\t// the full line fits.\n\t\tconst modelName = state.model?.id || \"no-model\";\n\t\tconst fastIndicator = this.session.isFastModeActive() ? FAST_MODE_INDICATOR : \"\";\n\t\tlet minimalRight = `${fastIndicator}${modelName}`;\n\t\tif (state.model?.reasoning) {\n\t\t\tconst thinkingLevel = state.thinkingLevel || \"off\";\n\t\t\tminimalRight = thinkingLevel === \"off\" ? `${minimalRight}:off` : `${minimalRight}:${thinkingLevel}`;\n\t\t}\n\t\tconst minimal: FooterSegment = { plain: minimalRight, colored: colorRightSide(minimalRight) };\n\t\tlet accountSuffix = \"\";\n\t\tif (state.model) {\n\t\t\ttry {\n\t\t\t\taccountSuffix = accountFooterSuffix(\n\t\t\t\t\tthis.session.modelRegistry.authStorage.get(state.model.provider),\n\t\t\t\t\tthis.session.sessionManager.getSessionId(),\n\t\t\t\t);\n\t\t\t} catch {\n\t\t\t\t// The footer must render even when credential storage is unreadable.\n\t\t\t}\n\t\t}\n\t\tconst providerPrefix =\n\t\t\t(this.footerData.getAvailableProviderCount() > 1 || accountSuffix !== \"\") && state.model\n\t\t\t\t? `(${state.model.provider}${accountSuffix}) `\n\t\t\t\t: \"\";\n\t\tconst full: FooterSegment | undefined = providerPrefix\n\t\t\t? { plain: `${providerPrefix}${minimalRight}`, colored: colorRightSide(`${providerPrefix}${minimalRight}`) }\n\t\t\t: undefined;\n\n\t\tconst marker: FooterSegment = { plain: \"…\", colored: theme.fg(\"dim\", \"…\") };\n\t\tconst plan = planFooterLayout({\n\t\t\twidth,\n\t\t\tanchor,\n\t\t\tpwdIndex,\n\t\t\tmiddle,\n\t\t\ttail,\n\t\t\tright: { minimal, full },\n\t\t\tseparator,\n\t\t\tminPadding: 2,\n\t\t\tellipsisMarker: marker,\n\t\t});\n\n\t\tconst joinSegments = (segments: readonly FooterSegment[]): { colored: string; width: number } => ({\n\t\t\tcolored: segments.map((segment) => segment.colored).join(sepColored),\n\t\t\twidth: visibleWidth(segments.map((segment) => segment.plain).join(separator)),\n\t\t});\n\n\t\tlet left: { colored: string; width: number };\n\t\tlet right: FooterSegment;\n\t\tif (plan.kind === \"full\") {\n\t\t\tright = plan.useFullRight && full ? full : minimal;\n\t\t\tleft = joinSegments([...anchor, ...middle, tail]);\n\t\t} else if (plan.kind === \"middle-elided\") {\n\t\t\tright = plan.useFullRight && full ? full : minimal;\n\t\t\tconst segments = [...anchor, ...middle.slice(0, plan.keptMiddleCount)];\n\t\t\tif (plan.showMarker) segments.push(marker);\n\t\t\tsegments.push(tail);\n\t\t\tleft = joinSegments(segments);\n\t\t} else if (plan.kind === \"pwd-elided\") {\n\t\t\tright = plan.useFullRight && full ? full : minimal;\n\t\t\tconst segments: FooterSegment[] = [\n\t\t\t\t...anchor.map((segment, index) =>\n\t\t\t\t\tindex === pwdIndex ? { plain: plan.pwdPlain, colored: theme.fg(\"accent\", plan.pwdPlain) } : segment,\n\t\t\t\t),\n\t\t\t\t...middle.slice(0, plan.keptMiddleCount),\n\t\t\t];\n\t\t\tif (plan.showMarker) segments.push(marker);\n\t\t\tsegments.push(tail);\n\t\t\tleft = joinSegments(segments);\n\t\t} else if (plan.kind === \"left-elided\") {\n\t\t\tright = minimal;\n\t\t\tleft = { colored: theme.fg(\"muted\", plan.leftPlain), width: visibleWidth(plan.leftPlain) };\n\t\t} else {\n\t\t\tleft = { colored: \"\", width: 0 };\n\t\t\tright = { plain: plan.rightPlain, colored: colorRightSide(plan.rightPlain) };\n\t\t}\n\n\t\tconst rightWidth = visibleWidth(right.plain);\n\t\tconst padding = \" \".repeat(Math.max(0, width - left.width - rightWidth));\n\t\tconst lines = [left.colored + padding + right.colored];\n\n\t\t// Add extension statuses on a single line, sorted by key alphabetically\n\t\tconst extensionStatuses = this.footerData.getExtensionStatuses();\n\t\tif (extensionStatuses.size > 0) {\n\t\t\tconst sortedStatuses = Array.from(extensionStatuses.entries())\n\t\t\t\t.sort(([a], [b]) => a.localeCompare(b))\n\t\t\t\t.map(([, text]) => sanitizeStatusText(text));\n\t\t\tconst statusLine = sortedStatuses.join(\" \");\n\t\t\t// Truncate to terminal width with dim ellipsis for consistency with footer style\n\t\t\tlines.push(truncateToWidth(statusLine, width, theme.fg(\"dim\", \"...\")));\n\t\t}\n\n\t\treturn lines;\n\t}\n}\n"]}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import type { Component, EditorOptions, EditorTheme, TUI } from "@earendil-works/pi-tui";
|
|
2
|
-
import type { AgentSession } from "../../../core/agent-session.ts";
|
|
3
2
|
import type { WorkingIndicatorOptions } from "../../../core/extensions/index.ts";
|
|
4
3
|
import type { ReadonlyFooterDataProvider } from "../../../core/footer-data-provider.ts";
|
|
5
4
|
import type { KeybindingsManager } from "../../../core/keybindings.ts";
|
|
6
5
|
import { CustomEditor } from "../components/custom-editor.ts";
|
|
7
6
|
import { WorkingStatusIndicator } from "../components/status-indicator.ts";
|
|
8
7
|
import type { ToolExecutionPresentation } from "../components/tool-execution.ts";
|
|
8
|
+
import type { InteractiveSession } from "../interactive-host-runtime.ts";
|
|
9
9
|
export interface InteractiveFooter extends Component {
|
|
10
|
-
setSession(session:
|
|
10
|
+
setSession(session: InteractiveSession): void;
|
|
11
11
|
setAutoCompactEnabled(enabled: boolean): void;
|
|
12
12
|
invalidate(): void;
|
|
13
13
|
dispose(): void;
|
|
@@ -28,7 +28,7 @@ export interface InteractiveChrome {
|
|
|
28
28
|
editorOptions: EditorOptions;
|
|
29
29
|
}): CustomEditor;
|
|
30
30
|
getEditorTheme(): EditorTheme;
|
|
31
|
-
createFooter(session:
|
|
31
|
+
createFooter(session: InteractiveSession, footerData: ReadonlyFooterDataProvider): InteractiveFooter;
|
|
32
32
|
createWelcomeContent(appName: string, version: string): Component;
|
|
33
33
|
createWorkingIndicator(ui: TUI, message: string, indicator?: WorkingIndicatorOptions): WorkingStatusIndicator;
|
|
34
34
|
getEditorBorderColor(context: EditorBorderContext): (text: string) => string;
|
|
@@ -42,7 +42,7 @@ export declare class GrokChrome implements InteractiveChrome {
|
|
|
42
42
|
editorOptions: EditorOptions;
|
|
43
43
|
}): CustomEditor;
|
|
44
44
|
getEditorTheme(): EditorTheme;
|
|
45
|
-
createFooter(session:
|
|
45
|
+
createFooter(session: InteractiveSession, footerData: ReadonlyFooterDataProvider): InteractiveFooter;
|
|
46
46
|
createWelcomeContent(appName: string, version: string): Component;
|
|
47
47
|
createWorkingIndicator(ui: TUI, message: string, indicator?: WorkingIndicatorOptions): WorkingStatusIndicator;
|
|
48
48
|
getEditorBorderColor(_context: EditorBorderContext): (text: string) => string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chrome.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/grok/chrome.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,WAAW,EAAE,GAAG,EAAE,MAAM,wBAAwB,CAAC;AACzF,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"chrome.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/grok/chrome.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,WAAW,EAAE,GAAG,EAAE,MAAM,wBAAwB,CAAC;AACzF,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,mCAAmC,CAAC;AACjF,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,uCAAuC,CAAC;AACxF,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AACvE,OAAO,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AAC9D,OAAO,EAAE,sBAAsB,EAAE,MAAM,mCAAmC,CAAC;AAC3E,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,iCAAiC,CAAC;AACjF,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AAQzE,MAAM,WAAW,iBAAkB,SAAQ,SAAS;IACnD,UAAU,CAAC,OAAO,EAAE,kBAAkB,GAAG,IAAI,CAAC;IAC9C,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IAC9C,UAAU,IAAI,IAAI,CAAC;IACnB,OAAO,IAAI,IAAI,CAAC;CAChB;AAED,MAAM,MAAM,mBAAmB,GAAG;IACjC,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;CAC/B,CAAC;AAEF;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IACjC,QAAQ,CAAC,gBAAgB,EAAE,yBAAyB,CAAC;IACrD,gBAAgB,CAAC,OAAO,EAAE;QAAE,EAAE,EAAE,GAAG,CAAC;QAAC,WAAW,EAAE,kBAAkB,CAAC;QAAC,aAAa,EAAE,aAAa,CAAA;KAAE,GAAG,YAAY,CAAC;IACpH,cAAc,IAAI,WAAW,CAAC;IAC9B,YAAY,CAAC,OAAO,EAAE,kBAAkB,EAAE,UAAU,EAAE,0BAA0B,GAAG,iBAAiB,CAAC;IACrG,oBAAoB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;IAClE,sBAAsB,CAAC,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,uBAAuB,GAAG,sBAAsB,CAAC;IAC9G,oBAAoB,CAAC,OAAO,EAAE,mBAAmB,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IAC7E,WAAW,CAAC,QAAQ,EAAE,SAAS,SAAS,EAAE,EAAE,EAAE,CAAC,EAAE,GAAG,GAAG,SAAS,EAAE,CAAC;CACnE;AA8DD,qBAAa,UAAW,YAAW,iBAAiB;IACnD,QAAQ,CAAC,gBAAgB,EAAG,MAAM,CAAU;IAE5C,gBAAgB,CAAC,EAChB,EAAE,EACF,WAAW,EACX,aAAa,GACb,EAAE;QACF,EAAE,EAAE,GAAG,CAAC;QACR,WAAW,EAAE,kBAAkB,CAAC;QAChC,aAAa,EAAE,aAAa,CAAC;KAC7B,GAAG,YAAY;IAIhB,cAAc,IAAI,WAAW;IAkB7B,YAAY,CAAC,OAAO,EAAE,kBAAkB,EAAE,UAAU,EAAE,0BAA0B,GAAG,iBAAiB;IAIpG,oBAAoB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,SAAS;IAIjE,sBAAsB,CAAC,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,uBAAuB,GAAG,sBAAsB;IAQ7G,oBAAoB,CAAC,QAAQ,EAAE,mBAAmB,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM;IAI7E,WAAW,CAAC,QAAQ,EAAE,SAAS,SAAS,EAAE,EAAE,EAAE,CAAC,EAAE,GAAG,GAAG,SAAS,EAAE;CAYlE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chrome.js","sourceRoot":"","sources":["../../../../src/modes/interactive/grok/chrome.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Component, EditorOptions, EditorTheme, TUI } from \"@earendil-works/pi-tui\";\nimport type { AgentSession } from \"../../../core/agent-session.ts\";\nimport type { WorkingIndicatorOptions } from \"../../../core/extensions/index.ts\";\nimport type { ReadonlyFooterDataProvider } from \"../../../core/footer-data-provider.ts\";\nimport type { KeybindingsManager } from \"../../../core/keybindings.ts\";\nimport { CustomEditor } from \"../components/custom-editor.ts\";\nimport { WorkingStatusIndicator } from \"../components/status-indicator.ts\";\nimport type { ToolExecutionPresentation } from \"../components/tool-execution.ts\";\nimport { theme } from \"../theme/theme.ts\";\nimport { getGrokChromeTokens } from \"./chrome-tokens.ts\";\nimport { GrokFooter } from \"./footer.ts\";\nimport { GrokInputCard } from \"./input-card.ts\";\nimport { GROK_GLYPHS } from \"./palette.ts\";\nimport { GrokWelcomeCard } from \"./welcome-card.ts\";\n\nexport interface InteractiveFooter extends Component {\n\tsetSession(session: AgentSession): void;\n\tsetAutoCompactEnabled(enabled: boolean): void;\n\tinvalidate(): void;\n\tdispose(): void;\n}\n\nexport type EditorBorderContext = {\n\treadonly isBashMode: boolean;\n\treadonly thinkingLevel: string;\n};\n\n/**\n * Mode-owned chrome seam for InteractiveMode. Extensions continue to own their\n * editor factory; this strategy only creates and decorates the base editor.\n */\nexport interface InteractiveChrome {\n\treadonly toolPresentation: ToolExecutionPresentation;\n\tcreateBaseEditor(context: { ui: TUI; keybindings: KeybindingsManager; editorOptions: EditorOptions }): CustomEditor;\n\tgetEditorTheme(): EditorTheme;\n\tcreateFooter(session: AgentSession, footerData: ReadonlyFooterDataProvider): InteractiveFooter;\n\tcreateWelcomeContent(appName: string, version: string): Component;\n\tcreateWorkingIndicator(ui: TUI, message: string, indicator?: WorkingIndicatorOptions): WorkingStatusIndicator;\n\tgetEditorBorderColor(context: EditorBorderContext): (text: string) => string;\n\tarrangeRoot(children: readonly Component[], ui?: TUI): Component[];\n}\n\nclass GrokFooterSurface implements Component {\n\tprivate readonly content: Component;\n\n\tconstructor(content: Component) {\n\t\tthis.content = content;\n\t}\n\n\tinvalidate(): void {\n\t\tthis.content.invalidate();\n\t}\n\n\trender(width: number): string[] {\n\t\tconst surface = getGrokChromeTokens().surface;\n\t\treturn this.content.render(width).map(surface);\n\t}\n\n\tdispose(): void {\n\t\tthis.content.dispose?.();\n\t}\n}\n\nclass GrokRootSpacer implements Component {\n\tprivate readonly ui: TUI;\n\tprivate readonly content: readonly Component[];\n\n\tconstructor(ui: TUI, content: readonly Component[]) {\n\t\tthis.ui = ui;\n\t\tthis.content = content;\n\t}\n\n\tinvalidate(): void {\n\t\t// The spacer derives its height from the current terminal dimensions.\n\t}\n\n\trender(width: number): string[] {\n\t\tconst contentHeight = this.content.reduce((height, component) => height + component.render(width).length, 0);\n\t\treturn Array.from({ length: Math.max(0, this.ui.terminal.rows - contentHeight) }, () => \"\");\n\t}\n}\n\nclass GrokEditor extends CustomEditor {\n\tprivate readonly card: GrokInputCard;\n\n\tconstructor(ui: TUI, editorTheme: EditorTheme, keybindings: KeybindingsManager, options: EditorOptions) {\n\t\tsuper(ui, editorTheme, keybindings, options);\n\t\tthis.card = new GrokInputCard({\n\t\t\trender: (width) => this.renderBase(width),\n\t\t\tinvalidate: () => super.invalidate(),\n\t\t});\n\t}\n\n\toverride render(width: number): string[] {\n\t\treturn this.card.render(width);\n\t}\n\n\tprivate renderBase(width: number): string[] {\n\t\treturn super.render(width);\n\t}\n}\n\nexport class GrokChrome implements InteractiveChrome {\n\treadonly toolPresentation = \"grok\" as const;\n\n\tcreateBaseEditor({\n\t\tui,\n\t\tkeybindings,\n\t\teditorOptions,\n\t}: {\n\t\tui: TUI;\n\t\tkeybindings: KeybindingsManager;\n\t\teditorOptions: EditorOptions;\n\t}): CustomEditor {\n\t\treturn new GrokEditor(ui, this.getEditorTheme(), keybindings, editorOptions);\n\t}\n\n\tgetEditorTheme(): EditorTheme {\n\t\tconst tokens = getGrokChromeTokens();\n\t\treturn {\n\t\t\tborderColor: tokens.inputBorder,\n\t\t\tselectList: {\n\t\t\t\tselectedPrefix: (text) => theme.fg(\"accent\", text),\n\t\t\t\tselectedText: (text) => tokens.primaryText(text),\n\t\t\t\tdescription: (text) => tokens.mutedText(text),\n\t\t\t\tscrollInfo: (text) => tokens.mutedText(text),\n\t\t\t\tnoMatch: (text) => tokens.mutedText(text),\n\t\t\t\trenderRow: ({ prefix, primary, description, isSelected }) => {\n\t\t\t\t\tconst row = `${prefix}${tokens.primaryText(primary)}${description ? tokens.mutedText(description) : \"\"}`;\n\t\t\t\t\treturn isSelected ? theme.bg(\"selectedBg\", row) : row;\n\t\t\t\t},\n\t\t\t},\n\t\t};\n\t}\n\n\tcreateFooter(session: AgentSession, footerData: ReadonlyFooterDataProvider): InteractiveFooter {\n\t\treturn new GrokFooter(session, footerData);\n\t}\n\n\tcreateWelcomeContent(appName: string, version: string): Component {\n\t\treturn new GrokWelcomeCard(appName, version);\n\t}\n\n\tcreateWorkingIndicator(ui: TUI, message: string, indicator?: WorkingIndicatorOptions): WorkingStatusIndicator {\n\t\treturn new WorkingStatusIndicator(ui, message, {\n\t\t\t...indicator,\n\t\t\tframes: [GROK_GLYPHS.spinner],\n\t\t\tindicatorFormatter: (frame) => theme.fg(\"accent\", frame),\n\t\t});\n\t}\n\n\tgetEditorBorderColor(_context: EditorBorderContext): (text: string) => string {\n\t\treturn getGrokChromeTokens().inputBorder;\n\t}\n\n\tarrangeRoot(children: readonly Component[], ui?: TUI): Component[] {\n\t\t// pi-tui concatenates root children without a layout pass. Keep transcript\n\t\t// content first and calculate the remaining rows at render time from the TUI's\n\t\t// terminal height, so the input tail is truly bottom-anchored when it fits.\n\t\tconst inputTailStart = Math.max(0, children.length - 3);\n\t\tconst content = children.slice(0, inputTailStart);\n\t\tconst inputTail = children.slice(inputTailStart);\n\t\tconst footer = inputTail.at(-1);\n\t\tconst tail = footer ? [...inputTail.slice(0, -1), new GrokFooterSurface(footer)] : [...inputTail];\n\t\tconst arranged = [...content, ...tail];\n\t\treturn ui ? [...content, new GrokRootSpacer(ui, arranged), ...tail] : arranged;\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"chrome.js","sourceRoot":"","sources":["../../../../src/modes/interactive/grok/chrome.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AAC9D,OAAO,EAAE,sBAAsB,EAAE,MAAM,mCAAmC,CAAC;AAG3E,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC1C,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AA6BpD,MAAM,iBAAiB;IAGtB,YAAY,OAAkB;QAC7B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACxB,CAAC;IAED,UAAU;QACT,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC;IAC3B,CAAC;IAED,MAAM,CAAC,KAAa;QACnB,MAAM,OAAO,GAAG,mBAAmB,EAAE,CAAC,OAAO,CAAC;QAC9C,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAChD,CAAC;IAED,OAAO;QACN,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC;IAC1B,CAAC;CACD;AAED,MAAM,cAAc;IAInB,YAAY,EAAO,EAAE,OAA6B;QACjD,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;QACb,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACxB,CAAC;IAED,UAAU;QACT,sEAAsE;IACvE,CAAC;IAED,MAAM,CAAC,KAAa;QACnB,MAAM,aAAa,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,CAAC,MAAM,GAAG,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QAC7G,OAAO,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,QAAQ,CAAC,IAAI,GAAG,aAAa,CAAC,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;IAC7F,CAAC;CACD;AAED,MAAM,UAAW,SAAQ,YAAY;IAGpC,YAAY,EAAO,EAAE,WAAwB,EAAE,WAA+B,EAAE,OAAsB;QACrG,KAAK,CAAC,EAAE,EAAE,WAAW,EAAE,WAAW,EAAE,OAAO,CAAC,CAAC;QAC7C,IAAI,CAAC,IAAI,GAAG,IAAI,aAAa,CAAC;YAC7B,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC;YACzC,UAAU,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,UAAU,EAAE;SACpC,CAAC,CAAC;IACJ,CAAC;IAEQ,MAAM,CAAC,KAAa;QAC5B,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAChC,CAAC;IAEO,UAAU,CAAC,KAAa;QAC/B,OAAO,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC5B,CAAC;CACD;AAED,MAAM,OAAO,UAAU;IAAvB;QACU,qBAAgB,GAAG,MAAe,CAAC;IAgE7C,CAAC;IA9DA,gBAAgB,CAAC,EAChB,EAAE,EACF,WAAW,EACX,aAAa,GAKb;QACA,OAAO,IAAI,UAAU,CAAC,EAAE,EAAE,IAAI,CAAC,cAAc,EAAE,EAAE,WAAW,EAAE,aAAa,CAAC,CAAC;IAC9E,CAAC;IAED,cAAc;QACb,MAAM,MAAM,GAAG,mBAAmB,EAAE,CAAC;QACrC,OAAO;YACN,WAAW,EAAE,MAAM,CAAC,WAAW;YAC/B,UAAU,EAAE;gBACX,cAAc,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,IAAI,CAAC;gBAClD,YAAY,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC;gBAChD,WAAW,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC;gBAC7C,UAAU,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC;gBAC5C,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC;gBACzC,SAAS,EAAE,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,EAAE,EAAE;oBAC3D,MAAM,GAAG,GAAG,GAAG,MAAM,GAAG,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;oBACzG,OAAO,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;gBACvD,CAAC;aACD;SACD,CAAC;IACH,CAAC;IAED,YAAY,CAAC,OAA2B,EAAE,UAAsC;QAC/E,OAAO,IAAI,UAAU,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;IAC5C,CAAC;IAED,oBAAoB,CAAC,OAAe,EAAE,OAAe;QACpD,OAAO,IAAI,eAAe,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAC9C,CAAC;IAED,sBAAsB,CAAC,EAAO,EAAE,OAAe,EAAE,SAAmC;QACnF,OAAO,IAAI,sBAAsB,CAAC,EAAE,EAAE,OAAO,EAAE;YAC9C,GAAG,SAAS;YACZ,MAAM,EAAE,CAAC,WAAW,CAAC,OAAO,CAAC;YAC7B,kBAAkB,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,KAAK,CAAC;SACxD,CAAC,CAAC;IACJ,CAAC;IAED,oBAAoB,CAAC,QAA6B;QACjD,OAAO,mBAAmB,EAAE,CAAC,WAAW,CAAC;IAC1C,CAAC;IAED,WAAW,CAAC,QAA8B,EAAE,EAAQ;QACnD,2EAA2E;QAC3E,+EAA+E;QAC/E,4EAA4E;QAC5E,MAAM,cAAc,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QACxD,MAAM,OAAO,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,cAAc,CAAC,CAAC;QAClD,MAAM,SAAS,GAAG,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;QACjD,MAAM,MAAM,GAAG,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QAChC,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,iBAAiB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC;QAClG,MAAM,QAAQ,GAAG,CAAC,GAAG,OAAO,EAAE,GAAG,IAAI,CAAC,CAAC;QACvC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,EAAE,IAAI,cAAc,CAAC,EAAE,EAAE,QAAQ,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;IAChF,CAAC;CACD","sourcesContent":["import type { Component, EditorOptions, EditorTheme, TUI } from \"@earendil-works/pi-tui\";\nimport type { WorkingIndicatorOptions } from \"../../../core/extensions/index.ts\";\nimport type { ReadonlyFooterDataProvider } from \"../../../core/footer-data-provider.ts\";\nimport type { KeybindingsManager } from \"../../../core/keybindings.ts\";\nimport { CustomEditor } from \"../components/custom-editor.ts\";\nimport { WorkingStatusIndicator } from \"../components/status-indicator.ts\";\nimport type { ToolExecutionPresentation } from \"../components/tool-execution.ts\";\nimport type { InteractiveSession } from \"../interactive-host-runtime.ts\";\nimport { theme } from \"../theme/theme.ts\";\nimport { getGrokChromeTokens } from \"./chrome-tokens.ts\";\nimport { GrokFooter } from \"./footer.ts\";\nimport { GrokInputCard } from \"./input-card.ts\";\nimport { GROK_GLYPHS } from \"./palette.ts\";\nimport { GrokWelcomeCard } from \"./welcome-card.ts\";\n\nexport interface InteractiveFooter extends Component {\n\tsetSession(session: InteractiveSession): void;\n\tsetAutoCompactEnabled(enabled: boolean): void;\n\tinvalidate(): void;\n\tdispose(): void;\n}\n\nexport type EditorBorderContext = {\n\treadonly isBashMode: boolean;\n\treadonly thinkingLevel: string;\n};\n\n/**\n * Mode-owned chrome seam for InteractiveMode. Extensions continue to own their\n * editor factory; this strategy only creates and decorates the base editor.\n */\nexport interface InteractiveChrome {\n\treadonly toolPresentation: ToolExecutionPresentation;\n\tcreateBaseEditor(context: { ui: TUI; keybindings: KeybindingsManager; editorOptions: EditorOptions }): CustomEditor;\n\tgetEditorTheme(): EditorTheme;\n\tcreateFooter(session: InteractiveSession, footerData: ReadonlyFooterDataProvider): InteractiveFooter;\n\tcreateWelcomeContent(appName: string, version: string): Component;\n\tcreateWorkingIndicator(ui: TUI, message: string, indicator?: WorkingIndicatorOptions): WorkingStatusIndicator;\n\tgetEditorBorderColor(context: EditorBorderContext): (text: string) => string;\n\tarrangeRoot(children: readonly Component[], ui?: TUI): Component[];\n}\n\nclass GrokFooterSurface implements Component {\n\tprivate readonly content: Component;\n\n\tconstructor(content: Component) {\n\t\tthis.content = content;\n\t}\n\n\tinvalidate(): void {\n\t\tthis.content.invalidate();\n\t}\n\n\trender(width: number): string[] {\n\t\tconst surface = getGrokChromeTokens().surface;\n\t\treturn this.content.render(width).map(surface);\n\t}\n\n\tdispose(): void {\n\t\tthis.content.dispose?.();\n\t}\n}\n\nclass GrokRootSpacer implements Component {\n\tprivate readonly ui: TUI;\n\tprivate readonly content: readonly Component[];\n\n\tconstructor(ui: TUI, content: readonly Component[]) {\n\t\tthis.ui = ui;\n\t\tthis.content = content;\n\t}\n\n\tinvalidate(): void {\n\t\t// The spacer derives its height from the current terminal dimensions.\n\t}\n\n\trender(width: number): string[] {\n\t\tconst contentHeight = this.content.reduce((height, component) => height + component.render(width).length, 0);\n\t\treturn Array.from({ length: Math.max(0, this.ui.terminal.rows - contentHeight) }, () => \"\");\n\t}\n}\n\nclass GrokEditor extends CustomEditor {\n\tprivate readonly card: GrokInputCard;\n\n\tconstructor(ui: TUI, editorTheme: EditorTheme, keybindings: KeybindingsManager, options: EditorOptions) {\n\t\tsuper(ui, editorTheme, keybindings, options);\n\t\tthis.card = new GrokInputCard({\n\t\t\trender: (width) => this.renderBase(width),\n\t\t\tinvalidate: () => super.invalidate(),\n\t\t});\n\t}\n\n\toverride render(width: number): string[] {\n\t\treturn this.card.render(width);\n\t}\n\n\tprivate renderBase(width: number): string[] {\n\t\treturn super.render(width);\n\t}\n}\n\nexport class GrokChrome implements InteractiveChrome {\n\treadonly toolPresentation = \"grok\" as const;\n\n\tcreateBaseEditor({\n\t\tui,\n\t\tkeybindings,\n\t\teditorOptions,\n\t}: {\n\t\tui: TUI;\n\t\tkeybindings: KeybindingsManager;\n\t\teditorOptions: EditorOptions;\n\t}): CustomEditor {\n\t\treturn new GrokEditor(ui, this.getEditorTheme(), keybindings, editorOptions);\n\t}\n\n\tgetEditorTheme(): EditorTheme {\n\t\tconst tokens = getGrokChromeTokens();\n\t\treturn {\n\t\t\tborderColor: tokens.inputBorder,\n\t\t\tselectList: {\n\t\t\t\tselectedPrefix: (text) => theme.fg(\"accent\", text),\n\t\t\t\tselectedText: (text) => tokens.primaryText(text),\n\t\t\t\tdescription: (text) => tokens.mutedText(text),\n\t\t\t\tscrollInfo: (text) => tokens.mutedText(text),\n\t\t\t\tnoMatch: (text) => tokens.mutedText(text),\n\t\t\t\trenderRow: ({ prefix, primary, description, isSelected }) => {\n\t\t\t\t\tconst row = `${prefix}${tokens.primaryText(primary)}${description ? tokens.mutedText(description) : \"\"}`;\n\t\t\t\t\treturn isSelected ? theme.bg(\"selectedBg\", row) : row;\n\t\t\t\t},\n\t\t\t},\n\t\t};\n\t}\n\n\tcreateFooter(session: InteractiveSession, footerData: ReadonlyFooterDataProvider): InteractiveFooter {\n\t\treturn new GrokFooter(session, footerData);\n\t}\n\n\tcreateWelcomeContent(appName: string, version: string): Component {\n\t\treturn new GrokWelcomeCard(appName, version);\n\t}\n\n\tcreateWorkingIndicator(ui: TUI, message: string, indicator?: WorkingIndicatorOptions): WorkingStatusIndicator {\n\t\treturn new WorkingStatusIndicator(ui, message, {\n\t\t\t...indicator,\n\t\t\tframes: [GROK_GLYPHS.spinner],\n\t\t\tindicatorFormatter: (frame) => theme.fg(\"accent\", frame),\n\t\t});\n\t}\n\n\tgetEditorBorderColor(_context: EditorBorderContext): (text: string) => string {\n\t\treturn getGrokChromeTokens().inputBorder;\n\t}\n\n\tarrangeRoot(children: readonly Component[], ui?: TUI): Component[] {\n\t\t// pi-tui concatenates root children without a layout pass. Keep transcript\n\t\t// content first and calculate the remaining rows at render time from the TUI's\n\t\t// terminal height, so the input tail is truly bottom-anchored when it fits.\n\t\tconst inputTailStart = Math.max(0, children.length - 3);\n\t\tconst content = children.slice(0, inputTailStart);\n\t\tconst inputTail = children.slice(inputTailStart);\n\t\tconst footer = inputTail.at(-1);\n\t\tconst tail = footer ? [...inputTail.slice(0, -1), new GrokFooterSurface(footer)] : [...inputTail];\n\t\tconst arranged = [...content, ...tail];\n\t\treturn ui ? [...content, new GrokRootSpacer(ui, arranged), ...tail] : arranged;\n\t}\n}\n"]}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { type Component } from "@earendil-works/pi-tui";
|
|
2
|
-
import type { AgentSession } from "../../../core/agent-session.ts";
|
|
3
2
|
import type { ReadonlyFooterDataProvider } from "../../../core/footer-data-provider.ts";
|
|
3
|
+
import type { InteractiveSession } from "../interactive-host-runtime.ts";
|
|
4
4
|
/** Compact status footer for grok chrome. */
|
|
5
5
|
export declare class GrokFooter implements Component {
|
|
6
6
|
private session;
|
|
7
|
-
constructor(session:
|
|
8
|
-
setSession(session:
|
|
7
|
+
constructor(session: InteractiveSession, _footerData: ReadonlyFooterDataProvider);
|
|
8
|
+
setSession(session: InteractiveSession): void;
|
|
9
9
|
setAutoCompactEnabled(_enabled: boolean): void;
|
|
10
10
|
invalidate(): void;
|
|
11
11
|
dispose(): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"footer.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/grok/footer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAmB,MAAM,wBAAwB,CAAC;AACzE,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"footer.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/grok/footer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAmB,MAAM,wBAAwB,CAAC;AACzE,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,uCAAuC,CAAC;AACxF,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AAGzE,6CAA6C;AAC7C,qBAAa,UAAW,YAAW,SAAS;IAC3C,OAAO,CAAC,OAAO,CAAqB;gBAExB,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAAE,0BAA0B;IAIhF,UAAU,CAAC,OAAO,EAAE,kBAAkB,GAAG,IAAI;IAI7C,qBAAqB,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI;IAI9C,UAAU,IAAI,IAAI;IAIlB,OAAO,IAAI,IAAI;IAIf,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE;CAM/B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"footer.js","sourceRoot":"","sources":["../../../../src/modes/interactive/grok/footer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAGzE,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAEzD,6CAA6C;AAC7C,MAAM,OAAO,UAAU;IAGtB,YAAY,
|
|
1
|
+
{"version":3,"file":"footer.js","sourceRoot":"","sources":["../../../../src/modes/interactive/grok/footer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAGzE,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAEzD,6CAA6C;AAC7C,MAAM,OAAO,UAAU;IAGtB,YAAY,OAA2B,EAAE,WAAuC;QAC/E,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACxB,CAAC;IAED,UAAU,CAAC,OAA2B;QACrC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACxB,CAAC;IAED,qBAAqB,CAAC,QAAiB;QACtC,6DAA6D;IAC9D,CAAC;IAED,UAAU;QACT,8DAA8D;IAC/D,CAAC;IAED,OAAO;QACN,yCAAyC;IAC1C,CAAC;IAED,MAAM,CAAC,KAAa;QACnB,MAAM,MAAM,GAAG,mBAAmB,EAAE,CAAC;QACrC,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,MAAM,EAAE,CAAC;QACjD,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,EAAE,IAAI,UAAU,CAAC;QACzD,OAAO,CAAC,eAAe,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC;IACvF,CAAC;CACD","sourcesContent":["import { type Component, truncateToWidth } from \"@earendil-works/pi-tui\";\nimport type { ReadonlyFooterDataProvider } from \"../../../core/footer-data-provider.ts\";\nimport type { InteractiveSession } from \"../interactive-host-runtime.ts\";\nimport { getGrokChromeTokens } from \"./chrome-tokens.ts\";\n\n/** Compact status footer for grok chrome. */\nexport class GrokFooter implements Component {\n\tprivate session: InteractiveSession;\n\n\tconstructor(session: InteractiveSession, _footerData: ReadonlyFooterDataProvider) {\n\t\tthis.session = session;\n\t}\n\n\tsetSession(session: InteractiveSession): void {\n\t\tthis.session = session;\n\t}\n\n\tsetAutoCompactEnabled(_enabled: boolean): void {\n\t\t// The grok footer intentionally presents model and cwd only.\n\t}\n\n\tinvalidate(): void {\n\t\t// Values are read directly from the session during rendering.\n\t}\n\n\tdispose(): void {\n\t\t// No resources are owned by this footer.\n\t}\n\n\trender(width: number): string[] {\n\t\tconst tokens = getGrokChromeTokens();\n\t\tconst cwd = this.session.sessionManager.getCwd();\n\t\tconst model = this.session.state.model?.id ?? \"no-model\";\n\t\treturn [truncateToWidth(`${tokens.cwd(cwd)} ${tokens.modelLabel(model)}`, width, \"\")];\n\t}\n}\n"]}
|
|
@@ -1,12 +1,27 @@
|
|
|
1
|
+
import type { ThinkingLevel } from "@earendil-works/pi-agent-core";
|
|
2
|
+
import type { AgentSession } from "../../core/agent-session.ts";
|
|
1
3
|
import type { AgentSessionRuntime } from "../../core/agent-session-runtime.ts";
|
|
2
4
|
import { type EnsuredHost } from "../rpc/host-ensure.ts";
|
|
3
5
|
import { type RpcClientEvent } from "../rpc/rpc-client.ts";
|
|
4
6
|
export declare const INTERACTIVE_HOST_FALLBACK_WARNING = "Warning: shared interactive host unavailable; continuing locally";
|
|
5
7
|
export interface InteractiveHostWarning {
|
|
6
|
-
readonly type: "interactive_host_fallback";
|
|
8
|
+
readonly type: "interactive_host_fallback" | "interactive_host_action_failed";
|
|
7
9
|
readonly message: string;
|
|
8
10
|
readonly cause: unknown;
|
|
9
11
|
}
|
|
12
|
+
/**
|
|
13
|
+
* The session contract InteractiveMode actually runs against. The local
|
|
14
|
+
* AgentSession answers these reads synchronously; the shared-host proxy answers
|
|
15
|
+
* them over RPC. Declaring the union here keeps the proxy honest (no more
|
|
16
|
+
* `as unknown as` lie at the boundary) and lets the compiler find every TUI
|
|
17
|
+
* call site that must await.
|
|
18
|
+
*/
|
|
19
|
+
export type InteractiveSession = Omit<AgentSession, "cycleThinkingLevel" | "getAvailableThinkingLevels" | "getSessionStats" | "getUserMessagesForForking"> & {
|
|
20
|
+
cycleThinkingLevel(): ThinkingLevel | undefined | Promise<ThinkingLevel | undefined>;
|
|
21
|
+
getAvailableThinkingLevels(): ThinkingLevel[] | Promise<ThinkingLevel[]>;
|
|
22
|
+
getSessionStats(): ReturnType<AgentSession["getSessionStats"]> | Promise<ReturnType<AgentSession["getSessionStats"]>>;
|
|
23
|
+
getUserMessagesForForking(): ReturnType<AgentSession["getUserMessagesForForking"]> | Promise<ReturnType<AgentSession["getUserMessagesForForking"]>>;
|
|
24
|
+
};
|
|
10
25
|
export interface InteractiveHostRuntimeOptions {
|
|
11
26
|
readonly socket: string;
|
|
12
27
|
readonly agentDir?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interactive-host-runtime.d.ts","sourceRoot":"","sources":["../../../src/modes/interactive/interactive-host-runtime.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"interactive-host-runtime.d.ts","sourceRoot":"","sources":["../../../src/modes/interactive/interactive-host-runtime.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,KAAK,EAAE,YAAY,EAAgD,MAAM,6BAA6B,CAAC;AAC9G,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qCAAqC,CAAC;AAE/E,OAAO,EAAE,KAAK,WAAW,EAAc,MAAM,uBAAuB,CAAC;AACrE,OAAO,EAAa,KAAK,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtE,eAAO,MAAM,iCAAiC,qEAAqE,CAAC;AAEpH,MAAM,WAAW,sBAAsB;IACtC,QAAQ,CAAC,IAAI,EAAE,2BAA2B,GAAG,gCAAgC,CAAC;IAC9E,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;CACxB;AAED;;;;;;GAMG;AACH,MAAM,MAAM,kBAAkB,GAAG,IAAI,CACpC,YAAY,EACZ,oBAAoB,GAAG,4BAA4B,GAAG,iBAAiB,GAAG,2BAA2B,CACrG,GAAG;IACH,kBAAkB,IAAI,aAAa,GAAG,SAAS,GAAG,OAAO,CAAC,aAAa,GAAG,SAAS,CAAC,CAAC;IACrF,0BAA0B,IAAI,aAAa,EAAE,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC,CAAC;IACzE,eAAe,IACZ,UAAU,CAAC,YAAY,CAAC,iBAAiB,CAAC,CAAC,GAC3C,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC;IACxD,yBAAyB,IACtB,UAAU,CAAC,YAAY,CAAC,2BAA2B,CAAC,CAAC,GACrD,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC,2BAA2B,CAAC,CAAC,CAAC,CAAC;CAClE,CAAC;AAEF,MAAM,WAAW,6BAA6B;IAC7C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC,CAAC;IAC3G,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,sBAAsB,KAAK,IAAI,CAAC;CACtD;AAED;;;;;GAKG;AACH,wBAAsB,4BAA4B,CACjD,YAAY,EAAE,mBAAmB,EACjC,OAAO,EAAE,6BAA6B,GACpC,OAAO,CAAC,mBAAmB,CAAC,CA0B9B;AAoOD,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,cAAc,GAAG,KAAK,IAAI,OAAO,CAAC,cAAc,EAAE;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAEhH"}
|
|
@@ -23,7 +23,7 @@ export async function createInteractiveHostRuntime(localRuntime, options) {
|
|
|
23
23
|
modelId: localRuntime.session.model?.id,
|
|
24
24
|
thinkingLevel: localRuntime.session.thinkingLevel,
|
|
25
25
|
});
|
|
26
|
-
const remoteSession = createRemoteSessionProxy(localRuntime.session, client, opened.state);
|
|
26
|
+
const remoteSession = createRemoteSessionProxy(localRuntime.session, client, opened.state, options.onWarning);
|
|
27
27
|
return new RemoteInteractiveRuntime(localRuntime, remoteSession, client);
|
|
28
28
|
}
|
|
29
29
|
catch (cause) {
|
|
@@ -101,7 +101,17 @@ class RemoteInteractiveRuntime {
|
|
|
101
101
|
throw new Error("Session import is not available while connected to the shared host");
|
|
102
102
|
}
|
|
103
103
|
}
|
|
104
|
-
function createRemoteSessionProxy(local, client, initialState) {
|
|
104
|
+
function createRemoteSessionProxy(local, client, initialState, onWarning) {
|
|
105
|
+
// Fire-and-forget setters keep the sync AgentSession signature, but their RPC
|
|
106
|
+
// failures must not vanish: the matching *_changed wire event confirms success,
|
|
107
|
+
// and a rejection here is the only signal of failure.
|
|
108
|
+
const reportActionFailure = (action) => (error) => {
|
|
109
|
+
onWarning?.({
|
|
110
|
+
type: "interactive_host_action_failed",
|
|
111
|
+
message: `Warning: shared interactive host ${action} failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
112
|
+
cause: error,
|
|
113
|
+
});
|
|
114
|
+
};
|
|
105
115
|
let state = initialState;
|
|
106
116
|
let streamingAssistant;
|
|
107
117
|
const listeners = new Set();
|
|
@@ -135,7 +145,13 @@ function createRemoteSessionProxy(local, client, initialState) {
|
|
|
135
145
|
const session = new Proxy(local, {
|
|
136
146
|
get(target, property, receiver) {
|
|
137
147
|
if (property === "prompt")
|
|
138
|
-
return (message, options) => client.prompt(message,
|
|
148
|
+
return (message, options) => client.prompt(message, {
|
|
149
|
+
...(options?.images ? { images: options.images } : {}),
|
|
150
|
+
...(options?.streamingBehavior ? { streamingBehavior: options.streamingBehavior } : {}),
|
|
151
|
+
...(options?.thinkingLevel ? { thinkingLevel: options.thinkingLevel } : {}),
|
|
152
|
+
...(options?.promptDisposition ? { promptDisposition: options.promptDisposition } : {}),
|
|
153
|
+
...(options?.preflightResult ? { preflightResult: options.preflightResult } : {}),
|
|
154
|
+
});
|
|
139
155
|
if (property === "abort")
|
|
140
156
|
return () => client.abort();
|
|
141
157
|
if (property === "steer")
|
|
@@ -153,29 +169,29 @@ function createRemoteSessionProxy(local, client, initialState) {
|
|
|
153
169
|
if (property === "cycleModel")
|
|
154
170
|
return () => client.cycleModel();
|
|
155
171
|
if (property === "setThinkingLevel")
|
|
156
|
-
return (level) => void client.setThinkingLevel(level);
|
|
172
|
+
return (level) => void client.setThinkingLevel(level).catch(reportActionFailure("setThinkingLevel"));
|
|
157
173
|
if (property === "cycleThinkingLevel")
|
|
158
174
|
return () => client.cycleThinkingLevel().then((result) => result?.level);
|
|
159
175
|
if (property === "getAvailableThinkingLevels")
|
|
160
176
|
return () => client.getAvailableThinkingLevels();
|
|
161
177
|
if (property === "setSteeringMode")
|
|
162
|
-
return (mode) => void client.setSteeringMode(mode);
|
|
178
|
+
return (mode) => void client.setSteeringMode(mode).catch(reportActionFailure("setSteeringMode"));
|
|
163
179
|
if (property === "setFollowUpMode")
|
|
164
|
-
return (mode) => void client.setFollowUpMode(mode);
|
|
180
|
+
return (mode) => void client.setFollowUpMode(mode).catch(reportActionFailure("setFollowUpMode"));
|
|
165
181
|
if (property === "compact")
|
|
166
182
|
return (instructions) => client.compact(instructions);
|
|
167
183
|
if (property === "setAutoCompactionEnabled")
|
|
168
|
-
return (enabled) => void client.setAutoCompaction(enabled);
|
|
184
|
+
return (enabled) => void client.setAutoCompaction(enabled).catch(reportActionFailure("setAutoCompaction"));
|
|
169
185
|
if (property === "executeBash")
|
|
170
186
|
return (command) => client.bash(command);
|
|
171
187
|
if (property === "abortBash")
|
|
172
|
-
return () => void client.abortBash();
|
|
188
|
+
return () => void client.abortBash().catch(reportActionFailure("abortBash"));
|
|
173
189
|
if (property === "getSessionStats")
|
|
174
190
|
return () => client.getSessionStats();
|
|
175
191
|
if (property === "exportToHtml")
|
|
176
192
|
return (outputPath) => client.exportHtml(outputPath).then((result) => result.path);
|
|
177
193
|
if (property === "setSessionName")
|
|
178
|
-
return (name) => void client.setSessionName(name);
|
|
194
|
+
return (name) => void client.setSessionName(name).catch(reportActionFailure("setSessionName"));
|
|
179
195
|
if (property === "getUserMessagesForForking")
|
|
180
196
|
return () => client.getForkMessages();
|
|
181
197
|
if (property === "subscribe")
|
|
@@ -189,6 +205,17 @@ function createRemoteSessionProxy(local, client, initialState) {
|
|
|
189
205
|
};
|
|
190
206
|
if (property === "isStreaming")
|
|
191
207
|
return state.isStreaming;
|
|
208
|
+
// The footer and other renderers read session.state.*; surface the
|
|
209
|
+
// host-authoritative fields there too, not only via the direct getters.
|
|
210
|
+
if (property === "state") {
|
|
211
|
+
const localState = target.state;
|
|
212
|
+
return {
|
|
213
|
+
...localState,
|
|
214
|
+
model: state.model ?? localState.model,
|
|
215
|
+
thinkingLevel: state.thinkingLevel,
|
|
216
|
+
isStreaming: state.isStreaming,
|
|
217
|
+
};
|
|
218
|
+
}
|
|
192
219
|
if (property === "sessionFile")
|
|
193
220
|
return state.sessionFile;
|
|
194
221
|
if (property === "sessionId")
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interactive-host-runtime.js","sourceRoot":"","sources":["../../../src/modes/interactive/interactive-host-runtime.ts"],"names":[],"mappings":"AAGA,OAAO,EAAoB,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACrE,OAAO,EAAE,SAAS,EAAuB,MAAM,sBAAsB,CAAC;AAEtE,MAAM,CAAC,MAAM,iCAAiC,GAAG,kEAAkE,CAAC;AAepH;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,4BAA4B,CACjD,YAAiC,EACjC,OAAsC;IAEtC,MAAM,WAAW,GAAG,YAAY,CAAC,OAAO,CAAC,WAAW,CAAC;IACrD,IAAI,CAAC,WAAW;QAAE,OAAO,YAAY,CAAC;IACtC,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,IAAI,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,CAAC;IACnF,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC,EAAE,UAAU,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAC7D,IAAI,CAAC;QACJ,MAAM,SAAS,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;QACxE,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;QACrB,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC;YACvC,WAAW;YACX,GAAG,EAAE,YAAY,CAAC,GAAG;YACrB,QAAQ,EAAE,YAAY,CAAC,OAAO,CAAC,KAAK,EAAE,QAAQ;YAC9C,OAAO,EAAE,YAAY,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE;YACvC,aAAa,EAAE,YAAY,CAAC,OAAO,CAAC,aAAa;SACjD,CAAC,CAAC;QACH,MAAM,aAAa,GAAG,wBAAwB,CAAC,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;QAC3F,OAAO,IAAI,wBAAwB,CAAC,YAAY,EAAE,aAAa,EAAE,MAAM,CAAmC,CAAC;IAC5G,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QACpC,OAAO,CAAC,SAAS,EAAE,CAAC;YACnB,IAAI,EAAE,2BAA2B;YACjC,OAAO,EAAE,GAAG,iCAAiC,KAAK,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;YAC1G,KAAK;SACL,CAAC,CAAC;QACH,OAAO,YAAY,CAAC;IACrB,CAAC;AACF,CAAC;AAED,MAAM,wBAAwB;IACpB,MAAM,CAAsB;IAC5B,QAAQ,CAAe;IACvB,OAAO,CAAY;IAC5B,cAAc,CAAoC;IAClD,wBAAwB,CAA2B;IAEnD,YAAY,KAA0B,EAAE,OAAqB,EAAE,MAAiB;QAC/E,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;QACpB,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC;QACxB,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;IACvB,CAAC;IAED,IAAI,OAAO;QACV,OAAO,IAAI,CAAC,QAAQ,CAAC;IACtB,CAAC;IACD,IAAI,QAAQ;QACX,OAAO,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC;IAC7B,CAAC;IACD,IAAI,GAAG;QACN,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC;IACxB,CAAC;IACD,IAAI,WAAW;QACd,OAAO,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC;IAChC,CAAC;IACD,IAAI,oBAAoB;QACvB,OAAO,IAAI,CAAC,MAAM,CAAC,oBAAoB,CAAC;IACzC,CAAC;IACD,IAAI,aAAa;QAChB,OAAO,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC;IAClC,CAAC;IACD,0BAA0B,CAAC,QAAqB;QAC/C,IAAI,CAAC,wBAAwB,GAAG,QAAQ,CAAC;IAC1C,CAAC;IACD,gBAAgB,CAAC,QAA8B;QAC9C,IAAI,CAAC,cAAc,GAAG,QAAQ,CAAC;IAChC,CAAC;IACD,KAAK,CAAC,OAAO;QACZ,MAAM,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,CAAC;QAClC,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;QAC1B,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;IAC7B,CAAC;IACD,KAAK,CAAC,UAAU;QACf,IAAI,CAAC,wBAAwB,EAAE,EAAE,CAAC;QAClC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC;QAC/C,IAAI,CAAC,MAAM,CAAC,SAAS;YAAE,MAAM,IAAI,CAAC,cAAc,EAAE,EAAE,CAAC;QACrD,OAAO,MAAM,CAAC;IACf,CAAC;IACD,KAAK,CAAC,aAAa,CAAC,WAAmB;QACtC,IAAI,CAAC,wBAAwB,EAAE,EAAE,CAAC;QAClC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC;QAC7D,IAAI,CAAC,MAAM,CAAC,SAAS;YAAE,MAAM,IAAI,CAAC,cAAc,EAAE,EAAE,CAAC;QACrD,OAAO,MAAM,CAAC;IACf,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,OAAe;QACzB,IAAI,CAAC,wBAAwB,EAAE,EAAE,CAAC;QAClC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAChD,IAAI,CAAC,MAAM,CAAC,SAAS;YAAE,MAAM,IAAI,CAAC,cAAc,EAAE,EAAE,CAAC;QACrD,OAAO,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,YAAY,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC;IACnE,CAAC;IACD,KAAK,CAAC,eAAe;QACpB,MAAM,IAAI,KAAK,CAAC,oEAAoE,CAAC,CAAC;IACvF,CAAC;CACD;AAED,SAAS,wBAAwB,CAChC,KAAmB,EACnB,MAAiB,EACjB,YAA6C;IAE7C,IAAI,KAAK,GAAG,YAAY,CAAC;IACzB,IAAI,kBAAgG,CAAC;IACrG,MAAM,SAAS,GAAG,IAAI,GAAG,EAA6B,CAAC;IACvD,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,EAAE,EAAE;QAC5B,IAAI,SAAS,CAAC,IAAI,KAAK,eAAe;YAAE,KAAK,GAAG,EAAE,GAAG,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC;QACjF,IAAI,SAAS,CAAC,IAAI,KAAK,aAAa;YAAE,KAAK,GAAG,EAAE,GAAG,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC;QAC9E,IAAI,SAAS,CAAC,IAAI,KAAK,eAAe,EAAE,CAAC;YACxC,KAAK,GAAG,EAAE,GAAG,KAAK,EAAE,KAAK,EAAE,SAAS,CAAC,KAAK,EAAE,aAAa,EAAE,SAAS,CAAC,aAAa,EAAE,CAAC;QACtF,CAAC;QACD,IAAI,SAAS,CAAC,IAAI,KAAK,wBAAwB;YAAE,KAAK,GAAG,EAAE,GAAG,KAAK,EAAE,aAAa,EAAE,SAAS,CAAC,KAAK,EAAE,CAAC;QACtG,IAAI,SAAS,CAAC,IAAI,KAAK,eAAe,EAAE,CAAC;YACxC,IAAI,SAAS,CAAC,OAAO,CAAC,IAAI,KAAK,WAAW;gBAAE,kBAAkB,GAAG,eAAe,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;YACpG,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,eAAe,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC;QACrE,CAAC;QACD,IAAI,SAAS,CAAC,IAAI,KAAK,aAAa,EAAE,CAAC;YACtC,IAAI,SAAS,CAAC,OAAO,CAAC,IAAI,KAAK,WAAW;gBAAE,kBAAkB,GAAG,eAAe,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;YACpG,MAAM,QAAQ,GAAG,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC;YAC5C,MAAM,QAAQ,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;YACjC,IAAI,QAAQ,EAAE,IAAI,KAAK,SAAS,CAAC,OAAO,CAAC,IAAI;gBAC5C,QAAQ,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,eAAe,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QACrE,CAAC;QACD,MAAM,KAAK,GAAG,oBAAoB,CAAC,SAAS,EAAE,kBAAkB,CAAC,CAAC;QAClE,KAAK,MAAM,QAAQ,IAAI,SAAS;YAAE,QAAQ,CAAC,KAAK,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;IACH,MAAM,OAAO,GAAG,IAAI,KAAK,CAAC,KAAK,EAAE;QAChC,GAAG,CAAC,MAAM,EAAE,QAAQ,EAAE,QAAQ;YAC7B,IAAI,QAAQ,KAAK,QAAQ;gBACxB,OAAO,CAAC,OAAe,EAAE,OAA+C,EAAE,EAAE,CAC3E,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;YAC1C,IAAI,QAAQ,KAAK,OAAO;gBAAE,OAAO,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;YACtD,IAAI,QAAQ,KAAK,OAAO;gBACvB,OAAO,CAAC,OAAe,EAAE,MAA6C,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;YAC1G,IAAI,QAAQ,KAAK,UAAU;gBAC1B,OAAO,CAAC,OAAe,EAAE,MAAgD,EAAE,EAAE,CAC5E,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;YACnC,IAAI,QAAQ,KAAK,aAAa;gBAAE,OAAO,GAAG,EAAE,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;YAClE,IAAI,QAAQ,KAAK,sBAAsB;gBAAE,OAAO,GAAG,EAAE,CAAC,MAAM,CAAC,oBAAoB,EAAE,CAAC;YACpF,IAAI,QAAQ,KAAK,UAAU;gBAC1B,OAAO,KAAK,EAAE,KAAyC,EAAE,EAAE;oBAC1D,MAAM,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC;gBACjD,CAAC,CAAC;YACH,IAAI,QAAQ,KAAK,YAAY;gBAAE,OAAO,GAAG,EAAE,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC;YAChE,IAAI,QAAQ,KAAK,kBAAkB;gBAClC,OAAO,CAAC,KAAoC,EAAE,EAAE,CAAC,KAAK,MAAM,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC;YACtF,IAAI,QAAQ,KAAK,oBAAoB;gBACpC,OAAO,GAAG,EAAE,CAAC,MAAM,CAAC,kBAAkB,EAAE,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;YAC1E,IAAI,QAAQ,KAAK,4BAA4B;gBAAE,OAAO,GAAG,EAAE,CAAC,MAAM,CAAC,0BAA0B,EAAE,CAAC;YAChG,IAAI,QAAQ,KAAK,iBAAiB;gBACjC,OAAO,CAAC,IAAkC,EAAE,EAAE,CAAC,KAAK,MAAM,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;YAClF,IAAI,QAAQ,KAAK,iBAAiB;gBACjC,OAAO,CAAC,IAAkC,EAAE,EAAE,CAAC,KAAK,MAAM,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;YAClF,IAAI,QAAQ,KAAK,SAAS;gBAAE,OAAO,CAAC,YAAqB,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;YAC3F,IAAI,QAAQ,KAAK,0BAA0B;gBAC1C,OAAO,CAAC,OAAgB,EAAE,EAAE,CAAC,KAAK,MAAM,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC;YACrE,IAAI,QAAQ,KAAK,aAAa;gBAAE,OAAO,CAAC,OAAe,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACjF,IAAI,QAAQ,KAAK,WAAW;gBAAE,OAAO,GAAG,EAAE,CAAC,KAAK,MAAM,CAAC,SAAS,EAAE,CAAC;YACnE,IAAI,QAAQ,KAAK,iBAAiB;gBAAE,OAAO,GAAG,EAAE,CAAC,MAAM,CAAC,eAAe,EAAE,CAAC;YAC1E,IAAI,QAAQ,KAAK,cAAc;gBAC9B,OAAO,CAAC,UAAmB,EAAE,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAC7F,IAAI,QAAQ,KAAK,gBAAgB;gBAAE,OAAO,CAAC,IAAY,EAAE,EAAE,CAAC,KAAK,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;YAC7F,IAAI,QAAQ,KAAK,2BAA2B;gBAAE,OAAO,GAAG,EAAE,CAAC,MAAM,CAAC,eAAe,EAAE,CAAC;YACpF,IAAI,QAAQ,KAAK,WAAW;gBAC3B,OAAO,CAAC,QAAmC,EAAE,EAAE;oBAC9C,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;oBACxB,MAAM,gBAAgB,GAAG,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;oBACpD,OAAO,GAAG,EAAE;wBACX,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;wBAC3B,gBAAgB,EAAE,CAAC;oBACpB,CAAC,CAAC;gBACH,CAAC,CAAC;YACH,IAAI,QAAQ,KAAK,aAAa;gBAAE,OAAO,KAAK,CAAC,WAAW,CAAC;YACzD,IAAI,QAAQ,KAAK,aAAa;gBAAE,OAAO,KAAK,CAAC,WAAW,CAAC;YACzD,IAAI,QAAQ,KAAK,WAAW;gBAAE,OAAO,KAAK,CAAC,SAAS,CAAC;YACrD,IAAI,QAAQ,KAAK,UAAU;gBAAE,OAAO,MAAM,CAAC,QAAQ,CAAC;YACpD,IAAI,QAAQ,KAAK,OAAO;gBAAE,OAAO,KAAK,CAAC,KAAK,IAAI,MAAM,CAAC,KAAK,CAAC;YAC7D,IAAI,QAAQ,KAAK,eAAe;gBAAE,OAAO,KAAK,CAAC,aAAa,CAAC;YAC7D,OAAO,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;QAChD,CAAC;KACD,CAAC,CAAC;IACH,OAAO,OAAO,CAAC;AAChB,CAAC;AAED,SAAS,oBAAoB,CAC5B,KAAqB,EACrB,kBAAgG;IAEhG,IAAI,KAAK,CAAC,IAAI,KAAK,gBAAgB,IAAI,CAAC,kBAAkB;QAAE,OAAO,KAAqC,CAAC;IACzG,MAAM,MAAM,GAAG,KAAK,CAAC,qBAAqB,CAAC;IAC3C,IAAI,MAAM,CAAC,IAAI,KAAK,YAAY,IAAI,MAAM,CAAC,IAAI,KAAK,gBAAgB,IAAI,MAAM,CAAC,IAAI,KAAK,gBAAgB,EAAE,CAAC;QAC1G,OAAO,KAAqC,CAAC;IAC9C,CAAC;IACD,MAAM,OAAO,GAAG,kBAAkB,CAAC,OAAO,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;IAChE,IAAI,MAAM,CAAC,IAAI,KAAK,YAAY,IAAI,OAAO,EAAE,IAAI,KAAK,MAAM;QAAE,OAAO,CAAC,IAAI,IAAI,MAAM,CAAC,KAAK,CAAC;IAC3F,IAAI,MAAM,CAAC,IAAI,KAAK,gBAAgB,IAAI,OAAO,EAAE,IAAI,KAAK,UAAU;QAAE,OAAO,CAAC,QAAQ,IAAI,MAAM,CAAC,KAAK,CAAC;IACvG,IAAI,MAAM,CAAC,IAAI,KAAK,gBAAgB,IAAI,OAAO,EAAE,IAAI,KAAK,UAAU,EAAE,CAAC;QACtE,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,SAAS,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC;QAC7D,IAAI,CAAC;YACJ,MAAM,MAAM,GAAY,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YACxC,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC7E,OAAO,CAAC,SAAS,GAAG,MAAiC,CAAC;YACvD,CAAC;QACF,CAAC;QAAC,MAAM,CAAC;YACR,gEAAgE;QACjE,CAAC;IACF,CAAC;IACD,kBAAkB,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;IACvC,OAAO;QACN,IAAI,EAAE,gBAAgB;QACtB,OAAO,EAAE,eAAe,CAAC,kBAAkB,CAAC;QAC5C,qBAAqB,EAAE,EAAE,GAAG,MAAM,EAAE,OAAO,EAAE,eAAe,CAAC,kBAAkB,CAAC,EAAE;KAC7D,CAAC;AACxB,CAAC;AAED,SAAS,YAAY,CAAC,KAMrB;IACA,OAAO,KAAK,CAAC;AACd,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,KAAqB;IAC3D,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,MAAM,IAAI,KAAK,CAAC;AACvE,CAAC","sourcesContent":["import type { AgentSession, AgentSessionEvent, AgentSessionEventListener } from \"../../core/agent-session.ts\";\nimport type { AgentSessionRuntime } from \"../../core/agent-session-runtime.ts\";\nimport type { AgentSessionRuntimeDiagnostic } from \"../../core/agent-session-services.ts\";\nimport { type EnsuredHost, ensureHost } from \"../rpc/host-ensure.ts\";\nimport { RpcClient, type RpcClientEvent } from \"../rpc/rpc-client.ts\";\n\nexport const INTERACTIVE_HOST_FALLBACK_WARNING = \"Warning: shared interactive host unavailable; continuing locally\";\n\nexport interface InteractiveHostWarning {\n\treadonly type: \"interactive_host_fallback\";\n\treadonly message: string;\n\treadonly cause: unknown;\n}\n\nexport interface InteractiveHostRuntimeOptions {\n\treadonly socket: string;\n\treadonly agentDir?: string;\n\treadonly ensureHost?: (options: { socket: string; agentDir?: string }) => Promise<EnsuredHost | undefined>;\n\tonWarning?: (warning: InteractiveHostWarning) => void;\n}\n\n/**\n * Replace only the transport-facing session operations. The object returned is\n * deliberately still an AgentSessionRuntime: InteractiveMode and extensions\n * retain their existing runtime seam, while the authoritative prompt/session\n * state is hosted by the shared RPC process.\n */\nexport async function createInteractiveHostRuntime(\n\tlocalRuntime: AgentSessionRuntime,\n\toptions: InteractiveHostRuntimeOptions,\n): Promise<AgentSessionRuntime> {\n\tconst sessionPath = localRuntime.session.sessionFile;\n\tif (!sessionPath) return localRuntime;\n\tconst startHost = options.ensureHost ?? ((hostOptions) => ensureHost(hostOptions));\n\tconst client = new RpcClient({ socketPath: options.socket });\n\ttry {\n\t\tawait startHost({ socket: options.socket, agentDir: options.agentDir });\n\t\tawait client.start();\n\t\tconst opened = await client.openSession({\n\t\t\tsessionPath,\n\t\t\tcwd: localRuntime.cwd,\n\t\t\tprovider: localRuntime.session.model?.provider,\n\t\t\tmodelId: localRuntime.session.model?.id,\n\t\t\tthinkingLevel: localRuntime.session.thinkingLevel,\n\t\t});\n\t\tconst remoteSession = createRemoteSessionProxy(localRuntime.session, client, opened.state);\n\t\treturn new RemoteInteractiveRuntime(localRuntime, remoteSession, client) as unknown as AgentSessionRuntime;\n\t} catch (cause) {\n\t\tawait client.stop().catch(() => {});\n\t\toptions.onWarning?.({\n\t\t\ttype: \"interactive_host_fallback\",\n\t\t\tmessage: `${INTERACTIVE_HOST_FALLBACK_WARNING}: ${cause instanceof Error ? cause.message : String(cause)}`,\n\t\t\tcause,\n\t\t});\n\t\treturn localRuntime;\n\t}\n}\n\nclass RemoteInteractiveRuntime {\n\treadonly #local: AgentSessionRuntime;\n\treadonly #session: AgentSession;\n\treadonly #client: RpcClient;\n\t#rebindSession: (() => Promise<void>) | undefined;\n\t#beforeSessionInvalidate: (() => void) | undefined;\n\n\tconstructor(local: AgentSessionRuntime, session: AgentSession, client: RpcClient) {\n\t\tthis.#local = local;\n\t\tthis.#session = session;\n\t\tthis.#client = client;\n\t}\n\n\tget session(): AgentSession {\n\t\treturn this.#session;\n\t}\n\tget services(): AgentSessionRuntime[\"services\"] {\n\t\treturn this.#local.services;\n\t}\n\tget cwd(): string {\n\t\treturn this.#local.cwd;\n\t}\n\tget diagnostics(): readonly AgentSessionRuntimeDiagnostic[] {\n\t\treturn this.#local.diagnostics;\n\t}\n\tget modelFallbackMessage(): string | undefined {\n\t\treturn this.#local.modelFallbackMessage;\n\t}\n\tget launchProfile(): AgentSessionRuntime[\"launchProfile\"] {\n\t\treturn this.#local.launchProfile;\n\t}\n\tsetBeforeSessionInvalidate(callback?: () => void): void {\n\t\tthis.#beforeSessionInvalidate = callback;\n\t}\n\tsetRebindSession(callback?: () => Promise<void>): void {\n\t\tthis.#rebindSession = callback;\n\t}\n\tasync dispose(): Promise<void> {\n\t\tawait this.#client.closeSession();\n\t\tawait this.#client.stop();\n\t\tawait this.#local.dispose();\n\t}\n\tasync newSession(): Promise<{ cancelled: boolean }> {\n\t\tthis.#beforeSessionInvalidate?.();\n\t\tconst result = await this.#client.newSession();\n\t\tif (!result.cancelled) await this.#rebindSession?.();\n\t\treturn result;\n\t}\n\tasync switchSession(sessionPath: string): Promise<{ cancelled: boolean }> {\n\t\tthis.#beforeSessionInvalidate?.();\n\t\tconst result = await this.#client.switchSession(sessionPath);\n\t\tif (!result.cancelled) await this.#rebindSession?.();\n\t\treturn result;\n\t}\n\tasync fork(entryId: string): Promise<{ cancelled: boolean; selectedText?: string }> {\n\t\tthis.#beforeSessionInvalidate?.();\n\t\tconst result = await this.#client.fork(entryId);\n\t\tif (!result.cancelled) await this.#rebindSession?.();\n\t\treturn { cancelled: result.cancelled, selectedText: result.text };\n\t}\n\tasync importFromJsonl(): Promise<{ cancelled: boolean }> {\n\t\tthrow new Error(\"Session import is not available while connected to the shared host\");\n\t}\n}\n\nfunction createRemoteSessionProxy(\n\tlocal: AgentSession,\n\tclient: RpcClient,\n\tinitialState: ReturnType<typeof stateFromRpc>,\n): AgentSession {\n\tlet state = initialState;\n\tlet streamingAssistant: Extract<AgentSession[\"messages\"][number], { role: \"assistant\" }> | undefined;\n\tconst listeners = new Set<AgentSessionEventListener>();\n\tclient.onEvent((wireEvent) => {\n\t\tif (wireEvent.type === \"agent_settled\") state = { ...state, isStreaming: false };\n\t\tif (wireEvent.type === \"agent_start\") state = { ...state, isStreaming: true };\n\t\tif (wireEvent.type === \"model_changed\") {\n\t\t\tstate = { ...state, model: wireEvent.model, thinkingLevel: wireEvent.thinkingLevel };\n\t\t}\n\t\tif (wireEvent.type === \"thinking_level_changed\") state = { ...state, thinkingLevel: wireEvent.level };\n\t\tif (wireEvent.type === \"message_start\") {\n\t\t\tif (wireEvent.message.role === \"assistant\") streamingAssistant = structuredClone(wireEvent.message);\n\t\t\tlocal.agent.state.messages.push(structuredClone(wireEvent.message));\n\t\t}\n\t\tif (wireEvent.type === \"message_end\") {\n\t\t\tif (wireEvent.message.role === \"assistant\") streamingAssistant = structuredClone(wireEvent.message);\n\t\t\tconst messages = local.agent.state.messages;\n\t\t\tconst previous = messages.at(-1);\n\t\t\tif (previous?.role === wireEvent.message.role)\n\t\t\t\tmessages[messages.length - 1] = structuredClone(wireEvent.message);\n\t\t}\n\t\tconst event = hydrateMessageUpdate(wireEvent, streamingAssistant);\n\t\tfor (const listener of listeners) listener(event);\n\t});\n\tconst session = new Proxy(local, {\n\t\tget(target, property, receiver) {\n\t\t\tif (property === \"prompt\")\n\t\t\t\treturn (message: string, options?: Parameters<AgentSession[\"prompt\"]>[1]) =>\n\t\t\t\t\tclient.prompt(message, options?.images);\n\t\t\tif (property === \"abort\") return () => client.abort();\n\t\t\tif (property === \"steer\")\n\t\t\t\treturn (message: string, images?: Parameters<AgentSession[\"steer\"]>[1]) => client.steer(message, images);\n\t\t\tif (property === \"followUp\")\n\t\t\t\treturn (message: string, images?: Parameters<AgentSession[\"followUp\"]>[1]) =>\n\t\t\t\t\tclient.followUp(message, images);\n\t\t\tif (property === \"waitForIdle\") return () => client.waitForIdle();\n\t\t\tif (property === \"getLastAssistantText\") return () => target.getLastAssistantText();\n\t\t\tif (property === \"setModel\")\n\t\t\t\treturn async (model: NonNullable<AgentSession[\"model\"]>) => {\n\t\t\t\t\tawait client.setModel(model.provider, model.id);\n\t\t\t\t};\n\t\t\tif (property === \"cycleModel\") return () => client.cycleModel();\n\t\t\tif (property === \"setThinkingLevel\")\n\t\t\t\treturn (level: AgentSession[\"thinkingLevel\"]) => void client.setThinkingLevel(level);\n\t\t\tif (property === \"cycleThinkingLevel\")\n\t\t\t\treturn () => client.cycleThinkingLevel().then((result) => result?.level);\n\t\t\tif (property === \"getAvailableThinkingLevels\") return () => client.getAvailableThinkingLevels();\n\t\t\tif (property === \"setSteeringMode\")\n\t\t\t\treturn (mode: AgentSession[\"steeringMode\"]) => void client.setSteeringMode(mode);\n\t\t\tif (property === \"setFollowUpMode\")\n\t\t\t\treturn (mode: AgentSession[\"followUpMode\"]) => void client.setFollowUpMode(mode);\n\t\t\tif (property === \"compact\") return (instructions?: string) => client.compact(instructions);\n\t\t\tif (property === \"setAutoCompactionEnabled\")\n\t\t\t\treturn (enabled: boolean) => void client.setAutoCompaction(enabled);\n\t\t\tif (property === \"executeBash\") return (command: string) => client.bash(command);\n\t\t\tif (property === \"abortBash\") return () => void client.abortBash();\n\t\t\tif (property === \"getSessionStats\") return () => client.getSessionStats();\n\t\t\tif (property === \"exportToHtml\")\n\t\t\t\treturn (outputPath?: string) => client.exportHtml(outputPath).then((result) => result.path);\n\t\t\tif (property === \"setSessionName\") return (name: string) => void client.setSessionName(name);\n\t\t\tif (property === \"getUserMessagesForForking\") return () => client.getForkMessages();\n\t\t\tif (property === \"subscribe\")\n\t\t\t\treturn (listener: AgentSessionEventListener) => {\n\t\t\t\t\tlisteners.add(listener);\n\t\t\t\t\tconst localUnsubscribe = target.subscribe(listener);\n\t\t\t\t\treturn () => {\n\t\t\t\t\t\tlisteners.delete(listener);\n\t\t\t\t\t\tlocalUnsubscribe();\n\t\t\t\t\t};\n\t\t\t\t};\n\t\t\tif (property === \"isStreaming\") return state.isStreaming;\n\t\t\tif (property === \"sessionFile\") return state.sessionFile;\n\t\t\tif (property === \"sessionId\") return state.sessionId;\n\t\t\tif (property === \"messages\") return target.messages;\n\t\t\tif (property === \"model\") return state.model ?? target.model;\n\t\t\tif (property === \"thinkingLevel\") return state.thinkingLevel;\n\t\t\treturn Reflect.get(target, property, receiver);\n\t\t},\n\t});\n\treturn session;\n}\n\nfunction hydrateMessageUpdate(\n\tevent: RpcClientEvent,\n\tstreamingAssistant: Extract<AgentSession[\"messages\"][number], { role: \"assistant\" }> | undefined,\n): AgentSessionEvent {\n\tif (event.type !== \"message_update\" || !streamingAssistant) return event as unknown as AgentSessionEvent;\n\tconst update = event.assistantMessageEvent;\n\tif (update.type !== \"text_delta\" && update.type !== \"thinking_delta\" && update.type !== \"toolcall_delta\") {\n\t\treturn event as unknown as AgentSessionEvent;\n\t}\n\tconst content = streamingAssistant.content[update.contentIndex];\n\tif (update.type === \"text_delta\" && content?.type === \"text\") content.text += update.delta;\n\tif (update.type === \"thinking_delta\" && content?.type === \"thinking\") content.thinking += update.delta;\n\tif (update.type === \"toolcall_delta\" && content?.type === \"toolCall\") {\n\t\tconst raw = JSON.stringify(content.arguments) + update.delta;\n\t\ttry {\n\t\t\tconst parsed: unknown = JSON.parse(raw);\n\t\t\tif (typeof parsed === \"object\" && parsed !== null && !Array.isArray(parsed)) {\n\t\t\t\tcontent.arguments = parsed as Record<string, unknown>;\n\t\t\t}\n\t\t} catch {\n\t\t\t// Keep the last valid arguments until the next complete update.\n\t\t}\n\t}\n\tstreamingAssistant.usage = event.usage;\n\treturn {\n\t\ttype: \"message_update\",\n\t\tmessage: structuredClone(streamingAssistant),\n\t\tassistantMessageEvent: { ...update, partial: structuredClone(streamingAssistant) },\n\t} as AgentSessionEvent;\n}\n\nfunction stateFromRpc(state: {\n\tmodel?: AgentSession[\"model\"];\n\tthinkingLevel: AgentSession[\"thinkingLevel\"];\n\tisStreaming: boolean;\n\tsessionFile?: string;\n\tsessionId: string;\n}) {\n\treturn state;\n}\n\nexport function isInteractiveHostEvent(event: RpcClientEvent): event is Extract<RpcClientEvent, { type: string }> {\n\treturn typeof event === \"object\" && event !== null && \"type\" in event;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"interactive-host-runtime.js","sourceRoot":"","sources":["../../../src/modes/interactive/interactive-host-runtime.ts"],"names":[],"mappings":"AAIA,OAAO,EAAoB,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACrE,OAAO,EAAE,SAAS,EAAuB,MAAM,sBAAsB,CAAC;AAEtE,MAAM,CAAC,MAAM,iCAAiC,GAAG,kEAAkE,CAAC;AAoCpH;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,4BAA4B,CACjD,YAAiC,EACjC,OAAsC;IAEtC,MAAM,WAAW,GAAG,YAAY,CAAC,OAAO,CAAC,WAAW,CAAC;IACrD,IAAI,CAAC,WAAW;QAAE,OAAO,YAAY,CAAC;IACtC,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,IAAI,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,CAAC;IACnF,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC,EAAE,UAAU,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAC7D,IAAI,CAAC;QACJ,MAAM,SAAS,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;QACxE,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;QACrB,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC;YACvC,WAAW;YACX,GAAG,EAAE,YAAY,CAAC,GAAG;YACrB,QAAQ,EAAE,YAAY,CAAC,OAAO,CAAC,KAAK,EAAE,QAAQ;YAC9C,OAAO,EAAE,YAAY,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE;YACvC,aAAa,EAAE,YAAY,CAAC,OAAO,CAAC,aAAa;SACjD,CAAC,CAAC;QACH,MAAM,aAAa,GAAG,wBAAwB,CAAC,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC;QAC9G,OAAO,IAAI,wBAAwB,CAAC,YAAY,EAAE,aAAa,EAAE,MAAM,CAAmC,CAAC;IAC5G,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QACpC,OAAO,CAAC,SAAS,EAAE,CAAC;YACnB,IAAI,EAAE,2BAA2B;YACjC,OAAO,EAAE,GAAG,iCAAiC,KAAK,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;YAC1G,KAAK;SACL,CAAC,CAAC;QACH,OAAO,YAAY,CAAC;IACrB,CAAC;AACF,CAAC;AAED,MAAM,wBAAwB;IACpB,MAAM,CAAsB;IAC5B,QAAQ,CAAe;IACvB,OAAO,CAAY;IAC5B,cAAc,CAAoC;IAClD,wBAAwB,CAA2B;IAEnD,YAAY,KAA0B,EAAE,OAAqB,EAAE,MAAiB;QAC/E,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;QACpB,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC;QACxB,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;IACvB,CAAC;IAED,IAAI,OAAO;QACV,OAAO,IAAI,CAAC,QAAQ,CAAC;IACtB,CAAC;IACD,IAAI,QAAQ;QACX,OAAO,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC;IAC7B,CAAC;IACD,IAAI,GAAG;QACN,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC;IACxB,CAAC;IACD,IAAI,WAAW;QACd,OAAO,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC;IAChC,CAAC;IACD,IAAI,oBAAoB;QACvB,OAAO,IAAI,CAAC,MAAM,CAAC,oBAAoB,CAAC;IACzC,CAAC;IACD,IAAI,aAAa;QAChB,OAAO,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC;IAClC,CAAC;IACD,0BAA0B,CAAC,QAAqB;QAC/C,IAAI,CAAC,wBAAwB,GAAG,QAAQ,CAAC;IAC1C,CAAC;IACD,gBAAgB,CAAC,QAA8B;QAC9C,IAAI,CAAC,cAAc,GAAG,QAAQ,CAAC;IAChC,CAAC;IACD,KAAK,CAAC,OAAO;QACZ,MAAM,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,CAAC;QAClC,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;QAC1B,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;IAC7B,CAAC;IACD,KAAK,CAAC,UAAU;QACf,IAAI,CAAC,wBAAwB,EAAE,EAAE,CAAC;QAClC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC;QAC/C,IAAI,CAAC,MAAM,CAAC,SAAS;YAAE,MAAM,IAAI,CAAC,cAAc,EAAE,EAAE,CAAC;QACrD,OAAO,MAAM,CAAC;IACf,CAAC;IACD,KAAK,CAAC,aAAa,CAAC,WAAmB;QACtC,IAAI,CAAC,wBAAwB,EAAE,EAAE,CAAC;QAClC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC;QAC7D,IAAI,CAAC,MAAM,CAAC,SAAS;YAAE,MAAM,IAAI,CAAC,cAAc,EAAE,EAAE,CAAC;QACrD,OAAO,MAAM,CAAC;IACf,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,OAAe;QACzB,IAAI,CAAC,wBAAwB,EAAE,EAAE,CAAC;QAClC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAChD,IAAI,CAAC,MAAM,CAAC,SAAS;YAAE,MAAM,IAAI,CAAC,cAAc,EAAE,EAAE,CAAC;QACrD,OAAO,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,YAAY,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC;IACnE,CAAC;IACD,KAAK,CAAC,eAAe;QACpB,MAAM,IAAI,KAAK,CAAC,oEAAoE,CAAC,CAAC;IACvF,CAAC;CACD;AAED,SAAS,wBAAwB,CAChC,KAAmB,EACnB,MAAiB,EACjB,YAA6C,EAC7C,SAAqD;IAErD,8EAA8E;IAC9E,gFAAgF;IAChF,sDAAsD;IACtD,MAAM,mBAAmB,GAAG,CAAC,MAAc,EAAE,EAAE,CAAC,CAAC,KAAc,EAAE,EAAE;QAClE,SAAS,EAAE,CAAC;YACX,IAAI,EAAE,gCAAgC;YACtC,OAAO,EAAE,oCAAoC,MAAM,YAAY,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;YACvH,KAAK,EAAE,KAAK;SACZ,CAAC,CAAC;IACJ,CAAC,CAAC;IACF,IAAI,KAAK,GAAG,YAAY,CAAC;IACzB,IAAI,kBAAgG,CAAC;IACrG,MAAM,SAAS,GAAG,IAAI,GAAG,EAA6B,CAAC;IACvD,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,EAAE,EAAE;QAC5B,IAAI,SAAS,CAAC,IAAI,KAAK,eAAe;YAAE,KAAK,GAAG,EAAE,GAAG,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC;QACjF,IAAI,SAAS,CAAC,IAAI,KAAK,aAAa;YAAE,KAAK,GAAG,EAAE,GAAG,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC;QAC9E,IAAI,SAAS,CAAC,IAAI,KAAK,eAAe,EAAE,CAAC;YACxC,KAAK,GAAG,EAAE,GAAG,KAAK,EAAE,KAAK,EAAE,SAAS,CAAC,KAAK,EAAE,aAAa,EAAE,SAAS,CAAC,aAAa,EAAE,CAAC;QACtF,CAAC;QACD,IAAI,SAAS,CAAC,IAAI,KAAK,wBAAwB;YAAE,KAAK,GAAG,EAAE,GAAG,KAAK,EAAE,aAAa,EAAE,SAAS,CAAC,KAAK,EAAE,CAAC;QACtG,IAAI,SAAS,CAAC,IAAI,KAAK,eAAe,EAAE,CAAC;YACxC,IAAI,SAAS,CAAC,OAAO,CAAC,IAAI,KAAK,WAAW;gBAAE,kBAAkB,GAAG,eAAe,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;YACpG,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,eAAe,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC;QACrE,CAAC;QACD,IAAI,SAAS,CAAC,IAAI,KAAK,aAAa,EAAE,CAAC;YACtC,IAAI,SAAS,CAAC,OAAO,CAAC,IAAI,KAAK,WAAW;gBAAE,kBAAkB,GAAG,eAAe,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;YACpG,MAAM,QAAQ,GAAG,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC;YAC5C,MAAM,QAAQ,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;YACjC,IAAI,QAAQ,EAAE,IAAI,KAAK,SAAS,CAAC,OAAO,CAAC,IAAI;gBAC5C,QAAQ,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,eAAe,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QACrE,CAAC;QACD,MAAM,KAAK,GAAG,oBAAoB,CAAC,SAAS,EAAE,kBAAkB,CAAC,CAAC;QAClE,KAAK,MAAM,QAAQ,IAAI,SAAS;YAAE,QAAQ,CAAC,KAAK,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;IACH,MAAM,OAAO,GAAG,IAAI,KAAK,CAAC,KAAK,EAAE;QAChC,GAAG,CAAC,MAAM,EAAE,QAAQ,EAAE,QAAQ;YAC7B,IAAI,QAAQ,KAAK,QAAQ;gBACxB,OAAO,CAAC,OAAe,EAAE,OAA+C,EAAE,EAAE,CAC3E,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE;oBACtB,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;oBACtD,GAAG,CAAC,OAAO,EAAE,iBAAiB,CAAC,CAAC,CAAC,EAAE,iBAAiB,EAAE,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;oBACvF,GAAG,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,OAAO,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;oBAC3E,GAAG,CAAC,OAAO,EAAE,iBAAiB,CAAC,CAAC,CAAC,EAAE,iBAAiB,EAAE,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;oBACvF,GAAG,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC,CAAC,EAAE,eAAe,EAAE,OAAO,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;iBACjF,CAAC,CAAC;YACL,IAAI,QAAQ,KAAK,OAAO;gBAAE,OAAO,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;YACtD,IAAI,QAAQ,KAAK,OAAO;gBACvB,OAAO,CAAC,OAAe,EAAE,MAA6C,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;YAC1G,IAAI,QAAQ,KAAK,UAAU;gBAC1B,OAAO,CAAC,OAAe,EAAE,MAAgD,EAAE,EAAE,CAC5E,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;YACnC,IAAI,QAAQ,KAAK,aAAa;gBAAE,OAAO,GAAG,EAAE,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;YAClE,IAAI,QAAQ,KAAK,sBAAsB;gBAAE,OAAO,GAAG,EAAE,CAAC,MAAM,CAAC,oBAAoB,EAAE,CAAC;YACpF,IAAI,QAAQ,KAAK,UAAU;gBAC1B,OAAO,KAAK,EAAE,KAAyC,EAAE,EAAE;oBAC1D,MAAM,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC;gBACjD,CAAC,CAAC;YACH,IAAI,QAAQ,KAAK,YAAY;gBAAE,OAAO,GAAG,EAAE,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC;YAChE,IAAI,QAAQ,KAAK,kBAAkB;gBAClC,OAAO,CAAC,KAAoC,EAAE,EAAE,CAC/C,KAAK,MAAM,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,mBAAmB,CAAC,kBAAkB,CAAC,CAAC,CAAC;YACrF,IAAI,QAAQ,KAAK,oBAAoB;gBACpC,OAAO,GAAG,EAAE,CAAC,MAAM,CAAC,kBAAkB,EAAE,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;YAC1E,IAAI,QAAQ,KAAK,4BAA4B;gBAAE,OAAO,GAAG,EAAE,CAAC,MAAM,CAAC,0BAA0B,EAAE,CAAC;YAChG,IAAI,QAAQ,KAAK,iBAAiB;gBACjC,OAAO,CAAC,IAAkC,EAAE,EAAE,CAC7C,KAAK,MAAM,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,mBAAmB,CAAC,iBAAiB,CAAC,CAAC,CAAC;YAClF,IAAI,QAAQ,KAAK,iBAAiB;gBACjC,OAAO,CAAC,IAAkC,EAAE,EAAE,CAC7C,KAAK,MAAM,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,mBAAmB,CAAC,iBAAiB,CAAC,CAAC,CAAC;YAClF,IAAI,QAAQ,KAAK,SAAS;gBAAE,OAAO,CAAC,YAAqB,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;YAC3F,IAAI,QAAQ,KAAK,0BAA0B;gBAC1C,OAAO,CAAC,OAAgB,EAAE,EAAE,CAC3B,KAAK,MAAM,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,mBAAmB,CAAC,mBAAmB,CAAC,CAAC,CAAC;YACzF,IAAI,QAAQ,KAAK,aAAa;gBAAE,OAAO,CAAC,OAAe,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACjF,IAAI,QAAQ,KAAK,WAAW;gBAAE,OAAO,GAAG,EAAE,CAAC,KAAK,MAAM,CAAC,SAAS,EAAE,CAAC,KAAK,CAAC,mBAAmB,CAAC,WAAW,CAAC,CAAC,CAAC;YAC3G,IAAI,QAAQ,KAAK,iBAAiB;gBAAE,OAAO,GAAG,EAAE,CAAC,MAAM,CAAC,eAAe,EAAE,CAAC;YAC1E,IAAI,QAAQ,KAAK,cAAc;gBAC9B,OAAO,CAAC,UAAmB,EAAE,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAC7F,IAAI,QAAQ,KAAK,gBAAgB;gBAChC,OAAO,CAAC,IAAY,EAAE,EAAE,CAAC,KAAK,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,mBAAmB,CAAC,gBAAgB,CAAC,CAAC,CAAC;YACxG,IAAI,QAAQ,KAAK,2BAA2B;gBAAE,OAAO,GAAG,EAAE,CAAC,MAAM,CAAC,eAAe,EAAE,CAAC;YACpF,IAAI,QAAQ,KAAK,WAAW;gBAC3B,OAAO,CAAC,QAAmC,EAAE,EAAE;oBAC9C,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;oBACxB,MAAM,gBAAgB,GAAG,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;oBACpD,OAAO,GAAG,EAAE;wBACX,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;wBAC3B,gBAAgB,EAAE,CAAC;oBACpB,CAAC,CAAC;gBACH,CAAC,CAAC;YACH,IAAI,QAAQ,KAAK,aAAa;gBAAE,OAAO,KAAK,CAAC,WAAW,CAAC;YACzD,mEAAmE;YACnE,wEAAwE;YACxE,IAAI,QAAQ,KAAK,OAAO,EAAE,CAAC;gBAC1B,MAAM,UAAU,GAAG,MAAM,CAAC,KAAK,CAAC;gBAChC,OAAO;oBACN,GAAG,UAAU;oBACb,KAAK,EAAE,KAAK,CAAC,KAAK,IAAI,UAAU,CAAC,KAAK;oBACtC,aAAa,EAAE,KAAK,CAAC,aAAa;oBAClC,WAAW,EAAE,KAAK,CAAC,WAAW;iBAC9B,CAAC;YACH,CAAC;YACD,IAAI,QAAQ,KAAK,aAAa;gBAAE,OAAO,KAAK,CAAC,WAAW,CAAC;YACzD,IAAI,QAAQ,KAAK,WAAW;gBAAE,OAAO,KAAK,CAAC,SAAS,CAAC;YACrD,IAAI,QAAQ,KAAK,UAAU;gBAAE,OAAO,MAAM,CAAC,QAAQ,CAAC;YACpD,IAAI,QAAQ,KAAK,OAAO;gBAAE,OAAO,KAAK,CAAC,KAAK,IAAI,MAAM,CAAC,KAAK,CAAC;YAC7D,IAAI,QAAQ,KAAK,eAAe;gBAAE,OAAO,KAAK,CAAC,aAAa,CAAC;YAC7D,OAAO,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;QAChD,CAAC;KACD,CAAC,CAAC;IACH,OAAO,OAAO,CAAC;AAChB,CAAC;AAED,SAAS,oBAAoB,CAC5B,KAAqB,EACrB,kBAAgG;IAEhG,IAAI,KAAK,CAAC,IAAI,KAAK,gBAAgB,IAAI,CAAC,kBAAkB;QAAE,OAAO,KAAqC,CAAC;IACzG,MAAM,MAAM,GAAG,KAAK,CAAC,qBAAqB,CAAC;IAC3C,IAAI,MAAM,CAAC,IAAI,KAAK,YAAY,IAAI,MAAM,CAAC,IAAI,KAAK,gBAAgB,IAAI,MAAM,CAAC,IAAI,KAAK,gBAAgB,EAAE,CAAC;QAC1G,OAAO,KAAqC,CAAC;IAC9C,CAAC;IACD,MAAM,OAAO,GAAG,kBAAkB,CAAC,OAAO,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;IAChE,IAAI,MAAM,CAAC,IAAI,KAAK,YAAY,IAAI,OAAO,EAAE,IAAI,KAAK,MAAM;QAAE,OAAO,CAAC,IAAI,IAAI,MAAM,CAAC,KAAK,CAAC;IAC3F,IAAI,MAAM,CAAC,IAAI,KAAK,gBAAgB,IAAI,OAAO,EAAE,IAAI,KAAK,UAAU;QAAE,OAAO,CAAC,QAAQ,IAAI,MAAM,CAAC,KAAK,CAAC;IACvG,IAAI,MAAM,CAAC,IAAI,KAAK,gBAAgB,IAAI,OAAO,EAAE,IAAI,KAAK,UAAU,EAAE,CAAC;QACtE,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,SAAS,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC;QAC7D,IAAI,CAAC;YACJ,MAAM,MAAM,GAAY,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YACxC,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC7E,OAAO,CAAC,SAAS,GAAG,MAAiC,CAAC;YACvD,CAAC;QACF,CAAC;QAAC,MAAM,CAAC;YACR,gEAAgE;QACjE,CAAC;IACF,CAAC;IACD,kBAAkB,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;IACvC,OAAO;QACN,IAAI,EAAE,gBAAgB;QACtB,OAAO,EAAE,eAAe,CAAC,kBAAkB,CAAC;QAC5C,qBAAqB,EAAE,EAAE,GAAG,MAAM,EAAE,OAAO,EAAE,eAAe,CAAC,kBAAkB,CAAC,EAAE;KAC7D,CAAC;AACxB,CAAC;AAED,SAAS,YAAY,CAAC,KAMrB;IACA,OAAO,KAAK,CAAC;AACd,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,KAAqB;IAC3D,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,MAAM,IAAI,KAAK,CAAC;AACvE,CAAC","sourcesContent":["import type { ThinkingLevel } from \"@earendil-works/pi-agent-core\";\nimport type { AgentSession, AgentSessionEvent, AgentSessionEventListener } from \"../../core/agent-session.ts\";\nimport type { AgentSessionRuntime } from \"../../core/agent-session-runtime.ts\";\nimport type { AgentSessionRuntimeDiagnostic } from \"../../core/agent-session-services.ts\";\nimport { type EnsuredHost, ensureHost } from \"../rpc/host-ensure.ts\";\nimport { RpcClient, type RpcClientEvent } from \"../rpc/rpc-client.ts\";\n\nexport const INTERACTIVE_HOST_FALLBACK_WARNING = \"Warning: shared interactive host unavailable; continuing locally\";\n\nexport interface InteractiveHostWarning {\n\treadonly type: \"interactive_host_fallback\" | \"interactive_host_action_failed\";\n\treadonly message: string;\n\treadonly cause: unknown;\n}\n\n/**\n * The session contract InteractiveMode actually runs against. The local\n * AgentSession answers these reads synchronously; the shared-host proxy answers\n * them over RPC. Declaring the union here keeps the proxy honest (no more\n * `as unknown as` lie at the boundary) and lets the compiler find every TUI\n * call site that must await.\n */\nexport type InteractiveSession = Omit<\n\tAgentSession,\n\t\"cycleThinkingLevel\" | \"getAvailableThinkingLevels\" | \"getSessionStats\" | \"getUserMessagesForForking\"\n> & {\n\tcycleThinkingLevel(): ThinkingLevel | undefined | Promise<ThinkingLevel | undefined>;\n\tgetAvailableThinkingLevels(): ThinkingLevel[] | Promise<ThinkingLevel[]>;\n\tgetSessionStats():\n\t\t| ReturnType<AgentSession[\"getSessionStats\"]>\n\t\t| Promise<ReturnType<AgentSession[\"getSessionStats\"]>>;\n\tgetUserMessagesForForking():\n\t\t| ReturnType<AgentSession[\"getUserMessagesForForking\"]>\n\t\t| Promise<ReturnType<AgentSession[\"getUserMessagesForForking\"]>>;\n};\n\nexport interface InteractiveHostRuntimeOptions {\n\treadonly socket: string;\n\treadonly agentDir?: string;\n\treadonly ensureHost?: (options: { socket: string; agentDir?: string }) => Promise<EnsuredHost | undefined>;\n\tonWarning?: (warning: InteractiveHostWarning) => void;\n}\n\n/**\n * Replace only the transport-facing session operations. The object returned is\n * deliberately still an AgentSessionRuntime: InteractiveMode and extensions\n * retain their existing runtime seam, while the authoritative prompt/session\n * state is hosted by the shared RPC process.\n */\nexport async function createInteractiveHostRuntime(\n\tlocalRuntime: AgentSessionRuntime,\n\toptions: InteractiveHostRuntimeOptions,\n): Promise<AgentSessionRuntime> {\n\tconst sessionPath = localRuntime.session.sessionFile;\n\tif (!sessionPath) return localRuntime;\n\tconst startHost = options.ensureHost ?? ((hostOptions) => ensureHost(hostOptions));\n\tconst client = new RpcClient({ socketPath: options.socket });\n\ttry {\n\t\tawait startHost({ socket: options.socket, agentDir: options.agentDir });\n\t\tawait client.start();\n\t\tconst opened = await client.openSession({\n\t\t\tsessionPath,\n\t\t\tcwd: localRuntime.cwd,\n\t\t\tprovider: localRuntime.session.model?.provider,\n\t\t\tmodelId: localRuntime.session.model?.id,\n\t\t\tthinkingLevel: localRuntime.session.thinkingLevel,\n\t\t});\n\t\tconst remoteSession = createRemoteSessionProxy(localRuntime.session, client, opened.state, options.onWarning);\n\t\treturn new RemoteInteractiveRuntime(localRuntime, remoteSession, client) as unknown as AgentSessionRuntime;\n\t} catch (cause) {\n\t\tawait client.stop().catch(() => {});\n\t\toptions.onWarning?.({\n\t\t\ttype: \"interactive_host_fallback\",\n\t\t\tmessage: `${INTERACTIVE_HOST_FALLBACK_WARNING}: ${cause instanceof Error ? cause.message : String(cause)}`,\n\t\t\tcause,\n\t\t});\n\t\treturn localRuntime;\n\t}\n}\n\nclass RemoteInteractiveRuntime {\n\treadonly #local: AgentSessionRuntime;\n\treadonly #session: AgentSession;\n\treadonly #client: RpcClient;\n\t#rebindSession: (() => Promise<void>) | undefined;\n\t#beforeSessionInvalidate: (() => void) | undefined;\n\n\tconstructor(local: AgentSessionRuntime, session: AgentSession, client: RpcClient) {\n\t\tthis.#local = local;\n\t\tthis.#session = session;\n\t\tthis.#client = client;\n\t}\n\n\tget session(): AgentSession {\n\t\treturn this.#session;\n\t}\n\tget services(): AgentSessionRuntime[\"services\"] {\n\t\treturn this.#local.services;\n\t}\n\tget cwd(): string {\n\t\treturn this.#local.cwd;\n\t}\n\tget diagnostics(): readonly AgentSessionRuntimeDiagnostic[] {\n\t\treturn this.#local.diagnostics;\n\t}\n\tget modelFallbackMessage(): string | undefined {\n\t\treturn this.#local.modelFallbackMessage;\n\t}\n\tget launchProfile(): AgentSessionRuntime[\"launchProfile\"] {\n\t\treturn this.#local.launchProfile;\n\t}\n\tsetBeforeSessionInvalidate(callback?: () => void): void {\n\t\tthis.#beforeSessionInvalidate = callback;\n\t}\n\tsetRebindSession(callback?: () => Promise<void>): void {\n\t\tthis.#rebindSession = callback;\n\t}\n\tasync dispose(): Promise<void> {\n\t\tawait this.#client.closeSession();\n\t\tawait this.#client.stop();\n\t\tawait this.#local.dispose();\n\t}\n\tasync newSession(): Promise<{ cancelled: boolean }> {\n\t\tthis.#beforeSessionInvalidate?.();\n\t\tconst result = await this.#client.newSession();\n\t\tif (!result.cancelled) await this.#rebindSession?.();\n\t\treturn result;\n\t}\n\tasync switchSession(sessionPath: string): Promise<{ cancelled: boolean }> {\n\t\tthis.#beforeSessionInvalidate?.();\n\t\tconst result = await this.#client.switchSession(sessionPath);\n\t\tif (!result.cancelled) await this.#rebindSession?.();\n\t\treturn result;\n\t}\n\tasync fork(entryId: string): Promise<{ cancelled: boolean; selectedText?: string }> {\n\t\tthis.#beforeSessionInvalidate?.();\n\t\tconst result = await this.#client.fork(entryId);\n\t\tif (!result.cancelled) await this.#rebindSession?.();\n\t\treturn { cancelled: result.cancelled, selectedText: result.text };\n\t}\n\tasync importFromJsonl(): Promise<{ cancelled: boolean }> {\n\t\tthrow new Error(\"Session import is not available while connected to the shared host\");\n\t}\n}\n\nfunction createRemoteSessionProxy(\n\tlocal: AgentSession,\n\tclient: RpcClient,\n\tinitialState: ReturnType<typeof stateFromRpc>,\n\tonWarning?: (warning: InteractiveHostWarning) => void,\n): AgentSession {\n\t// Fire-and-forget setters keep the sync AgentSession signature, but their RPC\n\t// failures must not vanish: the matching *_changed wire event confirms success,\n\t// and a rejection here is the only signal of failure.\n\tconst reportActionFailure = (action: string) => (error: unknown) => {\n\t\tonWarning?.({\n\t\t\ttype: \"interactive_host_action_failed\",\n\t\t\tmessage: `Warning: shared interactive host ${action} failed: ${error instanceof Error ? error.message : String(error)}`,\n\t\t\tcause: error,\n\t\t});\n\t};\n\tlet state = initialState;\n\tlet streamingAssistant: Extract<AgentSession[\"messages\"][number], { role: \"assistant\" }> | undefined;\n\tconst listeners = new Set<AgentSessionEventListener>();\n\tclient.onEvent((wireEvent) => {\n\t\tif (wireEvent.type === \"agent_settled\") state = { ...state, isStreaming: false };\n\t\tif (wireEvent.type === \"agent_start\") state = { ...state, isStreaming: true };\n\t\tif (wireEvent.type === \"model_changed\") {\n\t\t\tstate = { ...state, model: wireEvent.model, thinkingLevel: wireEvent.thinkingLevel };\n\t\t}\n\t\tif (wireEvent.type === \"thinking_level_changed\") state = { ...state, thinkingLevel: wireEvent.level };\n\t\tif (wireEvent.type === \"message_start\") {\n\t\t\tif (wireEvent.message.role === \"assistant\") streamingAssistant = structuredClone(wireEvent.message);\n\t\t\tlocal.agent.state.messages.push(structuredClone(wireEvent.message));\n\t\t}\n\t\tif (wireEvent.type === \"message_end\") {\n\t\t\tif (wireEvent.message.role === \"assistant\") streamingAssistant = structuredClone(wireEvent.message);\n\t\t\tconst messages = local.agent.state.messages;\n\t\t\tconst previous = messages.at(-1);\n\t\t\tif (previous?.role === wireEvent.message.role)\n\t\t\t\tmessages[messages.length - 1] = structuredClone(wireEvent.message);\n\t\t}\n\t\tconst event = hydrateMessageUpdate(wireEvent, streamingAssistant);\n\t\tfor (const listener of listeners) listener(event);\n\t});\n\tconst session = new Proxy(local, {\n\t\tget(target, property, receiver) {\n\t\t\tif (property === \"prompt\")\n\t\t\t\treturn (message: string, options?: Parameters<AgentSession[\"prompt\"]>[1]) =>\n\t\t\t\t\tclient.prompt(message, {\n\t\t\t\t\t\t...(options?.images ? { images: options.images } : {}),\n\t\t\t\t\t\t...(options?.streamingBehavior ? { streamingBehavior: options.streamingBehavior } : {}),\n\t\t\t\t\t\t...(options?.thinkingLevel ? { thinkingLevel: options.thinkingLevel } : {}),\n\t\t\t\t\t\t...(options?.promptDisposition ? { promptDisposition: options.promptDisposition } : {}),\n\t\t\t\t\t\t...(options?.preflightResult ? { preflightResult: options.preflightResult } : {}),\n\t\t\t\t\t});\n\t\t\tif (property === \"abort\") return () => client.abort();\n\t\t\tif (property === \"steer\")\n\t\t\t\treturn (message: string, images?: Parameters<AgentSession[\"steer\"]>[1]) => client.steer(message, images);\n\t\t\tif (property === \"followUp\")\n\t\t\t\treturn (message: string, images?: Parameters<AgentSession[\"followUp\"]>[1]) =>\n\t\t\t\t\tclient.followUp(message, images);\n\t\t\tif (property === \"waitForIdle\") return () => client.waitForIdle();\n\t\t\tif (property === \"getLastAssistantText\") return () => target.getLastAssistantText();\n\t\t\tif (property === \"setModel\")\n\t\t\t\treturn async (model: NonNullable<AgentSession[\"model\"]>) => {\n\t\t\t\t\tawait client.setModel(model.provider, model.id);\n\t\t\t\t};\n\t\t\tif (property === \"cycleModel\") return () => client.cycleModel();\n\t\t\tif (property === \"setThinkingLevel\")\n\t\t\t\treturn (level: AgentSession[\"thinkingLevel\"]) =>\n\t\t\t\t\tvoid client.setThinkingLevel(level).catch(reportActionFailure(\"setThinkingLevel\"));\n\t\t\tif (property === \"cycleThinkingLevel\")\n\t\t\t\treturn () => client.cycleThinkingLevel().then((result) => result?.level);\n\t\t\tif (property === \"getAvailableThinkingLevels\") return () => client.getAvailableThinkingLevels();\n\t\t\tif (property === \"setSteeringMode\")\n\t\t\t\treturn (mode: AgentSession[\"steeringMode\"]) =>\n\t\t\t\t\tvoid client.setSteeringMode(mode).catch(reportActionFailure(\"setSteeringMode\"));\n\t\t\tif (property === \"setFollowUpMode\")\n\t\t\t\treturn (mode: AgentSession[\"followUpMode\"]) =>\n\t\t\t\t\tvoid client.setFollowUpMode(mode).catch(reportActionFailure(\"setFollowUpMode\"));\n\t\t\tif (property === \"compact\") return (instructions?: string) => client.compact(instructions);\n\t\t\tif (property === \"setAutoCompactionEnabled\")\n\t\t\t\treturn (enabled: boolean) =>\n\t\t\t\t\tvoid client.setAutoCompaction(enabled).catch(reportActionFailure(\"setAutoCompaction\"));\n\t\t\tif (property === \"executeBash\") return (command: string) => client.bash(command);\n\t\t\tif (property === \"abortBash\") return () => void client.abortBash().catch(reportActionFailure(\"abortBash\"));\n\t\t\tif (property === \"getSessionStats\") return () => client.getSessionStats();\n\t\t\tif (property === \"exportToHtml\")\n\t\t\t\treturn (outputPath?: string) => client.exportHtml(outputPath).then((result) => result.path);\n\t\t\tif (property === \"setSessionName\")\n\t\t\t\treturn (name: string) => void client.setSessionName(name).catch(reportActionFailure(\"setSessionName\"));\n\t\t\tif (property === \"getUserMessagesForForking\") return () => client.getForkMessages();\n\t\t\tif (property === \"subscribe\")\n\t\t\t\treturn (listener: AgentSessionEventListener) => {\n\t\t\t\t\tlisteners.add(listener);\n\t\t\t\t\tconst localUnsubscribe = target.subscribe(listener);\n\t\t\t\t\treturn () => {\n\t\t\t\t\t\tlisteners.delete(listener);\n\t\t\t\t\t\tlocalUnsubscribe();\n\t\t\t\t\t};\n\t\t\t\t};\n\t\t\tif (property === \"isStreaming\") return state.isStreaming;\n\t\t\t// The footer and other renderers read session.state.*; surface the\n\t\t\t// host-authoritative fields there too, not only via the direct getters.\n\t\t\tif (property === \"state\") {\n\t\t\t\tconst localState = target.state;\n\t\t\t\treturn {\n\t\t\t\t\t...localState,\n\t\t\t\t\tmodel: state.model ?? localState.model,\n\t\t\t\t\tthinkingLevel: state.thinkingLevel,\n\t\t\t\t\tisStreaming: state.isStreaming,\n\t\t\t\t};\n\t\t\t}\n\t\t\tif (property === \"sessionFile\") return state.sessionFile;\n\t\t\tif (property === \"sessionId\") return state.sessionId;\n\t\t\tif (property === \"messages\") return target.messages;\n\t\t\tif (property === \"model\") return state.model ?? target.model;\n\t\t\tif (property === \"thinkingLevel\") return state.thinkingLevel;\n\t\t\treturn Reflect.get(target, property, receiver);\n\t\t},\n\t});\n\treturn session;\n}\n\nfunction hydrateMessageUpdate(\n\tevent: RpcClientEvent,\n\tstreamingAssistant: Extract<AgentSession[\"messages\"][number], { role: \"assistant\" }> | undefined,\n): AgentSessionEvent {\n\tif (event.type !== \"message_update\" || !streamingAssistant) return event as unknown as AgentSessionEvent;\n\tconst update = event.assistantMessageEvent;\n\tif (update.type !== \"text_delta\" && update.type !== \"thinking_delta\" && update.type !== \"toolcall_delta\") {\n\t\treturn event as unknown as AgentSessionEvent;\n\t}\n\tconst content = streamingAssistant.content[update.contentIndex];\n\tif (update.type === \"text_delta\" && content?.type === \"text\") content.text += update.delta;\n\tif (update.type === \"thinking_delta\" && content?.type === \"thinking\") content.thinking += update.delta;\n\tif (update.type === \"toolcall_delta\" && content?.type === \"toolCall\") {\n\t\tconst raw = JSON.stringify(content.arguments) + update.delta;\n\t\ttry {\n\t\t\tconst parsed: unknown = JSON.parse(raw);\n\t\t\tif (typeof parsed === \"object\" && parsed !== null && !Array.isArray(parsed)) {\n\t\t\t\tcontent.arguments = parsed as Record<string, unknown>;\n\t\t\t}\n\t\t} catch {\n\t\t\t// Keep the last valid arguments until the next complete update.\n\t\t}\n\t}\n\tstreamingAssistant.usage = event.usage;\n\treturn {\n\t\ttype: \"message_update\",\n\t\tmessage: structuredClone(streamingAssistant),\n\t\tassistantMessageEvent: { ...update, partial: structuredClone(streamingAssistant) },\n\t} as AgentSessionEvent;\n}\n\nfunction stateFromRpc(state: {\n\tmodel?: AgentSession[\"model\"];\n\tthinkingLevel: AgentSession[\"thinkingLevel\"];\n\tisStreaming: boolean;\n\tsessionFile?: string;\n\tsessionId: string;\n}) {\n\treturn state;\n}\n\nexport function isInteractiveHostEvent(event: RpcClientEvent): event is Extract<RpcClientEvent, { type: string }> {\n\treturn typeof event === \"object\" && event !== null && \"type\" in event;\n}\n"]}
|