zidane 6.2.7 → 6.2.11

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.
Files changed (104) hide show
  1. package/dist/{acp-B_8CI9-1.js → acp-DuEMbOoQ.js} +4 -4
  2. package/dist/{acp-B_8CI9-1.js.map → acp-DuEMbOoQ.js.map} +1 -1
  3. package/dist/acp-cli.js +7 -7
  4. package/dist/acp.d.ts +1 -1
  5. package/dist/acp.js +1 -1
  6. package/dist/{agent-DPO6GKX5.js → agent-6iGNP46b.js} +5 -5
  7. package/dist/{agent-DPO6GKX5.js.map → agent-6iGNP46b.js.map} +1 -1
  8. package/dist/agent.d.ts +1 -1
  9. package/dist/agent.js +1 -1
  10. package/dist/{anthropic-J2tBjcSQ.js → anthropic-BD-lwEKp.js} +3 -3
  11. package/dist/{anthropic-J2tBjcSQ.js.map → anthropic-BD-lwEKp.js.map} +1 -1
  12. package/dist/{auth-Cexpxjfa.js → auth-BH6G59RL.js} +8 -8
  13. package/dist/auth-BH6G59RL.js.map +1 -0
  14. package/dist/chat/pure.d.ts +3 -3
  15. package/dist/chat.d.ts +14 -5
  16. package/dist/chat.d.ts.map +1 -1
  17. package/dist/chat.js +3 -3
  18. package/dist/contexts/daytona.d.ts +1 -1
  19. package/dist/contexts/e2b.d.ts +1 -1
  20. package/dist/eval.d.ts +1 -1
  21. package/dist/eval.js +1 -1
  22. package/dist/extensions.d.ts +1 -1
  23. package/dist/extensions.js +1 -1
  24. package/dist/headless.d.ts +1 -1
  25. package/dist/headless.js +3 -3
  26. package/dist/{index-CNyYEOy0.d.ts → index-BFNt9GAs.d.ts} +59 -7
  27. package/dist/index-BFNt9GAs.d.ts.map +1 -0
  28. package/dist/index.d.ts +1 -1
  29. package/dist/index.js +10 -10
  30. package/dist/{login-Bp_tRj_e.js → login-B5nMPF8w.js} +3 -3
  31. package/dist/{login-Bp_tRj_e.js.map → login-B5nMPF8w.js.map} +1 -1
  32. package/dist/{mcp-CkHUripi.js → mcp-BCaN_Gyg.js} +140 -29
  33. package/dist/mcp-BCaN_Gyg.js.map +1 -0
  34. package/dist/mcp.d.ts +1 -1
  35. package/dist/mcp.js +1 -1
  36. package/dist/{messages-DEPX32kc.js → messages-BDpXLFoe.js} +2 -2
  37. package/dist/{messages-DEPX32kc.js.map → messages-BDpXLFoe.js.map} +1 -1
  38. package/dist/{openai-compat-LGAsBush.js → openai-compat-J_JZ7qsw.js} +1 -19
  39. package/dist/openai-compat-J_JZ7qsw.js.map +1 -0
  40. package/dist/output/stream-json.d.ts +1 -1
  41. package/dist/output/terminal.d.ts +1 -1
  42. package/dist/presets.d.ts +1 -1
  43. package/dist/presets.js +1 -1
  44. package/dist/providers/anthropic.d.ts +1 -1
  45. package/dist/providers/anthropic.js +1 -1
  46. package/dist/providers/arcee.d.ts +1 -1
  47. package/dist/providers/arcee.js +1 -1
  48. package/dist/providers/baseten.d.ts +1 -1
  49. package/dist/providers/baseten.js +1 -1
  50. package/dist/providers/cerebras.d.ts +1 -1
  51. package/dist/providers/cerebras.js +1 -1
  52. package/dist/providers/local.d.ts +1 -1
  53. package/dist/providers/local.js +1 -1
  54. package/dist/providers/openai-compat.d.ts +1 -1
  55. package/dist/providers/openai-compat.js +1 -1
  56. package/dist/providers/openai.d.ts +1 -1
  57. package/dist/providers/openai.js +548 -1
  58. package/dist/providers/openai.js.map +1 -0
  59. package/dist/providers/openrouter.d.ts +1 -1
  60. package/dist/providers/openrouter.js +1 -1
  61. package/dist/providers/xai.d.ts +1 -1
  62. package/dist/providers/xai.js +1 -1
  63. package/dist/{providers-BM6VuE_i.js → providers-CclOzGxc.js} +3 -3
  64. package/dist/{providers-BM6VuE_i.js.map → providers-CclOzGxc.js.map} +1 -1
  65. package/dist/providers.d.ts +1 -1
  66. package/dist/providers.js +5 -5
  67. package/dist/restate.d.ts +1 -1
  68. package/dist/session/sqlite.d.ts +1 -1
  69. package/dist/{session-Dc1v4Otm.js → session-CIXE-Bzp.js} +2 -2
  70. package/dist/{session-Dc1v4Otm.js.map → session-CIXE-Bzp.js.map} +1 -1
  71. package/dist/session.d.ts +1 -1
  72. package/dist/session.js +2 -2
  73. package/dist/{skills-BlmY7QhV.js → skills-CDpejYOf.js} +168 -44
  74. package/dist/skills-CDpejYOf.js.map +1 -0
  75. package/dist/skills.d.ts +2 -2
  76. package/dist/skills.js +1 -1
  77. package/dist/{tool-formatters-B7oWiy5m.d.ts → tool-formatters-B_zQsYfa.d.ts} +2 -2
  78. package/dist/{tool-formatters-B7oWiy5m.d.ts.map → tool-formatters-B_zQsYfa.d.ts.map} +1 -1
  79. package/dist/tools/fetch-url.d.ts +1 -1
  80. package/dist/tools/web-search.d.ts +1 -1
  81. package/dist/tools.d.ts +1 -1
  82. package/dist/tools.js +1 -1
  83. package/dist/{transcript-anchors-BUZ915pM.d.ts → transcript-anchors-2wafjV-s.d.ts} +9 -2
  84. package/dist/{transcript-anchors-BUZ915pM.d.ts.map → transcript-anchors-2wafjV-s.d.ts.map} +1 -1
  85. package/dist/{transcript-anchors-DtOaKu4d.js → transcript-anchors-B_kUHJ16.js} +225 -10
  86. package/dist/transcript-anchors-B_kUHJ16.js.map +1 -0
  87. package/dist/tui.d.ts +12 -7
  88. package/dist/tui.d.ts.map +1 -1
  89. package/dist/tui.js +356 -70
  90. package/dist/tui.js.map +1 -1
  91. package/dist/{turn-operations-2Ou_DkbC.d.ts → turn-operations-DVA52KMG.d.ts} +3 -3
  92. package/dist/{turn-operations-2Ou_DkbC.d.ts.map → turn-operations-DVA52KMG.d.ts.map} +1 -1
  93. package/dist/types.d.ts +1 -1
  94. package/dist/{xai-BYAyEPiJ.js → xai-D-wALLuZ.js} +2 -2
  95. package/dist/{xai-BYAyEPiJ.js.map → xai-D-wALLuZ.js.map} +1 -1
  96. package/package.json +2 -2
  97. package/dist/auth-Cexpxjfa.js.map +0 -1
  98. package/dist/index-CNyYEOy0.d.ts.map +0 -1
  99. package/dist/mcp-CkHUripi.js.map +0 -1
  100. package/dist/openai-BcmYm0t4.js +0 -579
  101. package/dist/openai-BcmYm0t4.js.map +0 -1
  102. package/dist/openai-compat-LGAsBush.js.map +0 -1
  103. package/dist/skills-BlmY7QhV.js.map +0 -1
  104. package/dist/transcript-anchors-DtOaKu4d.js.map +0 -1
