zidane 6.2.7 → 6.2.10
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-B_8CI9-1.js → acp-DuEMbOoQ.js} +4 -4
- package/dist/{acp-B_8CI9-1.js.map → acp-DuEMbOoQ.js.map} +1 -1
- package/dist/acp-cli.js +7 -7
- package/dist/acp.d.ts +1 -1
- package/dist/acp.js +1 -1
- package/dist/{agent-DPO6GKX5.js → agent-6iGNP46b.js} +5 -5
- package/dist/{agent-DPO6GKX5.js.map → agent-6iGNP46b.js.map} +1 -1
- package/dist/agent.d.ts +1 -1
- package/dist/agent.js +1 -1
- package/dist/{anthropic-J2tBjcSQ.js → anthropic-BD-lwEKp.js} +3 -3
- package/dist/{anthropic-J2tBjcSQ.js.map → anthropic-BD-lwEKp.js.map} +1 -1
- package/dist/{auth-Cexpxjfa.js → auth-BH6G59RL.js} +8 -8
- package/dist/auth-BH6G59RL.js.map +1 -0
- package/dist/chat/pure.d.ts +3 -3
- package/dist/chat.d.ts +14 -44
- 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/eval.js +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 +3 -3
- package/dist/{index-CNyYEOy0.d.ts → index-BFNt9GAs.d.ts} +59 -7
- package/dist/index-BFNt9GAs.d.ts.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +10 -10
- package/dist/{login-Bp_tRj_e.js → login-B5nMPF8w.js} +3 -3
- package/dist/{login-Bp_tRj_e.js.map → login-B5nMPF8w.js.map} +1 -1
- package/dist/{mcp-CkHUripi.js → mcp-BCaN_Gyg.js} +140 -29
- package/dist/mcp-BCaN_Gyg.js.map +1 -0
- package/dist/mcp.d.ts +1 -1
- package/dist/mcp.js +1 -1
- package/dist/{messages-DEPX32kc.js → messages-BDpXLFoe.js} +2 -2
- package/dist/{messages-DEPX32kc.js.map → messages-BDpXLFoe.js.map} +1 -1
- package/dist/{openai-compat-LGAsBush.js → openai-compat-J_JZ7qsw.js} +1 -19
- package/dist/openai-compat-J_JZ7qsw.js.map +1 -0
- 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/arcee.js +1 -1
- package/dist/providers/baseten.d.ts +1 -1
- package/dist/providers/baseten.js +1 -1
- package/dist/providers/cerebras.d.ts +1 -1
- package/dist/providers/cerebras.js +1 -1
- package/dist/providers/local.d.ts +1 -1
- package/dist/providers/local.js +1 -1
- package/dist/providers/openai-compat.d.ts +1 -1
- package/dist/providers/openai-compat.js +1 -1
- package/dist/providers/openai.d.ts +1 -1
- package/dist/providers/openai.js +548 -1
- package/dist/providers/openai.js.map +1 -0
- package/dist/providers/openrouter.d.ts +1 -1
- package/dist/providers/openrouter.js +1 -1
- package/dist/providers/xai.d.ts +1 -1
- package/dist/providers/xai.js +1 -1
- package/dist/{providers-BM6VuE_i.js → providers-CclOzGxc.js} +3 -3
- package/dist/{providers-BM6VuE_i.js.map → providers-CclOzGxc.js.map} +1 -1
- package/dist/providers.d.ts +1 -1
- package/dist/providers.js +5 -5
- package/dist/restate.d.ts +1 -1
- package/dist/session/sqlite.d.ts +1 -1
- package/dist/{session-Dc1v4Otm.js → session-CIXE-Bzp.js} +2 -2
- package/dist/{session-Dc1v4Otm.js.map → session-CIXE-Bzp.js.map} +1 -1
- package/dist/session.d.ts +1 -1
- package/dist/session.js +2 -2
- package/dist/{skills-BlmY7QhV.js → skills-CDpejYOf.js} +168 -44
- package/dist/skills-CDpejYOf.js.map +1 -0
- package/dist/skills.d.ts +2 -2
- package/dist/skills.js +1 -1
- package/dist/{tool-formatters-B7oWiy5m.d.ts → tool-formatters-B_zQsYfa.d.ts} +2 -2
- package/dist/{tool-formatters-B7oWiy5m.d.ts.map → tool-formatters-B_zQsYfa.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-DtOaKu4d.js → transcript-anchors-BUigMBQt.js} +227 -11
- package/dist/transcript-anchors-BUigMBQt.js.map +1 -0
- package/dist/{transcript-anchors-BUZ915pM.d.ts → transcript-anchors-C1Zqb8uS.d.ts} +49 -3
- package/dist/transcript-anchors-C1Zqb8uS.d.ts.map +1 -0
- package/dist/tui.d.ts +12 -7
- package/dist/tui.d.ts.map +1 -1
- package/dist/tui.js +391 -70
- package/dist/tui.js.map +1 -1
- package/dist/{turn-operations-2Ou_DkbC.d.ts → turn-operations-DVA52KMG.d.ts} +3 -3
- package/dist/{turn-operations-2Ou_DkbC.d.ts.map → turn-operations-DVA52KMG.d.ts.map} +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/{xai-BYAyEPiJ.js → xai-D-wALLuZ.js} +2 -2
- package/dist/{xai-BYAyEPiJ.js.map → xai-D-wALLuZ.js.map} +1 -1
- package/package.json +2 -2
- package/dist/auth-Cexpxjfa.js.map +0 -1
- package/dist/index-CNyYEOy0.d.ts.map +0 -1
- package/dist/mcp-CkHUripi.js.map +0 -1
- package/dist/openai-BcmYm0t4.js +0 -579
- package/dist/openai-BcmYm0t4.js.map +0 -1
- package/dist/openai-compat-LGAsBush.js.map +0 -1
- package/dist/skills-BlmY7QhV.js.map +0 -1
- package/dist/transcript-anchors-BUZ915pM.d.ts.map +0 -1
- package/dist/transcript-anchors-DtOaKu4d.js.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 useMcpAuthDispatch, $n as buildBuildSystem, $t as providerKeySetChanged, A as runOAuthLogin, B as refreshMcpToolsCatalog, Ct as SETTINGS_CATEGORIES, D as formatPathForCwd, Dt as SettingsProvider, En as accentColor, Et as SETTINGS_TOGGLES, F as mcpsDiscoveryPaths, Gt as ConfigProvider, H as subscribeMcpToolsCache, Hn as useActiveTodos, Ht as DiscoveryProvider, J as parentServerName, Jt as resolveStoragePaths, K as buildVisibleMcpRows, Kt as useConfig, M as buildMcpServers, Mn as TODO_STATUS_GLYPHS, Mt as resolveChipColor, Nt as resolveTheme, O as fetchOAuthRedirect, Ot as clampFps, P as discoverProjectMcps, Q as McpAuthProvider, Qt as filterChainFallbacks, R as loadMcpToolsCache, St as DEFAULT_SETTINGS, T as suggestSafelistEntries, Tt as SETTINGS_INPUTS, Ut as useDiscovery, Vt as createDiscoverySlot, W as useMcpToolToggleMap, Wt as useDiscoveryOptional, Xt as chainPositionOf, Y as createFileMcpCredentialStore, Yt as buildRunModel, Zt as chainsEqual, _ as useSafeModeQueue, _n as chatAutoCompactBehavior, _t as truncateTrailing, a as useSurfaces, ar as compactSummaryEvent, at as PRESENT_PLAN_TOOL, b as getSafelist, br as updateToolEventOutcomes, bt as listProjectFiles, c as useStreamBuffer, cn as useUpdateCheck, cr as eventsFromTurns, d as discoverProjectSkills, dr as loadState, en as restoreChainFallbacks, er as buildPlanSystem, et as useMcpAuthState, fr as marginTopFor, ft as useInteractionsActions, g as useSafeModeActions, gr as sumRunCosts, gt as hintsLength, h as SafeModeProvider, hr as stripSpawnTokensLine, ht as clipHintsToWidth, i as useSelectStyle, in as tryOpenBrowser, it as InteractionsProvider, j as supportsOAuth, k as oauthUsesManualCodePaste, kt as useSettings, l as buildSkillsConfig, lr as lastContextSizeFromTurns, lt as makeRequestInteraction, m as writeSessionExport, mr as serverToolResultSummary, mt as EMPTY_HINTS, n as ThemeProvider, nn as toggleChainEntry, nr as chatReferenceTokensForPrompt, on as bootTick, ot as buildResumedToolResultsTurn, pt as useInteractionsQueue, q as indexOfServerRow, qt as resolveConfig, r as useColors, rn as useCompletion, rr as createChatTurnsReadTool, rt as ASK_USER_TOOL, s as useTheme, sn as buildUpdateHint, sr as deriveSessionTitle, st as createInteractionTools, t as computeTurnAnchors, tr as envSection, tt as getMcpAuthStatus, u as defaultSkillScanPaths, ur as listSessionMeta, ut as pendingInteractionsFromTurns, vn as discoverAgentsMd, vr as toolCallPreview, vt as buildHints, wt as SETTINGS_CHOICES, x as isOnSafelist, xr as usageByModel, xt as useEnabledToggleSet, y as addToSafelist, yr as toolResultText, z as mcpToolsCachePath } from "./transcript-anchors-BUigMBQt.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-
|
|
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-
|
|
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-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")
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
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
|
-
*
|
|
2042
|
-
*
|
|
2043
|
-
*
|
|
2044
|
-
*
|
|
2045
|
-
*
|
|
2046
|
-
*
|
|
2047
|
-
*
|
|
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__ */
|
|
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() {
|
|
@@ -4568,11 +4660,14 @@ function CwdPickerModal({ currentCwd, onPick }) {
|
|
|
4568
4660
|
const FILES_REFRESH_THROTTLE_MS = 3e3;
|
|
4569
4661
|
const SKILLS_REFRESH_THROTTLE_MS = 3e4;
|
|
4570
4662
|
const MCP_TOOLS_CACHE_POLL_MS = 4e3;
|
|
4663
|
+
const MCPS_CONFIG_POLL_MS = 3e3;
|
|
4571
4664
|
function debugLog$1(...args) {
|
|
4572
4665
|
if (process.env.ZIDANE_DEBUG) process.stderr.write(`[zidane/tui] ${args.map(errorMessage).join(" ")}\n`);
|
|
4573
4666
|
}
|
|
4574
4667
|
function DiscoveryShell({ children }) {
|
|
4575
4668
|
const config = useConfig();
|
|
4669
|
+
const { settings } = useSettings();
|
|
4670
|
+
const foreignAgents = settings.importForeignConfigs === true;
|
|
4576
4671
|
const dispatchAuth = useMcpAuthDispatch();
|
|
4577
4672
|
const dispatchAuthRef = useRef(dispatchAuth);
|
|
4578
4673
|
dispatchAuthRef.current = dispatchAuth;
|
|
@@ -4586,6 +4681,8 @@ function DiscoveryShell({ children }) {
|
|
|
4586
4681
|
const [mcpToolsByServer, setMcpToolsByServer] = useState(() => readToolsByServer(dataDir));
|
|
4587
4682
|
const filesSlotRef = useRef(null);
|
|
4588
4683
|
const skillsSlotRef = useRef(null);
|
|
4684
|
+
/** Last-published MCP discovery result — see the value-compare in `refreshMcps`. */
|
|
4685
|
+
const mcpsFingerprintRef = useRef(null);
|
|
4589
4686
|
useEffect(() => {
|
|
4590
4687
|
filesSlotRef.current?.abort();
|
|
4591
4688
|
skillsSlotRef.current?.abort();
|
|
@@ -4608,7 +4705,8 @@ function DiscoveryShell({ children }) {
|
|
|
4608
4705
|
throttleMs: SKILLS_REFRESH_THROTTLE_MS,
|
|
4609
4706
|
walk: () => discoverProjectSkills({
|
|
4610
4707
|
cwd: projectDir,
|
|
4611
|
-
prefix: config.prefix
|
|
4708
|
+
prefix: config.prefix,
|
|
4709
|
+
foreignAgents
|
|
4612
4710
|
}),
|
|
4613
4711
|
onLoad: (items) => {
|
|
4614
4712
|
if (skillsSlotRef.current === skillsSlot) setSkillsCatalog(items);
|
|
@@ -4623,7 +4721,12 @@ function DiscoveryShell({ children }) {
|
|
|
4623
4721
|
try {
|
|
4624
4722
|
const { servers, errors } = discoverProjectMcps({
|
|
4625
4723
|
cwd: projectDir,
|
|
4626
|
-
prefix: config.prefix
|
|
4724
|
+
prefix: config.prefix,
|
|
4725
|
+
foreignAgents
|
|
4726
|
+
});
|
|
4727
|
+
mcpsFingerprintRef.current = JSON.stringify({
|
|
4728
|
+
servers,
|
|
4729
|
+
errors
|
|
4627
4730
|
});
|
|
4628
4731
|
setMcpsCatalog(servers);
|
|
4629
4732
|
setMcpsErrors(errors);
|
|
@@ -4650,7 +4753,8 @@ function DiscoveryShell({ children }) {
|
|
|
4650
4753
|
}, [
|
|
4651
4754
|
projectDir,
|
|
4652
4755
|
config.prefix,
|
|
4653
|
-
mcpCredentialStore
|
|
4756
|
+
mcpCredentialStore,
|
|
4757
|
+
foreignAgents
|
|
4654
4758
|
]);
|
|
4655
4759
|
const ensureFiles = useCallback(() => filesSlotRef.current?.ensure() ?? Promise.resolve([]), []);
|
|
4656
4760
|
const ensureSkills = useCallback(() => skillsSlotRef.current?.ensure() ?? Promise.resolve([]), []);
|
|
@@ -4660,8 +4764,15 @@ function DiscoveryShell({ children }) {
|
|
|
4660
4764
|
try {
|
|
4661
4765
|
const { servers, errors } = discoverProjectMcps({
|
|
4662
4766
|
cwd: projectDir,
|
|
4663
|
-
prefix: config.prefix
|
|
4767
|
+
prefix: config.prefix,
|
|
4768
|
+
foreignAgents
|
|
4664
4769
|
});
|
|
4770
|
+
const fingerprint = JSON.stringify({
|
|
4771
|
+
servers,
|
|
4772
|
+
errors
|
|
4773
|
+
});
|
|
4774
|
+
if (fingerprint === mcpsFingerprintRef.current) return Promise.resolve();
|
|
4775
|
+
mcpsFingerprintRef.current = fingerprint;
|
|
4665
4776
|
setMcpsCatalog(servers);
|
|
4666
4777
|
setMcpsErrors(errors);
|
|
4667
4778
|
for (const entry of servers) {
|
|
@@ -4683,7 +4794,27 @@ function DiscoveryShell({ children }) {
|
|
|
4683
4794
|
}, [
|
|
4684
4795
|
projectDir,
|
|
4685
4796
|
config.prefix,
|
|
4686
|
-
mcpCredentialStore
|
|
4797
|
+
mcpCredentialStore,
|
|
4798
|
+
foreignAgents
|
|
4799
|
+
]);
|
|
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
|
|
4687
4818
|
]);
|
|
4688
4819
|
useEffect(() => {
|
|
4689
4820
|
let lastSignature = cacheFileSignature(dataDir);
|
|
@@ -4742,6 +4873,21 @@ function cacheFileSignature(dataDir) {
|
|
|
4742
4873
|
const stat = statSync(mcpToolsCachePath(dataDir), { throwIfNoEntry: false });
|
|
4743
4874
|
return stat ? `${stat.mtimeMs}:${stat.size}` : null;
|
|
4744
4875
|
}
|
|
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
|
+
}
|
|
4745
4891
|
function readToolsByServer(dataDir) {
|
|
4746
4892
|
const cache = loadMcpToolsCache({ dataDir });
|
|
4747
4893
|
const out = {};
|
|
@@ -4963,7 +5109,7 @@ const BASE_LEVELS$1 = [
|
|
|
4963
5109
|
},
|
|
4964
5110
|
{
|
|
4965
5111
|
id: "minimal",
|
|
4966
|
-
description: "tiny reasoning budget
|
|
5112
|
+
description: "tiny reasoning budget"
|
|
4967
5113
|
},
|
|
4968
5114
|
{
|
|
4969
5115
|
id: "low",
|
|
@@ -4979,16 +5125,16 @@ const BASE_LEVELS$1 = [
|
|
|
4979
5125
|
},
|
|
4980
5126
|
{
|
|
4981
5127
|
id: "xhigh",
|
|
4982
|
-
description: "very deep reasoning
|
|
5128
|
+
description: "very deep reasoning"
|
|
4983
5129
|
},
|
|
4984
5130
|
{
|
|
4985
5131
|
id: "max",
|
|
4986
|
-
description: "maximum reasoning effort
|
|
5132
|
+
description: "maximum reasoning effort"
|
|
4987
5133
|
}
|
|
4988
5134
|
];
|
|
4989
5135
|
const ADAPTIVE_LEVEL$1 = {
|
|
4990
5136
|
id: "adaptive",
|
|
4991
|
-
description: "model decides per-turn
|
|
5137
|
+
description: "model decides per-turn"
|
|
4992
5138
|
};
|
|
4993
5139
|
function ModelOptionsPickerModal({ supportsReasoning, supportsAdaptive, currentEffort, options, enabled, onPickEffort, onToggleOption }) {
|
|
4994
5140
|
const COLOR = useColors();
|
|
@@ -11452,13 +11598,17 @@ function filterLogRecords(records, minLevel) {
|
|
|
11452
11598
|
}
|
|
11453
11599
|
//#endregion
|
|
11454
11600
|
//#region src/tui/settings-form-dialog.tsx
|
|
11455
|
-
|
|
11601
|
+
/** Shared dialog width — pickers use it to size their own ellipsed rows. */
|
|
11602
|
+
function formDialogWidth(termWidth) {
|
|
11603
|
+
return Math.min(96, Math.max(48, termWidth - 8));
|
|
11604
|
+
}
|
|
11605
|
+
function FormDialog({ title, error, hint, contentRows, children }) {
|
|
11456
11606
|
const COLOR = useColors();
|
|
11457
11607
|
const SURFACE = useSurfaces();
|
|
11458
11608
|
const { width: termWidth, height: termHeight } = useTerminalDimensions();
|
|
11459
|
-
const width =
|
|
11609
|
+
const width = formDialogWidth(termWidth);
|
|
11460
11610
|
const left = Math.max(0, Math.floor((termWidth - width) / 2));
|
|
11461
|
-
const top = Math.max(1, Math.floor(termHeight / 2) - 7);
|
|
11611
|
+
const top = contentRows !== void 0 ? Math.max(1, Math.floor((termHeight - (contentRows + 4)) / 2)) : Math.max(1, Math.floor(termHeight / 2) - 7);
|
|
11462
11612
|
return /* @__PURE__ */ jsxs("box", {
|
|
11463
11613
|
title: ` ${title} `,
|
|
11464
11614
|
style: {
|
|
@@ -11747,13 +11897,13 @@ function SkillInstallDialog({ active, onSubmit, onCancel }) {
|
|
|
11747
11897
|
focused: row === "source",
|
|
11748
11898
|
label: "source",
|
|
11749
11899
|
inputRef: sourceRef,
|
|
11750
|
-
placeholder: "owner/repo · skills.sh
|
|
11900
|
+
placeholder: "owner/repo · skills.sh URL · npx skills add … · pkg@version"
|
|
11751
11901
|
}),
|
|
11752
11902
|
/* @__PURE__ */ jsx$1(InputRow$1, {
|
|
11753
11903
|
focused: row === "skill",
|
|
11754
11904
|
label: "skill",
|
|
11755
11905
|
inputRef: skillRef,
|
|
11756
|
-
placeholder: "pick one from multi-skill repos (optional)"
|
|
11906
|
+
placeholder: "pick one from multi-skill repos (optional — empty offers import-all)"
|
|
11757
11907
|
}),
|
|
11758
11908
|
/* @__PURE__ */ jsx$1(CycleRow, {
|
|
11759
11909
|
focused: row === "scope",
|
|
@@ -11765,6 +11915,130 @@ function SkillInstallDialog({ active, onSubmit, onCancel }) {
|
|
|
11765
11915
|
]
|
|
11766
11916
|
});
|
|
11767
11917
|
}
|
|
11918
|
+
/** Rows shown at once in the picker; longer lists scroll around the cursor. */
|
|
11919
|
+
const SKILL_PICKER_MAX_VISIBLE = 10;
|
|
11920
|
+
/**
|
|
11921
|
+
* Shown when a skill install hit a multi-skill source without a selector
|
|
11922
|
+
* (`multiple-candidates`): a checkbox picker over everything the repo
|
|
11923
|
+
* contains, all pre-selected. `space` toggles the row under the cursor,
|
|
11924
|
+
* `a` flips all/none, `enter` imports the checked subset, `esc` cancels
|
|
11925
|
+
* back to the idle Skills tab.
|
|
11926
|
+
*/
|
|
11927
|
+
function SkillImportDialog({ active, source, items, onConfirm, onCancel }) {
|
|
11928
|
+
const COLOR = useColors();
|
|
11929
|
+
const { width: termWidth } = useTerminalDimensions();
|
|
11930
|
+
const [cursor, setCursor] = useState(0);
|
|
11931
|
+
const [checked, setChecked] = useState(() => new Set(items.map((_, i) => i)));
|
|
11932
|
+
const [error, setError] = useState(null);
|
|
11933
|
+
const count = items.length;
|
|
11934
|
+
useKeyboard((key) => {
|
|
11935
|
+
if (!active) return;
|
|
11936
|
+
if (key.name === "escape") {
|
|
11937
|
+
onCancel();
|
|
11938
|
+
return;
|
|
11939
|
+
}
|
|
11940
|
+
if (key.name === "up" || key.name === "tab" && key.shift) {
|
|
11941
|
+
setCursor((c) => (c + count - 1) % count);
|
|
11942
|
+
return;
|
|
11943
|
+
}
|
|
11944
|
+
if (key.name === "down" || key.name === "tab") {
|
|
11945
|
+
setCursor((c) => (c + 1) % count);
|
|
11946
|
+
return;
|
|
11947
|
+
}
|
|
11948
|
+
if (key.name === "space") {
|
|
11949
|
+
setError(null);
|
|
11950
|
+
setChecked((prev) => {
|
|
11951
|
+
const next = new Set(prev);
|
|
11952
|
+
if (next.has(cursor)) next.delete(cursor);
|
|
11953
|
+
else next.add(cursor);
|
|
11954
|
+
return next;
|
|
11955
|
+
});
|
|
11956
|
+
return;
|
|
11957
|
+
}
|
|
11958
|
+
if (key.name === "a") {
|
|
11959
|
+
setError(null);
|
|
11960
|
+
setChecked((prev) => prev.size === count ? /* @__PURE__ */ new Set() : new Set(items.map((_, i) => i)));
|
|
11961
|
+
return;
|
|
11962
|
+
}
|
|
11963
|
+
if (key.name === "return") {
|
|
11964
|
+
const selected = items.filter((_, i) => checked.has(i)).map((item) => item.rel);
|
|
11965
|
+
if (selected.length === 0) {
|
|
11966
|
+
setError("nothing selected — space toggles, a selects all");
|
|
11967
|
+
return;
|
|
11968
|
+
}
|
|
11969
|
+
onConfirm(selected);
|
|
11970
|
+
}
|
|
11971
|
+
});
|
|
11972
|
+
const start = Math.max(0, Math.min(cursor - Math.floor(SKILL_PICKER_MAX_VISIBLE / 2), count - SKILL_PICKER_MAX_VISIBLE));
|
|
11973
|
+
const visible = items.slice(start, start + SKILL_PICKER_MAX_VISIBLE);
|
|
11974
|
+
const innerWidth = formDialogWidth(termWidth) - 6;
|
|
11975
|
+
const hasOverflowUp = start > 0;
|
|
11976
|
+
const hasOverflowDown = start + SKILL_PICKER_MAX_VISIBLE < count;
|
|
11977
|
+
return /* @__PURE__ */ jsxs(FormDialog, {
|
|
11978
|
+
title: "import skills",
|
|
11979
|
+
error,
|
|
11980
|
+
contentRows: 1 + visible.length + (hasOverflowUp ? 1 : 0) + (hasOverflowDown ? 1 : 0),
|
|
11981
|
+
hint: " ↑↓ move · space toggle · a all/none · enter import · esc cancel",
|
|
11982
|
+
children: [
|
|
11983
|
+
/* @__PURE__ */ jsxs("text", {
|
|
11984
|
+
fg: COLOR.mute,
|
|
11985
|
+
children: [
|
|
11986
|
+
" ",
|
|
11987
|
+
/* @__PURE__ */ jsx$1("span", {
|
|
11988
|
+
fg: COLOR.warn,
|
|
11989
|
+
children: source
|
|
11990
|
+
}),
|
|
11991
|
+
` — ${checked.size}/${count} selected`
|
|
11992
|
+
]
|
|
11993
|
+
}),
|
|
11994
|
+
hasOverflowUp && /* @__PURE__ */ jsx$1("text", {
|
|
11995
|
+
fg: COLOR.mute,
|
|
11996
|
+
children: ` ↑ ${start} more`
|
|
11997
|
+
}),
|
|
11998
|
+
visible.map((item, vi) => {
|
|
11999
|
+
const i = start + vi;
|
|
12000
|
+
const focusedRow = i === cursor;
|
|
12001
|
+
const isChecked = checked.has(i);
|
|
12002
|
+
const label = clipEnd(item.description ? `${item.rel} — ${item.description}` : item.rel, Math.max(8, innerWidth - 8), item.rel.length);
|
|
12003
|
+
return /* @__PURE__ */ jsxs("text", {
|
|
12004
|
+
fg: COLOR.mute,
|
|
12005
|
+
children: [
|
|
12006
|
+
` ${focusedRow ? "❯" : " "} [`,
|
|
12007
|
+
/* @__PURE__ */ jsx$1("span", {
|
|
12008
|
+
fg: isChecked ? COLOR.accent : COLOR.mute,
|
|
12009
|
+
children: isChecked ? "✓" : " "
|
|
12010
|
+
}),
|
|
12011
|
+
"] ",
|
|
12012
|
+
/* @__PURE__ */ jsx$1("span", {
|
|
12013
|
+
fg: focusedRow ? COLOR.warn : isChecked ? COLOR.accent : COLOR.mute,
|
|
12014
|
+
children: label.name
|
|
12015
|
+
}),
|
|
12016
|
+
label.rest && /* @__PURE__ */ jsx$1("span", {
|
|
12017
|
+
fg: COLOR.mute,
|
|
12018
|
+
children: label.rest
|
|
12019
|
+
})
|
|
12020
|
+
]
|
|
12021
|
+
}, item.rel);
|
|
12022
|
+
}),
|
|
12023
|
+
hasOverflowDown && /* @__PURE__ */ jsx$1("text", {
|
|
12024
|
+
fg: COLOR.mute,
|
|
12025
|
+
children: ` ↓ ${count - start - SKILL_PICKER_MAX_VISIBLE} more`
|
|
12026
|
+
})
|
|
12027
|
+
]
|
|
12028
|
+
});
|
|
12029
|
+
}
|
|
12030
|
+
/**
|
|
12031
|
+
* Clip `text` to `max` columns with a trailing ellipsis, split into the
|
|
12032
|
+
* name segment (first `nameLen` chars — colored per row state) and the
|
|
12033
|
+
* dim remainder so the description stays one ellipsed line.
|
|
12034
|
+
*/
|
|
12035
|
+
function clipEnd(text, max, nameLen) {
|
|
12036
|
+
const clipped = text.length > max ? `${text.slice(0, Math.max(1, max - 1))}…` : text;
|
|
12037
|
+
return {
|
|
12038
|
+
name: clipped.slice(0, Math.min(nameLen, clipped.length)),
|
|
12039
|
+
rest: clipped.slice(Math.min(nameLen, clipped.length))
|
|
12040
|
+
};
|
|
12041
|
+
}
|
|
11768
12042
|
const MCP_TRANSPORTS = [
|
|
11769
12043
|
"stdio",
|
|
11770
12044
|
"streamable-http",
|
|
@@ -12372,6 +12646,7 @@ function SettingsModal({ skillsCatalog: skillsCatalogProp, mcpsCatalog: mcpsCata
|
|
|
12372
12646
|
const [removeArmed, setRemoveArmed] = useState(null);
|
|
12373
12647
|
const [extInstallOpen, setExtInstallOpen] = useState(false);
|
|
12374
12648
|
const [skillInstallOpen, setSkillInstallOpen] = useState(false);
|
|
12649
|
+
const [skillImportAll, setSkillImportAll] = useState(null);
|
|
12375
12650
|
const [skillOp, setSkillOp] = useState(null);
|
|
12376
12651
|
const [mcpAdd, setMcpAdd] = useState(false);
|
|
12377
12652
|
const [mcpOp, setMcpOp] = useState(null);
|
|
@@ -12381,6 +12656,7 @@ function SettingsModal({ skillsCatalog: skillsCatalogProp, mcpsCatalog: mcpsCata
|
|
|
12381
12656
|
const configEditActive = activeTab === "extensions" && configEdit !== null;
|
|
12382
12657
|
const extInstallActive = activeTab === "extensions" && extInstallOpen;
|
|
12383
12658
|
const skillInstallActive = activeTab === "skills" && skillInstallOpen;
|
|
12659
|
+
const skillImportAllActive = activeTab === "skills" && skillImportAll !== null;
|
|
12384
12660
|
const mcpAddActive = activeTab === "mcps" && mcpAdd;
|
|
12385
12661
|
useEffect(() => {
|
|
12386
12662
|
if (activeTab !== "extensions" && configEdit) setConfigEdit(null);
|
|
@@ -12391,14 +12667,18 @@ function SettingsModal({ skillsCatalog: skillsCatalogProp, mcpsCatalog: mcpsCata
|
|
|
12391
12667
|
useEffect(() => {
|
|
12392
12668
|
if (activeTab !== "skills" && skillInstallOpen) setSkillInstallOpen(false);
|
|
12393
12669
|
}, [activeTab, skillInstallOpen]);
|
|
12670
|
+
useEffect(() => {
|
|
12671
|
+
if (activeTab !== "skills" && skillImportAll) setSkillImportAll(null);
|
|
12672
|
+
}, [activeTab, skillImportAll]);
|
|
12394
12673
|
useEffect(() => {
|
|
12395
12674
|
if (activeTab !== "mcps" && mcpAdd) setMcpAdd(false);
|
|
12396
12675
|
}, [activeTab, mcpAdd]);
|
|
12397
12676
|
useEffect(() => {
|
|
12398
|
-
if (!extInstallOpen && !skillInstallOpen && !mcpAdd) inputRef.current?.focus();
|
|
12677
|
+
if (!extInstallOpen && !skillInstallOpen && !skillImportAll && !mcpAdd) inputRef.current?.focus();
|
|
12399
12678
|
}, [
|
|
12400
12679
|
extInstallOpen,
|
|
12401
12680
|
skillInstallOpen,
|
|
12681
|
+
skillImportAll,
|
|
12402
12682
|
mcpAdd
|
|
12403
12683
|
]);
|
|
12404
12684
|
/** Run a skill install off the dialog's payload, streaming progress into the op line. */
|
|
@@ -12412,6 +12692,8 @@ function SettingsModal({ skillsCatalog: skillsCatalogProp, mcpsCatalog: mcpsCata
|
|
|
12412
12692
|
actions.onInstallSkill({
|
|
12413
12693
|
source: req.source,
|
|
12414
12694
|
...req.skill !== void 0 ? { skill: req.skill } : {},
|
|
12695
|
+
...req.all !== void 0 ? { all: req.all } : {},
|
|
12696
|
+
...req.skills !== void 0 ? { skills: req.skills } : {},
|
|
12415
12697
|
scope: req.choice,
|
|
12416
12698
|
onProgress: (message) => setSkillOp({
|
|
12417
12699
|
kind: "busy",
|
|
@@ -12420,10 +12702,22 @@ function SettingsModal({ skillsCatalog: skillsCatalogProp, mcpsCatalog: mcpsCata
|
|
|
12420
12702
|
}).then((message) => setSkillOp({
|
|
12421
12703
|
kind: "notice",
|
|
12422
12704
|
text: message
|
|
12423
|
-
})).catch((err) =>
|
|
12424
|
-
|
|
12425
|
-
|
|
12426
|
-
|
|
12705
|
+
})).catch((err) => {
|
|
12706
|
+
if (err instanceof SkillInstallError && err.code === "multiple-candidates" && err.candidates && err.candidates.length > 0) {
|
|
12707
|
+
setSkillOp(null);
|
|
12708
|
+
const items = err.details && err.details.length === err.candidates.length ? err.details : err.candidates.map((rel) => ({ rel }));
|
|
12709
|
+
setSkillImportAll({
|
|
12710
|
+
source: req.source,
|
|
12711
|
+
scope: req.choice,
|
|
12712
|
+
items
|
|
12713
|
+
});
|
|
12714
|
+
return;
|
|
12715
|
+
}
|
|
12716
|
+
setSkillOp({
|
|
12717
|
+
kind: "error",
|
|
12718
|
+
text: errorMessage(err)
|
|
12719
|
+
});
|
|
12720
|
+
});
|
|
12427
12721
|
}, [actions]);
|
|
12428
12722
|
/** Add-MCP submit: persist through the host, then surface the outcome. */
|
|
12429
12723
|
const runAddMcp = useCallback((result) => {
|
|
@@ -12788,7 +13082,7 @@ function SettingsModal({ skillsCatalog: skillsCatalogProp, mcpsCatalog: mcpsCata
|
|
|
12788
13082
|
if (key.name === "escape" && configEdit?.kind !== "model") setConfigEdit(null);
|
|
12789
13083
|
return;
|
|
12790
13084
|
}
|
|
12791
|
-
if (extInstallActive || skillInstallActive) return;
|
|
13085
|
+
if (extInstallActive || skillInstallActive || skillImportAllActive) return;
|
|
12792
13086
|
if (mcpAddActive) return;
|
|
12793
13087
|
if (key.name === "escape" && oauthPasteActive && focusedMcp) {
|
|
12794
13088
|
actions?.onCancelLoginMcp?.(focusedMcp.config.name);
|
|
@@ -13033,7 +13327,7 @@ function SettingsModal({ skillsCatalog: skillsCatalogProp, mcpsCatalog: mcpsCata
|
|
|
13033
13327
|
horizontalMargin: 0,
|
|
13034
13328
|
verticalMargin: 0,
|
|
13035
13329
|
...version ? { bottomTitle: `zidane v${version}` } : {},
|
|
13036
|
-
disableEscape: configEditActive || !!editingInputKey || extInstallActive || skillInstallActive || mcpAddActive,
|
|
13330
|
+
disableEscape: configEditActive || !!editingInputKey || extInstallActive || skillInstallActive || skillImportAllActive || mcpAddActive,
|
|
13037
13331
|
children: [
|
|
13038
13332
|
/* @__PURE__ */ jsx$1("box", {
|
|
13039
13333
|
style: { flexShrink: 0 },
|
|
@@ -13054,7 +13348,7 @@ function SettingsModal({ skillsCatalog: skillsCatalogProp, mcpsCatalog: mcpsCata
|
|
|
13054
13348
|
},
|
|
13055
13349
|
children: /* @__PURE__ */ jsx$1("input", {
|
|
13056
13350
|
ref: inputRef,
|
|
13057
|
-
focused: !oauthPasteActive && !configEditActive && !editingInputKey && !extInstallActive && !skillInstallActive && !mcpAddActive,
|
|
13351
|
+
focused: !oauthPasteActive && !configEditActive && !editingInputKey && !extInstallActive && !skillInstallActive && !skillImportAllActive && !mcpAddActive,
|
|
13058
13352
|
placeholder: searchPlaceholder(activeTab),
|
|
13059
13353
|
onInput: handleQueryChange,
|
|
13060
13354
|
onSubmit: () => {},
|
|
@@ -13285,6 +13579,25 @@ function SettingsModal({ skillsCatalog: skillsCatalogProp, mcpsCatalog: mcpsCata
|
|
|
13285
13579
|
},
|
|
13286
13580
|
onCancel: () => setSkillInstallOpen(false)
|
|
13287
13581
|
}),
|
|
13582
|
+
skillImportAllActive && skillImportAll && /* @__PURE__ */ jsx$1(SkillImportDialog, {
|
|
13583
|
+
active: skillImportAllActive,
|
|
13584
|
+
source: skillImportAll.source,
|
|
13585
|
+
items: skillImportAll.items,
|
|
13586
|
+
onConfirm: (selected) => {
|
|
13587
|
+
const req = skillImportAll;
|
|
13588
|
+
setSkillImportAll(null);
|
|
13589
|
+
runSkillInstall(selected.length === req.items.length ? {
|
|
13590
|
+
source: req.source,
|
|
13591
|
+
all: true,
|
|
13592
|
+
choice: req.scope
|
|
13593
|
+
} : {
|
|
13594
|
+
source: req.source,
|
|
13595
|
+
skills: selected,
|
|
13596
|
+
choice: req.scope
|
|
13597
|
+
});
|
|
13598
|
+
},
|
|
13599
|
+
onCancel: () => setSkillImportAll(null)
|
|
13600
|
+
}),
|
|
13288
13601
|
mcpAddActive && /* @__PURE__ */ jsx$1(McpAddDialog, {
|
|
13289
13602
|
active: mcpAddActive,
|
|
13290
13603
|
existingNames: mcpsCatalog.map((s) => s.config.name),
|
|
@@ -15936,6 +16249,8 @@ function AppShell() {
|
|
|
15936
16249
|
skillsCatalogRef.current = skillsCatalog;
|
|
15937
16250
|
const enabledSkillsRef = useRef(settings.enabledSkills);
|
|
15938
16251
|
enabledSkillsRef.current = settings.enabledSkills;
|
|
16252
|
+
const importForeignConfigsRef = useRef(settings.importForeignConfigs);
|
|
16253
|
+
importForeignConfigsRef.current = settings.importForeignConfigs;
|
|
15939
16254
|
const mcpsCatalogRef = useRef(mcpsCatalog);
|
|
15940
16255
|
mcpsCatalogRef.current = mcpsCatalog;
|
|
15941
16256
|
const enabledMcpsRef = useRef(settings.enabledMcps);
|
|
@@ -16793,7 +17108,8 @@ function AppShell() {
|
|
|
16793
17108
|
const profile = pickedAgentRef.current;
|
|
16794
17109
|
const skillsScan = defaultSkillScanPaths({
|
|
16795
17110
|
cwd: projectDir,
|
|
16796
|
-
prefix: config.prefix
|
|
17111
|
+
prefix: config.prefix,
|
|
17112
|
+
foreignAgents: importForeignConfigsRef.current === true
|
|
16797
17113
|
});
|
|
16798
17114
|
const liveExtensionRegistry = filterExtensionRegistry(extensionRegistry, enabledExtensionsRef.current);
|
|
16799
17115
|
const extensionSkillNames = liveExtensionRegistry.skills.map((s) => s.name);
|
|
@@ -17295,7 +17611,9 @@ function AppShell() {
|
|
|
17295
17611
|
setLastInputTokens(ctx.effectiveTokens);
|
|
17296
17612
|
lastInputTokensRef.current = ctx.effectiveTokens;
|
|
17297
17613
|
});
|
|
17614
|
+
const spawnStartedAt = /* @__PURE__ */ new Map();
|
|
17298
17615
|
agent.hooks.hook("spawn:before", ({ id, task, depth, model }) => {
|
|
17616
|
+
spawnStartedAt.set(id, Date.now());
|
|
17299
17617
|
const taskPreview = previewLine(task, 80);
|
|
17300
17618
|
stream.appendImmediate({
|
|
17301
17619
|
kind: "spawn-start",
|
|
@@ -17307,9 +17625,14 @@ function AppShell() {
|
|
|
17307
17625
|
});
|
|
17308
17626
|
agent.hooks.hook("spawn:complete", ({ id, depth, status, stats }) => {
|
|
17309
17627
|
const tag = status === "aborted" ? "aborted" : status === "error" ? "error" : "done";
|
|
17628
|
+
const startedAt = spawnStartedAt.get(id);
|
|
17629
|
+
spawnStartedAt.delete(id);
|
|
17630
|
+
const elapsed = startedAt !== void 0 ? ` · ${formatDuration(Date.now() - startedAt)}` : "";
|
|
17631
|
+
const cost = flattenTurns(stats).reduce((sum, turn) => sum + (turn.cost ?? 0), 0);
|
|
17632
|
+
const segments = `${elapsed}${cost > 0 ? ` · $${cost.toFixed(cost < .01 ? 4 : 2)}` : ""}`;
|
|
17310
17633
|
stream.appendImmediate({
|
|
17311
17634
|
kind: "spawn-end",
|
|
17312
|
-
text: `${tag} ${formatTokenUsage(stats)}`,
|
|
17635
|
+
text: segments ? `${tag}${segments} · ${formatTokenUsage(stats)}` : `${tag} ${formatTokenUsage(stats)}`,
|
|
17313
17636
|
childId: id,
|
|
17314
17637
|
depth: depth ?? 1
|
|
17315
17638
|
});
|
|
@@ -17904,22 +18227,20 @@ function AppShell() {
|
|
|
17904
18227
|
* catalog refresh makes the new skill togglable immediately.
|
|
17905
18228
|
*/
|
|
17906
18229
|
const onInstallSkill = useCallback(async (req) => {
|
|
17907
|
-
|
|
17908
|
-
|
|
17909
|
-
|
|
17910
|
-
|
|
17911
|
-
|
|
17912
|
-
|
|
17913
|
-
|
|
17914
|
-
|
|
17915
|
-
|
|
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
|
-
}
|
|
18230
|
+
const result = await installSkillFromSpec({
|
|
18231
|
+
source: req.source,
|
|
18232
|
+
scope: req.scope,
|
|
18233
|
+
cwd: cwdRef.current,
|
|
18234
|
+
prefix: config.prefix,
|
|
18235
|
+
...req.skill !== void 0 ? { skill: req.skill } : {},
|
|
18236
|
+
...req.all !== void 0 ? { all: req.all } : {},
|
|
18237
|
+
...req.skills !== void 0 ? { skills: req.skills } : {},
|
|
18238
|
+
...req.onProgress !== void 0 ? { onProgress: req.onProgress } : {}
|
|
18239
|
+
});
|
|
17921
18240
|
await onRefreshSkills();
|
|
17922
|
-
|
|
18241
|
+
const skippedNote = result.skipped?.length ? ` — skipped existing: ${result.skipped.join(", ")}` : "";
|
|
18242
|
+
const failedNote = result.failed?.length ? ` — ⚠ invalid: ${result.failed.join(", ")}` : "";
|
|
18243
|
+
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
18244
|
}, [config.prefix, onRefreshSkills]);
|
|
17924
18245
|
/**
|
|
17925
18246
|
* Persist a new MCP server (Settings → MCPs → ctrl+g form). Upserts
|
|
@@ -20498,7 +20819,7 @@ const BASE_LEVELS = [
|
|
|
20498
20819
|
},
|
|
20499
20820
|
{
|
|
20500
20821
|
id: "minimal",
|
|
20501
|
-
description: "tiny reasoning budget
|
|
20822
|
+
description: "tiny reasoning budget"
|
|
20502
20823
|
},
|
|
20503
20824
|
{
|
|
20504
20825
|
id: "low",
|
|
@@ -20514,16 +20835,16 @@ const BASE_LEVELS = [
|
|
|
20514
20835
|
},
|
|
20515
20836
|
{
|
|
20516
20837
|
id: "xhigh",
|
|
20517
|
-
description: "very deep reasoning
|
|
20838
|
+
description: "very deep reasoning"
|
|
20518
20839
|
},
|
|
20519
20840
|
{
|
|
20520
20841
|
id: "max",
|
|
20521
|
-
description: "maximum reasoning effort
|
|
20842
|
+
description: "maximum reasoning effort"
|
|
20522
20843
|
}
|
|
20523
20844
|
];
|
|
20524
20845
|
const ADAPTIVE_LEVEL = {
|
|
20525
20846
|
id: "adaptive",
|
|
20526
|
-
description: "model decides per-turn
|
|
20847
|
+
description: "model decides per-turn"
|
|
20527
20848
|
};
|
|
20528
20849
|
function EffortPickerModal({ current, supportsAdaptive, onPick }) {
|
|
20529
20850
|
const COLOR = useColors();
|