zidane 6.2.10 → 6.2.12
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/dist/{acp-DuEMbOoQ.js → acp-C-auiVTk.js} +2 -2
- package/dist/{acp-DuEMbOoQ.js.map → acp-C-auiVTk.js.map} +1 -1
- package/dist/acp-cli.js +4 -4
- package/dist/acp.d.ts +1 -1
- package/dist/acp.js +1 -1
- package/dist/{agent-6iGNP46b.js → agent-DhfdXgL2.js} +81 -1
- package/dist/{agent-6iGNP46b.js.map → agent-DhfdXgL2.js.map} +1 -1
- package/dist/agent.d.ts +1 -1
- package/dist/agent.js +1 -1
- package/dist/{anthropic-BD-lwEKp.js → anthropic-uXfsormU.js} +87 -2
- package/dist/anthropic-uXfsormU.js.map +1 -0
- package/dist/{auth-BH6G59RL.js → auth-TZg3MVi2.js} +2 -2
- package/dist/{auth-BH6G59RL.js.map → auth-TZg3MVi2.js.map} +1 -1
- package/dist/chat/pure.d.ts +3 -3
- package/dist/chat.d.ts +43 -4
- package/dist/chat.d.ts.map +1 -1
- package/dist/chat.js +3 -3
- package/dist/contexts/daytona.d.ts +1 -1
- package/dist/contexts/e2b.d.ts +1 -1
- package/dist/eval.d.ts +1 -1
- package/dist/extensions.d.ts +1 -1
- package/dist/extensions.js +1 -1
- package/dist/headless.d.ts +1 -1
- package/dist/headless.js +1 -1
- package/dist/{index-BFNt9GAs.d.ts → index-l0wehkWU.d.ts} +44 -6
- package/dist/index-l0wehkWU.d.ts.map +1 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +4 -4
- package/dist/{login-B5nMPF8w.js → login-Clf-R27F.js} +2 -2
- package/dist/{login-B5nMPF8w.js.map → login-Clf-R27F.js.map} +1 -1
- package/dist/mcp.d.ts +1 -1
- package/dist/output/stream-json.d.ts +1 -1
- package/dist/output/terminal.d.ts +1 -1
- package/dist/presets.d.ts +1 -1
- package/dist/presets.js +1 -1
- package/dist/providers/anthropic.d.ts +1 -1
- package/dist/providers/anthropic.js +1 -1
- package/dist/providers/arcee.d.ts +1 -1
- package/dist/providers/baseten.d.ts +1 -1
- package/dist/providers/cerebras.d.ts +1 -1
- package/dist/providers/local.d.ts +1 -1
- package/dist/providers/openai-compat.d.ts +1 -1
- package/dist/providers/openai.d.ts +1 -1
- package/dist/providers/openrouter.d.ts +1 -1
- package/dist/providers/xai.d.ts +1 -1
- package/dist/providers.d.ts +2 -2
- package/dist/providers.js +1 -1
- package/dist/restate.d.ts +1 -1
- package/dist/session/sqlite.d.ts +1 -1
- package/dist/session.d.ts +1 -1
- package/dist/{skills-CDpejYOf.js → skills-DKWqoaYH.js} +4 -3
- package/dist/skills-DKWqoaYH.js.map +1 -0
- package/dist/skills.d.ts +1 -1
- package/dist/skills.js +1 -1
- package/dist/{tool-formatters-B_zQsYfa.d.ts → tool-formatters-BSwVkSX2.d.ts} +2 -2
- package/dist/{tool-formatters-B_zQsYfa.d.ts.map → tool-formatters-BSwVkSX2.d.ts.map} +1 -1
- package/dist/tools/fetch-url.d.ts +1 -1
- package/dist/tools/web-search.d.ts +1 -1
- package/dist/tools.d.ts +1 -1
- package/dist/tools.js +1 -1
- package/dist/{transcript-anchors-BUigMBQt.js → transcript-anchors-BzcuKnq8.js} +108 -37
- package/dist/transcript-anchors-BzcuKnq8.js.map +1 -0
- package/dist/{transcript-anchors-C1Zqb8uS.d.ts → transcript-anchors-DKjXpQ0h.d.ts} +3 -42
- package/dist/transcript-anchors-DKjXpQ0h.d.ts.map +1 -0
- package/dist/tui.d.ts +3 -3
- package/dist/tui.d.ts.map +1 -1
- package/dist/tui.js +199 -150
- package/dist/tui.js.map +1 -1
- package/dist/{turn-operations-DVA52KMG.d.ts → turn-operations-CjkgQKmR.d.ts} +3 -3
- package/dist/{turn-operations-DVA52KMG.d.ts.map → turn-operations-CjkgQKmR.d.ts.map} +1 -1
- package/dist/types.d.ts +1 -1
- package/package.json +1 -1
- package/dist/anthropic-BD-lwEKp.js.map +0 -1
- package/dist/index-BFNt9GAs.d.ts.map +0 -1
- package/dist/skills-CDpejYOf.js.map +0 -1
- package/dist/transcript-anchors-BUigMBQt.js.map +0 -1
- package/dist/transcript-anchors-C1Zqb8uS.d.ts.map +0 -1
package/dist/tui.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { $ as
|
|
2
|
-
import { $ as composeExtensionPreset, B as ExtensionInstallError, Bt as ensureKeybindingsFile, Et as createModelSearchTool, H as installExtensionFromSpec, Ht as groupBindings, J as createExtensionHud, K as removeInstalledExtension, P as summaryToTurn, St as tailTruncate, Ut as keybindingsPath, Vt as formatBindingForDisplay, Wt as matchesBinding, X as discoverAndBuildExtensionRegistry, Y as registerExtensionHostModules, Yt as resolveExtensionKeybindings, _ as buildPostCompactAttachments, c as applyCompactSummaryCutoff, dn as sanitizeExtensionConfigActionPatch, en as inlineLoadedExtension, et as disposeExtensionRegistry, f as cleanupPersistedSession, g as resolveTasksDir, h as resolvePersistDir, hn as effectiveContextWindow, ht as isSpawnTool, it as createExtensionHostRuntimeBridge, lt as basic_default, m as resolveMcpWarningsDir, mn as OUTPUT_RESERVE_TOKENS, nn as parseExtensionScanPathEnv, on as coerceExtensionConfigInput, q as updateInstalledExtension, rn as scanExtensionDirectories, rt as partitionExtensionCatalog, t as createAgent, tt as filterExtensionRegistry, un as resolveExtensionConfigValue, wt as looksBinary, x as compactConversation, y as selectFilesFromSession, z as createExtensionPromptBridge, zt as KEYBINDING_KEY_COL_WIDTH } from "./agent-
|
|
1
|
+
import { $ as useMcpAuthState, $n as buildPlanSystem, $t as restoreChainFallbacks, A as runOAuthLogin, Bt as createDiscoverySlot, Ct as SETTINGS_CHOICES, D as formatPathForCwd, Dt as clampFps, Et as SettingsProvider, G as buildVisibleMcpRows, Gt as useConfig, Ht as useDiscovery, J as createFileMcpCredentialStore, Jt as buildRunModel, K as indexOfServerRow, Kt as resolveConfig, L as loadMcpToolsCache, M as buildMcpServers, Mt as resolveTheme, O as fetchOAuthRedirect, Ot as useSettings, P as discoverProjectMcps, Q as useMcpAuthDispatch, Qn as buildBuildSystem, Qt as providerKeySetChanged, R as mcpToolsCachePath, St as SETTINGS_CATEGORIES, T as suggestSafelistEntries, Tn as accentColor, Tt as SETTINGS_TOGGLES, U as useMcpToolToggleMap, Ut as useDiscoveryOptional, V as subscribeMcpToolsCache, Vn as useActiveTodos, Vt as DiscoveryProvider, Wt as ConfigProvider, Xt as chainsEqual, Yt as chainPositionOf, Z as McpAuthProvider, Zt as filterChainFallbacks, _ as useSafeModeQueue, _n as discoverAgentsMd, _r as toolCallPreview, _t as buildHints, a as useSurfaces, an as bootTick, at as buildResumedToolResultsTurn, b as getSafelist, br as usageByModel, bt as useEnabledToggleSet, c as useStreamBuffer, cr as lastContextSizeFromTurns, ct as makeRequestInteraction, d as discoverProjectSkills, dr as marginTopFor, dt as useInteractionsActions, er as envSection, et as getMcpAuthStatus, ft as useInteractionsQueue, g as useSafeModeActions, gn as chatAutoCompactBehavior, gt as truncateTrailing, h as SafeModeProvider, hr as sumRunCosts, ht as hintsLength, i as useSelectStyle, ir as compactSummaryEvent, it as PRESENT_PLAN_TOOL, j as supportsOAuth, jn as TODO_STATUS_GLYPHS, jt as resolveChipColor, k as oauthUsesManualCodePaste, l as buildSkillsConfig, lr as listSessionMeta, lt as pendingInteractionsFromTurns, m as writeSessionExport, mr as stripSpawnTokensLine, mt as clipHintsToWidth, n as ThemeProvider, nn as useCompletion, nr as createChatTurnsReadTool, nt as ASK_USER_TOOL, on as buildUpdateHint, or as deriveSessionTitle, ot as createInteractionTools, pr as serverToolResultSummary, pt as EMPTY_HINTS, q as parentServerName, qt as resolveStoragePaths, r as useColors, rn as tryOpenBrowser, rt as InteractionsProvider, s as useTheme, sn as useUpdateCheck, sr as eventsFromTurns, t as computeTurnAnchors, tn as toggleChainEntry, tr as chatReferenceTokensForPrompt, u as defaultSkillScanPaths, ur as loadState, vr as toolResultText, wt as SETTINGS_INPUTS, x as isOnSafelist, xt as DEFAULT_SETTINGS, y as addToSafelist, yr as updateToolEventOutcomes, yt as listProjectFiles, z as refreshMcpToolsCatalog } from "./transcript-anchors-BzcuKnq8.js";
|
|
2
|
+
import { $ as composeExtensionPreset, B as ExtensionInstallError, Bt as ensureKeybindingsFile, Et as createModelSearchTool, H as installExtensionFromSpec, Ht as groupBindings, J as createExtensionHud, K as removeInstalledExtension, P as summaryToTurn, St as tailTruncate, Ut as keybindingsPath, Vt as formatBindingForDisplay, Wt as matchesBinding, X as discoverAndBuildExtensionRegistry, Y as registerExtensionHostModules, Yt as resolveExtensionKeybindings, _ as buildPostCompactAttachments, c as applyCompactSummaryCutoff, dn as sanitizeExtensionConfigActionPatch, en as inlineLoadedExtension, et as disposeExtensionRegistry, f as cleanupPersistedSession, g as resolveTasksDir, h as resolvePersistDir, hn as effectiveContextWindow, ht as isSpawnTool, it as createExtensionHostRuntimeBridge, lt as basic_default, m as resolveMcpWarningsDir, mn as OUTPUT_RESERVE_TOKENS, nn as parseExtensionScanPathEnv, on as coerceExtensionConfigInput, q as updateInstalledExtension, rn as scanExtensionDirectories, rt as partitionExtensionCatalog, t as createAgent, tt as filterExtensionRegistry, un as resolveExtensionConfigValue, wt as looksBinary, x as compactConversation, y as selectFilesFromSession, z as createExtensionPromptBridge, zt as KEYBINDING_KEY_COL_WIDTH } from "./agent-DhfdXgL2.js";
|
|
3
3
|
import { a as formatDuration, c as previewLine, i as fmtTokens, l as shortId, n as compactPath, o as formatTaskStatus, r as fmtCost, s as formatTaskSummary, t as ageString } from "./format-BF745pLL.js";
|
|
4
4
|
import { n as appendCapped } from "./output-cap-kBUHBlnq.js";
|
|
5
5
|
import { i as killProcessGroup, n as SUPPORTS_PROCESS_GROUPS, r as createProcessContext } from "./contexts-A4ep-iJs.js";
|
|
@@ -14,9 +14,9 @@ import { o as withTimeout } from "./timeout-BDetbuN6.js";
|
|
|
14
14
|
import { n as connectMcpServers, u as McpOAuthProvider } from "./mcp-BCaN_Gyg.js";
|
|
15
15
|
import { a as generateStructuredData, c as shouldAutoGenerateTitle, f as commandBlockToEvent, g as parseCommandInvocation, h as executeCommand, n as patchInlineGhost, p as commandBlocksToContent, r as resolveInlineSuggestion, s as generateSessionTitle, t as createPathAutocompleteProvider } from "./inline-autocomplete-BAwBcZtD.js";
|
|
16
16
|
import { s as resolveCompletionSubmit } from "./completion-core-BRo86R_L.js";
|
|
17
|
-
import { i as installSkillFromSpec, r as SkillInstallError } from "./skills-
|
|
18
|
-
import { i as ZIDANE_EXTENSION_SKILL_NAME, l as withZidaneExtensionSkill, o as extensionDirForCwd, r as EXTENSION_EDIT_METADATA_KEY, s as extensionScaffold, t as loginMcpServer } from "./login-
|
|
19
|
-
import { C as restoreModelOptions, S as piIdOf, _ as modelOptionsFor, m as getContextWindow, p as enabledModelOptions, s as setProviderCredential, t as detectAuth, v as modelSupportsReasoning } from "./auth-
|
|
17
|
+
import { i as installSkillFromSpec, r as SkillInstallError } from "./skills-DKWqoaYH.js";
|
|
18
|
+
import { i as ZIDANE_EXTENSION_SKILL_NAME, l as withZidaneExtensionSkill, o as extensionDirForCwd, r as EXTENSION_EDIT_METADATA_KEY, s as extensionScaffold, t as loginMcpServer } from "./login-Clf-R27F.js";
|
|
19
|
+
import { C as restoreModelOptions, S as piIdOf, _ as modelOptionsFor, m as getContextWindow, p as enabledModelOptions, s as setProviderCredential, t as detectAuth, v as modelSupportsReasoning } from "./auth-TZg3MVi2.js";
|
|
20
20
|
import { createDockerContext } from "./contexts/docker.js";
|
|
21
21
|
import { createTuiStore } from "./session/sqlite.js";
|
|
22
22
|
import { $ as buildEditOutcomesAnnotation, A as blendHsl, B as turnSelectionOwnership, C as stripHtmlCommentsOutsideCode, E as uniqueSkillNamesFromReferences, F as isTurnHighlighted, H as buildContextualDiff, I as isUserBashEvent, J as filetypeFromPath, L as isVisible, M as BASH_CALL_ID_PREFIX, N as EDIT_TOOL_NAMES, O as createFilesCompletionProvider, P as isEditErrorResult, R as promptHistoryFromEvents, S as splitMarkdownCodeBlocks, T as createSkillsCompletionProvider, U as buildUnifiedDiff, W as clipDiffForRender, Y as previewEditPayload, Z as summarizeEditPayload, _ as filterModelCatalog, a as TOOL_DISPLAY, at as stripEditOutcomesAnnotation, b as chunkMarkdownForRender, d as finalizeStreamingMarkdown, f as finalizeStreamingMarkdownForOwner, g as buildModelCatalog, h as splitPromptSegments, i as turnAsText, it as rewriteMultiEditHeader, j as buildLinearRamp, lt as createChatsCompletionProvider, m as turnContextSize, n as deleteTurnSafely, nt as parseEditOutcomesFromResult, o as displayNameFor, ot as summarizeOutcomes, q as extractEditPayload, r as truncateTurnsAt, rt as resolveApprovalForPayload, s as formatToolCall, tt as mergeApprovalAndBodyOutcomes, u as capTranscriptEvents, v as indexOfEntry, x as normalizeMarkdownCodeFences, z as selectableTurnIds } from "./turn-operations-CXjRaltC.js";
|
|
@@ -1505,7 +1505,7 @@ const BASH_RESULT_MAX_LINES = 10;
|
|
|
1505
1505
|
* same-turn events read as one continuous highlighted block instead of a
|
|
1506
1506
|
* striped list.
|
|
1507
1507
|
*/
|
|
1508
|
-
const EventLine = memo(({ event, previous, depthOffset = 0, selected = false, anchorId, hideChildLabel = false, settleCodeEpoch = 0 }) => {
|
|
1508
|
+
const EventLine = memo(({ event, previous, depthOffset = 0, selected = false, anchorId, hideChildLabel = false, settleCodeEpoch = 0, liveSpawn }) => {
|
|
1509
1509
|
const SURFACE = useSurfaces();
|
|
1510
1510
|
const gap = marginTopFor(event, previous);
|
|
1511
1511
|
return /* @__PURE__ */ jsx$1("box", {
|
|
@@ -1524,7 +1524,8 @@ const EventLine = memo(({ event, previous, depthOffset = 0, selected = false, an
|
|
|
1524
1524
|
depthOffset,
|
|
1525
1525
|
hideChildLabel,
|
|
1526
1526
|
selected,
|
|
1527
|
-
settleCodeEpoch
|
|
1527
|
+
settleCodeEpoch,
|
|
1528
|
+
liveSpawn
|
|
1528
1529
|
})
|
|
1529
1530
|
});
|
|
1530
1531
|
});
|
|
@@ -1977,10 +1978,12 @@ function Transcript({ events, settings, selectedTurnId = null, busy = false }) {
|
|
|
1977
1978
|
for (let i = items.length - 1; i >= 0 && open.size > 0; i--) {
|
|
1978
1979
|
const item = items[i];
|
|
1979
1980
|
const here = [];
|
|
1980
|
-
for (const [id,
|
|
1981
|
+
for (const [id, child] of open) if (item.kind === "child-run" ? item.events.some((e) => e.childId === id) : item.event.kind === "spawn-start" && item.event.childId === id) {
|
|
1981
1982
|
here.push({
|
|
1982
1983
|
id,
|
|
1983
|
-
activity: spawnActivity(
|
|
1984
|
+
activity: spawnActivity(child.events),
|
|
1985
|
+
startedAt: child.start.spawn?.startedAt ?? Date.now(),
|
|
1986
|
+
turns: observedSpawnTurns(child.events)
|
|
1984
1987
|
});
|
|
1985
1988
|
open.delete(id);
|
|
1986
1989
|
}
|
|
@@ -2030,18 +2033,14 @@ function Transcript({ events, settings, selectedTurnId = null, busy = false }) {
|
|
|
2030
2033
|
children: [items.map((item, i) => {
|
|
2031
2034
|
if (item.kind === "event") {
|
|
2032
2035
|
const live = liveByItem.get(i);
|
|
2033
|
-
|
|
2036
|
+
return /* @__PURE__ */ jsx$1(EventLine, {
|
|
2034
2037
|
event: item.event,
|
|
2035
2038
|
previous: item.previous,
|
|
2036
2039
|
selected: isTurnHighlighted(item.event, selectedTurnId, ownership),
|
|
2037
2040
|
anchorId: anchors.ids[i][0],
|
|
2038
|
-
settleCodeEpoch: codeSettle.current.targets.has(item.event) ? codeSettle.current.epoch : 0
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
return /* @__PURE__ */ jsxs("box", { children: [line, live.map((spawn) => /* @__PURE__ */ jsx$1(LiveSpawnRow, {
|
|
2042
|
-
spawn,
|
|
2043
|
-
showLabel: true
|
|
2044
|
-
}, spawn.id))] }, i);
|
|
2041
|
+
settleCodeEpoch: codeSettle.current.targets.has(item.event) ? codeSettle.current.epoch : 0,
|
|
2042
|
+
liveSpawn: live?.[0]
|
|
2043
|
+
}, i);
|
|
2045
2044
|
}
|
|
2046
2045
|
return /* @__PURE__ */ jsx$1(SubagentBlock, {
|
|
2047
2046
|
events: item.events,
|
|
@@ -2068,27 +2067,37 @@ function Transcript({ events, settings, selectedTurnId = null, busy = false }) {
|
|
|
2068
2067
|
* events they've produced since. Computed against the FULL event list — a
|
|
2069
2068
|
* parent-depth row (e.g. a background-task banner) can split one child's
|
|
2070
2069
|
* events across two boxes, and only a global scan knows whether the child
|
|
2071
|
-
* actually finished. `spawn:
|
|
2072
|
-
*
|
|
2073
|
-
*
|
|
2074
|
-
*
|
|
2070
|
+
* actually finished. `spawn:complete` fires for EVERY terminal state
|
|
2071
|
+
* (success/abort/timeout/error \u2014 see spawn.ts), so a `spawn-end` marker is
|
|
2072
|
+
* the normal close; a child-tagged `error` event (`spawn:error`, e.g. a
|
|
2073
|
+
* destroy failure surfaced after completion) also closes, covering
|
|
2074
|
+
* whichever order the two arrive in. Live-only signal: replayed sessions
|
|
2075
|
+
* always synthesize a `spawn-end` per child run, so nothing stays open
|
|
2076
|
+
* after a reload.
|
|
2075
2077
|
*/
|
|
2076
2078
|
function openSpawns(events) {
|
|
2077
2079
|
const open = /* @__PURE__ */ new Map();
|
|
2078
2080
|
for (const event of events) {
|
|
2079
2081
|
if (!event.childId || (event.depth ?? 0) === 0) continue;
|
|
2080
2082
|
if (event.kind === "spawn-start") {
|
|
2081
|
-
open.set(event.childId,
|
|
2083
|
+
open.set(event.childId, {
|
|
2084
|
+
start: event,
|
|
2085
|
+
events: []
|
|
2086
|
+
});
|
|
2082
2087
|
continue;
|
|
2083
2088
|
}
|
|
2084
2089
|
if (event.kind === "spawn-end" || event.kind === "error") {
|
|
2085
2090
|
open.delete(event.childId);
|
|
2086
2091
|
continue;
|
|
2087
2092
|
}
|
|
2088
|
-
open.get(event.childId)?.push(event);
|
|
2093
|
+
open.get(event.childId)?.events.push(event);
|
|
2089
2094
|
}
|
|
2090
2095
|
return open;
|
|
2091
2096
|
}
|
|
2097
|
+
/** Distinct child-loop turns observed in the streamed event tail. */
|
|
2098
|
+
function observedSpawnTurns(events) {
|
|
2099
|
+
return new Set(events.flatMap((event) => event.turnId ? [event.turnId] : [])).size;
|
|
2100
|
+
}
|
|
2092
2101
|
/**
|
|
2093
2102
|
* One-word-ish description of what a running child is doing right now,
|
|
2094
2103
|
* derived from its trailing events: `text` while prose streams, `thinking`
|
|
@@ -2114,8 +2123,30 @@ function spawnActivity(events) {
|
|
|
2114
2123
|
default: return "working";
|
|
2115
2124
|
}
|
|
2116
2125
|
}
|
|
2126
|
+
/**
|
|
2127
|
+
* Pair lifecycle markers from the end so reused labels (`child-1` in a
|
|
2128
|
+
* later top-level run) don't make an old terminal hide a new active start.
|
|
2129
|
+
* Exported for the layout invariant test; renderers otherwise use it only
|
|
2130
|
+
* through {@link partitionTranscript}.
|
|
2131
|
+
*/
|
|
2132
|
+
function collapseCompletedSpawnStarts(events) {
|
|
2133
|
+
const keep = Array.from({ length: events.length }).fill(true);
|
|
2134
|
+
const terminalByChild = /* @__PURE__ */ new Map();
|
|
2135
|
+
for (let i = events.length - 1; i >= 0; i--) {
|
|
2136
|
+
const event = events[i];
|
|
2137
|
+
if (event.kind === "spawn-end" && event.childId) terminalByChild.set(event.childId, (terminalByChild.get(event.childId) ?? 0) + 1);
|
|
2138
|
+
else if (event.kind === "spawn-start" && event.childId) {
|
|
2139
|
+
const terminals = terminalByChild.get(event.childId) ?? 0;
|
|
2140
|
+
if (terminals > 0) {
|
|
2141
|
+
keep[i] = false;
|
|
2142
|
+
terminalByChild.set(event.childId, terminals - 1);
|
|
2143
|
+
}
|
|
2144
|
+
}
|
|
2145
|
+
}
|
|
2146
|
+
return events.filter((_, i) => keep[i]);
|
|
2147
|
+
}
|
|
2117
2148
|
function partitionTranscript(events, settings) {
|
|
2118
|
-
const visible = events.filter((e) => isVisible(e, settings));
|
|
2149
|
+
const visible = collapseCompletedSpawnStarts(events).filter((e) => isVisible(e, settings));
|
|
2119
2150
|
if (visible.length === 0) return [];
|
|
2120
2151
|
if (settings.hideSubagentOutput) return visible.map((event, i) => ({
|
|
2121
2152
|
kind: "event",
|
|
@@ -2171,7 +2202,7 @@ function SubagentBlock({ events, previous, selectedTurnId = null, anchorIds, cod
|
|
|
2171
2202
|
const title = childIds.length === 0 ? " subagent " : childIds.length === 1 ? ` ${childIds[0]} ` : ` subagents · ${childIds.join(", ")} `;
|
|
2172
2203
|
const marginTop = previous ? 1 : 0;
|
|
2173
2204
|
const hideChildLabel = childIds.length === 1;
|
|
2174
|
-
return /* @__PURE__ */
|
|
2205
|
+
return /* @__PURE__ */ jsx$1("box", {
|
|
2175
2206
|
title,
|
|
2176
2207
|
style: {
|
|
2177
2208
|
border: true,
|
|
@@ -2185,38 +2216,81 @@ function SubagentBlock({ events, previous, selectedTurnId = null, anchorIds, cod
|
|
|
2185
2216
|
flexShrink: 0,
|
|
2186
2217
|
alignSelf: "stretch"
|
|
2187
2218
|
},
|
|
2188
|
-
children:
|
|
2219
|
+
children: events.map((evt, i) => /* @__PURE__ */ jsx$1(EventLine, {
|
|
2189
2220
|
event: evt,
|
|
2190
2221
|
previous: events[i - 1],
|
|
2191
2222
|
depthOffset: 1,
|
|
2192
2223
|
selected: selectedTurnId !== null && evt.turnId === selectedTurnId,
|
|
2193
2224
|
anchorId: anchorIds?.[i],
|
|
2194
2225
|
hideChildLabel,
|
|
2195
|
-
settleCodeEpoch: codeSettleTargets?.has(evt) ? codeSettleEpoch : 0
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
children: /* @__PURE__ */ jsx$1(LiveSpawnRow, {
|
|
2199
|
-
spawn,
|
|
2200
|
-
showLabel: !hideChildLabel
|
|
2201
|
-
})
|
|
2202
|
-
}, spawn.id))]
|
|
2226
|
+
settleCodeEpoch: codeSettleTargets?.has(evt) ? codeSettleEpoch : 0,
|
|
2227
|
+
liveSpawn: evt.kind === "spawn-start" ? live?.find((spawn) => spawn.id === evt.childId) : void 0
|
|
2228
|
+
}, i))
|
|
2203
2229
|
});
|
|
2204
2230
|
}
|
|
2205
|
-
/**
|
|
2206
|
-
|
|
2231
|
+
/**
|
|
2232
|
+
* Stable one-row subagent lifecycle layout. Identity/model/task stay in
|
|
2233
|
+
* the left lane for the whole run; only the right tail changes:
|
|
2234
|
+
* active `2 turns · 14s · ⠋ tool call`, done `4 turns`.
|
|
2235
|
+
*/
|
|
2236
|
+
function SpawnLifecycleMarker({ row, dim, event, hideChildLabel, live }) {
|
|
2207
2237
|
const COLOR = useColors();
|
|
2208
|
-
|
|
2209
|
-
|
|
2238
|
+
const frame = useSpinnerFrame();
|
|
2239
|
+
const terminal = event.kind === "spawn-end";
|
|
2240
|
+
const failed = terminal && (event.text.startsWith("error") || event.text.startsWith("aborted"));
|
|
2241
|
+
const turns = terminal ? event.spawn?.turns : live?.turns;
|
|
2242
|
+
const turnLabel = `${turns ?? 0} turn${turns === 1 ? "" : "s"}`;
|
|
2243
|
+
const elapsed = live ? formatDuration(Math.max(0, Date.now() - live.startedAt)) : null;
|
|
2244
|
+
return /* @__PURE__ */ jsxs("box", {
|
|
2245
|
+
style: {
|
|
2246
|
+
...row,
|
|
2247
|
+
flexDirection: "row",
|
|
2248
|
+
alignItems: "center"
|
|
2249
|
+
},
|
|
2210
2250
|
children: [
|
|
2211
|
-
/* @__PURE__ */
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2251
|
+
/* @__PURE__ */ jsxs("text", {
|
|
2252
|
+
fg: dim,
|
|
2253
|
+
wrapMode: "none",
|
|
2254
|
+
style: { flexShrink: 1 },
|
|
2255
|
+
children: [
|
|
2256
|
+
/* @__PURE__ */ jsx$1("span", {
|
|
2257
|
+
fg: failed ? COLOR.error : COLOR.accent,
|
|
2258
|
+
children: terminal ? failed ? "✗ " : "🌳 " : "🌱 "
|
|
2259
|
+
}),
|
|
2260
|
+
!hideChildLabel && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx$1("span", {
|
|
2261
|
+
fg: COLOR.brand,
|
|
2262
|
+
children: event.childId ?? "child"
|
|
2263
|
+
}), /* @__PURE__ */ jsx$1("span", {
|
|
2264
|
+
fg: COLOR.mute,
|
|
2265
|
+
children: " · "
|
|
2266
|
+
})] }),
|
|
2267
|
+
event.model !== void 0 && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx$1("span", {
|
|
2268
|
+
fg: COLOR.model,
|
|
2269
|
+
children: event.model
|
|
2270
|
+
}), /* @__PURE__ */ jsx$1("span", {
|
|
2271
|
+
fg: COLOR.mute,
|
|
2272
|
+
children: " · "
|
|
2273
|
+
})] }),
|
|
2274
|
+
/* @__PURE__ */ jsx$1("span", {
|
|
2275
|
+
fg: COLOR.dim,
|
|
2276
|
+
children: terminal ? event.spawn?.task ?? event.text : event.text
|
|
2277
|
+
})
|
|
2278
|
+
]
|
|
2279
|
+
}),
|
|
2280
|
+
/* @__PURE__ */ jsx$1("box", { style: { flexGrow: 1 } }),
|
|
2281
|
+
/* @__PURE__ */ jsxs("text", {
|
|
2216
2282
|
fg: COLOR.mute,
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2283
|
+
wrapMode: "none",
|
|
2284
|
+
style: { flexShrink: 0 },
|
|
2285
|
+
children: [/* @__PURE__ */ jsx$1("span", { children: turnLabel }), live && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2286
|
+
/* @__PURE__ */ jsx$1("span", { children: ` · ${elapsed} · ` }),
|
|
2287
|
+
/* @__PURE__ */ jsx$1("span", {
|
|
2288
|
+
fg: COLOR.warn,
|
|
2289
|
+
children: frame
|
|
2290
|
+
}),
|
|
2291
|
+
/* @__PURE__ */ jsx$1("span", { children: ` ${live.activity}` })
|
|
2292
|
+
] })]
|
|
2293
|
+
})
|
|
2220
2294
|
]
|
|
2221
2295
|
});
|
|
2222
2296
|
}
|
|
@@ -2259,7 +2333,7 @@ function rowStyle(paddingLeft) {
|
|
|
2259
2333
|
alignSelf: "stretch"
|
|
2260
2334
|
};
|
|
2261
2335
|
}
|
|
2262
|
-
function EventLineImpl({ event, previous, depthOffset = 0, hideChildLabel = false, selected = false, settleCodeEpoch = 0 }) {
|
|
2336
|
+
function EventLineImpl({ event, previous, depthOffset = 0, hideChildLabel = false, selected = false, settleCodeEpoch = 0, liveSpawn }) {
|
|
2263
2337
|
const COLOR = useColors();
|
|
2264
2338
|
const { settings } = useSettings();
|
|
2265
2339
|
const cleanText = stripTerminalControlChars(event.text);
|
|
@@ -2382,58 +2456,18 @@ function EventLineImpl({ event, previous, depthOffset = 0, hideChildLabel = fals
|
|
|
2382
2456
|
settleCodeEpoch
|
|
2383
2457
|
})
|
|
2384
2458
|
});
|
|
2385
|
-
case "spawn-start": return /* @__PURE__ */ jsx$1(
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
fg: COLOR.accent,
|
|
2392
|
-
children: "🌱 "
|
|
2393
|
-
}),
|
|
2394
|
-
!hideChildLabel && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx$1("span", {
|
|
2395
|
-
fg: COLOR.brand,
|
|
2396
|
-
children: event.childId ?? "child"
|
|
2397
|
-
}), /* @__PURE__ */ jsx$1("span", {
|
|
2398
|
-
fg: COLOR.mute,
|
|
2399
|
-
children: " · "
|
|
2400
|
-
})] }),
|
|
2401
|
-
event.model !== void 0 && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx$1("span", {
|
|
2402
|
-
fg: COLOR.model,
|
|
2403
|
-
children: event.model
|
|
2404
|
-
}), /* @__PURE__ */ jsx$1("span", {
|
|
2405
|
-
fg: COLOR.mute,
|
|
2406
|
-
children: " · "
|
|
2407
|
-
})] }),
|
|
2408
|
-
/* @__PURE__ */ jsx$1("span", {
|
|
2409
|
-
fg: COLOR.dim,
|
|
2410
|
-
children: safeText
|
|
2411
|
-
})
|
|
2412
|
-
]
|
|
2413
|
-
})
|
|
2459
|
+
case "spawn-start": return /* @__PURE__ */ jsx$1(SpawnLifecycleMarker, {
|
|
2460
|
+
row,
|
|
2461
|
+
dim: COLOR.dim,
|
|
2462
|
+
event,
|
|
2463
|
+
hideChildLabel,
|
|
2464
|
+
live: liveSpawn
|
|
2414
2465
|
});
|
|
2415
|
-
case "spawn-end": return /* @__PURE__ */ jsx$1(
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
/* @__PURE__ */ jsx$1("span", {
|
|
2421
|
-
fg: COLOR.accent,
|
|
2422
|
-
children: "🌳 "
|
|
2423
|
-
}),
|
|
2424
|
-
!hideChildLabel && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx$1("span", {
|
|
2425
|
-
fg: COLOR.brand,
|
|
2426
|
-
children: event.childId ?? "child"
|
|
2427
|
-
}), /* @__PURE__ */ jsx$1("span", {
|
|
2428
|
-
fg: COLOR.mute,
|
|
2429
|
-
children: " · "
|
|
2430
|
-
})] }),
|
|
2431
|
-
/* @__PURE__ */ jsx$1("span", {
|
|
2432
|
-
fg: COLOR.mute,
|
|
2433
|
-
children: safeText
|
|
2434
|
-
})
|
|
2435
|
-
]
|
|
2436
|
-
})
|
|
2466
|
+
case "spawn-end": return /* @__PURE__ */ jsx$1(SpawnLifecycleMarker, {
|
|
2467
|
+
row,
|
|
2468
|
+
dim: COLOR.dim,
|
|
2469
|
+
event,
|
|
2470
|
+
hideChildLabel
|
|
2437
2471
|
});
|
|
2438
2472
|
case "compact-summary": return /* @__PURE__ */ jsx$1(CompactSummaryBlock, {
|
|
2439
2473
|
event,
|
|
@@ -4651,6 +4685,44 @@ function CwdPickerModal({ currentCwd, onPick }) {
|
|
|
4651
4685
|
});
|
|
4652
4686
|
}
|
|
4653
4687
|
//#endregion
|
|
4688
|
+
//#region src/tui/project-location-context.tsx
|
|
4689
|
+
const ProjectLocationContext = createContext(null);
|
|
4690
|
+
/** Resolve the project root used by BOTH discovery and agent activation. */
|
|
4691
|
+
function resolveProjectLocation(cwd) {
|
|
4692
|
+
return {
|
|
4693
|
+
cwd,
|
|
4694
|
+
projectDir: findGitRoot(cwd) ?? cwd
|
|
4695
|
+
};
|
|
4696
|
+
}
|
|
4697
|
+
/**
|
|
4698
|
+
* Single source of truth for the TUI's active cwd/project root. It must
|
|
4699
|
+
* sit ABOVE both `DiscoveryShell` and `AppShell`: discovery used to derive
|
|
4700
|
+
* a frozen root from `process.cwd()` while AppShell independently honored
|
|
4701
|
+
* `launch.cwd` and runtime project switches, causing `.agents` skills/MCPs
|
|
4702
|
+
* to be read from the wrong repository.
|
|
4703
|
+
*/
|
|
4704
|
+
function ProjectLocationProvider({ initialCwd, children }) {
|
|
4705
|
+
const [location, setLocation] = useState(() => resolveProjectLocation(initialCwd));
|
|
4706
|
+
const setCwd = useCallback((next) => {
|
|
4707
|
+
process.chdir(next);
|
|
4708
|
+
setLocation(resolveProjectLocation(next));
|
|
4709
|
+
}, []);
|
|
4710
|
+
const value = useMemo(() => ({
|
|
4711
|
+
cwd: location.cwd,
|
|
4712
|
+
projectDir: location.projectDir,
|
|
4713
|
+
setCwd
|
|
4714
|
+
}), [location, setCwd]);
|
|
4715
|
+
return /* @__PURE__ */ jsx(ProjectLocationContext.Provider, {
|
|
4716
|
+
value,
|
|
4717
|
+
children
|
|
4718
|
+
});
|
|
4719
|
+
}
|
|
4720
|
+
function useProjectLocation() {
|
|
4721
|
+
const value = useContext(ProjectLocationContext);
|
|
4722
|
+
if (!value) throw new Error("useProjectLocation must be used inside ProjectLocationProvider");
|
|
4723
|
+
return value;
|
|
4724
|
+
}
|
|
4725
|
+
//#endregion
|
|
4654
4726
|
//#region src/tui/discovery-shell.tsx
|
|
4655
4727
|
/**
|
|
4656
4728
|
* SWR throttles. `files` is short so a long-open `@` popover picks up
|
|
@@ -4660,7 +4732,6 @@ function CwdPickerModal({ currentCwd, onPick }) {
|
|
|
4660
4732
|
const FILES_REFRESH_THROTTLE_MS = 3e3;
|
|
4661
4733
|
const SKILLS_REFRESH_THROTTLE_MS = 3e4;
|
|
4662
4734
|
const MCP_TOOLS_CACHE_POLL_MS = 4e3;
|
|
4663
|
-
const MCPS_CONFIG_POLL_MS = 3e3;
|
|
4664
4735
|
function debugLog$1(...args) {
|
|
4665
4736
|
if (process.env.ZIDANE_DEBUG) process.stderr.write(`[zidane/tui] ${args.map(errorMessage).join(" ")}\n`);
|
|
4666
4737
|
}
|
|
@@ -4671,7 +4742,7 @@ function DiscoveryShell({ children }) {
|
|
|
4671
4742
|
const dispatchAuth = useMcpAuthDispatch();
|
|
4672
4743
|
const dispatchAuthRef = useRef(dispatchAuth);
|
|
4673
4744
|
dispatchAuthRef.current = dispatchAuth;
|
|
4674
|
-
const
|
|
4745
|
+
const { projectDir } = useProjectLocation();
|
|
4675
4746
|
const dataDir = config.paths.userDir;
|
|
4676
4747
|
const mcpCredentialStore = useMemo(() => createFileMcpCredentialStore(dataDir), [dataDir]);
|
|
4677
4748
|
const [skillsCatalog, setSkillsCatalog] = useState([]);
|
|
@@ -4797,25 +4868,6 @@ function DiscoveryShell({ children }) {
|
|
|
4797
4868
|
mcpCredentialStore,
|
|
4798
4869
|
foreignAgents
|
|
4799
4870
|
]);
|
|
4800
|
-
useEffect(() => {
|
|
4801
|
-
let lastSignature = mcpsConfigSignature(projectDir, config.prefix, foreignAgents);
|
|
4802
|
-
const id = setInterval(() => {
|
|
4803
|
-
try {
|
|
4804
|
-
const signature = mcpsConfigSignature(projectDir, config.prefix, foreignAgents);
|
|
4805
|
-
if (signature === lastSignature) return;
|
|
4806
|
-
lastSignature = signature;
|
|
4807
|
-
refreshMcps();
|
|
4808
|
-
} catch (err) {
|
|
4809
|
-
debugLog$1("mcps config poll failed", err);
|
|
4810
|
-
}
|
|
4811
|
-
}, MCPS_CONFIG_POLL_MS);
|
|
4812
|
-
return () => clearInterval(id);
|
|
4813
|
-
}, [
|
|
4814
|
-
projectDir,
|
|
4815
|
-
config.prefix,
|
|
4816
|
-
refreshMcps,
|
|
4817
|
-
foreignAgents
|
|
4818
|
-
]);
|
|
4819
4871
|
useEffect(() => {
|
|
4820
4872
|
let lastSignature = cacheFileSignature(dataDir);
|
|
4821
4873
|
const id = setInterval(() => {
|
|
@@ -4873,21 +4925,6 @@ function cacheFileSignature(dataDir) {
|
|
|
4873
4925
|
const stat = statSync(mcpToolsCachePath(dataDir), { throwIfNoEntry: false });
|
|
4874
4926
|
return stat ? `${stat.mtimeMs}:${stat.size}` : null;
|
|
4875
4927
|
}
|
|
4876
|
-
/**
|
|
4877
|
-
* Change signature across every candidate `mcp(s).json` path (project +
|
|
4878
|
-
* user, both filename variants). Missing files contribute their bare path
|
|
4879
|
-
* so create/delete flips the signature just like an edit does.
|
|
4880
|
-
*/
|
|
4881
|
-
function mcpsConfigSignature(projectDir, prefix, foreignAgents) {
|
|
4882
|
-
return mcpsDiscoveryPaths({
|
|
4883
|
-
cwd: projectDir,
|
|
4884
|
-
prefix,
|
|
4885
|
-
foreignAgents
|
|
4886
|
-
}).map(({ path }) => {
|
|
4887
|
-
const stat = statSync(path, { throwIfNoEntry: false });
|
|
4888
|
-
return stat ? `${path}:${stat.mtimeMs}:${stat.size}` : path;
|
|
4889
|
-
}).join("|");
|
|
4890
|
-
}
|
|
4891
4928
|
function readToolsByServer(dataDir) {
|
|
4892
4929
|
const cache = loadMcpToolsCache({ dataDir });
|
|
4893
4930
|
const out = {};
|
|
@@ -12705,11 +12742,13 @@ function SettingsModal({ skillsCatalog: skillsCatalogProp, mcpsCatalog: mcpsCata
|
|
|
12705
12742
|
})).catch((err) => {
|
|
12706
12743
|
if (err instanceof SkillInstallError && err.code === "multiple-candidates" && err.candidates && err.candidates.length > 0) {
|
|
12707
12744
|
setSkillOp(null);
|
|
12708
|
-
const
|
|
12745
|
+
const fullCatalog = err.details !== void 0 && err.details.length === err.candidates.length;
|
|
12746
|
+
const items = fullCatalog && err.details ? err.details : err.candidates.map((rel) => ({ rel }));
|
|
12709
12747
|
setSkillImportAll({
|
|
12710
12748
|
source: req.source,
|
|
12711
12749
|
scope: req.choice,
|
|
12712
|
-
items
|
|
12750
|
+
items,
|
|
12751
|
+
fullCatalog
|
|
12713
12752
|
});
|
|
12714
12753
|
return;
|
|
12715
12754
|
}
|
|
@@ -13586,7 +13625,7 @@ function SettingsModal({ skillsCatalog: skillsCatalogProp, mcpsCatalog: mcpsCata
|
|
|
13586
13625
|
onConfirm: (selected) => {
|
|
13587
13626
|
const req = skillImportAll;
|
|
13588
13627
|
setSkillImportAll(null);
|
|
13589
|
-
runSkillInstall(selected.length === req.items.length ? {
|
|
13628
|
+
runSkillInstall(req.fullCatalog && selected.length === req.items.length ? {
|
|
13590
13629
|
source: req.source,
|
|
13591
13630
|
all: true,
|
|
13592
13631
|
choice: req.scope
|
|
@@ -16026,7 +16065,8 @@ function App({ config }) {
|
|
|
16026
16065
|
*/
|
|
16027
16066
|
function ThemedShell() {
|
|
16028
16067
|
const { settings } = useSettings();
|
|
16029
|
-
const
|
|
16068
|
+
const config = useConfig();
|
|
16069
|
+
const [extensionRegistry, setExtensionRegistry] = useState(config.extensions);
|
|
16030
16070
|
useEffect(() => () => {
|
|
16031
16071
|
disposeExtensionRegistry(extensionRegistry);
|
|
16032
16072
|
}, [extensionRegistry]);
|
|
@@ -16043,7 +16083,10 @@ function ThemedShell() {
|
|
|
16043
16083
|
registry: renderersRegistry,
|
|
16044
16084
|
children: /* @__PURE__ */ jsx$1(ThemeProvider, {
|
|
16045
16085
|
theme,
|
|
16046
|
-
children: /* @__PURE__ */ jsx$1(MdStyleProvider, { children: /* @__PURE__ */ jsx$1(ChipStyleProvider, { children: /* @__PURE__ */ jsx$1(SafeModeProvider, { children: /* @__PURE__ */ jsx$1(InteractionsProvider, { children: /* @__PURE__ */ jsx$1(McpAuthProvider, { children: /* @__PURE__ */ jsx$1(
|
|
16086
|
+
children: /* @__PURE__ */ jsx$1(MdStyleProvider, { children: /* @__PURE__ */ jsx$1(ChipStyleProvider, { children: /* @__PURE__ */ jsx$1(SafeModeProvider, { children: /* @__PURE__ */ jsx$1(InteractionsProvider, { children: /* @__PURE__ */ jsx$1(McpAuthProvider, { children: /* @__PURE__ */ jsx$1(ProjectLocationProvider, {
|
|
16087
|
+
initialCwd: config.launch?.cwd ?? process.cwd(),
|
|
16088
|
+
children: /* @__PURE__ */ jsx$1(DiscoveryShell, { children: /* @__PURE__ */ jsx$1(ModalRoot, { children: /* @__PURE__ */ jsx$1(AppShell, {}) }) })
|
|
16089
|
+
}) }) }) }) }) })
|
|
16047
16090
|
})
|
|
16048
16091
|
})
|
|
16049
16092
|
});
|
|
@@ -16219,16 +16262,9 @@ function AppShell() {
|
|
|
16219
16262
|
useEffect(() => {
|
|
16220
16263
|
smoothStreamingRef.current = settings.smoothStreaming;
|
|
16221
16264
|
}, [settings.smoothStreaming]);
|
|
16222
|
-
const
|
|
16223
|
-
const [projectDir, setProjectDir] = useState(() => findGitRoot(initialCwd) ?? initialCwd);
|
|
16224
|
-
const [cwd, setCwdRaw] = useState(() => initialCwd);
|
|
16265
|
+
const { cwd, projectDir, setCwd } = useProjectLocation();
|
|
16225
16266
|
const cwdRef = useRef(cwd);
|
|
16226
16267
|
cwdRef.current = cwd;
|
|
16227
|
-
const setCwd = useCallback((next) => {
|
|
16228
|
-
process.chdir(next);
|
|
16229
|
-
setCwdRaw(next);
|
|
16230
|
-
setProjectDir(findGitRoot(next) ?? next);
|
|
16231
|
-
}, []);
|
|
16232
16268
|
const safelistRef = useRef(null);
|
|
16233
16269
|
const readSafelist = useCallback(() => {
|
|
16234
16270
|
if (safelistRef.current === null) safelistRef.current = getSafelist(dataDir, projectDir);
|
|
@@ -17613,19 +17649,26 @@ function AppShell() {
|
|
|
17613
17649
|
});
|
|
17614
17650
|
const spawnStartedAt = /* @__PURE__ */ new Map();
|
|
17615
17651
|
agent.hooks.hook("spawn:before", ({ id, task, depth, model }) => {
|
|
17616
|
-
|
|
17652
|
+
const startedAt = Date.now();
|
|
17617
17653
|
const taskPreview = previewLine(task, 80);
|
|
17654
|
+
spawnStartedAt.set(id, {
|
|
17655
|
+
startedAt,
|
|
17656
|
+
task: taskPreview,
|
|
17657
|
+
...model ? { model } : {}
|
|
17658
|
+
});
|
|
17618
17659
|
stream.appendImmediate({
|
|
17619
17660
|
kind: "spawn-start",
|
|
17620
17661
|
text: taskPreview,
|
|
17621
17662
|
childId: id,
|
|
17622
17663
|
depth: depth ?? 1,
|
|
17664
|
+
spawn: { startedAt },
|
|
17623
17665
|
...model ? { model } : {}
|
|
17624
17666
|
});
|
|
17625
17667
|
});
|
|
17626
17668
|
agent.hooks.hook("spawn:complete", ({ id, depth, status, stats }) => {
|
|
17627
17669
|
const tag = status === "aborted" ? "aborted" : status === "error" ? "error" : "done";
|
|
17628
|
-
const
|
|
17670
|
+
const started = spawnStartedAt.get(id);
|
|
17671
|
+
const startedAt = started?.startedAt;
|
|
17629
17672
|
spawnStartedAt.delete(id);
|
|
17630
17673
|
const elapsed = startedAt !== void 0 ? ` · ${formatDuration(Date.now() - startedAt)}` : "";
|
|
17631
17674
|
const cost = flattenTurns(stats).reduce((sum, turn) => sum + (turn.cost ?? 0), 0);
|
|
@@ -17634,7 +17677,13 @@ function AppShell() {
|
|
|
17634
17677
|
kind: "spawn-end",
|
|
17635
17678
|
text: segments ? `${tag}${segments} · ${formatTokenUsage(stats)}` : `${tag} ${formatTokenUsage(stats)}`,
|
|
17636
17679
|
childId: id,
|
|
17637
|
-
depth: depth ?? 1
|
|
17680
|
+
depth: depth ?? 1,
|
|
17681
|
+
spawn: {
|
|
17682
|
+
startedAt: startedAt ?? Date.now(),
|
|
17683
|
+
...started?.task ? { task: started.task } : {},
|
|
17684
|
+
turns: stats.turns
|
|
17685
|
+
},
|
|
17686
|
+
...started?.model ? { model: started.model } : {}
|
|
17638
17687
|
});
|
|
17639
17688
|
});
|
|
17640
17689
|
agent.hooks.hook("spawn:error", ({ id, depth, error }) => {
|