package/dist/tui.js CHANGED
@@ -1,5 +1,5 @@
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-DtOaKu4d.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-DPO6GKX5.js";
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-B_kUHJ16.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-6iGNP46b.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";
@@ -7,16 +7,16 @@ import { l as errorMessage } from "./errors-DJUxZg9b.js";
7
7
  import { M as findGitRoot, j as projectUserPaths } from "./resolve-HtxmBWs9.js";
8
8
  import { a as createRingBufferSink, i as createLoggingHooks, l as logFileTimestamp, n as createFileSink, o as fanoutSink, r as createLogger, s as formatLogLine, t as consoleSink } from "./logger-DBX9uYOw.js";
9
9
  import { i as sniffImageMediaType } from "./media-sniff-Bn76JxAu.js";
10
- import { r as formatTokenUsage, t as effectiveInputFromTurn } from "./stats-DAKBEKjc.js";
10
+ import { n as flattenTurns, r as formatTokenUsage, t as effectiveInputFromTurn } from "./stats-DAKBEKjc.js";
11
11
  import { replaceDynamicSection } from "./prompt.js";
12
- import { a as getExtensionSessionState, i as demoteStaleRunningStatus, o as loadSession, s as setExtensionSessionState, t as createSession } from "./session-Dc1v4Otm.js";
12
+ import { a as getExtensionSessionState, i as demoteStaleRunningStatus, o as loadSession, s as setExtensionSessionState, t as createSession } from "./session-CIXE-Bzp.js";
13
13
  import { o as withTimeout } from "./timeout-BDetbuN6.js";
14
- import { n as connectMcpServers, u as McpOAuthProvider } from "./mcp-CkHUripi.js";
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-BlmY7QhV.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-Bp_tRj_e.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-Cexpxjfa.js";
17
+ import { i as installSkillFromSpec, r as SkillInstallError } from "./skills-CDpejYOf.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-B5nMPF8w.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-BH6G59RL.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";
@@ -1971,6 +1971,23 @@ function Transcript({ events, settings, selectedTurnId = null, busy = false }) {
1971
1971
  scrollbox.scrollBy(direction, key.shift ? "content" : "viewport");
1972
1972
  }, [modal]));
1973
1973
  const anchors = useMemo(() => computeTurnAnchors(items), [items]);
