zidane 7.0.13 → 7.0.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{acp-bTPYx7Sd.js → acp-Bw2b_kka.js} +3 -3
- package/dist/{acp-bTPYx7Sd.js.map → acp-Bw2b_kka.js.map} +1 -1
- package/dist/acp-cli.js +4 -4
- package/dist/acp.d.ts +1 -1
- package/dist/acp.js +1 -1
- package/dist/{agent-DRNT6DbC.js → agent-B_uQo4f1.js} +650 -49
- package/dist/agent-B_uQo4f1.js.map +1 -0
- package/dist/agent.d.ts +1 -1
- package/dist/agent.js +1 -1
- package/dist/{anthropic-Da39cE-d.js → anthropic-QbHqqTkV.js} +2 -2
- package/dist/{anthropic-Da39cE-d.js.map → anthropic-QbHqqTkV.js.map} +1 -1
- package/dist/{approvals-Ch6gmO8H.js → approvals-B9aIQJRQ.js} +287 -45
- package/dist/approvals-B9aIQJRQ.js.map +1 -0
- package/dist/artifacts-CV2hUKnL.js +112 -0
- package/dist/artifacts-CV2hUKnL.js.map +1 -0
- package/dist/{auth-Ddk-rCdG.js → auth-plw6npda.js} +19 -7
- package/dist/auth-plw6npda.js.map +1 -0
- package/dist/chat/pure.d.ts +3 -3
- package/dist/chat/pure.js +1 -1
- package/dist/chat.d.ts +6 -6
- package/dist/chat.js +5 -5
- package/dist/contexts/daytona.d.ts +1 -1
- package/dist/contexts/e2b.d.ts +1 -1
- package/dist/daemon-cli.js +1 -1
- package/dist/eval.d.ts +1 -1
- package/dist/eval.js +1 -1
- package/dist/extensions.d.ts +2 -2
- package/dist/extensions.js +2 -2
- package/dist/headless.d.ts +1 -1
- package/dist/headless.js +2 -2
- package/dist/{index-DFGECPfm.d.ts → index-Dc_zYpEu.d.ts} +351 -2
- package/dist/index-Dc_zYpEu.d.ts.map +1 -0
- package/dist/{index-DP7xYXr9.d.ts → index-Df2CH6bn.d.ts} +92 -7
- package/dist/index-Df2CH6bn.d.ts.map +1 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +7 -6
- package/dist/{ipc-C8MCEu1E.js → ipc-T_pPnHkp.js} +2 -2
- package/dist/{ipc-C8MCEu1E.js.map → ipc-T_pPnHkp.js.map} +1 -1
- package/dist/ipc.d.ts +54 -6
- package/dist/ipc.d.ts.map +1 -1
- package/dist/ipc.js +3 -3
- package/dist/mcp.d.ts +1 -1
- package/dist/{oauth-C4GvY_p1.js → oauth-EIBUuSDK.js} +2 -2
- package/dist/{oauth-C4GvY_p1.js.map → oauth-EIBUuSDK.js.map} +1 -1
- package/dist/output/stream-json.d.ts +1 -1
- package/dist/output/terminal.d.ts +1 -1
- package/dist/plugins.d.ts +1 -1
- package/dist/presets.d.ts +2 -2
- package/dist/presets.js +2 -2
- package/dist/providers/anthropic.d.ts +1 -1
- package/dist/providers/anthropic.js +1 -1
- package/dist/providers/arcee.d.ts +1 -1
- package/dist/providers/baseten.d.ts +1 -1
- package/dist/providers/cerebras.d.ts +1 -1
- package/dist/providers/local.d.ts +1 -1
- package/dist/providers/openai-compat.d.ts +1 -1
- package/dist/providers/openai.d.ts +1 -1
- package/dist/providers/openai.js +1 -1
- package/dist/providers/openrouter.d.ts +1 -1
- package/dist/providers/xai.d.ts +1 -1
- package/dist/providers/xai.js +2 -2
- package/dist/{providers-BYgyPb15.js → providers-CoK1rZ1p.js} +2 -2
- package/dist/{providers-BYgyPb15.js.map → providers-CoK1rZ1p.js.map} +1 -1
- package/dist/providers.d.ts +1 -1
- package/dist/providers.js +3 -3
- package/dist/restate.d.ts +1 -1
- package/dist/restate.js +1 -1
- package/dist/{server-CGmy4363.js → server-DXM8ZbGi.js} +64 -6
- package/dist/server-DXM8ZbGi.js.map +1 -0
- package/dist/session/sqlite.d.ts +1 -1
- package/dist/session/sqlite.d.ts.map +1 -1
- package/dist/session/sqlite.js +117 -1
- package/dist/session/sqlite.js.map +1 -1
- package/dist/{session-K3icbPH9.js → session-DPZnncaQ.js} +60 -1
- package/dist/session-DPZnncaQ.js.map +1 -0
- package/dist/session.d.ts +2 -2
- package/dist/session.js +3 -2
- package/dist/skills.d.ts +1 -1
- package/dist/{tool-formatters-C-s_-u0v.d.ts → tool-formatters-BgdOYAy9.d.ts} +2 -2
- package/dist/{tool-formatters-C-s_-u0v.d.ts.map → tool-formatters-BgdOYAy9.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 +2 -2
- package/dist/tools.js +2 -2
- package/dist/{transcript-anchors-D1ToF-EW.d.ts → transcript-anchors-CtnwuQJM.d.ts} +3 -3
- package/dist/transcript-anchors-CtnwuQJM.d.ts.map +1 -0
- package/dist/tui.d.ts +3 -3
- package/dist/tui.d.ts.map +1 -1
- package/dist/tui.js +576 -102
- package/dist/tui.js.map +1 -1
- package/dist/{turn-operations-CZLsNgw-.js → turn-operations-DkJ1R0p8.js} +4 -3
- package/dist/turn-operations-DkJ1R0p8.js.map +1 -0
- package/dist/{turn-operations-Bp5-BAki.d.ts → turn-operations-khAvr7KJ.d.ts} +5 -3
- package/dist/turn-operations-khAvr7KJ.d.ts.map +1 -0
- package/dist/types.d.ts +1 -1
- package/dist/{xai-DILdFGzN.js → xai-CazjStOK.js} +3 -3
- package/dist/{xai-DILdFGzN.js.map → xai-CazjStOK.js.map} +1 -1
- package/docs/EXTENSIONS.md +58 -0
- package/docs/IPC.md +9 -0
- package/docs/TUI.md +2 -0
- package/package.json +1 -1
- package/dist/agent-DRNT6DbC.js.map +0 -1
- package/dist/approvals-Ch6gmO8H.js.map +0 -1
- package/dist/auth-Ddk-rCdG.js.map +0 -1
- package/dist/index-DFGECPfm.d.ts.map +0 -1
- package/dist/index-DP7xYXr9.d.ts.map +0 -1
- package/dist/server-CGmy4363.js.map +0 -1
- package/dist/session-K3icbPH9.js.map +0 -1
- package/dist/transcript-anchors-D1ToF-EW.d.ts.map +0 -1
- package/dist/turn-operations-Bp5-BAki.d.ts.map +0 -1
- package/dist/turn-operations-CZLsNgw-.js.map +0 -1
package/dist/tui.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { C as estimateRebilledCostUsd } from "./openai-compat-DY-AKxCg.js";
|
|
2
2
|
import { t as buildContextSegments } from "./context-segments-CJCtJ9sU.js";
|
|
3
|
-
import { $ as installExtensionFromSpec,
|
|
3
|
+
import { $ as installExtensionFromSpec, A as selectFilesFromSession, C as resolveLegacySessionDir, Cn as createDebugLog, D as resolveTasksDir, Dn as coerceExtensionConfigInput, Dt as isSpawnTool, E as resolveSessionDir, Fn as createExtensionBus, Ft as tailTruncate, G as summaryToTurn, Jn as OUTPUT_RESERVE_TOKENS, Jt as artifacts_default, Lt as looksBinary, M as compactConversation, Mn as sanitizeExtensionConfigActionPatch, O as buildPostCompactAttachments, Rn as artifactKindLabel, S as resolveLegacyPersistDir, Sn as scanExtensionDirectories, T as resolvePersistDir, Un as refreshArtifact, Wn as renderArtifactRow, X as createExtensionPromptBridge, Yn as effectiveContextWindow, Z as ExtensionInstallError, an as matchesBinding, at as createExtensionHud, dt as filterExtensionRegistry, en as KEYBINDING_KEY_COL_WIDTH, f as applyCompactSummaryCutoff, ft as filterRegistryPlugins, gt as createExtensionHostRuntimeBridge, hn as registerExtensionHostModules, in as keybindingsPath, it as updateInstalledExtension, jn as resolveExtensionConfigValue, lt as composeExtensionPreset, mt as partitionExtensionCatalog, nn as formatBindingForDisplay, ot as discoverAndBuildExtensionRegistry, rn as groupBindings, rt as removeInstalledExtension, t as createAgent, tn as ensureKeybindingsFile, un as resolveExtensionKeybindings, ut as disposeExtensionRegistry, v as cleanupPersistedSession, vt as composePresets, w as resolveMcpWarningsDir, wn as setDebugLogSink, x as rehomePersistedStubs, xn as parseExtensionScanPathEnv, xt as basic_default, yn as inlineLoadedExtension, zt as createModelSearchTool } from "./agent-B_uQo4f1.js";
|
|
4
4
|
import { D as shouldAutoGenerateTitle, E as generateSessionTitle, F as parseCommandInvocation, M as commandBlocksToContent, P as executeCommand, S as resolveInlineSuggestion, a as loginMcpServer, b as createPathAutocompleteProvider, c as SKILL_EDIT_METADATA_KEY, g as readSkillEditMarker, h as extensionScaffold, j as commandBlockToEvent, l as ZIDANE_EXTENSION_SKILL_NAME, m as extensionDirForCwd, p as editSessionMetadata, u as ZIDANE_SKILL_EDIT_SKILL_NAME, v as withZidaneExtensionSkill, w as generateStructuredData, x as patchInlineGhost, y as withZidaneSkillEditSkill } from "./src-DzzhE2YO.js";
|
|
5
5
|
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";
|
|
6
6
|
import { n as appendCapped } from "./output-cap-C9zukcCj.js";
|
|
@@ -12,17 +12,17 @@ import { a as createRingBufferSink, c as logFileTimestamp, i as createLoggingHoo
|
|
|
12
12
|
import { i as sniffImageMediaType } from "./media-sniff-UKijEaiQ.js";
|
|
13
13
|
import { _ as hasAuthorizationHeader, h as McpOAuthProvider, n as connectMcpServers, s as nonOwningMcpView } from "./mcp-BIWa57eY.js";
|
|
14
14
|
import { replaceDynamicSection, splitSystemPrompt } from "./prompt.js";
|
|
15
|
-
import { a as getExtensionSessionState, c as setExtensionSessionState, i as demoteStaleRunningStatus, o as loadSession, t as createSession } from "./session-
|
|
15
|
+
import { a as getExtensionSessionState, c as setExtensionSessionState, i as demoteStaleRunningStatus, o as loadSession, t as createSession } from "./session-DPZnncaQ.js";
|
|
16
16
|
import { t as effectiveInputFromTurn } from "./stats-DAKBEKjc.js";
|
|
17
17
|
import { s as withTimeout } from "./timeout-CjOG2mea.js";
|
|
18
18
|
import { i as installCacheBreakLogger } from "./cache-telemetry-ehVdWsg2.js";
|
|
19
19
|
import { s as resolveCompletionSubmit } from "./completion-core-BRo86R_L.js";
|
|
20
20
|
import { n as JsonRpcRemoteError, t as JsonRpcConnectionClosedError } from "./json-rpc-rSWMUh9b.js";
|
|
21
|
-
import { $t as hasRunReceipt, A as chunkMarkdownForRender, At as SESSION_EVENT_STATUS_STYLE, B as DAEMON_HEALTH_STYLE, Bt as sessionEventExcerpt, C as usageTone, Cn as createChatsCompletionProvider, Ct as selectableTurnIds, E as filterModelCatalog, Et as turnSelectionOwnership, F as stripHtmlCommentsOutsideCode, Ht as sessionEventMeta, I as cacheBreakChip, K as filterChainFallbacks, Kt as fitRunReceiptCells, L as compactingLabel, M as codeTokenHasClosingFence, N as normalizeMarkdownCodeFences, O as parseCustomModelQuery, P as splitMarkdownCodeBlocks, Pt as isMainSession, Q as restoreChainFallbacks, S as resetLabel, St as retagUserPromptEventsFromRefs, T as buildModelCatalog, Tt as streamEventSearchText, U as chainPositionOf, Ut as shortSessionId, V as buildRunModel, W as chainsEqual, Wt as truncateTitle, X as providerKeySetChanged, Xt as formatRunReceiptLine, Yt as formatRunReceiptCells, Z as reorderKeyed, Zt as formatTokenCount, _ as turnContextSize, _n as resolveApprovalForPayload, _t as isVisible, a as TOOL_DISPLAY, b as formatUsagePercent, bn as summarizeOutcomes, cn as filetypeFromPath, d as finalizeStreamingMarkdown, dn as summarizeEditPayload, dt as buildLinearRamp, en as runReceiptFromRun, et as toggleChainEntry, f as finalizeStreamingMarkdownForOwner, ft as BASH_CALL_ID_PREFIX, g as revealEarlierTranscriptEvents, gn as parseEditOutcomesFromResult, gt as isUserBashEvent, h as replaceTranscriptTurnEvents, hn as mergeApprovalAndBodyOutcomes, ht as isTurnHighlighted, i as turnAsText, in as clipDiffForRender, it as uniqueSkillNamesFromReferences, j as closeDanglingCodeFence, ln as previewEditPayload, lt as createCommandsCompletionProvider, mt as isEditErrorResult, n as deleteTurnSafely, nn as buildContextualDiff, o as displayNameFor, ot as createFilesCompletionProvider, p as hiddenEarlierTranscriptCount, pn as buildEditOutcomesAnnotation, pt as EDIT_TOOL_NAMES, q as pickChainPrimary, qt as formatCostUsd, r as truncateTurnsAt, rn as buildUnifiedDiff, rt as createSkillsCompletionProvider, s as formatToolCall, sn as extractEditPayload, u as capTranscriptEvents, ut as blendHsl, v as formatBalance, vn as rewriteMultiEditHeader, vt as isVisibleDuringSearch, w as splitPromptSegments, wt as selectionAfterTurnRemoval, x as mostConstrainedWindow, xt as retagUserPromptEvents, yn as stripEditOutcomesAnnotation, yt as promptHistoryFromEvents, zt as sessionDirLabel } from "./turn-operations-
|
|
21
|
+
import { $t as hasRunReceipt, A as chunkMarkdownForRender, At as SESSION_EVENT_STATUS_STYLE, B as DAEMON_HEALTH_STYLE, Bt as sessionEventExcerpt, C as usageTone, Cn as createChatsCompletionProvider, Ct as selectableTurnIds, E as filterModelCatalog, Et as turnSelectionOwnership, F as stripHtmlCommentsOutsideCode, Ht as sessionEventMeta, I as cacheBreakChip, K as filterChainFallbacks, Kt as fitRunReceiptCells, L as compactingLabel, M as codeTokenHasClosingFence, N as normalizeMarkdownCodeFences, O as parseCustomModelQuery, P as splitMarkdownCodeBlocks, Pt as isMainSession, Q as restoreChainFallbacks, S as resetLabel, St as retagUserPromptEventsFromRefs, T as buildModelCatalog, Tt as streamEventSearchText, U as chainPositionOf, Ut as shortSessionId, V as buildRunModel, W as chainsEqual, Wt as truncateTitle, X as providerKeySetChanged, Xt as formatRunReceiptLine, Yt as formatRunReceiptCells, Z as reorderKeyed, Zt as formatTokenCount, _ as turnContextSize, _n as resolveApprovalForPayload, _t as isVisible, a as TOOL_DISPLAY, b as formatUsagePercent, bn as summarizeOutcomes, cn as filetypeFromPath, d as finalizeStreamingMarkdown, dn as summarizeEditPayload, dt as buildLinearRamp, en as runReceiptFromRun, et as toggleChainEntry, f as finalizeStreamingMarkdownForOwner, ft as BASH_CALL_ID_PREFIX, g as revealEarlierTranscriptEvents, gn as parseEditOutcomesFromResult, gt as isUserBashEvent, h as replaceTranscriptTurnEvents, hn as mergeApprovalAndBodyOutcomes, ht as isTurnHighlighted, i as turnAsText, in as clipDiffForRender, it as uniqueSkillNamesFromReferences, j as closeDanglingCodeFence, ln as previewEditPayload, lt as createCommandsCompletionProvider, mt as isEditErrorResult, n as deleteTurnSafely, nn as buildContextualDiff, o as displayNameFor, ot as createFilesCompletionProvider, p as hiddenEarlierTranscriptCount, pn as buildEditOutcomesAnnotation, pt as EDIT_TOOL_NAMES, q as pickChainPrimary, qt as formatCostUsd, r as truncateTurnsAt, rn as buildUnifiedDiff, rt as createSkillsCompletionProvider, s as formatToolCall, sn as extractEditPayload, u as capTranscriptEvents, ut as blendHsl, v as formatBalance, vn as rewriteMultiEditHeader, vt as isVisibleDuringSearch, w as splitPromptSegments, wt as selectionAfterTurnRemoval, x as mostConstrainedWindow, xt as retagUserPromptEvents, yn as stripEditOutcomesAnnotation, yt as promptHistoryFromEvents, zt as sessionDirLabel } from "./turn-operations-DkJ1R0p8.js";
|
|
22
22
|
import { a as searchHighlightRanges, c as searchSessionHistoryIndexAsync, i as highlightSegments, n as buildSessionSearchIndexAsync, r as filterSessionSearchCatalog, u as searchSessionIndexAsync } from "./history-search-C4bk1Wz_.js";
|
|
23
|
-
import { $ as supportsOAuth, $n as
|
|
24
|
-
import { E as renderDefaultCallbackPage, T as restoreModelOptions, b as modelSupportsReasoning, c as setPreferredCredential, g as getContextWindow, h as enabledModelOptions, l as setProviderCredential, n as applyApiKeyEnv, t as detectAuth, w as piIdOf, y as modelOptionsFor } from "./auth-
|
|
25
|
-
import { a as connectIpcClient, d as defaultSocketPath, m as selfDaemonSpawnCommand, o as connectOrSpawnDaemon, p as probeSocket } from "./server-
|
|
23
|
+
import { $ as supportsOAuth, $n as tryOpenBrowser, A as useSafeModeQueue, An as createDiscoverySlot, At as makeRequestInteraction, Ci as sumRunCosts, Ct as InteractionsProvider, Di as updateToolEventOutcomes, Dr as accentColor, Dt as createInteractionTools, Ei as toolResultText, Et as createAutomaticInteractionResponse, Fn as useConfig, G as usageChecksOptedOut, Gn as mcpsWritePath, Gr as setTodosForRun, H as fetchAllProviderUsage, Hn as countClaudeSessionFiles, Hr as pruneTodosByRun, In as resolveConfig, Ir as applyTodosSnapshot, J as fetchOAuthRedirect, Jn as buildMcpServers, Jt as buildPluginContributions, Kn as removeMcpServer, Kr as todoProgressLabel, Ln as resolveStoragePaths, M as addToSafelist, Mn as useDiscovery, N as getSafelist, Nn as useDiscoveryOptional, Nt as useInteractionsActions, O as SafeModeProvider, Oi as usageByModel, On as parseEditorCommand, P as isOnSafelist, Pn as ConfigProvider, Pr as TODO_STATUS_GLYPHS, Pt as useInteractionsQueue, Q as runOAuthLogin, R as suggestSafelistEntries, Si as stripSpawnTokensLine, St as HOST_INTERACTION_ID_PREFIX, Ti as toolCallPreview, Tt as buildResumedToolResultsTurn, U as fetchProviderUsage, Un as hasClaudeCodeSetup, Ut as createBuiltinCommands, V as clearProviderUsageCache, Vn as useCompletion, Vr as pickActiveRunId, W as providerUsageSupported, Wn as importFromClaudeCode, Wr as selectActiveTodos, Wt as createMainSession, X as redirectUriFromAuthUrl, Xt as parsePluginScanPathEnv, Yn as dedupMcpServersByName, Yt as discoverProjectPlugins, Z as oauthUsesManualCodePaste, Zn as discoverProjectMcps, Zt as attachMcpWarnLog, _ as buildSpawnEndEvent, _i as loadState, _r as groupArtifacts, _t as useMcpAuthState, ai as buildPlanSystem, at as subscribeMcpToolsCache, b as defaultSkillScanPaths, bn as resolveTheme, bt as ASK_USER_TOOL, c as useSelectStyle, ci as createChatTurnsReadTool, cn as DEFAULT_SETTINGS, d as useTheme, dn as SETTINGS_INPUTS, dt as parentServerName, en as EMPTY_HINTS, f as discoverSystemMd, fi as deriveSessionTitle, fn as SETTINGS_TOGGLES, ft as createFileMcpCredentialStore, g as useStreamBuffer, gi as listSessionMeta, gn as useSettings, gt as useMcpAuthDispatch, h as userSystemMdPath, hi as lastContextSizeFromTurns, hr as chatAutoCompactBehavior, ht as McpAuthProvider, ii as buildBuildSystem, in as buildHints, jn as DiscoveryProvider, jt as pendingInteractionsFromTurns, k as useSafeModeActions, kn as quoteForShell, kt as isModelInteraction, l as useSurfaces, ln as SETTINGS_CATEGORIES, lt as buildVisibleMcpRows, m as userScopeOverridesLoad, mi as getSessionMeta, mn as clampFps, nn as hintsLength, nr as buildUpdateHint, nt as mcpToolsCachePath, o as ThemeProvider, oi as envSection, on as listProjectFiles, p as renderSystemMdSeed, pi as eventsFromTurns, pn as SettingsProvider, q as formatPathForCwd, qn as upsertMcpServer, qr as useActiveTodos, qt as runEndNotice, r as computeTurnAnchors, rn as truncateTrailing, rr as useUpdateCheck, rt as refreshMcpToolsCatalog, s as useColors, si as chatReferenceTokensForPrompt, sn as useEnabledToggleSet, st as useMcpToolToggleMap, tn as clipHintsToWidth, tr as bootTick, tt as loadMcpToolsCache, ui as compactSummaryEvent, un as SETTINGS_CHOICES, ut as indexOfServerRow, v as buildSpawnStartEvent, vi as marginTopFor, vt as getMcpAuthStatus, w as writeSessionExport, wt as PRESENT_PLAN_TOOL, x as discoverProjectSkills, xi as serverToolResultSummary, y as buildSkillsConfig, yi as noticeTurnContent, yn as resolveChipColor, yr as discoverAgentsMd, zn as createArtifactsCompletionProvider } from "./approvals-B9aIQJRQ.js";
|
|
24
|
+
import { E as renderDefaultCallbackPage, T as restoreModelOptions, b as modelSupportsReasoning, c as setPreferredCredential, g as getContextWindow, h as enabledModelOptions, l as setProviderCredential, n as applyApiKeyEnv, t as detectAuth, w as piIdOf, y as modelOptionsFor } from "./auth-plw6npda.js";
|
|
25
|
+
import { a as connectIpcClient, d as defaultSocketPath, m as selfDaemonSpawnCommand, o as connectOrSpawnDaemon, p as probeSocket } from "./server-DXM8ZbGi.js";
|
|
26
26
|
import { createDockerContext } from "./contexts/docker.js";
|
|
27
27
|
import { createTuiStore } from "./session/sqlite.js";
|
|
28
28
|
import { _ as buildVisibleAuthRows, a as editTodo, b as parentProviderKey, c as NOTICE_GLYPH, f as validateMcpForm, g as instructionPreviewLines, h as instructionOriginBadge, i as cycleTodoStatus, l as MCP_TRANSPORTS, m as buildVisibleInstructionRows, n as buildTodoRetryMessage, r as clearTodos, s as removeTodo, t as addTodo, v as indexOfProviderRow, x as selectableSources } from "./todo-edits-Dw2oO2ON.js";
|
|
@@ -516,7 +516,7 @@ function AgentPickerModal({ agents, currentAgentId, onPick }) {
|
|
|
516
516
|
children: [
|
|
517
517
|
currentMissing && /* @__PURE__ */ jsx$1("text", {
|
|
518
518
|
fg: COLOR.warn,
|
|
519
|
-
children: `Current agent "${currentAgentId}" is not in this registry
|
|
519
|
+
children: `Current agent "${currentAgentId}" is not in this registry. Pick one below.`
|
|
520
520
|
}),
|
|
521
521
|
/* @__PURE__ */ jsx$1("select", {
|
|
522
522
|
...SELECT_THEME,
|
|
@@ -572,6 +572,291 @@ function EmptyState$1() {
|
|
|
572
572
|
})]
|
|
573
573
|
});
|
|
574
574
|
}
|
|
575
|
+
//#endregion
|
|
576
|
+
//#region src/tui/artifacts-modal.tsx
|
|
577
|
+
const MIN_MODAL_HEIGHT$1 = 12;
|
|
578
|
+
const MAX_MODAL_HEIGHT$2 = 40;
|
|
579
|
+
function ArtifactsModal({ load, subscribe, registry, initialScope = "session", projectRoot, onOpen, onCopy, onJump, sessionTitle, onDelete, onRefresh }) {
|
|
580
|
+
const COLOR = useColors();
|
|
581
|
+
const SURFACE = useSurfaces();
|
|
582
|
+
const modal = useModal();
|
|
583
|
+
const { height: termHeight } = useTerminalDimensions();
|
|
584
|
+
const [scope, setScope] = useState(initialScope);
|
|
585
|
+
const [artifacts, setArtifacts] = useState(null);
|
|
586
|
+
const [cursorRaw, setCursorRaw] = useState(0);
|
|
587
|
+
const scrollRef = useRef(null);
|
|
588
|
+
const generation = useRef(0);
|
|
589
|
+
const refresh = useCallback(() => {
|
|
590
|
+
const gen = ++generation.current;
|
|
591
|
+
load(scope).then((rows) => {
|
|
592
|
+
if (gen === generation.current) setArtifacts(rows);
|
|
593
|
+
}).catch(() => {
|
|
594
|
+
if (gen === generation.current) setArtifacts([]);
|
|
595
|
+
});
|
|
596
|
+
}, [load, scope]);
|
|
597
|
+
useEffect(() => {
|
|
598
|
+
refresh();
|
|
599
|
+
}, [refresh]);
|
|
600
|
+
useEffect(() => subscribe?.(refresh), [subscribe, refresh]);
|
|
601
|
+
const groups = useMemo(() => groupArtifacts(artifacts ?? [], registry), [artifacts, registry]);
|
|
602
|
+
const flat = useMemo(() => groups.flatMap((g) => g.rows), [groups]);
|
|
603
|
+
const total = flat.length;
|
|
604
|
+
const focused = flat[total === 0 ? 0 : Math.min(cursorRaw, total - 1)] ?? null;
|
|
605
|
+
useEffect(() => {
|
|
606
|
+
if (!focused) return;
|
|
607
|
+
const sb = scrollRef.current;
|
|
608
|
+
if (!sb) return;
|
|
609
|
+
const handle = requestAnimationFrame(() => sb.scrollChildIntoView(`artifact-row-${focused.artifact.id}`));
|
|
610
|
+
return () => cancelAnimationFrame(handle);
|
|
611
|
+
}, [focused]);
|
|
612
|
+
const refreshedRef = useRef(/* @__PURE__ */ new Set());
|
|
613
|
+
useEffect(() => {
|
|
614
|
+
if (!focused || !onRefresh || refreshedRef.current.has(focused.artifact.id)) return;
|
|
615
|
+
refreshedRef.current.add(focused.artifact.id);
|
|
616
|
+
const id = focused.artifact.id;
|
|
617
|
+
onRefresh(focused.artifact).then((updated) => {
|
|
618
|
+
if (!updated) return;
|
|
619
|
+
setArtifacts((current) => current?.map((a) => a.id === id ? updated : a) ?? current);
|
|
620
|
+
}).catch(() => {});
|
|
621
|
+
}, [focused, onRefresh]);
|
|
622
|
+
const canToggleScope = projectRoot !== void 0;
|
|
623
|
+
const detail = useMemo(() => {
|
|
624
|
+
if (!focused || !registry) return void 0;
|
|
625
|
+
return registry.tuiContributions.artifactRenderers.find((r) => r.kind === focused.artifact.kind);
|
|
626
|
+
}, [focused, registry]);
|
|
627
|
+
useKeyboard((key) => {
|
|
628
|
+
if (key.name === "up") {
|
|
629
|
+
setCursorRaw((c) => Math.max(0, c - 1));
|
|
630
|
+
return;
|
|
631
|
+
}
|
|
632
|
+
if (key.name === "down") {
|
|
633
|
+
setCursorRaw((c) => Math.min(Math.max(0, total - 1), c + 1));
|
|
634
|
+
return;
|
|
635
|
+
}
|
|
636
|
+
if (key.name === "tab" && canToggleScope) {
|
|
637
|
+
setCursorRaw(0);
|
|
638
|
+
setScope((s) => s === "session" ? "project" : "session");
|
|
639
|
+
return;
|
|
640
|
+
}
|
|
641
|
+
if (key.name === "return") {
|
|
642
|
+
if (focused?.row.href && onOpen) onOpen(focused.row.href, focused.artifact);
|
|
643
|
+
return;
|
|
644
|
+
}
|
|
645
|
+
if (key.name === "c") {
|
|
646
|
+
if (focused && onCopy) onCopy(focused.row.href ?? focused.artifact.uri);
|
|
647
|
+
return;
|
|
648
|
+
}
|
|
649
|
+
if (key.name === "j") {
|
|
650
|
+
if (focused && onJump && scope === "session" && focused.artifact.turnId) {
|
|
651
|
+
onJump(focused.artifact);
|
|
652
|
+
modal.close();
|
|
653
|
+
}
|
|
654
|
+
return;
|
|
655
|
+
}
|
|
656
|
+
if (key.name === "d") {
|
|
657
|
+
if (!focused || !onDelete) return;
|
|
658
|
+
const id = focused.artifact.id;
|
|
659
|
+
setArtifacts((current) => current?.filter((a) => a.id !== id) ?? current);
|
|
660
|
+
onDelete(focused.artifact).catch(() => refresh());
|
|
661
|
+
}
|
|
662
|
+
});
|
|
663
|
+
const idealHeight = Math.floor((termHeight - 4) * .7);
|
|
664
|
+
const maxHeight = Math.max(MIN_MODAL_HEIGHT$1, Math.min(MAX_MODAL_HEIGHT$2, idealHeight));
|
|
665
|
+
return /* @__PURE__ */ jsxs(Modal, {
|
|
666
|
+
title: scope === "project" ? "artifacts · project" : "artifacts · this session",
|
|
667
|
+
bottomTitle: total > 0 ? `${total} artifact${total === 1 ? "" : "s"} · esc close` : "esc close",
|
|
668
|
+
rightTitle: groups.length > 0 ? /* @__PURE__ */ jsx$1(CountsBadge$2, { groups }) : null,
|
|
669
|
+
maxWidth: 110,
|
|
670
|
+
minWidth: 60,
|
|
671
|
+
maxHeight,
|
|
672
|
+
children: [
|
|
673
|
+
artifacts === null ? /* @__PURE__ */ jsx$1("text", { children: /* @__PURE__ */ jsx$1("span", {
|
|
674
|
+
fg: COLOR.mute,
|
|
675
|
+
children: "loading…"
|
|
676
|
+
}) }) : total === 0 ? /* @__PURE__ */ jsx$1("text", {
|
|
677
|
+
wrapMode: "word",
|
|
678
|
+
children: /* @__PURE__ */ jsx$1("span", {
|
|
679
|
+
fg: COLOR.mute,
|
|
680
|
+
children: scope === "project" ? `no artifacts recorded for ${projectRoot ?? "this project"} yet` : "no artifacts yet. Pull requests, branches, commits and created files appear here as the agent produces them"
|
|
681
|
+
})
|
|
682
|
+
}) : /* @__PURE__ */ jsx$1("box", {
|
|
683
|
+
style: {
|
|
684
|
+
flexDirection: "column",
|
|
685
|
+
flexGrow: 1,
|
|
686
|
+
flexShrink: 1,
|
|
687
|
+
overflow: "hidden"
|
|
688
|
+
},
|
|
689
|
+
children: /* @__PURE__ */ jsx$1("scrollbox", {
|
|
690
|
+
ref: scrollRef,
|
|
691
|
+
focusable: false,
|
|
692
|
+
stickyScroll: false,
|
|
693
|
+
style: {
|
|
694
|
+
flexGrow: 1,
|
|
695
|
+
flexShrink: 1
|
|
696
|
+
},
|
|
697
|
+
children: groups.map((group) => /* @__PURE__ */ jsxs("box", {
|
|
698
|
+
style: {
|
|
699
|
+
flexDirection: "column",
|
|
700
|
+
flexShrink: 0
|
|
701
|
+
},
|
|
702
|
+
children: [/* @__PURE__ */ jsx$1("text", {
|
|
703
|
+
wrapMode: "none",
|
|
704
|
+
children: /* @__PURE__ */ jsx$1("span", {
|
|
705
|
+
fg: COLOR.brand,
|
|
706
|
+
children: group.rows.length === 1 ? group.label : `${group.label}s`
|
|
707
|
+
})
|
|
708
|
+
}), group.rows.map((row) => {
|
|
709
|
+
return /* @__PURE__ */ jsx$1(ArtifactRow, {
|
|
710
|
+
row,
|
|
711
|
+
focused: focused?.artifact.id === row.artifact.id,
|
|
712
|
+
showSession: scope === "project",
|
|
713
|
+
sessionTitle,
|
|
714
|
+
onClick: () => setCursorRaw(flat.indexOf(row))
|
|
715
|
+
}, row.artifact.id);
|
|
716
|
+
})]
|
|
717
|
+
}, group.kind))
|
|
718
|
+
})
|
|
719
|
+
}),
|
|
720
|
+
focused && detail && /* @__PURE__ */ jsx$1("box", {
|
|
721
|
+
style: {
|
|
722
|
+
flexShrink: 0,
|
|
723
|
+
flexDirection: "column",
|
|
724
|
+
paddingTop: 1,
|
|
725
|
+
backgroundColor: SURFACE.selection
|
|
726
|
+
},
|
|
727
|
+
children: /* @__PURE__ */ jsx$1(DetailBoundary, {
|
|
728
|
+
resetKey: `${detail.owner}:${focused.artifact.id}`,
|
|
729
|
+
fallback: null,
|
|
730
|
+
children: detail.renderDetail(focused.artifact)
|
|
731
|
+
})
|
|
732
|
+
}),
|
|
733
|
+
/* @__PURE__ */ jsx$1("box", {
|
|
734
|
+
style: {
|
|
735
|
+
flexShrink: 0,
|
|
736
|
+
flexDirection: "column",
|
|
737
|
+
paddingTop: 1
|
|
738
|
+
},
|
|
739
|
+
children: /* @__PURE__ */ jsx$1(ModalHints, { hints: [
|
|
740
|
+
total > 0 && focused?.row.href !== void 0 && onOpen !== void 0 && {
|
|
741
|
+
key: "↵",
|
|
742
|
+
label: "open"
|
|
743
|
+
},
|
|
744
|
+
canToggleScope && {
|
|
745
|
+
key: "tab",
|
|
746
|
+
label: scope === "session" ? "project" : "session"
|
|
747
|
+
},
|
|
748
|
+
total > 0 && onCopy !== void 0 && {
|
|
749
|
+
key: "c",
|
|
750
|
+
label: "copy"
|
|
751
|
+
},
|
|
752
|
+
total > 0 && onJump !== void 0 && scope === "session" && focused?.artifact.turnId !== void 0 && {
|
|
753
|
+
key: "j",
|
|
754
|
+
label: "jump"
|
|
755
|
+
},
|
|
756
|
+
total > 0 && onDelete !== void 0 && {
|
|
757
|
+
key: "d",
|
|
758
|
+
label: "remove"
|
|
759
|
+
}
|
|
760
|
+
] })
|
|
761
|
+
})
|
|
762
|
+
]
|
|
763
|
+
});
|
|
764
|
+
}
|
|
765
|
+
function ArtifactRow({ row, focused, showSession, sessionTitle, onClick }) {
|
|
766
|
+
const COLOR = useColors();
|
|
767
|
+
const { artifact, row: view } = row;
|
|
768
|
+
const session = showSession ? sessionTitle?.(artifact.sessionId) ?? artifact.sessionId.slice(0, 8) : void 0;
|
|
769
|
+
return /* @__PURE__ */ jsxs("box", {
|
|
770
|
+
id: `artifact-row-${artifact.id}`,
|
|
771
|
+
onMouseDown: (event) => {
|
|
772
|
+
event.stopPropagation();
|
|
773
|
+
event.preventDefault();
|
|
774
|
+
onClick();
|
|
775
|
+
},
|
|
776
|
+
style: {
|
|
777
|
+
flexShrink: 0,
|
|
778
|
+
flexDirection: "column"
|
|
779
|
+
},
|
|
780
|
+
children: [/* @__PURE__ */ jsxs("text", {
|
|
781
|
+
wrapMode: "none",
|
|
782
|
+
children: [
|
|
783
|
+
/* @__PURE__ */ jsx$1("span", {
|
|
784
|
+
fg: focused ? COLOR.brand : COLOR.mute,
|
|
785
|
+
children: focused ? "▶ " : " "
|
|
786
|
+
}),
|
|
787
|
+
/* @__PURE__ */ jsx$1("span", {
|
|
788
|
+
fg: focused ? COLOR.brand : COLOR.dim,
|
|
789
|
+
children: view.title
|
|
790
|
+
}),
|
|
791
|
+
view.status && /* @__PURE__ */ jsx$1("span", {
|
|
792
|
+
fg: COLOR.warn,
|
|
793
|
+
children: ` ${view.status}`
|
|
794
|
+
}),
|
|
795
|
+
session && /* @__PURE__ */ jsx$1("span", {
|
|
796
|
+
fg: COLOR.mute,
|
|
797
|
+
children: ` · ${session}`
|
|
798
|
+
})
|
|
799
|
+
]
|
|
800
|
+
}), view.subtitle && view.subtitle !== view.title && /* @__PURE__ */ jsx$1("box", {
|
|
801
|
+
style: {
|
|
802
|
+
flexShrink: 0,
|
|
803
|
+
paddingLeft: 4
|
|
804
|
+
},
|
|
805
|
+
children: /* @__PURE__ */ jsx$1("text", {
|
|
806
|
+
wrapMode: "none",
|
|
807
|
+
fg: COLOR.mute,
|
|
808
|
+
children: view.subtitle
|
|
809
|
+
})
|
|
810
|
+
})]
|
|
811
|
+
});
|
|
812
|
+
}
|
|
813
|
+
function CountsBadge$2({ groups }) {
|
|
814
|
+
const COLOR = useColors();
|
|
815
|
+
return /* @__PURE__ */ jsxs("text", {
|
|
816
|
+
wrapMode: "none",
|
|
817
|
+
children: [
|
|
818
|
+
/* @__PURE__ */ jsx$1("span", {
|
|
819
|
+
fg: COLOR.mute,
|
|
820
|
+
children: " "
|
|
821
|
+
}),
|
|
822
|
+
groups.map((g, i) => /* @__PURE__ */ jsxs("span", { children: [
|
|
823
|
+
i > 0 && /* @__PURE__ */ jsx$1("span", {
|
|
824
|
+
fg: COLOR.mute,
|
|
825
|
+
children: " · "
|
|
826
|
+
}),
|
|
827
|
+
/* @__PURE__ */ jsx$1("span", {
|
|
828
|
+
fg: COLOR.accent,
|
|
829
|
+
children: String(g.rows.length)
|
|
830
|
+
}),
|
|
831
|
+
/* @__PURE__ */ jsx$1("span", {
|
|
832
|
+
fg: COLOR.mute,
|
|
833
|
+
children: ` ${g.rows.length === 1 ? g.label.toLowerCase() : `${g.label.toLowerCase()}s`}`
|
|
834
|
+
})
|
|
835
|
+
] }, g.kind)),
|
|
836
|
+
/* @__PURE__ */ jsx$1("span", {
|
|
837
|
+
fg: COLOR.mute,
|
|
838
|
+
children: " "
|
|
839
|
+
})
|
|
840
|
+
]
|
|
841
|
+
});
|
|
842
|
+
}
|
|
843
|
+
/**
|
|
844
|
+
* A throwing `renderDetail` degrades to nothing — the row above already
|
|
845
|
+
* carries the guaranteed fallback presentation. Re-arms when the focused
|
|
846
|
+
* artifact or the owning extension changes.
|
|
847
|
+
*/
|
|
848
|
+
var DetailBoundary = class extends Component {
|
|
849
|
+
state = { failed: false };
|
|
850
|
+
static getDerivedStateFromError() {
|
|
851
|
+
return { failed: true };
|
|
852
|
+
}
|
|
853
|
+
componentDidUpdate(prev) {
|
|
854
|
+
if (this.state.failed && prev.resetKey !== this.props.resetKey) this.setState({ failed: false });
|
|
855
|
+
}
|
|
856
|
+
render() {
|
|
857
|
+
return this.state.failed ? this.props.fallback : this.props.children;
|
|
858
|
+
}
|
|
859
|
+
};
|
|
575
860
|
/**
|
|
576
861
|
* The shell `!` commands run through — the user's own (`$SHELL`), so their
|
|
577
862
|
* shell's syntax (zsh globbing, fish semantics, …) matches what they'd get
|
|
@@ -1462,7 +1747,7 @@ function CustomEventBlock({ event, renderFallback }) {
|
|
|
1462
1747
|
fallback: renderFallback(event.text),
|
|
1463
1748
|
notice: /* @__PURE__ */ jsx$1("text", {
|
|
1464
1749
|
fg: COLOR.dim,
|
|
1465
|
-
children:
|
|
1750
|
+
children: `renderer ${binding.renderer} failed, showing fallback`
|
|
1466
1751
|
}),
|
|
1467
1752
|
children: /* @__PURE__ */ jsx$1(RendererRowContext.Provider, {
|
|
1468
1753
|
value: rowValue,
|
|
@@ -1495,7 +1780,7 @@ function ToolResultCustomBlock({ event, indent, renderDefault }) {
|
|
|
1495
1780
|
fallback: renderDefault(),
|
|
1496
1781
|
notice: /* @__PURE__ */ jsx$1("text", {
|
|
1497
1782
|
fg: COLOR.dim,
|
|
1498
|
-
children:
|
|
1783
|
+
children: `tool renderer for ${props.tool} failed, showing default`
|
|
1499
1784
|
}),
|
|
1500
1785
|
children: /* @__PURE__ */ jsx$1(RenderCall, { render: () => {
|
|
1501
1786
|
for (const candidate of candidates) {
|
|
@@ -3617,7 +3902,7 @@ function SessionEventBlock({ event, indent, onOpen }) {
|
|
|
3617
3902
|
/* @__PURE__ */ jsx$1("span", { children: ` ${style.verb}` }),
|
|
3618
3903
|
sessionEvent.status === "needs-attention" && /* @__PURE__ */ jsx$1("span", {
|
|
3619
3904
|
fg: COLOR.warn,
|
|
3620
|
-
children: "
|
|
3905
|
+
children: " · click to answer"
|
|
3621
3906
|
}),
|
|
3622
3907
|
meta.map((cell, i) => /* @__PURE__ */ jsx$1("span", {
|
|
3623
3908
|
fg: COLOR.dim,
|
|
@@ -4473,7 +4758,7 @@ function EditDiffBlock({ payload, dim }) {
|
|
|
4473
4758
|
...dim ? { fg: COLOR.dim } : {}
|
|
4474
4759
|
}), fullDiff.hiddenLines > 0 && /* @__PURE__ */ jsx$1("text", {
|
|
4475
4760
|
fg: COLOR.mute,
|
|
4476
|
-
children: ` … diff clipped
|
|
4761
|
+
children: ` … diff clipped, showing ${fullDiff.totalLines - fullDiff.hiddenLines} of ${fullDiff.totalLines} lines (the change applies in full)`
|
|
4477
4762
|
})]
|
|
4478
4763
|
})]
|
|
4479
4764
|
});
|
|
@@ -4677,7 +4962,7 @@ function HunkBlock({ index, hunk, outcome, tool, path, filetype, mdStyle, COLOR,
|
|
|
4677
4962
|
...dimmed ? { fg: COLOR.dim } : {}
|
|
4678
4963
|
}), diffText.hiddenLines > 0 && /* @__PURE__ */ jsx$1("text", {
|
|
4679
4964
|
fg: COLOR.mute,
|
|
4680
|
-
children: ` … diff clipped
|
|
4965
|
+
children: ` … diff clipped, showing ${diffText.totalLines - diffText.hiddenLines} of ${diffText.totalLines} lines`
|
|
4681
4966
|
})]
|
|
4682
4967
|
})]
|
|
4683
4968
|
});
|
|
@@ -5032,7 +5317,7 @@ function ContextPanelModal({ breakdown, modelUsage }) {
|
|
|
5032
5317
|
children: [/* @__PURE__ */ jsx$1("span", {
|
|
5033
5318
|
fg: COLOR.mute,
|
|
5034
5319
|
children: "~"
|
|
5035
|
-
}), " estimated
|
|
5320
|
+
}), " estimated, exact counts unavailable for this provider"]
|
|
5036
5321
|
}),
|
|
5037
5322
|
/* @__PURE__ */ jsx$1(ModalHints, { hints: [
|
|
5038
5323
|
expandableIds.length > 0 && {
|
|
@@ -6645,7 +6930,7 @@ function KeybindingsEditFileButton({ filePath, highlightBg }) {
|
|
|
6645
6930
|
children: " "
|
|
6646
6931
|
}), /* @__PURE__ */ jsx$1("span", {
|
|
6647
6932
|
fg: COLOR.dim,
|
|
6648
|
-
children: `${display}
|
|
6933
|
+
children: `${display}. Restart to apply`
|
|
6649
6934
|
})]
|
|
6650
6935
|
})]
|
|
6651
6936
|
});
|
|
@@ -6809,7 +7094,7 @@ function useDaemonHealth() {
|
|
|
6809
7094
|
const BASE_LEVELS$1 = [
|
|
6810
7095
|
{
|
|
6811
7096
|
id: "off",
|
|
6812
|
-
description: "no reasoning
|
|
7097
|
+
description: "no reasoning. fastest, shortest output"
|
|
6813
7098
|
},
|
|
6814
7099
|
{
|
|
6815
7100
|
id: "minimal",
|
|
@@ -6821,11 +7106,11 @@ const BASE_LEVELS$1 = [
|
|
|
6821
7106
|
},
|
|
6822
7107
|
{
|
|
6823
7108
|
id: "medium",
|
|
6824
|
-
description: "balanced
|
|
7109
|
+
description: "balanced. default"
|
|
6825
7110
|
},
|
|
6826
7111
|
{
|
|
6827
7112
|
id: "high",
|
|
6828
|
-
description: "
|
|
7113
|
+
description: "most reasoning. slowest, longest"
|
|
6829
7114
|
},
|
|
6830
7115
|
{
|
|
6831
7116
|
id: "xhigh",
|
|
@@ -7256,7 +7541,7 @@ function ModelPickerModal({ providers, modelsFor, current, onPick, chain, onAppl
|
|
|
7256
7541
|
});
|
|
7257
7542
|
if (providers.length === 0) return /* @__PURE__ */ jsx$1(EmptyProvidersState, {});
|
|
7258
7543
|
return /* @__PURE__ */ jsxs(Modal, {
|
|
7259
|
-
title: chainMode ? "select models
|
|
7544
|
+
title: chainMode ? "select models · order is fallback priority" : "select model",
|
|
7260
7545
|
maxWidth: 100,
|
|
7261
7546
|
onClose: handleClose,
|
|
7262
7547
|
children: [
|
|
@@ -7271,7 +7556,7 @@ function ModelPickerModal({ providers, modelsFor, current, onPick, chain, onAppl
|
|
|
7271
7556
|
children: /* @__PURE__ */ jsx$1("input", {
|
|
7272
7557
|
ref: inputRef,
|
|
7273
7558
|
focused: true,
|
|
7274
|
-
placeholder: "search models
|
|
7559
|
+
placeholder: "search models: provider, name, capability",
|
|
7275
7560
|
onInput: handleQueryChange,
|
|
7276
7561
|
onSubmit: () => {},
|
|
7277
7562
|
style: { flexGrow: 1 }
|
|
@@ -7473,7 +7758,7 @@ function ModelSelectList({ catalog, multi = false, initial, onApply, onCancel, v
|
|
|
7473
7758
|
children: /* @__PURE__ */ jsx$1("input", {
|
|
7474
7759
|
ref: inputRef,
|
|
7475
7760
|
focused: true,
|
|
7476
|
-
placeholder: "search models
|
|
7761
|
+
placeholder: "search models: provider, name, capability",
|
|
7477
7762
|
onInput: handleQueryChange,
|
|
7478
7763
|
onSubmit: () => {},
|
|
7479
7764
|
style: { flexGrow: 1 }
|
|
@@ -7837,6 +8122,12 @@ async function connectDaemonSession(options) {
|
|
|
7837
8122
|
case "todos:snapshot":
|
|
7838
8123
|
callbacks.onTodosChanged?.(signal.snapshot);
|
|
7839
8124
|
break;
|
|
8125
|
+
case "artifact:recorded":
|
|
8126
|
+
callbacks.onArtifactRecorded?.(signal.artifact);
|
|
8127
|
+
break;
|
|
8128
|
+
case "artifact:changed":
|
|
8129
|
+
callbacks.onArtifactChanged?.();
|
|
8130
|
+
break;
|
|
7840
8131
|
case "cache:break":
|
|
7841
8132
|
callbacks.onCacheBreak(signal.info);
|
|
7842
8133
|
break;
|
|
@@ -7949,7 +8240,8 @@ async function connectDaemonSession(options) {
|
|
|
7949
8240
|
sessionId,
|
|
7950
8241
|
text,
|
|
7951
8242
|
...options?.activatedSkills?.length ? { activatedSkills: options.activatedSkills } : {},
|
|
7952
|
-
...options?.attachments?.length ? { attachments: options.attachments } : {}
|
|
8243
|
+
...options?.attachments?.length ? { attachments: options.attachments } : {},
|
|
8244
|
+
...options?.asCommand ? { asCommand: options.asCommand } : {}
|
|
7953
8245
|
}));
|
|
7954
8246
|
if (result) return result.delivered;
|
|
7955
8247
|
const { delivered } = await client.request("chat.pushQueued", {
|
|
@@ -8004,6 +8296,19 @@ async function connectDaemonSession(options) {
|
|
|
8004
8296
|
async fetchContextBreakdown() {
|
|
8005
8297
|
return optional(() => client.request("sessions.contextBreakdown", { sessionId }));
|
|
8006
8298
|
},
|
|
8299
|
+
async fetchArtifacts(query) {
|
|
8300
|
+
if (query.scope === "project") return optional(() => client.request("artifacts.list", { projectRoot: query.projectRoot }));
|
|
8301
|
+
return optional(() => client.request("sessions.artifacts", { sessionId }));
|
|
8302
|
+
},
|
|
8303
|
+
async deleteArtifact(ownerSessionId, artifactId) {
|
|
8304
|
+
return optional(() => client.request("artifacts.delete", {
|
|
8305
|
+
sessionId: ownerSessionId,
|
|
8306
|
+
artifactId
|
|
8307
|
+
}));
|
|
8308
|
+
},
|
|
8309
|
+
async upsertArtifact(artifact) {
|
|
8310
|
+
return optional(() => client.request("artifacts.upsert", { artifact }));
|
|
8311
|
+
},
|
|
8007
8312
|
async mainSession() {
|
|
8008
8313
|
return optional(() => client.request("orchestration.main", {}));
|
|
8009
8314
|
},
|
|
@@ -8144,7 +8449,7 @@ function runEditorOnText(initialText, options = {}) {
|
|
|
8144
8449
|
if (status !== 0) return {
|
|
8145
8450
|
ok: false,
|
|
8146
8451
|
reason: "aborted",
|
|
8147
|
-
message: "editor exited without saving
|
|
8452
|
+
message: "editor exited without saving, prompt unchanged"
|
|
8148
8453
|
};
|
|
8149
8454
|
return {
|
|
8150
8455
|
ok: true,
|
|
@@ -8378,7 +8683,7 @@ async function readClipboardImage(hooks = {}) {
|
|
|
8378
8683
|
if (isRemoteSession(env)) return {
|
|
8379
8684
|
ok: false,
|
|
8380
8685
|
reason: "unsupported-env",
|
|
8381
|
-
detail: "clipboard image paste is unavailable over SSH
|
|
8686
|
+
detail: "clipboard image paste is unavailable over SSH. Paste the image file path instead"
|
|
8382
8687
|
};
|
|
8383
8688
|
if (platform === "darwin") return readMac(capture);
|
|
8384
8689
|
if (platform === "win32") return readWindows(capture);
|
|
@@ -8466,7 +8771,7 @@ async function readClipboardTextWith(capture, platform, env) {
|
|
|
8466
8771
|
if (result.truncated || result.stdout.length > 20971520) return {
|
|
8467
8772
|
ok: false,
|
|
8468
8773
|
reason: "too-large",
|
|
8469
|
-
detail: `clipboard text exceeds ${Math.round(MAX_CLIPBOARD_TEXT_BYTES / (1024 * 1024))} MB
|
|
8774
|
+
detail: `clipboard text exceeds ${Math.round(MAX_CLIPBOARD_TEXT_BYTES / (1024 * 1024))} MB. Paste it from a file instead`
|
|
8470
8775
|
};
|
|
8471
8776
|
if (result.code !== 0 && textTargetsExhausted) return {
|
|
8472
8777
|
ok: false,
|
|
@@ -8493,7 +8798,7 @@ async function readClipboardText(hooks = {}) {
|
|
|
8493
8798
|
if (isRemoteSession(env)) return {
|
|
8494
8799
|
ok: false,
|
|
8495
8800
|
reason: "unsupported-env",
|
|
8496
|
-
detail: "clipboard paste is unavailable over SSH
|
|
8801
|
+
detail: "clipboard paste is unavailable over SSH. Paste the text through your local terminal instead"
|
|
8497
8802
|
};
|
|
8498
8803
|
return readClipboardTextWith(hooks.capture ?? captureViaSpawn, platform, env);
|
|
8499
8804
|
}
|
|
@@ -9151,7 +9456,7 @@ function SingleEditApprovalModal({ request, payload, priorContent, priorError, t
|
|
|
9151
9456
|
}), diffText.hiddenLines > 0 && /* @__PURE__ */ jsx$1("text", {
|
|
9152
9457
|
fg: COLOR.mute,
|
|
9153
9458
|
style: { flexShrink: 0 },
|
|
9154
|
-
children: ` … diff clipped
|
|
9459
|
+
children: ` … diff clipped, showing ${diffText.totalLines - diffText.hiddenLines} of ${diffText.totalLines} lines (approval applies the full change)`
|
|
9155
9460
|
})]
|
|
9156
9461
|
}), /* @__PURE__ */ jsx$1(ActionBar, {
|
|
9157
9462
|
actions: BULK_ACTIONS,
|
|
@@ -9468,7 +9773,7 @@ function MultiEditApprovalModal({ request, payload, priorContent, priorError, ta
|
|
|
9468
9773
|
}), focusedDiffText.hiddenLines > 0 && /* @__PURE__ */ jsx$1("text", {
|
|
9469
9774
|
fg: COLOR.mute,
|
|
9470
9775
|
style: { flexShrink: 0 },
|
|
9471
|
-
children: ` … diff clipped
|
|
9776
|
+
children: ` … diff clipped, showing ${focusedDiffText.totalLines - focusedDiffText.hiddenLines} of ${focusedDiffText.totalLines} lines (approval applies the full change)`
|
|
9472
9777
|
})]
|
|
9473
9778
|
}) : /* @__PURE__ */ jsx$1(UnresolvedHunkPanel, {
|
|
9474
9779
|
hunk: payload.hunks[cursor],
|
|
@@ -9537,7 +9842,7 @@ function UnresolvedHunkPanel({ hunk, targetPath, width, ambiguous }) {
|
|
|
9537
9842
|
const COLOR = useColors();
|
|
9538
9843
|
const oldPreview = hunk ? snippet(hunk.oldString) : "(missing)";
|
|
9539
9844
|
const newPreview = hunk ? snippet(hunk.newString) : "(missing)";
|
|
9540
|
-
const headline = ambiguous ? `old_string matches multiple places in ${targetPath}
|
|
9845
|
+
const headline = ambiguous ? `old_string matches multiple places in ${targetPath}. Set replace_all=true or expand the match.` : `old_string not found in ${targetPath}.`;
|
|
9541
9846
|
return /* @__PURE__ */ jsxs("box", {
|
|
9542
9847
|
style: {
|
|
9543
9848
|
border: true,
|
|
@@ -9844,7 +10149,7 @@ const PLAN_OPTIONS = [
|
|
|
9844
10149
|
{
|
|
9845
10150
|
id: "reject",
|
|
9846
10151
|
label: "reject",
|
|
9847
|
-
description: "refuse the plan
|
|
10152
|
+
description: "refuse the plan. The agent sees your note and the run stops"
|
|
9848
10153
|
}
|
|
9849
10154
|
];
|
|
9850
10155
|
function PlanInteractionBlock({ request, onResolve }) {
|
|
@@ -10878,7 +11183,7 @@ function OAuthAuthBlock({ authUrl, maxLineWidth, chromeWidth = 14, paste }) {
|
|
|
10878
11183
|
}),
|
|
10879
11184
|
/* @__PURE__ */ jsx$1("text", {
|
|
10880
11185
|
fg: COLOR.dim,
|
|
10881
|
-
children: callbackUri ? `after you authorize, the browser lands on ${callbackUri} and fails
|
|
11186
|
+
children: callbackUri ? `after you authorize, the browser lands on ${callbackUri} and fails. Copy that whole address from its URL bar and paste it below.` : "after you authorize, copy the address the browser failed to reach (it starts with http://127.0.0.1) and paste it below."
|
|
10882
11187
|
}),
|
|
10883
11188
|
paste.hint && /* @__PURE__ */ jsx$1("text", {
|
|
10884
11189
|
fg: toneColor(paste.hint.tone, COLOR),
|
|
@@ -11114,7 +11419,7 @@ function McpAuthorizingPanel({ serverName, authUrl, maxLineWidth, chromeWidth, i
|
|
|
11114
11419
|
const inputRef = useRef(null);
|
|
11115
11420
|
const [hint, setHint] = useState(null);
|
|
11116
11421
|
const waited = useElapsedSeconds(authUrl === null);
|
|
11117
|
-
const status = hint && hint.tone !== "error" ? hint.text : authUrl === null ? `contacting ${serverName} for an authorization URL… (${waited}s)` : "complete the login in your browser
|
|
11422
|
+
const status = hint && hint.tone !== "error" ? hint.text : authUrl === null ? `contacting ${serverName} for an authorization URL… (${waited}s)` : "complete the login in your browser, waiting for the callback";
|
|
11118
11423
|
const onSubmit = useCallback(() => {
|
|
11119
11424
|
const value = inputRef.current?.value?.trim() ?? "";
|
|
11120
11425
|
if (!value) return;
|
|
@@ -11126,7 +11431,7 @@ function McpAuthorizingPanel({ serverName, authUrl, maxLineWidth, chromeWidth, i
|
|
|
11126
11431
|
try {
|
|
11127
11432
|
const result = await fetchOAuthRedirect(value, { ...authUrl ? { authUrl } : {} });
|
|
11128
11433
|
if (result.status >= 200 && result.status < 300) setHint({
|
|
11129
|
-
text: "redirect accepted
|
|
11434
|
+
text: "redirect accepted, finalizing",
|
|
11130
11435
|
tone: "accent"
|
|
11131
11436
|
});
|
|
11132
11437
|
else setHint({
|
|
@@ -11159,7 +11464,7 @@ function McpAuthorizingPanel({ serverName, authUrl, maxLineWidth, chromeWidth, i
|
|
|
11159
11464
|
/* @__PURE__ */ jsx$1(Spinner, { label: status }),
|
|
11160
11465
|
authUrl === null && waited >= SLOW_START_SECONDS && /* @__PURE__ */ jsx$1("text", {
|
|
11161
11466
|
fg: COLOR.warn,
|
|
11162
|
-
children: `${serverName} is slow to respond
|
|
11467
|
+
children: `${serverName} is slow to respond. esc cancels, then retry or check the server URL in this list.`
|
|
11163
11468
|
}),
|
|
11164
11469
|
authUrl !== null && /* @__PURE__ */ jsx$1(OAuthAuthBlock, {
|
|
11165
11470
|
authUrl,
|
|
@@ -11178,7 +11483,7 @@ function McpAuthorizingPanel({ serverName, authUrl, maxLineWidth, chromeWidth, i
|
|
|
11178
11483
|
})
|
|
11179
11484
|
]
|
|
11180
11485
|
}), /* @__PURE__ */ jsx$1(TitleOverlay, {
|
|
11181
|
-
title: `authorizing ${serverName}
|
|
11486
|
+
title: `authorizing ${serverName} · OAuth`,
|
|
11182
11487
|
bg: SURFACE.modal
|
|
11183
11488
|
})]
|
|
11184
11489
|
});
|
|
@@ -11331,7 +11636,7 @@ function AuthScreen({ onPick, initialConfigureKey }) {
|
|
|
11331
11636
|
value: p.key
|
|
11332
11637
|
})), ...providers.filter((p) => !p.available).map((p) => ({
|
|
11333
11638
|
name: p.label,
|
|
11334
|
-
description: "not configured
|
|
11639
|
+
description: "not configured. ↵ to set up",
|
|
11335
11640
|
value: p.key
|
|
11336
11641
|
}))];
|
|
11337
11642
|
return /* @__PURE__ */ jsxs("box", {
|
|
@@ -11667,7 +11972,7 @@ function PickMethodStep({ descriptor, error, onPick }) {
|
|
|
11667
11972
|
return items;
|
|
11668
11973
|
}, [descriptor]);
|
|
11669
11974
|
return /* @__PURE__ */ jsxs(WizardPanel, {
|
|
11670
|
-
title: `configure ${descriptor.label}
|
|
11975
|
+
title: `configure ${descriptor.label} · auth method`,
|
|
11671
11976
|
error,
|
|
11672
11977
|
children: [/* @__PURE__ */ jsx$1(WizardEscHint, {}), /* @__PURE__ */ jsx$1("select", {
|
|
11673
11978
|
...SELECT_THEME,
|
|
@@ -11815,7 +12120,7 @@ function EnterApiKeyStep({ descriptor, customFields, error, onSubmit }) {
|
|
|
11815
12120
|
onSubmit
|
|
11816
12121
|
]);
|
|
11817
12122
|
return /* @__PURE__ */ jsxs(WizardPanel, {
|
|
11818
|
-
title: `configure ${descriptor.label}
|
|
12123
|
+
title: `configure ${descriptor.label} · API key`,
|
|
11819
12124
|
error,
|
|
11820
12125
|
children: [/* @__PURE__ */ jsxs("text", {
|
|
11821
12126
|
fg: COLOR.dim,
|
|
@@ -11942,7 +12247,7 @@ function OAuthRunningStep({ descriptor, dataDir, onSuccess, onError }) {
|
|
|
11942
12247
|
const result = await fetchOAuthRedirect(value, { ...url ? { authUrl: url } : {} });
|
|
11943
12248
|
if (result.status >= 200 && result.status < 300) {
|
|
11944
12249
|
setPasteHint({
|
|
11945
|
-
text: "redirect accepted
|
|
12250
|
+
text: "redirect accepted, exchanging code",
|
|
11946
12251
|
tone: "accent"
|
|
11947
12252
|
});
|
|
11948
12253
|
setStatus("exchanging code…");
|
|
@@ -11959,7 +12264,7 @@ function OAuthRunningStep({ descriptor, dataDir, onSuccess, onError }) {
|
|
|
11959
12264
|
})();
|
|
11960
12265
|
}, [url]);
|
|
11961
12266
|
return /* @__PURE__ */ jsxs(WizardPanel, {
|
|
11962
|
-
title: `configure ${descriptor.label}
|
|
12267
|
+
title: `configure ${descriptor.label} · OAuth`,
|
|
11963
12268
|
children: [
|
|
11964
12269
|
/* @__PURE__ */ jsx$1(WizardEscHint, {}),
|
|
11965
12270
|
pending ? /* @__PURE__ */ jsx$1(Spinner, { label: pending.message }) : /* @__PURE__ */ jsx$1(Spinner, { label: status }),
|
|
@@ -12251,7 +12556,7 @@ function SessionsScreen({ sessions, currentId, focusedSessionId, onPick, onCreat
|
|
|
12251
12556
|
id: "session-search-input",
|
|
12252
12557
|
ref: inputRef,
|
|
12253
12558
|
focused,
|
|
12254
|
-
placeholder: "search sessions
|
|
12559
|
+
placeholder: "search sessions: title, project, or message content",
|
|
12255
12560
|
onInput: setQuery,
|
|
12256
12561
|
onPaste: onFilterPaste,
|
|
12257
12562
|
onSubmit: () => {},
|
|
@@ -12442,6 +12747,13 @@ function SessionRow({ row, anchorId, focused, isCurrent, separator = false, show
|
|
|
12442
12747
|
fg: COLOR.mute,
|
|
12443
12748
|
children: ` run${meta.runCount === 1 ? "" : "s"} · `
|
|
12444
12749
|
}),
|
|
12750
|
+
(meta.artifactCount ?? 0) > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx$1("span", {
|
|
12751
|
+
fg: COLOR.accent,
|
|
12752
|
+
children: meta.artifactCount
|
|
12753
|
+
}), /* @__PURE__ */ jsx$1("span", {
|
|
12754
|
+
fg: COLOR.mute,
|
|
12755
|
+
children: ` artifact${meta.artifactCount === 1 ? "" : "s"} · `
|
|
12756
|
+
})] }),
|
|
12445
12757
|
/* @__PURE__ */ jsx$1("span", {
|
|
12446
12758
|
fg: COLOR.mute,
|
|
12447
12759
|
children: ageString(meta.updatedAt)
|
|
@@ -12854,7 +13166,7 @@ function ApprovalBlock({ request, onPick }) {
|
|
|
12854
13166
|
value: "accept-safelist"
|
|
12855
13167
|
},
|
|
12856
13168
|
{
|
|
12857
|
-
name: "deny ·
|
|
13169
|
+
name: "deny · the model sees Blocked",
|
|
12858
13170
|
description: "",
|
|
12859
13171
|
value: "deny"
|
|
12860
13172
|
}
|
|
@@ -13141,7 +13453,7 @@ function PromptBlock({ userPrompts, onSubmit, completionProviders, inlineAutocom
|
|
|
13141
13453
|
*/
|
|
13142
13454
|
const attachClipboardImage = useCallback(async () => {
|
|
13143
13455
|
if (!attachmentsEnabled) {
|
|
13144
|
-
showNotice("attachments are disabled
|
|
13456
|
+
showNotice("attachments are disabled. Enable them in Settings → Agent");
|
|
13145
13457
|
return;
|
|
13146
13458
|
}
|
|
13147
13459
|
const result = await readClipboardImage();
|
|
@@ -13150,7 +13462,7 @@ function PromptBlock({ userPrompts, onSubmit, completionProviders, inlineAutocom
|
|
|
13150
13462
|
return;
|
|
13151
13463
|
}
|
|
13152
13464
|
if (result.data.length > MAX_IMAGE_BYTES) {
|
|
13153
|
-
showNotice(`clipboard image too large (${formatBytes(result.data.length)})
|
|
13465
|
+
showNotice(`clipboard image too large (${formatBytes(result.data.length)}), max ${formatBytes(MAX_IMAGE_BYTES)}`);
|
|
13154
13466
|
return;
|
|
13155
13467
|
}
|
|
13156
13468
|
setAttachments((prev) => {
|
|
@@ -13476,12 +13788,12 @@ function PromptBlock({ userPrompts, onSubmit, completionProviders, inlineAutocom
|
|
|
13476
13788
|
if (resolved.startsWith("~/")) resolved = (process.env.HOME ?? "") + resolved.slice(1);
|
|
13477
13789
|
if (resolved.length > 0 && (resolved.startsWith("/") || resolved.startsWith("."))) try {
|
|
13478
13790
|
const st = statSync(resolved);
|
|
13479
|
-
if (st.isFile() && st.size > MAX_FILE_ATTACHMENT_BYTES) showNotice(`file too large to attach (${formatBytes(st.size)}, cap ${formatBytes(MAX_FILE_ATTACHMENT_BYTES)})
|
|
13791
|
+
if (st.isFile() && st.size > MAX_FILE_ATTACHMENT_BYTES) showNotice(`file too large to attach (${formatBytes(st.size)}, cap ${formatBytes(MAX_FILE_ATTACHMENT_BYTES)}), pasted the path instead`);
|
|
13480
13792
|
else if (st.isFile()) {
|
|
13481
13793
|
const buf = readFileSync(resolved);
|
|
13482
13794
|
const ext = (resolved.split(".").pop() ?? "").toLowerCase();
|
|
13483
13795
|
const mediaType = sniffImageMediaType(buf) ?? IMAGE_MEDIA_TYPES[ext] ?? MIME_BY_EXT[ext] ?? "application/octet-stream";
|
|
13484
|
-
if (mediaType.startsWith("image/") && buf.length > MAX_IMAGE_BYTES) showNotice(`image too large to attach (${formatBytes(buf.length)}, cap ${formatBytes(MAX_IMAGE_BYTES)})
|
|
13796
|
+
if (mediaType.startsWith("image/") && buf.length > MAX_IMAGE_BYTES) showNotice(`image too large to attach (${formatBytes(buf.length)}, cap ${formatBytes(MAX_IMAGE_BYTES)}), pasted the path instead`);
|
|
13485
13797
|
else {
|
|
13486
13798
|
setAttachments((prev) => [...prev, {
|
|
13487
13799
|
name: basename(resolved),
|
|
@@ -13545,11 +13857,11 @@ function PromptBlock({ userPrompts, onSubmit, completionProviders, inlineAutocom
|
|
|
13545
13857
|
return;
|
|
13546
13858
|
}
|
|
13547
13859
|
if (!attachmentsEnabled) {
|
|
13548
|
-
showNotice("attachments are disabled
|
|
13860
|
+
showNotice("attachments are disabled. Enable them in Settings → Agent");
|
|
13549
13861
|
return;
|
|
13550
13862
|
}
|
|
13551
13863
|
if (result.data.length > MAX_IMAGE_BYTES) {
|
|
13552
|
-
showNotice(`clipboard image too large (${formatBytes(result.data.length)})
|
|
13864
|
+
showNotice(`clipboard image too large (${formatBytes(result.data.length)}), max ${formatBytes(MAX_IMAGE_BYTES)}`);
|
|
13553
13865
|
return;
|
|
13554
13866
|
}
|
|
13555
13867
|
setAttachments((prev) => {
|
|
@@ -13861,7 +14173,7 @@ function PromptBlock({ userPrompts, onSubmit, completionProviders, inlineAutocom
|
|
|
13861
14173
|
focused: focused && !selectMode && !suspended,
|
|
13862
14174
|
keyBindings: TEXTAREA_BINDINGS,
|
|
13863
14175
|
wrapMode: "word",
|
|
13864
|
-
placeholder: selectMode === "queue" ? "
|
|
14176
|
+
placeholder: selectMode === "queue" ? "queue select · ⎋ resumes typing" : searchMode ? "Search this conversation…" : shellMode ? "Run a shell command…" : "Ask zidane…",
|
|
13865
14177
|
syntaxStyle: chipStyle,
|
|
13866
14178
|
style: {
|
|
13867
14179
|
flexGrow: 1,
|
|
@@ -14396,11 +14708,11 @@ function SessionDetailsModal({ session, title, isCurrent, actions, keybindings }
|
|
|
14396
14708
|
*/
|
|
14397
14709
|
function ActionRow$2({ pending, copyStatus, titleStatus, titleError, hasGenerate, exportStatus, exportResult, exportError, hasExport, compactStatus, compactTokens, compactElapsedMs, compactResult, compactError, hasCompact, keys }) {
|
|
14398
14710
|
const COLOR = useColors();
|
|
14399
|
-
if (titleStatus === "loading") return /* @__PURE__ */ jsx$1(Spinner, { label: "generating title
|
|
14400
|
-
if (exportStatus === "writing") return /* @__PURE__ */ jsx$1(Spinner, { label: "exporting session
|
|
14711
|
+
if (titleStatus === "loading") return /* @__PURE__ */ jsx$1(Spinner, { label: "generating title" });
|
|
14712
|
+
if (exportStatus === "writing") return /* @__PURE__ */ jsx$1(Spinner, { label: "exporting session" });
|
|
14401
14713
|
if (compactStatus === "running") {
|
|
14402
14714
|
const elapsed = typeof compactElapsedMs === "number" && compactElapsedMs >= 1e3 ? ` · ${formatDuration(compactElapsedMs)}` : "";
|
|
14403
|
-
return /* @__PURE__ */ jsx$1(Spinner, { label: `compacting older turns${typeof compactTokens === "number" && compactTokens > 0 ? `
|
|
14715
|
+
return /* @__PURE__ */ jsx$1(Spinner, { label: `compacting older turns${typeof compactTokens === "number" && compactTokens > 0 ? ` · ~${fmtTokens(compactTokens)} tokens streamed${elapsed}` : ` · waiting for model${elapsed}`}` });
|
|
14404
14716
|
}
|
|
14405
14717
|
if (titleStatus === "failed") return /* @__PURE__ */ jsxs("text", {
|
|
14406
14718
|
fg: COLOR.dim,
|
|
@@ -14411,7 +14723,7 @@ function ActionRow$2({ pending, copyStatus, titleStatus, titleError, hasGenerate
|
|
|
14411
14723
|
}),
|
|
14412
14724
|
titleError ? /* @__PURE__ */ jsx$1("span", {
|
|
14413
14725
|
fg: COLOR.mute,
|
|
14414
|
-
children: `
|
|
14726
|
+
children: ` · ${titleError}`
|
|
14415
14727
|
}) : null,
|
|
14416
14728
|
" · ",
|
|
14417
14729
|
/* @__PURE__ */ jsx$1("span", {
|
|
@@ -14435,7 +14747,7 @@ function ActionRow$2({ pending, copyStatus, titleStatus, titleError, hasGenerate
|
|
|
14435
14747
|
}),
|
|
14436
14748
|
exportError ? /* @__PURE__ */ jsx$1("span", {
|
|
14437
14749
|
fg: COLOR.mute,
|
|
14438
|
-
children: `
|
|
14750
|
+
children: ` · ${exportError}`
|
|
14439
14751
|
}) : null,
|
|
14440
14752
|
" · ",
|
|
14441
14753
|
/* @__PURE__ */ jsx$1("span", {
|
|
@@ -14464,7 +14776,7 @@ function ActionRow$2({ pending, copyStatus, titleStatus, titleError, hasGenerate
|
|
|
14464
14776
|
}),
|
|
14465
14777
|
compactError ? /* @__PURE__ */ jsx$1("span", {
|
|
14466
14778
|
fg: COLOR.mute,
|
|
14467
|
-
children: `
|
|
14779
|
+
children: ` · ${compactError}`
|
|
14468
14780
|
}) : null,
|
|
14469
14781
|
" · ",
|
|
14470
14782
|
/* @__PURE__ */ jsx$1("span", {
|
|
@@ -15312,7 +15624,7 @@ function SkillInstallDialog({ active, onSubmit, onCancel }) {
|
|
|
15312
15624
|
focused: row === "skill",
|
|
15313
15625
|
label: "skill",
|
|
15314
15626
|
inputRef: skillRef,
|
|
15315
|
-
placeholder: "pick one from multi-skill repos (optional
|
|
15627
|
+
placeholder: "pick one from multi-skill repos (optional, empty imports all)"
|
|
15316
15628
|
}),
|
|
15317
15629
|
/* @__PURE__ */ jsx$1(CycleRow, {
|
|
15318
15630
|
focused: row === "scope",
|
|
@@ -15372,7 +15684,7 @@ function SkillImportDialog({ active, source, items, onConfirm, onCancel }) {
|
|
|
15372
15684
|
if (key.name === "return") {
|
|
15373
15685
|
const selected = items.filter((_, i) => checked.has(i)).map((item) => item.rel);
|
|
15374
15686
|
if (selected.length === 0) {
|
|
15375
|
-
setError("nothing selected
|
|
15687
|
+
setError("nothing selected. space toggles, a selects all");
|
|
15376
15688
|
return;
|
|
15377
15689
|
}
|
|
15378
15690
|
onConfirm(selected);
|
|
@@ -15397,7 +15709,7 @@ function SkillImportDialog({ active, source, items, onConfirm, onCancel }) {
|
|
|
15397
15709
|
fg: COLOR.warn,
|
|
15398
15710
|
children: source
|
|
15399
15711
|
}),
|
|
15400
|
-
`
|
|
15712
|
+
` · ${checked.size}/${count} selected`
|
|
15401
15713
|
]
|
|
15402
15714
|
}),
|
|
15403
15715
|
hasOverflowUp && /* @__PURE__ */ jsx$1("text", {
|
|
@@ -15408,7 +15720,7 @@ function SkillImportDialog({ active, source, items, onConfirm, onCancel }) {
|
|
|
15408
15720
|
const i = start + vi;
|
|
15409
15721
|
const focusedRow = i === cursor;
|
|
15410
15722
|
const isChecked = checked.has(i);
|
|
15411
|
-
const label = clipEnd(item.description ? `${item.rel}
|
|
15723
|
+
const label = clipEnd(item.description ? `${item.rel} · ${item.description}` : item.rel, Math.max(8, innerWidth - 8), item.rel.length);
|
|
15412
15724
|
return /* @__PURE__ */ jsxs("text", {
|
|
15413
15725
|
fg: COLOR.mute,
|
|
15414
15726
|
children: [
|
|
@@ -18551,7 +18863,7 @@ function InstructionsList({ rows, totalCount, loading, error, live, shadowedSyst
|
|
|
18551
18863
|
}, n)), preview.hidden > 0 && /* @__PURE__ */ jsx$1("text", {
|
|
18552
18864
|
wrapMode: "none",
|
|
18553
18865
|
fg: COLOR.mute,
|
|
18554
|
-
children: `… +${preview.hidden} more line${preview.hidden === 1 ? "" : "s"}${openable ? "
|
|
18866
|
+
children: `… +${preview.hidden} more line${preview.hidden === 1 ? "" : "s"}${openable ? ". ↵ opens the file" : ""}`
|
|
18555
18867
|
})]
|
|
18556
18868
|
})
|
|
18557
18869
|
]
|
|
@@ -18838,7 +19150,7 @@ function ToggleRow({ id, label, description, enabled, focused, bg, indent = 0, o
|
|
|
18838
19150
|
}), /* @__PURE__ */ jsx$1("text", {
|
|
18839
19151
|
wrapMode: "none",
|
|
18840
19152
|
fg: COLOR.mute,
|
|
18841
|
-
children: `${COL_TITLE}${blocked ? `requires “${blockedBy}
|
|
19153
|
+
children: `${COL_TITLE}${blocked ? `requires “${blockedBy}”. Turn that on first` : description}`
|
|
18842
19154
|
})]
|
|
18843
19155
|
});
|
|
18844
19156
|
}
|
|
@@ -19604,7 +19916,7 @@ function TodosModal({ getSession, subscribe, onCommit, onSteer }) {
|
|
|
19604
19916
|
total === 0 ? /* @__PURE__ */ jsxs("text", { children: [
|
|
19605
19917
|
/* @__PURE__ */ jsx$1("span", {
|
|
19606
19918
|
fg: COLOR.mute,
|
|
19607
|
-
children: "(no todos yet
|
|
19919
|
+
children: "(no todos yet, the agent has not called "
|
|
19608
19920
|
}),
|
|
19609
19921
|
/* @__PURE__ */ jsx$1("span", {
|
|
19610
19922
|
fg: COLOR.warn,
|
|
@@ -21574,7 +21886,7 @@ function AppShell() {
|
|
|
21574
21886
|
const { active, inactive } = await reloadExtensionsRef.current();
|
|
21575
21887
|
streamRef.current?.appendImmediate({
|
|
21576
21888
|
kind: "info",
|
|
21577
|
-
text:
|
|
21889
|
+
text: `extensions reloaded: ${active} active${inactive > 0 ? `, ${inactive} inactive (enable in Settings → Extensions)` : ""}. Agent tools apply on the next run.`
|
|
21578
21890
|
});
|
|
21579
21891
|
} catch (err) {
|
|
21580
21892
|
debugLog("extension watch: auto-reload failed", err);
|
|
@@ -21632,7 +21944,7 @@ function AppShell() {
|
|
|
21632
21944
|
await reloadExtensionsRef.current();
|
|
21633
21945
|
streamRef.current?.appendImmediate({
|
|
21634
21946
|
kind: "info",
|
|
21635
|
-
text:
|
|
21947
|
+
text: `enabled ${needsLoad.join(", ")}. Settings and UI are live, agent tools apply on the next run.`
|
|
21636
21948
|
});
|
|
21637
21949
|
} catch (err) {
|
|
21638
21950
|
debugLog("extension enable: hot-load failed", err);
|
|
@@ -21955,6 +22267,132 @@ function AppShell() {
|
|
|
21955
22267
|
todosListenersRef.current.delete(onChange);
|
|
21956
22268
|
};
|
|
21957
22269
|
}, []);
|
|
22270
|
+
const artifactsListenersRef = useRef(/* @__PURE__ */ new Set());
|
|
22271
|
+
/** Late-bound `refreshSessions` (declared further down) — see `refreshSessionsRef`. */
|
|
22272
|
+
const refreshSessionsForArtifactsRef = useRef(async () => void 0);
|
|
22273
|
+
const notifyArtifactsChanged = useCallback(() => {
|
|
22274
|
+
for (const listener of artifactsListenersRef.current) listener();
|
|
22275
|
+
refreshSessionsForArtifactsRef.current().catch((err) => debugLog("artifacts: refreshSessions failed", err));
|
|
22276
|
+
}, []);
|
|
22277
|
+
const subscribeArtifacts = useCallback((onChange) => {
|
|
22278
|
+
artifactsListenersRef.current.add(onChange);
|
|
22279
|
+
return () => {
|
|
22280
|
+
artifactsListenersRef.current.delete(onChange);
|
|
22281
|
+
};
|
|
22282
|
+
}, []);
|
|
22283
|
+
/**
|
|
22284
|
+
* Artifact query for the active session / its project. Under the daemon
|
|
22285
|
+
* the daemon is authoritative (its store is the one the loop wrote; a
|
|
22286
|
+
* different data dir or a remote host would make the local handle wrong),
|
|
22287
|
+
* falling back to the TUI's own handle only when the daemon predates the
|
|
22288
|
+
* RPC. Local runtime reads the store directly. Stores without artifact
|
|
22289
|
+
* support answer empty.
|
|
22290
|
+
*/
|
|
22291
|
+
const listArtifacts = useCallback(async (scope) => {
|
|
22292
|
+
const session = sessionRef.current;
|
|
22293
|
+
const root = session?.projectRoot ?? projectDir;
|
|
22294
|
+
const daemon = daemonRef.current;
|
|
22295
|
+
if (daemon) {
|
|
22296
|
+
const rows = await daemon.fetchArtifacts(scope === "project" ? {
|
|
22297
|
+
scope: "project",
|
|
22298
|
+
projectRoot: root ?? ""
|
|
22299
|
+
} : { scope: "session" });
|
|
22300
|
+
if (rows !== null) return scope === "project" && !root ? [] : rows;
|
|
22301
|
+
}
|
|
22302
|
+
if (!store.listArtifacts) return [];
|
|
22303
|
+
if (scope === "project") return root ? store.listArtifacts({ projectRoot: root }) : [];
|
|
22304
|
+
return session ? store.listArtifacts({ sessionId: session.id }) : [];
|
|
22305
|
+
}, [store, projectDir]);
|
|
22306
|
+
const listArtifactsRef = useRef(listArtifacts);
|
|
22307
|
+
listArtifactsRef.current = listArtifacts;
|
|
22308
|
+
const filteredExtensionRegistry = useMemo(() => filterExtensionRegistry(extensionRegistry, settings.enabledExtensions), [extensionRegistry, settings.enabledExtensions]);
|
|
22309
|
+
const extensionRegistryRef = useRef(filteredExtensionRegistry);
|
|
22310
|
+
extensionRegistryRef.current = filteredExtensionRegistry;
|
|
22311
|
+
/** Remove an artifact — daemon-owned write when attached, else the local store. */
|
|
22312
|
+
const deleteArtifact = useCallback(async (artifact) => {
|
|
22313
|
+
const daemon = daemonRef.current;
|
|
22314
|
+
if (daemon) {
|
|
22315
|
+
if (await daemon.deleteArtifact(artifact.sessionId, artifact.id) !== null) {
|
|
22316
|
+
notifyArtifactsChanged();
|
|
22317
|
+
return;
|
|
22318
|
+
}
|
|
22319
|
+
}
|
|
22320
|
+
await store.deleteArtifact?.(artifact.sessionId, artifact.id);
|
|
22321
|
+
notifyArtifactsChanged();
|
|
22322
|
+
}, [store, notifyArtifactsChanged]);
|
|
22323
|
+
/**
|
|
22324
|
+
* Lazy `resolve()` for the focused modal row ("is the PR merged?"): run the
|
|
22325
|
+
* kind's resolver, persist the refreshed row (daemon-owned when attached),
|
|
22326
|
+
* hand it back for immediate display. `undefined` = nothing changed.
|
|
22327
|
+
*/
|
|
22328
|
+
const refreshArtifactRow = useCallback(async (artifact) => {
|
|
22329
|
+
const updated = await refreshArtifact(artifact, extensionRegistryRef.current);
|
|
22330
|
+
if (!updated) return void 0;
|
|
22331
|
+
const daemon = daemonRef.current;
|
|
22332
|
+
if (daemon) {
|
|
22333
|
+
const stored = await daemon.upsertArtifact(updated);
|
|
22334
|
+
if (stored !== null) return stored;
|
|
22335
|
+
}
|
|
22336
|
+
return await store.upsertArtifact?.(updated) ?? updated;
|
|
22337
|
+
}, [store]);
|
|
22338
|
+
/**
|
|
22339
|
+
* `#` completion catalog for the active session's artifacts ("#pr" → the
|
|
22340
|
+
* PR URL). Lazily loaded on the first `#` keystroke and dropped on every
|
|
22341
|
+
* artifact change / session switch, so the next keystroke re-queries.
|
|
22342
|
+
*/
|
|
22343
|
+
const artifactCatalogRef = useRef([]);
|
|
22344
|
+
const artifactCatalogSessionRef = useRef(null);
|
|
22345
|
+
const ensureArtifactCatalog = useCallback(async () => {
|
|
22346
|
+
const session = sessionRef.current;
|
|
22347
|
+
if (!session) return [];
|
|
22348
|
+
if (artifactCatalogSessionRef.current === session.id) return artifactCatalogRef.current;
|
|
22349
|
+
const rows = await listArtifactsRef.current("session");
|
|
22350
|
+
const registry = extensionRegistryRef.current;
|
|
22351
|
+
const catalog = rows.map((artifact) => ({
|
|
22352
|
+
artifact,
|
|
22353
|
+
row: renderArtifactRow(artifact, registry),
|
|
22354
|
+
kindLabel: artifactKindLabel(artifact.kind, registry)
|
|
22355
|
+
}));
|
|
22356
|
+
artifactCatalogRef.current = catalog;
|
|
22357
|
+
artifactCatalogSessionRef.current = session.id;
|
|
22358
|
+
return catalog;
|
|
22359
|
+
}, []);
|
|
22360
|
+
useEffect(() => subscribeArtifacts(() => {
|
|
22361
|
+
artifactCatalogRef.current = [];
|
|
22362
|
+
artifactCatalogSessionRef.current = null;
|
|
22363
|
+
}), [subscribeArtifacts]);
|
|
22364
|
+
/** Late-bound so the once-built `/artifacts` command can open the modal. */
|
|
22365
|
+
const openArtifactsRef = useRef(() => false);
|
|
22366
|
+
const sessionTitleByIdRef = useRef(() => void 0);
|
|
22367
|
+
sessionTitleByIdRef.current = (id) => sessions.find((s) => s.id === id)?.title;
|
|
22368
|
+
const projectDirRef = useRef(projectDir);
|
|
22369
|
+
projectDirRef.current = projectDir;
|
|
22370
|
+
openArtifactsRef.current = useCallback((scope) => {
|
|
22371
|
+
const session = sessionRef.current;
|
|
22372
|
+
if (!session) return false;
|
|
22373
|
+
const projectRoot = session.projectRoot ?? projectDirRef.current;
|
|
22374
|
+
modal.open(/* @__PURE__ */ jsx$1(ArtifactsModal, {
|
|
22375
|
+
load: (scope) => listArtifactsRef.current(scope),
|
|
22376
|
+
subscribe: subscribeArtifacts,
|
|
22377
|
+
registry: extensionRegistryRef.current,
|
|
22378
|
+
initialScope: scope,
|
|
22379
|
+
...projectRoot ? { projectRoot } : {},
|
|
22380
|
+
onOpen: (href) => {
|
|
22381
|
+
if (/^https?:\/\//.test(href)) tryOpenBrowser(href);
|
|
22382
|
+
else launchEditor(href).catch((err) => debugLog("artifacts: open failed", err));
|
|
22383
|
+
},
|
|
22384
|
+
onCopy: (text) => writeToClipboard(text),
|
|
22385
|
+
sessionTitle: (id) => sessionTitleByIdRef.current(id),
|
|
22386
|
+
onDelete: deleteArtifact,
|
|
22387
|
+
onRefresh: refreshArtifactRow
|
|
22388
|
+
}));
|
|
22389
|
+
return true;
|
|
22390
|
+
}, [
|
|
22391
|
+
modal,
|
|
22392
|
+
subscribeArtifacts,
|
|
22393
|
+
deleteArtifact,
|
|
22394
|
+
refreshArtifactRow
|
|
22395
|
+
]);
|
|
21958
22396
|
const commitTodos = useCallback((items) => {
|
|
21959
22397
|
const session = sessionRef.current;
|
|
21960
22398
|
if (!session) return;
|
|
@@ -21971,7 +22409,7 @@ function AppShell() {
|
|
|
21971
22409
|
}).catch(() => {
|
|
21972
22410
|
streamRef.current?.appendImmediate({
|
|
21973
22411
|
kind: "info",
|
|
21974
|
-
text: "
|
|
22412
|
+
text: "todo edit did not reach the daemon. It re-syncs on reconnect."
|
|
21975
22413
|
});
|
|
21976
22414
|
});
|
|
21977
22415
|
}, [notifyTodosChanged]);
|
|
@@ -22093,7 +22531,13 @@ function AppShell() {
|
|
|
22093
22531
|
const builtinCommandsRef = useRef(void 0);
|
|
22094
22532
|
if (!builtinCommandsRef.current) builtinCommandsRef.current = createBuiltinCommands({
|
|
22095
22533
|
getCommands: () => commandsRef.current,
|
|
22096
|
-
reloadExtensions: () => reloadExtensionsRef.current()
|
|
22534
|
+
reloadExtensions: () => reloadExtensionsRef.current(),
|
|
22535
|
+
artifacts: {
|
|
22536
|
+
list: (scope) => listArtifactsRef.current(scope),
|
|
22537
|
+
projectRoot: () => sessionRef.current?.projectRoot ?? projectDirRef.current,
|
|
22538
|
+
registry: () => extensionRegistryRef.current,
|
|
22539
|
+
open: (scope) => openArtifactsRef.current(scope)
|
|
22540
|
+
}
|
|
22097
22541
|
});
|
|
22098
22542
|
commandsRef.current = useMemo(() => {
|
|
22099
22543
|
const merged = [];
|
|
@@ -22125,6 +22569,10 @@ function AppShell() {
|
|
|
22125
22569
|
getScope: () => chatReferenceScopeRef.current,
|
|
22126
22570
|
ensureCatalog: ensureChatCatalog
|
|
22127
22571
|
}),
|
|
22572
|
+
createArtifactsCompletionProvider({
|
|
22573
|
+
getCatalog: () => artifactCatalogSessionRef.current === sessionRef.current?.id ? artifactCatalogRef.current : [],
|
|
22574
|
+
ensureCatalog: ensureArtifactCatalog
|
|
22575
|
+
}),
|
|
22128
22576
|
...liveExtensionCompletionProviders
|
|
22129
22577
|
], [
|
|
22130
22578
|
filesCatalog,
|
|
@@ -22135,7 +22583,8 @@ function AppShell() {
|
|
|
22135
22583
|
chatReferenceScope,
|
|
22136
22584
|
ensureChatCatalog,
|
|
22137
22585
|
visibleChatCatalog,
|
|
22138
|
-
liveExtensionCompletionProviders
|
|
22586
|
+
liveExtensionCompletionProviders,
|
|
22587
|
+
ensureArtifactCatalog
|
|
22139
22588
|
]);
|
|
22140
22589
|
const inlineAutocompleteProviders = useMemo(() => [createPathAutocompleteProvider({ cwd: () => process.cwd() }), ...filterExtensionRegistry(extensionRegistry, settings.enabledExtensions).inlineAutocompleteProviders], [extensionRegistry, settings.enabledExtensions]);
|
|
22141
22590
|
useEffect(() => {
|
|
@@ -22564,7 +23013,7 @@ function AppShell() {
|
|
|
22564
23013
|
userDir: cacheDir,
|
|
22565
23014
|
sessionId: session.id
|
|
22566
23015
|
});
|
|
22567
|
-
const composedPreset = composeExtensionPreset(liveExtensionRegistry, profile.preset);
|
|
23016
|
+
const composedPreset = composeExtensionPreset(liveExtensionRegistry, composePresets(artifacts_default, profile.preset));
|
|
22568
23017
|
const modelCatalogTools = {};
|
|
22569
23018
|
const catalog = [];
|
|
22570
23019
|
for (const [providerKey, providerName] of nameByKey) for (const info of modelsFor(providerKey)) catalog.push({
|
|
@@ -22942,6 +23391,12 @@ function AppShell() {
|
|
|
22942
23391
|
});
|
|
22943
23392
|
if (name === "todowrite") notifyTodosChanged();
|
|
22944
23393
|
});
|
|
23394
|
+
agent.hooks.hook("artifact:recorded", () => {
|
|
23395
|
+
notifyArtifactsChanged();
|
|
23396
|
+
});
|
|
23397
|
+
agent.hooks.hook("child:artifact:recorded", () => {
|
|
23398
|
+
notifyArtifactsChanged();
|
|
23399
|
+
});
|
|
22945
23400
|
agent.hooks.hook("tool:error", ({ callId }) => {
|
|
22946
23401
|
unregisterInFlightTool(callId);
|
|
22947
23402
|
});
|
|
@@ -23498,6 +23953,7 @@ function AppShell() {
|
|
|
23498
23953
|
*/
|
|
23499
23954
|
const refreshSessionsRef = useRef(refreshSessions);
|
|
23500
23955
|
refreshSessionsRef.current = refreshSessions;
|
|
23956
|
+
refreshSessionsForArtifactsRef.current = refreshSessions;
|
|
23501
23957
|
const teardown = useCallback(async () => {
|
|
23502
23958
|
try {
|
|
23503
23959
|
daemonRef.current?.dispose();
|
|
@@ -23805,7 +24261,7 @@ function AppShell() {
|
|
|
23805
24261
|
});
|
|
23806
24262
|
stream.appendImmediate({
|
|
23807
24263
|
kind: "info",
|
|
23808
|
-
text:
|
|
24264
|
+
text: `model fallback: ${from.provider}/${from.model} failed, continuing on ${to.provider}/${to.model}`
|
|
23809
24265
|
});
|
|
23810
24266
|
},
|
|
23811
24267
|
onCacheBreak: (info) => {
|
|
@@ -23918,6 +24374,8 @@ function AppShell() {
|
|
|
23918
24374
|
const turnCost = usage.cost ?? 0;
|
|
23919
24375
|
if (turnCost > 0) setSessionCost((prev) => prev + turnCost);
|
|
23920
24376
|
},
|
|
24377
|
+
onArtifactRecorded: () => notifyArtifactsChanged(),
|
|
24378
|
+
onArtifactChanged: () => notifyArtifactsChanged(),
|
|
23921
24379
|
onTodosChanged: (snapshot) => {
|
|
23922
24380
|
todosApplySeqRef.current += 1;
|
|
23923
24381
|
const seq = todosApplySeqRef.current;
|
|
@@ -24011,13 +24469,13 @@ function AppShell() {
|
|
|
24011
24469
|
setDaemonHealth("connecting");
|
|
24012
24470
|
stream.appendImmediate({
|
|
24013
24471
|
kind: "info",
|
|
24014
|
-
text: "daemon connection lost
|
|
24472
|
+
text: "daemon connection lost, reconnecting"
|
|
24015
24473
|
});
|
|
24016
24474
|
setTimeout(() => {
|
|
24017
24475
|
if (sessionRef.current?.id === sessionId && settingsRef.current.useDaemon && daemonRef.current === controllerHandle) activateSessionRef.current(sessionId, pickedRef.current?.provider.key ?? "anthropic").catch(() => {
|
|
24018
24476
|
stream.appendImmediate({
|
|
24019
24477
|
kind: "error",
|
|
24020
|
-
text: "reconnect failed
|
|
24478
|
+
text: "reconnect failed. ctrl+r or reopen the session to retry"
|
|
24021
24479
|
});
|
|
24022
24480
|
});
|
|
24023
24481
|
}, 1500);
|
|
@@ -24045,7 +24503,7 @@ function AppShell() {
|
|
|
24045
24503
|
agentRef.current = buildAgent(session, key);
|
|
24046
24504
|
stream.appendImmediate({
|
|
24047
24505
|
kind: "info",
|
|
24048
|
-
text: `daemon unavailable (${errorMessage(err)})
|
|
24506
|
+
text: `daemon unavailable (${errorMessage(err)}), running this session in-process. Turn off “Use daemon runtime” to silence this.`
|
|
24049
24507
|
});
|
|
24050
24508
|
}
|
|
24051
24509
|
else agentRef.current = buildAgent(session, key);
|
|
@@ -24344,7 +24802,7 @@ function AppShell() {
|
|
|
24344
24802
|
* eviction makes the swap fully live, updated code included.
|
|
24345
24803
|
*/
|
|
24346
24804
|
const onUpdateExtension = useCallback(async (ext) => {
|
|
24347
|
-
if (!ext.dir) throw new Error(`"${ext.name}" is ${ext.source}
|
|
24805
|
+
if (!ext.dir) throw new Error(`"${ext.name}" is ${ext.source}: nothing on disk to update.`);
|
|
24348
24806
|
const result = await updateInstalledExtension({
|
|
24349
24807
|
dir: ext.dir,
|
|
24350
24808
|
cwd: cwdRef.current,
|
|
@@ -24357,7 +24815,7 @@ function AppShell() {
|
|
|
24357
24815
|
return `updated "${result.name}" → ${result.provenance}${delta}`;
|
|
24358
24816
|
}, [config.prefix, config.extensionScanPaths]);
|
|
24359
24817
|
const onRemoveExtension = useCallback(async (ext) => {
|
|
24360
|
-
if (!ext.dir) throw new Error(`"${ext.name}" is ${ext.source}
|
|
24818
|
+
if (!ext.dir) throw new Error(`"${ext.name}" is ${ext.source}: nothing on disk to remove.`);
|
|
24361
24819
|
removeInstalledExtension({
|
|
24362
24820
|
dir: ext.dir,
|
|
24363
24821
|
cwd: cwdRef.current,
|
|
@@ -24396,7 +24854,7 @@ function AppShell() {
|
|
|
24396
24854
|
...req.onProgress !== void 0 ? { onProgress: req.onProgress } : {}
|
|
24397
24855
|
});
|
|
24398
24856
|
} catch (err) {
|
|
24399
|
-
if (err instanceof ExtensionInstallError && err.code === "exists") throw new Error("already installed
|
|
24857
|
+
if (err instanceof ExtensionInstallError && err.code === "exists") throw new Error("already installed. Focus it and press ctrl+u to update, or ctrl+x to remove first.");
|
|
24400
24858
|
throw err;
|
|
24401
24859
|
}
|
|
24402
24860
|
const allow = enabledExtensionsRef.current;
|
|
@@ -24407,9 +24865,9 @@ function AppShell() {
|
|
|
24407
24865
|
}
|
|
24408
24866
|
const { active } = await reloadExtensionsRef.current();
|
|
24409
24867
|
const warnings = [...result.warnings];
|
|
24410
|
-
if (req.scope === "project" && !liveTrustProjectExtensions) warnings.push("Project extensions are
|
|
24411
|
-
const warn = warnings.length > 0 ?
|
|
24412
|
-
return `installed "${result.name}" (${result.provenance})
|
|
24868
|
+
if (req.scope === "project" && !liveTrustProjectExtensions) warnings.push("Project extensions are untrusted. Enable “Load project extensions” in Settings (or set ZIDANE_TRUST_PROJECT_EXTENSIONS=1) for it to load.");
|
|
24869
|
+
const warn = warnings.length > 0 ? `. ${warnings.join(". ")}` : "";
|
|
24870
|
+
return `installed "${result.name}" (${result.provenance}), ${active} active${warn}`;
|
|
24413
24871
|
}, [
|
|
24414
24872
|
config.prefix,
|
|
24415
24873
|
setSetting,
|
|
@@ -24434,8 +24892,8 @@ function AppShell() {
|
|
|
24434
24892
|
...req.onProgress !== void 0 ? { onProgress: req.onProgress } : {}
|
|
24435
24893
|
});
|
|
24436
24894
|
await onRefreshSkills();
|
|
24437
|
-
const skippedNote = result.skipped?.length ?
|
|
24438
|
-
const failedNote = result.failed?.length ?
|
|
24895
|
+
const skippedNote = result.skipped?.length ? `. Skipped existing: ${result.skipped.join(", ")}` : "";
|
|
24896
|
+
const failedNote = result.failed?.length ? `. Invalid: ${result.failed.join(", ")}` : "";
|
|
24439
24897
|
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}`;
|
|
24440
24898
|
}, [config.prefix, onRefreshSkills]);
|
|
24441
24899
|
/**
|
|
@@ -24469,8 +24927,8 @@ function AppShell() {
|
|
|
24469
24927
|
*/
|
|
24470
24928
|
const onRemoveSkill = useCallback(async (skill) => {
|
|
24471
24929
|
const dir = skill.baseDir ?? (skill.location ? dirname(skill.location) : void 0);
|
|
24472
|
-
if (!dir || skill.source === "inline" || skill.source === "builtin") throw new Error(`"${skill.name}" is ${skill.source ?? "inline"}
|
|
24473
|
-
if (!existsSync(join(dir, "SKILL.md"))) throw new Error(`${compactPath(dir)} has no SKILL.md
|
|
24930
|
+
if (!dir || skill.source === "inline" || skill.source === "builtin") throw new Error(`"${skill.name}" is ${skill.source ?? "inline"}: nothing on disk to delete.`);
|
|
24931
|
+
if (!existsSync(join(dir, "SKILL.md"))) throw new Error(`${compactPath(dir)} has no SKILL.md, not deleting.`);
|
|
24474
24932
|
rmSync(dir, {
|
|
24475
24933
|
recursive: true,
|
|
24476
24934
|
force: true
|
|
@@ -24495,7 +24953,7 @@ function AppShell() {
|
|
|
24495
24953
|
const onRemoveMcp = useCallback(async (entry) => {
|
|
24496
24954
|
const name = entry.config.name;
|
|
24497
24955
|
const prefix = (config.prefix ?? ".zidane").replace(/^\./, "");
|
|
24498
|
-
if (!entry.path.includes(`/.${prefix}/`)) throw new Error(`"${name}" is defined in ${compactPath(entry.path, 64)}
|
|
24956
|
+
if (!entry.path.includes(`/.${prefix}/`)) throw new Error(`"${name}" is defined in ${compactPath(entry.path, 64)}. zidane does not edit that file, remove the entry there.`);
|
|
24499
24957
|
removeMcpServer(entry.path, name);
|
|
24500
24958
|
const enabled = enabledMcpsRef.current;
|
|
24501
24959
|
if (enabled?.includes(name)) {
|
|
@@ -24907,7 +25365,7 @@ function AppShell() {
|
|
|
24907
25365
|
if (persisted?.status === "running" && Date.now() - persisted.updatedAt < 300 * 1e3 && !agent.isRunning && !(ownEnd?.id === session.id && persisted.updatedAt <= ownEnd.at + 2e3)) {
|
|
24908
25366
|
stream.appendImmediate({
|
|
24909
25367
|
kind: "error",
|
|
24910
|
-
text: "this session is running in another process
|
|
25368
|
+
text: "this session is running in another process. Wait for it to finish, interrupt it there, or enable \"Use daemon runtime\" to share the run."
|
|
24911
25369
|
});
|
|
24912
25370
|
return;
|
|
24913
25371
|
}
|
|
@@ -25168,7 +25626,7 @@ function AppShell() {
|
|
|
25168
25626
|
if (dataOpts.model && dataOpts.model !== picked.model) {
|
|
25169
25627
|
const ownerKey = credentialedModelEntries().find((e) => e.model.id === dataOpts.model)?.provider.key;
|
|
25170
25628
|
const owner = ownerKey ? providerRegistry[ownerKey] : void 0;
|
|
25171
|
-
if (!owner) throw new Error(`generateData: unknown model "${dataOpts.model}"
|
|
25629
|
+
if (!owner) throw new Error(`generateData: unknown model "${dataOpts.model}", not offered by any credentialed provider`);
|
|
25172
25630
|
genDescriptor = owner;
|
|
25173
25631
|
genModel = dataOpts.model;
|
|
25174
25632
|
}
|
|
@@ -25459,7 +25917,7 @@ function AppShell() {
|
|
|
25459
25917
|
onChunk: (acc) => upsertResult(lastLines(acc, BASH_STREAM_TAIL_LINES))
|
|
25460
25918
|
});
|
|
25461
25919
|
const body = tailTruncate(result.output.trim() || "(no output)", BASH_RESULT_MAX_BYTES);
|
|
25462
|
-
const overflowNote = result.overflowed ? "\n[output ceiling reached
|
|
25920
|
+
const overflowNote = result.overflowed ? "\n[output ceiling reached, process killed]" : "";
|
|
25463
25921
|
let finalText;
|
|
25464
25922
|
let isError = false;
|
|
25465
25923
|
if (result.aborted) {
|
|
@@ -25606,11 +26064,14 @@ function AppShell() {
|
|
|
25606
26064
|
const commandInvocation = parseCommandInvocation(effectivePrompt, commandsRef.current);
|
|
25607
26065
|
if (commandInvocation && extensionRegistry.commands.some((c) => c.name === commandInvocation.name)) {
|
|
25608
26066
|
try {
|
|
25609
|
-
await daemon.queueAdd(effectivePrompt, {
|
|
25610
|
-
|
|
25611
|
-
|
|
25612
|
-
|
|
25613
|
-
|
|
26067
|
+
await daemon.queueAdd(effectivePrompt, {
|
|
26068
|
+
asCommand: commandInvocation.name,
|
|
26069
|
+
...attachments.length > 0 ? { attachments: attachments.map((a) => ({
|
|
26070
|
+
mediaType: a.mediaType,
|
|
26071
|
+
data: a.content.toString("base64"),
|
|
26072
|
+
name: a.name
|
|
26073
|
+
})) } : {}
|
|
26074
|
+
});
|
|
25614
26075
|
} catch (err) {
|
|
25615
26076
|
stream.appendImmediate({
|
|
25616
26077
|
kind: "error",
|
|
@@ -25742,7 +26203,15 @@ function AppShell() {
|
|
|
25742
26203
|
throw err;
|
|
25743
26204
|
}
|
|
25744
26205
|
},
|
|
25745
|
-
workspaceAvailable: () => agentRef.current !== null
|
|
26206
|
+
workspaceAvailable: () => agentRef.current !== null,
|
|
26207
|
+
artifacts: () => {
|
|
26208
|
+
const session = sessionRef.current;
|
|
26209
|
+
return {
|
|
26210
|
+
store,
|
|
26211
|
+
...session ? { sessionId: session.id } : {},
|
|
26212
|
+
...session?.projectRoot ? { projectRoot: session.projectRoot } : {}
|
|
26213
|
+
};
|
|
26214
|
+
}
|
|
25746
26215
|
});
|
|
25747
26216
|
}, [
|
|
25748
26217
|
picked,
|
|
@@ -25750,7 +26219,8 @@ function AppShell() {
|
|
|
25750
26219
|
refreshSessions,
|
|
25751
26220
|
activateSession,
|
|
25752
26221
|
stream,
|
|
25753
|
-
credentialedModelEntries
|
|
26222
|
+
credentialedModelEntries,
|
|
26223
|
+
store
|
|
25754
26224
|
]);
|
|
25755
26225
|
/**
|
|
25756
26226
|
* Idle-path auto-wake: deliver queued `<task-notification>` blocks by
|
|
@@ -26245,7 +26715,7 @@ function AppShell() {
|
|
|
26245
26715
|
const hidden = transcriptSearchResults.length - shown.length;
|
|
26246
26716
|
if (hidden > 0) searchEvents.unshift({
|
|
26247
26717
|
kind: "info",
|
|
26248
|
-
text: `… ${hidden} earlier matched message${hidden === 1 ? "" : "s"} not shown
|
|
26718
|
+
text: `… ${hidden} earlier matched message${hidden === 1 ? "" : "s"} not shown. Refine the query to narrow results.`
|
|
26249
26719
|
});
|
|
26250
26720
|
return searchEvents;
|
|
26251
26721
|
}, [
|
|
@@ -26319,7 +26789,7 @@ function AppShell() {
|
|
|
26319
26789
|
if (runningRef.current) {
|
|
26320
26790
|
stream.appendImmediate({
|
|
26321
26791
|
kind: "error",
|
|
26322
|
-
text: "history
|
|
26792
|
+
text: "history cannot be edited while a run is in flight. Interrupt it first."
|
|
26323
26793
|
});
|
|
26324
26794
|
return null;
|
|
26325
26795
|
}
|
|
@@ -26327,7 +26797,7 @@ function AppShell() {
|
|
|
26327
26797
|
if (!fresh) {
|
|
26328
26798
|
stream.appendImmediate({
|
|
26329
26799
|
kind: "error",
|
|
26330
|
-
text: "could not reload the session for editing
|
|
26800
|
+
text: "could not reload the session for editing. Try again."
|
|
26331
26801
|
});
|
|
26332
26802
|
return null;
|
|
26333
26803
|
}
|
|
@@ -26356,7 +26826,7 @@ function AppShell() {
|
|
|
26356
26826
|
if (meta?.status === "running" && typeof meta.updatedAt === "number" && Date.now() - meta.updatedAt < 300 * 1e3) {
|
|
26357
26827
|
stream.appendImmediate({
|
|
26358
26828
|
kind: "error",
|
|
26359
|
-
text: "a run started while editing
|
|
26829
|
+
text: "a run started while editing, history was not modified. Interrupt the run and retry."
|
|
26360
26830
|
});
|
|
26361
26831
|
return false;
|
|
26362
26832
|
}
|
|
@@ -26530,7 +27000,7 @@ function AppShell() {
|
|
|
26530
27000
|
cacheDir
|
|
26531
27001
|
]);
|
|
26532
27002
|
const onGenerateTitle = useCallback(async (sessionId, signal) => {
|
|
26533
|
-
if (!picked) throw new Error("No provider picked
|
|
27003
|
+
if (!picked) throw new Error("No provider picked. Open the chat screen first.");
|
|
26534
27004
|
const descriptor = providerRegistry[picked.provider.key];
|
|
26535
27005
|
if (!descriptor) throw new Error(`Provider "${picked.provider.key}" is not registered.`);
|
|
26536
27006
|
let turns;
|
|
@@ -26616,7 +27086,7 @@ function AppShell() {
|
|
|
26616
27086
|
maybeAutoGenerateTitleRef.current = maybeAutoGenerateTitle;
|
|
26617
27087
|
}, [maybeAutoGenerateTitle]);
|
|
26618
27088
|
const onCompactSession = useCallback(async (sessionId, signal, onProgress) => {
|
|
26619
|
-
if (!picked) throw new Error("No provider picked
|
|
27089
|
+
if (!picked) throw new Error("No provider picked. Open the chat screen first.");
|
|
26620
27090
|
const descriptor = providerRegistry[picked.provider.key];
|
|
26621
27091
|
if (!descriptor) throw new Error(`Provider "${picked.provider.key}" is not registered.`);
|
|
26622
27092
|
const liveSession = sessionId === sessionRef.current?.id ? sessionRef.current : null;
|
|
@@ -26998,6 +27468,10 @@ function AppShell() {
|
|
|
26998
27468
|
}));
|
|
26999
27469
|
return;
|
|
27000
27470
|
}
|
|
27471
|
+
if (matchesBinding(key, keybindings.openArtifacts) && screen === "chat" && currentSession) {
|
|
27472
|
+
openArtifactsRef.current("session");
|
|
27473
|
+
return;
|
|
27474
|
+
}
|
|
27001
27475
|
if (matchesBinding(key, keybindings.openContextPanel) && screen === "chat" && picked) {
|
|
27002
27476
|
if (daemonRef.current) {
|
|
27003
27477
|
const controller = daemonRef.current;
|
|
@@ -27860,7 +28334,7 @@ function initTreeSitterWorker() {
|
|
|
27860
28334
|
const BASE_LEVELS = [
|
|
27861
28335
|
{
|
|
27862
28336
|
id: "off",
|
|
27863
|
-
description: "no reasoning
|
|
28337
|
+
description: "no reasoning. fastest, shortest output"
|
|
27864
28338
|
},
|
|
27865
28339
|
{
|
|
27866
28340
|
id: "minimal",
|
|
@@ -27872,11 +28346,11 @@ const BASE_LEVELS = [
|
|
|
27872
28346
|
},
|
|
27873
28347
|
{
|
|
27874
28348
|
id: "medium",
|
|
27875
|
-
description: "balanced
|
|
28349
|
+
description: "balanced. default"
|
|
27876
28350
|
},
|
|
27877
28351
|
{
|
|
27878
28352
|
id: "high",
|
|
27879
|
-
description: "
|
|
28353
|
+
description: "most reasoning. slowest, longest"
|
|
27880
28354
|
},
|
|
27881
28355
|
{
|
|
27882
28356
|
id: "xhigh",
|
|
@@ -28206,7 +28680,7 @@ function ExtensionsSettingsModal({ catalog, inactive }) {
|
|
|
28206
28680
|
}),
|
|
28207
28681
|
/* @__PURE__ */ jsx$1("span", {
|
|
28208
28682
|
fg: COLOR.mute,
|
|
28209
|
-
children: `
|
|
28683
|
+
children: ` · ${ext.error}`
|
|
28210
28684
|
})
|
|
28211
28685
|
]
|
|
28212
28686
|
}, ext.name))
|