1974
+ const liveByItem = useMemo(() => {
1975
+ const map = /* @__PURE__ */ new Map();
1976
+ const open = openSpawns(events);
1977
+ for (let i = items.length - 1; i >= 0 && open.size > 0; i--) {
1978
+ const item = items[i];
1979
+ const here = [];
1980
+ for (const [id, childEvents] of open) if (item.kind === "child-run" ? item.events.some((e) => e.childId === id) : item.event.kind === "spawn-start" && item.event.childId === id) {
1981
+ here.push({
1982
+ id,
1983
+ activity: spawnActivity(childEvents)
1984
+ });
1985
+ open.delete(id);
1986
+ }
1987
+ if (here.length > 0) map.set(i, here.reverse());
1988
+ }
1989
+ return map;
1990
+ }, [items, events]);
1974
1991
  useEffect(() => {
1975
1992
  if (!selectedTurnId) return;
1976
1993
  const scrollbox = scrollboxRef.current;
@@ -2011,20 +2028,29 @@ function Transcript({ events, settings, selectedTurnId = null, busy = false }) {
2011
2028
  }
2012
2029
  },
2013
2030
  children: [items.map((item, i) => {
2014
- if (item.kind === "event") return /* @__PURE__ */ jsx$1(EventLine, {
2015
- event: item.event,
2016
- previous: item.previous,
2017
- selected: isTurnHighlighted(item.event, selectedTurnId, ownership),
2018
- anchorId: anchors.ids[i][0],
2019
- settleCodeEpoch: codeSettle.current.targets.has(item.event) ? codeSettle.current.epoch : 0
2020
- }, i);
2031
+ if (item.kind === "event") {
2032
+ const live = liveByItem.get(i);
2033
+ const line = /* @__PURE__ */ jsx$1(EventLine, {
2034
+ event: item.event,
2035
+ previous: item.previous,
2036
+ selected: isTurnHighlighted(item.event, selectedTurnId, ownership),
2037
+ anchorId: anchors.ids[i][0],
2038
+ settleCodeEpoch: codeSettle.current.targets.has(item.event) ? codeSettle.current.epoch : 0
2039
+ }, live ? void 0 : i);
2040
+ if (!live) return line;
2041
+ return /* @__PURE__ */ jsxs("box", { children: [line, live.map((spawn) => /* @__PURE__ */ jsx$1(LiveSpawnRow, {
2042
+ spawn,
2043
+ showLabel: true
2044
+ }, spawn.id))] }, i);
2045
+ }
2021
2046
  return /* @__PURE__ */ jsx$1(SubagentBlock, {
2022
2047
  events: item.events,
2023
2048
  previous: item.previous,
2024
2049
  selectedTurnId,
2025
2050
  anchorIds: anchors.ids[i],
2026
2051
  codeSettleTargets: codeSettle.current.targets,
2027
- codeSettleEpoch: codeSettle.current.epoch
2052
+ codeSettleEpoch: codeSettle.current.epoch,
2053
+ live: liveByItem.get(i)
2028
2054
  }, i);
2029
2055
  }), showThrobber && /* @__PURE__ */ jsx$1("box", {
2030
2056
  style: { marginTop: items.length > 0 ? 1 : 0 },
@@ -2038,14 +2064,56 @@ function Transcript({ events, settings, selectedTurnId = null, busy = false }) {
2038
2064
  });
2039
2065
  }
2040
2066
  /**
2041
- * Walk the visible-event list once and group consecutive child events
2042
- * (`depth > 0`) into runs so we can wrap each run in a single bordered
2043
- * subagent box.
2044
- *
2045
- * When `hideSubagentOutput` is on, `isVisible` already filters most child
2046
- * events out; the surviving `spawn-start` / `spawn-end` markers render as
2047
- * plain entries (no boxing) there's nothing meaningful to box.
2067
+ * Children with a `spawn-start` but no terminal marker yet, mapped to the
2068
+ * events they've produced since. Computed against the FULL event list a
2069
+ * parent-depth row (e.g. a background-task banner) can split one child's
2070
+ * events across two boxes, and only a global scan knows whether the child
2071
+ * actually finished. `spawn:error` emits a child-tagged `error` event and
2072
+ * never a `spawn-end`, so that closes the child too. Live-only signal:
2073
+ * replayed sessions always synthesize a `spawn-end` per child run, so
2074
+ * nothing stays open after a reload.
2075
+ */
2076
+ function openSpawns(events) {
2077
+ const open = /* @__PURE__ */ new Map();
2078
+ for (const event of events) {
2079
+ if (!event.childId || (event.depth ?? 0) === 0) continue;
2080
+ if (event.kind === "spawn-start") {
2081
+ open.set(event.childId, []);
2082
+ continue;
2083
+ }
2084
+ if (event.kind === "spawn-end" || event.kind === "error") {
2085
+ open.delete(event.childId);
2086
+ continue;
2087
+ }
2088
+ open.get(event.childId)?.push(event);
2089
+ }
2090
+ return open;
2091
+ }
2092
+ /**
2093
+ * One-word-ish description of what a running child is doing right now,
2094
+ * derived from its trailing events: `text` while prose streams, `thinking`
2095
+ * during reasoning, the tool name for a single in-flight call, and
2096
+ * `tool call ×N` over an uninterrupted burst of calls.
2048
2097
  */
2098
+ function spawnActivity(events) {
2099
+ const last = events[events.length - 1];
2100
+ if (!last) return "starting";
2101
+ switch (last.kind) {
2102
+ case "markdown": return "text";
2103
+ case "thinking": return "thinking";
2104
+ case "tool":
2105
+ case "tool-result": {
2106
+ let calls = 0;
2107
+ for (let i = events.length - 1; i >= 0; i--) {
2108
+ const kind = events[i].kind;
2109
+ if (kind === "tool") calls += 1;
2110
+ else if (kind !== "tool-result") break;
2111
+ }
2112
+ return calls > 1 ? `tool call ×${calls}` : last.tool ?? "tool call";
2113
+ }
2114
+ default: return "working";
2115
+ }
2116
+ }
2049
2117
  function partitionTranscript(events, settings) {
2050
2118
  const visible = events.filter((e) => isVisible(e, settings));
2051
2119
  if (visible.length === 0) return [];
@@ -2093,7 +2161,7 @@ function partitionTranscript(events, settings) {
2093
2161
  * indented twice. Grandchildren (depth ≥ 2) still indent further, so
2094
2162
  * nested subagents remain visually distinct.
2095
2163
  */
2096
- function SubagentBlock({ events, previous, selectedTurnId = null, anchorIds, codeSettleTargets, codeSettleEpoch = 0 }) {
2164
+ function SubagentBlock({ events, previous, selectedTurnId = null, anchorIds, codeSettleTargets, codeSettleEpoch = 0, live }) {
2097
2165
  const COLOR = useColors();
2098
2166
  const childIds = useMemo(() => {
2099
2167
  const set = /* @__PURE__ */ new Set();
@@ -2103,7 +2171,7 @@ function SubagentBlock({ events, previous, selectedTurnId = null, anchorIds, cod
2103
2171
  const title = childIds.length === 0 ? " subagent " : childIds.length === 1 ? ` ${childIds[0]} ` : ` subagents · ${childIds.join(", ")} `;
2104
2172
  const marginTop = previous ? 1 : 0;
2105
2173
  const hideChildLabel = childIds.length === 1;
2106
- return /* @__PURE__ */ jsx$1("box", {
2174
+ return /* @__PURE__ */ jsxs("box", {
2107
2175
  title,
2108
2176
  style: {
2109
2177
  border: true,
@@ -2117,7 +2185,7 @@ function SubagentBlock({ events, previous, selectedTurnId = null, anchorIds, cod
2117
2185
  flexShrink: 0,
2118
2186
  alignSelf: "stretch"
2119
2187
  },
2120
- children: events.map((evt, i) => /* @__PURE__ */ jsx$1(EventLine, {
2188
+ children: [events.map((evt, i) => /* @__PURE__ */ jsx$1(EventLine, {
2121
2189
  event: evt,
2122
2190
  previous: events[i - 1],
2123
2191
  depthOffset: 1,
@@ -2125,7 +2193,31 @@ function SubagentBlock({ events, previous, selectedTurnId = null, anchorIds, cod
2125
2193
  anchorId: anchorIds?.[i],
2126
2194
  hideChildLabel,
2127
2195
  settleCodeEpoch: codeSettleTargets?.has(evt) ? codeSettleEpoch : 0
2128
- }, i))
2196
+ }, i)), live?.map((spawn) => /* @__PURE__ */ jsx$1("box", {
2197
+ style: { marginTop: events.length > 0 ? 1 : 0 },
2198
+ children: /* @__PURE__ */ jsx$1(LiveSpawnRow, {
2199
+ spawn,
2200
+ showLabel: !hideChildLabel
2201
+ })
2202
+ }, spawn.id))]
2203
+ });
2204
+ }
2205
+ /** Spinner + current-activity line for a still-running subagent. */
2206
+ function LiveSpawnRow({ spawn, showLabel }) {
2207
+ const COLOR = useColors();
2208
+ return /* @__PURE__ */ jsxs("text", {
2209
+ fg: COLOR.dim,
2210
+ children: [
2211
+ /* @__PURE__ */ jsx$1(StatusSpinner, { color: COLOR.warn }),
2212
+ showLabel && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx$1("span", {
2213
+ fg: COLOR.brand,
2214
+ children: ` ${spawn.id}`
2215
+ }), /* @__PURE__ */ jsx$1("span", {
2216
+ fg: COLOR.mute,
2217
+ children: " ·"
2218
+ })] }),
2219
+ ` ${spawn.activity}`
2220
+ ]
2129
2221
  });
2130
2222
  }
2131
2223
  function EmptyState() {
@@ -4573,6 +4665,8 @@ function debugLog$1(...args) {
4573
4665
  }
4574
4666
  function DiscoveryShell({ children }) {
4575
4667
  const config = useConfig();
4668
+ const { settings } = useSettings();
4669
+ const foreignAgents = settings.importForeignConfigs === true;
4576
4670
  const dispatchAuth = useMcpAuthDispatch();
4577
4671
  const dispatchAuthRef = useRef(dispatchAuth);
4578
4672
  dispatchAuthRef.current = dispatchAuth;
@@ -4586,6 +4680,8 @@ function DiscoveryShell({ children }) {
4586
4680
  const [mcpToolsByServer, setMcpToolsByServer] = useState(() => readToolsByServer(dataDir));
4587
4681
  const filesSlotRef = useRef(null);
4588
4682
  const skillsSlotRef = useRef(null);
4683
+ /** Last-published MCP discovery result — see the value-compare in `refreshMcps`. */
4684
+ const mcpsFingerprintRef = useRef(null);
4589
4685
  useEffect(() => {
4590
4686
  filesSlotRef.current?.abort();
4591
4687
  skillsSlotRef.current?.abort();
@@ -4608,7 +4704,8 @@ function DiscoveryShell({ children }) {
4608
4704
  throttleMs: SKILLS_REFRESH_THROTTLE_MS,
4609
4705
  walk: () => discoverProjectSkills({
4610
4706
  cwd: projectDir,
4611
- prefix: config.prefix
4707
+ prefix: config.prefix,
4708
+ foreignAgents
4612
4709
  }),
4613
4710
  onLoad: (items) => {
4614
4711
  if (skillsSlotRef.current === skillsSlot) setSkillsCatalog(items);
@@ -4623,7 +4720,12 @@ function DiscoveryShell({ children }) {
4623
4720
  try {
4624
4721
  const { servers, errors } = discoverProjectMcps({
4625
4722
  cwd: projectDir,
4626
- prefix: config.prefix
4723
+ prefix: config.prefix,
4724
+ foreignAgents
4725
+ });
4726
+ mcpsFingerprintRef.current = JSON.stringify({
4727
+ servers,
4728
+ errors
4627
4729
  });
4628
4730
  setMcpsCatalog(servers);
4629
4731
  setMcpsErrors(errors);
@@ -4650,7 +4752,8 @@ function DiscoveryShell({ children }) {
4650
4752
  }, [
4651
4753
  projectDir,
4652
4754
  config.prefix,
4653
- mcpCredentialStore
4755
+ mcpCredentialStore,
4756
+ foreignAgents
4654
4757
  ]);
4655
4758
  const ensureFiles = useCallback(() => filesSlotRef.current?.ensure() ?? Promise.resolve([]), []);
4656
4759
  const ensureSkills = useCallback(() => skillsSlotRef.current?.ensure() ?? Promise.resolve([]), []);
@@ -4660,8 +4763,15 @@ function DiscoveryShell({ children }) {
4660
4763
  try {
4661
4764
  const { servers, errors } = discoverProjectMcps({
4662
4765
  cwd: projectDir,
4663
- prefix: config.prefix
4766
+ prefix: config.prefix,
4767
+ foreignAgents
4664
4768
  });
4769
+ const fingerprint = JSON.stringify({
4770
+ servers,
4771
+ errors
4772
+ });
4773
+ if (fingerprint === mcpsFingerprintRef.current) return Promise.resolve();
4774
+ mcpsFingerprintRef.current = fingerprint;
4665
4775
  setMcpsCatalog(servers);
4666
4776
  setMcpsErrors(errors);
4667
4777
  for (const entry of servers) {
@@ -4683,7 +4793,8 @@ function DiscoveryShell({ children }) {
4683
4793
  }, [
4684
4794
  projectDir,
4685
4795
  config.prefix,
4686
- mcpCredentialStore
4796
+ mcpCredentialStore,
4797
+ foreignAgents
4687
4798
  ]);
4688
4799
  useEffect(() => {
4689
4800
  let lastSignature = cacheFileSignature(dataDir);
@@ -4963,7 +5074,7 @@ const BASE_LEVELS$1 = [
4963
5074
  },
4964
5075
  {
4965
5076
  id: "minimal",
4966
- description: "tiny reasoning budget (gpt-5 family)"
5077
+ description: "tiny reasoning budget"
4967
5078
  },
4968
5079
  {
4969
5080
  id: "low",
@@ -4979,16 +5090,16 @@ const BASE_LEVELS$1 = [
4979
5090
  },
4980
5091
  {
4981
5092
  id: "xhigh",
4982
- description: "very deep reasoning (Anthropic)"
5093
+ description: "very deep reasoning"
4983
5094
  },
4984
5095
  {
4985
5096
  id: "max",
4986
- description: "maximum reasoning effort (Anthropic)"
5097
+ description: "maximum reasoning effort"
4987
5098
  }
4988
5099
  ];
4989
5100
  const ADAPTIVE_LEVEL$1 = {
4990
5101
  id: "adaptive",
4991
- description: "model decides per-turn (Anthropic)"
5102
+ description: "model decides per-turn"
4992
5103
  };
4993
5104
  function ModelOptionsPickerModal({ supportsReasoning, supportsAdaptive, currentEffort, options, enabled, onPickEffort, onToggleOption }) {
4994
5105
  const COLOR = useColors();
@@ -11452,13 +11563,17 @@ function filterLogRecords(records, minLevel) {
11452
11563
  }
11453
11564
  //#endregion
11454
11565
  //#region src/tui/settings-form-dialog.tsx
11455
- function FormDialog({ title, error, hint, children }) {
11566
+ /** Shared dialog width pickers use it to size their own ellipsed rows. */
11567
+ function formDialogWidth(termWidth) {
11568
+ return Math.min(96, Math.max(48, termWidth - 8));
11569
+ }
11570
+ function FormDialog({ title, error, hint, contentRows, children }) {
11456
11571
  const COLOR = useColors();
11457
11572
  const SURFACE = useSurfaces();
11458
11573
  const { width: termWidth, height: termHeight } = useTerminalDimensions();
11459
- const width = Math.min(96, Math.max(48, termWidth - 8));
11574
+ const width = formDialogWidth(termWidth);
11460
11575
  const left = Math.max(0, Math.floor((termWidth - width) / 2));
11461
- const top = Math.max(1, Math.floor(termHeight / 2) - 7);
11576
+ const top = contentRows !== void 0 ? Math.max(1, Math.floor((termHeight - (contentRows + 4)) / 2)) : Math.max(1, Math.floor(termHeight / 2) - 7);
11462
11577
  return /* @__PURE__ */ jsxs("box", {
11463
11578
  title: ` ${title} `,
11464
11579
  style: {
@@ -11747,13 +11862,13 @@ function SkillInstallDialog({ active, onSubmit, onCancel }) {
11747
11862
  focused: row === "source",
11748
11863
  label: "source",
11749
11864
  inputRef: sourceRef,
11750
- placeholder: "owner/repo · skills.sh/owner/repo/skill · pkg@version"
11865
+ placeholder: "owner/repo · skills.sh URL · npx skills add … · pkg@version"
11751
11866
  }),
11752
11867
  /* @__PURE__ */ jsx$1(InputRow$1, {
11753
11868
  focused: row === "skill",
11754
11869
  label: "skill",
11755
11870
  inputRef: skillRef,
11756
- placeholder: "pick one from multi-skill repos (optional)"
11871
+ placeholder: "pick one from multi-skill repos (optional — empty offers import-all)"
11757
11872
  }),
11758
11873
  /* @__PURE__ */ jsx$1(CycleRow, {
11759
11874
  focused: row === "scope",
@@ -11765,6 +11880,130 @@ function SkillInstallDialog({ active, onSubmit, onCancel }) {
11765
11880
  ]
11766
11881
  });
11767
11882
  }
11883
+ /** Rows shown at once in the picker; longer lists scroll around the cursor. */
11884
+ const SKILL_PICKER_MAX_VISIBLE = 10;
11885
+ /**
11886
+ * Shown when a skill install hit a multi-skill source without a selector
11887
+ * (`multiple-candidates`): a checkbox picker over everything the repo
11888
+ * contains, all pre-selected. `space` toggles the row under the cursor,
11889
+ * `a` flips all/none, `enter` imports the checked subset, `esc` cancels
11890
+ * back to the idle Skills tab.
11891
+ */
11892
+ function SkillImportDialog({ active, source, items, onConfirm, onCancel }) {
11893
+ const COLOR = useColors();
11894
+ const { width: termWidth } = useTerminalDimensions();
11895
+ const [cursor, setCursor] = useState(0);
11896
+ const [checked, setChecked] = useState(() => new Set(items.map((_, i) => i)));
11897
+ const [error, setError] = useState(null);
11898
+ const count = items.length;
11899
+ useKeyboard((key) => {
11900
+ if (!active) return;
11901
+ if (key.name === "escape") {
11902
+ onCancel();
11903
+ return;
11904
+ }
11905
+ if (key.name === "up" || key.name === "tab" && key.shift) {
11906
+ setCursor((c) => (c + count - 1) % count);
11907
+ return;
11908
+ }
11909
+ if (key.name === "down" || key.name === "tab") {
11910
+ setCursor((c) => (c + 1) % count);
11911
+ return;
11912
+ }
11913
+ if (key.name === "space") {
11914
+ setError(null);
11915
+ setChecked((prev) => {
11916
+ const next = new Set(prev);
11917
+ if (next.has(cursor)) next.delete(cursor);
11918
+ else next.add(cursor);
11919
+ return next;
11920
+ });
11921
+ return;
11922
+ }
11923
+ if (key.name === "a") {
11924
+ setError(null);
11925
+ setChecked((prev) => prev.size === count ? /* @__PURE__ */ new Set() : new Set(items.map((_, i) => i)));
11926
+ return;
11927
+ }
11928
+ if (key.name === "return") {
11929
+ const selected = items.filter((_, i) => checked.has(i)).map((item) => item.rel);
11930
+ if (selected.length === 0) {
11931
+ setError("nothing selected — space toggles, a selects all");
11932
+ return;
11933
+ }
11934
+ onConfirm(selected);
11935
+ }
11936
+ });
11937
+ const start = Math.max(0, Math.min(cursor - Math.floor(SKILL_PICKER_MAX_VISIBLE / 2), count - SKILL_PICKER_MAX_VISIBLE));
11938
+ const visible = items.slice(start, start + SKILL_PICKER_MAX_VISIBLE);
11939
+ const innerWidth = formDialogWidth(termWidth) - 6;
11940
+ const hasOverflowUp = start > 0;
11941
+ const hasOverflowDown = start + SKILL_PICKER_MAX_VISIBLE < count;
11942
+ return /* @__PURE__ */ jsxs(FormDialog, {
11943
+ title: "import skills",
11944
+ error,
11945
+ contentRows: 1 + visible.length + (hasOverflowUp ? 1 : 0) + (hasOverflowDown ? 1 : 0),
11946
+ hint: " ↑↓ move · space toggle · a all/none · enter import · esc cancel",
11947
+ children: [
11948
+ /* @__PURE__ */ jsxs("text", {
11949
+ fg: COLOR.mute,
11950
+ children: [
11951
+ " ",
11952
+ /* @__PURE__ */ jsx$1("span", {
11953
+ fg: COLOR.warn,
11954
+ children: source
11955
+ }),
11956
+ ` — ${checked.size}/${count} selected`
11957
+ ]
11958
+ }),
11959
+ hasOverflowUp && /* @__PURE__ */ jsx$1("text", {
11960
+ fg: COLOR.mute,
11961
+ children: ` ↑ ${start} more`
11962
+ }),
11963
+ visible.map((item, vi) => {
11964
+ const i = start + vi;
11965
+ const focusedRow = i === cursor;
11966
+ const isChecked = checked.has(i);
11967
+ const label = clipEnd(item.description ? `${item.rel} — ${item.description}` : item.rel, Math.max(8, innerWidth - 8), item.rel.length);
11968
+ return /* @__PURE__ */ jsxs("text", {
11969
+ fg: COLOR.mute,
11970
+ children: [
11971
+ ` ${focusedRow ? "❯" : " "} [`,
11972
+ /* @__PURE__ */ jsx$1("span", {
11973
+ fg: isChecked ? COLOR.accent : COLOR.mute,
11974
+ children: isChecked ? "✓" : " "
11975
+ }),
11976
+ "] ",
11977
+ /* @__PURE__ */ jsx$1("span", {
11978
+ fg: focusedRow ? COLOR.warn : isChecked ? COLOR.accent : COLOR.mute,
11979
+ children: label.name
11980
+ }),
11981
+ label.rest && /* @__PURE__ */ jsx$1("span", {
11982
+ fg: COLOR.mute,
11983
+ children: label.rest
11984
+ })
11985
+ ]
11986
+ }, item.rel);
11987
+ }),
11988
+ hasOverflowDown && /* @__PURE__ */ jsx$1("text", {
11989
+ fg: COLOR.mute,
11990
+ children: ` ↓ ${count - start - SKILL_PICKER_MAX_VISIBLE} more`
11991
+ })
11992
+ ]
11993
+ });
11994
+ }
11995
+ /**
11996
+ * Clip `text` to `max` columns with a trailing ellipsis, split into the
11997
+ * name segment (first `nameLen` chars — colored per row state) and the
11998
+ * dim remainder so the description stays one ellipsed line.
11999
+ */
12000
+ function clipEnd(text, max, nameLen) {
12001
+ const clipped = text.length > max ? `${text.slice(0, Math.max(1, max - 1))}…` : text;
12002
+ return {
12003
+ name: clipped.slice(0, Math.min(nameLen, clipped.length)),
12004
+ rest: clipped.slice(Math.min(nameLen, clipped.length))
12005
+ };
12006
+ }
11768
12007
  const MCP_TRANSPORTS = [
11769
12008
  "stdio",
11770
12009
  "streamable-http",
@@ -12372,6 +12611,7 @@ function SettingsModal({ skillsCatalog: skillsCatalogProp, mcpsCatalog: mcpsCata
12372
12611
  const [removeArmed, setRemoveArmed] = useState(null);
12373
12612
  const [extInstallOpen, setExtInstallOpen] = useState(false);
12374
12613
  const [skillInstallOpen, setSkillInstallOpen] = useState(false);
12614
+ const [skillImportAll, setSkillImportAll] = useState(null);
12375
12615
  const [skillOp, setSkillOp] = useState(null);
12376
12616
  const [mcpAdd, setMcpAdd] = useState(false);
12377
12617
  const [mcpOp, setMcpOp] = useState(null);
@@ -12381,6 +12621,7 @@ function SettingsModal({ skillsCatalog: skillsCatalogProp, mcpsCatalog: mcpsCata
12381
12621
  const configEditActive = activeTab === "extensions" && configEdit !== null;
12382
12622
  const extInstallActive = activeTab === "extensions" && extInstallOpen;
12383
12623
  const skillInstallActive = activeTab === "skills" && skillInstallOpen;
12624
+ const skillImportAllActive = activeTab === "skills" && skillImportAll !== null;
12384
12625
  const mcpAddActive = activeTab === "mcps" && mcpAdd;
12385
12626
  useEffect(() => {
12386
12627
  if (activeTab !== "extensions" && configEdit) setConfigEdit(null);
@@ -12391,14 +12632,18 @@ function SettingsModal({ skillsCatalog: skillsCatalogProp, mcpsCatalog: mcpsCata
12391
12632
  useEffect(() => {
12392
12633
  if (activeTab !== "skills" && skillInstallOpen) setSkillInstallOpen(false);
12393
12634
  }, [activeTab, skillInstallOpen]);
12635
+ useEffect(() => {
12636
+ if (activeTab !== "skills" && skillImportAll) setSkillImportAll(null);
12637
+ }, [activeTab, skillImportAll]);
12394
12638
  useEffect(() => {
12395
12639
  if (activeTab !== "mcps" && mcpAdd) setMcpAdd(false);
12396
12640
  }, [activeTab, mcpAdd]);
12397
12641
  useEffect(() => {
12398
- if (!extInstallOpen && !skillInstallOpen && !mcpAdd) inputRef.current?.focus();
12642
+ if (!extInstallOpen && !skillInstallOpen && !skillImportAll && !mcpAdd) inputRef.current?.focus();
12399
12643
  }, [
12400
12644
  extInstallOpen,
12401
12645
  skillInstallOpen,
12646
+ skillImportAll,
12402
12647
  mcpAdd
12403
12648
  ]);
12404
12649
  /** Run a skill install off the dialog's payload, streaming progress into the op line. */
@@ -12412,6 +12657,8 @@ function SettingsModal({ skillsCatalog: skillsCatalogProp, mcpsCatalog: mcpsCata
12412
12657
  actions.onInstallSkill({
12413
12658
  source: req.source,
12414
12659
  ...req.skill !== void 0 ? { skill: req.skill } : {},
12660
+ ...req.all !== void 0 ? { all: req.all } : {},
12661
+ ...req.skills !== void 0 ? { skills: req.skills } : {},
12415
12662
  scope: req.choice,
12416
12663
  onProgress: (message) => setSkillOp({
12417
12664
  kind: "busy",
@@ -12420,10 +12667,22 @@ function SettingsModal({ skillsCatalog: skillsCatalogProp, mcpsCatalog: mcpsCata
12420
12667
  }).then((message) => setSkillOp({
12421
12668
  kind: "notice",
12422
12669
  text: message
12423
- })).catch((err) => setSkillOp({
12424
- kind: "error",
12425
- text: errorMessage(err)
12426
- }));
12670
+ })).catch((err) => {
12671
+ if (err instanceof SkillInstallError && err.code === "multiple-candidates" && err.candidates && err.candidates.length > 0) {
12672
+ setSkillOp(null);
12673
+ const items = err.details && err.details.length === err.candidates.length ? err.details : err.candidates.map((rel) => ({ rel }));
12674
+ setSkillImportAll({
12675
+ source: req.source,
12676
+ scope: req.choice,
12677
+ items
12678
+ });
12679
+ return;
12680
+ }
12681
+ setSkillOp({
12682
+ kind: "error",
12683
+ text: errorMessage(err)
12684
+ });
12685
+ });
12427
12686
  }, [actions]);
12428
12687
  /** Add-MCP submit: persist through the host, then surface the outcome. */
12429
12688
  const runAddMcp = useCallback((result) => {
@@ -12788,7 +13047,7 @@ function SettingsModal({ skillsCatalog: skillsCatalogProp, mcpsCatalog: mcpsCata
12788
13047
  if (key.name === "escape" && configEdit?.kind !== "model") setConfigEdit(null);
12789
13048
  return;
12790
13049
  }
12791
- if (extInstallActive || skillInstallActive) return;
13050
+ if (extInstallActive || skillInstallActive || skillImportAllActive) return;
12792
13051
  if (mcpAddActive) return;
12793
13052
  if (key.name === "escape" && oauthPasteActive && focusedMcp) {
12794
13053
  actions?.onCancelLoginMcp?.(focusedMcp.config.name);
@@ -13033,7 +13292,7 @@ function SettingsModal({ skillsCatalog: skillsCatalogProp, mcpsCatalog: mcpsCata
13033
13292
  horizontalMargin: 0,
13034
13293
  verticalMargin: 0,
13035
13294
  ...version ? { bottomTitle: `zidane v${version}` } : {},
13036
- disableEscape: configEditActive || !!editingInputKey || extInstallActive || skillInstallActive || mcpAddActive,
13295
+ disableEscape: configEditActive || !!editingInputKey || extInstallActive || skillInstallActive || skillImportAllActive || mcpAddActive,
13037
13296
  children: [
13038
13297
  /* @__PURE__ */ jsx$1("box", {
13039
13298
  style: { flexShrink: 0 },
@@ -13054,7 +13313,7 @@ function SettingsModal({ skillsCatalog: skillsCatalogProp, mcpsCatalog: mcpsCata
13054
13313
  },
13055
13314
  children: /* @__PURE__ */ jsx$1("input", {
13056
13315
  ref: inputRef,
13057
- focused: !oauthPasteActive && !configEditActive && !editingInputKey && !extInstallActive && !skillInstallActive && !mcpAddActive,
13316
+ focused: !oauthPasteActive && !configEditActive && !editingInputKey && !extInstallActive && !skillInstallActive && !skillImportAllActive && !mcpAddActive,
13058
13317
  placeholder: searchPlaceholder(activeTab),
13059
13318
  onInput: handleQueryChange,
13060
13319
  onSubmit: () => {},
@@ -13285,6 +13544,25 @@ function SettingsModal({ skillsCatalog: skillsCatalogProp, mcpsCatalog: mcpsCata
13285
13544
  },
13286
13545
  onCancel: () => setSkillInstallOpen(false)
13287
13546
  }),
13547
+ skillImportAllActive && skillImportAll && /* @__PURE__ */ jsx$1(SkillImportDialog, {
13548
+ active: skillImportAllActive,
13549
+ source: skillImportAll.source,
13550
+ items: skillImportAll.items,
13551
+ onConfirm: (selected) => {
13552
+ const req = skillImportAll;
13553
+ setSkillImportAll(null);
13554
+ runSkillInstall(selected.length === req.items.length ? {
13555
+ source: req.source,
13556
+ all: true,
13557
+ choice: req.scope
13558
+ } : {
13559
+ source: req.source,
13560
+ skills: selected,
13561
+ choice: req.scope
13562
+ });
13563
+ },
13564
+ onCancel: () => setSkillImportAll(null)
13565
+ }),
13288
13566
  mcpAddActive && /* @__PURE__ */ jsx$1(McpAddDialog, {
13289
13567
  active: mcpAddActive,
13290
13568
  existingNames: mcpsCatalog.map((s) => s.config.name),
@@ -15936,6 +16214,8 @@ function AppShell() {
15936
16214
  skillsCatalogRef.current = skillsCatalog;
15937
16215
  const enabledSkillsRef = useRef(settings.enabledSkills);
15938
16216
  enabledSkillsRef.current = settings.enabledSkills;
16217
+ const importForeignConfigsRef = useRef(settings.importForeignConfigs);
16218
+ importForeignConfigsRef.current = settings.importForeignConfigs;
15939
16219
  const mcpsCatalogRef = useRef(mcpsCatalog);
15940
16220
  mcpsCatalogRef.current = mcpsCatalog;
15941
16221
  const enabledMcpsRef = useRef(settings.enabledMcps);
@@ -16793,7 +17073,8 @@ function AppShell() {
16793
17073
  const profile = pickedAgentRef.current;
16794
17074
  const skillsScan = defaultSkillScanPaths({
16795
17075
  cwd: projectDir,
16796
- prefix: config.prefix
17076
+ prefix: config.prefix,
17077
+ foreignAgents: importForeignConfigsRef.current === true
16797
17078
  });
16798
17079
  const liveExtensionRegistry = filterExtensionRegistry(extensionRegistry, enabledExtensionsRef.current);
16799
17080
  const extensionSkillNames = liveExtensionRegistry.skills.map((s) => s.name);
@@ -17295,7 +17576,9 @@ function AppShell() {
17295
17576
  setLastInputTokens(ctx.effectiveTokens);
17296
17577
  lastInputTokensRef.current = ctx.effectiveTokens;
17297
17578
  });
17579
+ const spawnStartedAt = /* @__PURE__ */ new Map();
17298
17580
  agent.hooks.hook("spawn:before", ({ id, task, depth, model }) => {
17581
+ spawnStartedAt.set(id, Date.now());
17299
17582
  const taskPreview = previewLine(task, 80);
17300
17583
  stream.appendImmediate({
17301
17584
  kind: "spawn-start",
@@ -17307,9 +17590,14 @@ function AppShell() {
17307
17590
  });
17308
17591
  agent.hooks.hook("spawn:complete", ({ id, depth, status, stats }) => {
17309
17592
  const tag = status === "aborted" ? "aborted" : status === "error" ? "error" : "done";
17593
+ const startedAt = spawnStartedAt.get(id);
17594
+ spawnStartedAt.delete(id);
17595
+ const elapsed = startedAt !== void 0 ? ` · ${formatDuration(Date.now() - startedAt)}` : "";
17596
+ const cost = flattenTurns(stats).reduce((sum, turn) => sum + (turn.cost ?? 0), 0);
17597
+ const segments = `${elapsed}${cost > 0 ? ` · $${cost.toFixed(cost < .01 ? 4 : 2)}` : ""}`;
17310
17598
  stream.appendImmediate({
17311
17599
  kind: "spawn-end",
17312
- text: `${tag} ${formatTokenUsage(stats)}`,
17600
+ text: segments ? `${tag}${segments} · ${formatTokenUsage(stats)}` : `${tag} ${formatTokenUsage(stats)}`,
17313
17601
  childId: id,
17314
17602
  depth: depth ?? 1
17315
17603
  });
@@ -17904,22 +18192,20 @@ function AppShell() {
17904
18192
  * catalog refresh makes the new skill togglable immediately.
17905
18193
  */
17906
18194
  const onInstallSkill = useCallback(async (req) => {
17907
- let result;
17908
- try {
17909
- result = await installSkillFromSpec({
17910
- source: req.source,
17911
- scope: req.scope,
17912
- cwd: cwdRef.current,
17913
- prefix: config.prefix,
17914
- ...req.skill !== void 0 ? { skill: req.skill } : {},
17915
- ...req.onProgress !== void 0 ? { onProgress: req.onProgress } : {}
17916
- });
17917
- } catch (err) {
17918
- if (err instanceof SkillInstallError && err.code === "multiple-candidates") throw new Error(`${err.message} — re-run as “${req.source} <name>”.`);
17919
- throw err;
17920
- }
18195
+ const result = await installSkillFromSpec({
18196
+ source: req.source,
18197
+ scope: req.scope,
18198
+ cwd: cwdRef.current,
18199
+ prefix: config.prefix,
18200
+ ...req.skill !== void 0 ? { skill: req.skill } : {},
18201
+ ...req.all !== void 0 ? { all: req.all } : {},
18202
+ ...req.skills !== void 0 ? { skills: req.skills } : {},
18203
+ ...req.onProgress !== void 0 ? { onProgress: req.onProgress } : {}
18204
+ });
17921
18205
  await onRefreshSkills();
17922
- return result.engine === "skills-cli" ? `installed ${result.installed.join(", ")} via the skills.sh CLI` : `installed ${result.installed.join(", ")} (${req.scope}, ${result.provenance ?? "native"})`;
18206
+ const skippedNote = result.skipped?.length ? ` skipped existing: ${result.skipped.join(", ")}` : "";
18207
+ const failedNote = result.failed?.length ? ` — ⚠ invalid: ${result.failed.join(", ")}` : "";
18208
+ return result.engine === "skills-cli" ? `installed ${result.installed.join(", ")} via the skills.sh CLI` : `installed ${result.installed.join(", ")} (${req.scope}, ${result.provenance ?? "native"})${skippedNote}${failedNote}`;
17923
18209
  }, [config.prefix, onRefreshSkills]);
17924
18210
  /**
17925
18211
  * Persist a new MCP server (Settings → MCPs → ctrl+g form). Upserts
@@ -20498,7 +20784,7 @@ const BASE_LEVELS = [
20498
20784
  },
20499
20785
  {
20500
20786
  id: "minimal",
20501
- description: "tiny reasoning budget (gpt-5 family)"
20787
+ description: "tiny reasoning budget"
20502
20788
  },
20503
20789
  {
20504
20790
  id: "low",
@@ -20514,16 +20800,16 @@ const BASE_LEVELS = [
20514
20800
  },
20515
20801
  {
20516
20802
  id: "xhigh",
20517
- description: "very deep reasoning (Anthropic)"
20803
+ description: "very deep reasoning"
20518
20804
  },
20519
20805
  {
20520
20806
  id: "max",
20521
- description: "maximum reasoning effort (Anthropic)"
20807
+ description: "maximum reasoning effort"
20522
20808
  }
20523
20809
  ];
20524
20810
  const ADAPTIVE_LEVEL = {
20525
20811
  id: "adaptive",
20526
- description: "model decides per-turn (Anthropic)"
20812
+ description: "model decides per-turn"
20527
20813
  };
20528
20814
  function EffortPickerModal({ current, supportsAdaptive, onPick }) {
20529
20815
  const COLOR = useColors();