zidane 5.9.13 → 5.9.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/dist/chat/pure.js +3 -2
  2. package/dist/chat.d.ts +2 -2
  3. package/dist/chat.js +5 -4
  4. package/dist/chat.js.map +1 -1
  5. package/dist/{edit-utils-CzHl1ct_.js → edit-utils-BkPqw6WE.js} +2 -135
  6. package/dist/edit-utils-BkPqw6WE.js.map +1 -0
  7. package/dist/eval.d.ts +1 -1
  8. package/dist/eval.js +2 -2
  9. package/dist/format-BNOXpl-1.js +136 -0
  10. package/dist/format-BNOXpl-1.js.map +1 -0
  11. package/dist/{headless-C15FmGco.js → headless-DNBpUy-6.js} +6 -6
  12. package/dist/headless-DNBpUy-6.js.map +1 -0
  13. package/dist/headless.d.ts +2 -2
  14. package/dist/headless.js +2 -2
  15. package/dist/{index-DgLlL4AT.d.ts → index-DutpkJJ7.d.ts} +3 -2
  16. package/dist/index-DutpkJJ7.d.ts.map +1 -0
  17. package/dist/index.d.ts +1 -1
  18. package/dist/index.js +4 -4
  19. package/dist/{login-DiSC5Ows.js → login-CVUjBzaO.js} +2 -2
  20. package/dist/{login-DiSC5Ows.js.map → login-CVUjBzaO.js.map} +1 -1
  21. package/dist/output/stream-json.d.ts +24 -0
  22. package/dist/output/stream-json.d.ts.map +1 -0
  23. package/dist/output/stream-json.js +37 -0
  24. package/dist/output/stream-json.js.map +1 -0
  25. package/dist/output/terminal.d.ts +16 -0
  26. package/dist/output/terminal.d.ts.map +1 -0
  27. package/dist/output/terminal.js +272 -0
  28. package/dist/output/terminal.js.map +1 -0
  29. package/dist/output.d.ts +3 -0
  30. package/dist/output.js +3 -0
  31. package/dist/{presets-ChaDIZaf.js → presets-DNuF7aK5.js} +2 -2
  32. package/dist/{presets-ChaDIZaf.js.map → presets-DNuF7aK5.js.map} +1 -1
  33. package/dist/presets.d.ts +1 -1
  34. package/dist/presets.js +1 -1
  35. package/dist/{tools-BLAxircm.js → tools-Cf5IsJEu.js} +3 -2
  36. package/dist/{tools-BLAxircm.js.map → tools-Cf5IsJEu.js.map} +1 -1
  37. package/dist/tools.d.ts +1 -1
  38. package/dist/tools.js +1 -1
  39. package/dist/{transcript-anchors-DELDp3Tl.d.ts → transcript-anchors-D7Nc5Rmy.d.ts} +2 -2
  40. package/dist/{transcript-anchors-DELDp3Tl.d.ts.map → transcript-anchors-D7Nc5Rmy.d.ts.map} +1 -1
  41. package/dist/{transcript-anchors-awh3E-cq.js → transcript-anchors-NA-s8Ore.js} +5 -5
  42. package/dist/{transcript-anchors-awh3E-cq.js.map → transcript-anchors-NA-s8Ore.js.map} +1 -1
  43. package/dist/tui.d.ts +1 -1
  44. package/dist/tui.js +6 -6
  45. package/dist/{turn-operations-CP8vfESx.js → turn-operations-BKg16YDb.js} +2 -2
  46. package/dist/{turn-operations-CP8vfESx.js.map → turn-operations-BKg16YDb.js.map} +1 -1
  47. package/dist/types.d.ts +1 -1
  48. package/docs/HEADLESS.md +57 -0
  49. package/package.json +13 -1
  50. package/dist/edit-utils-CzHl1ct_.js.map +0 -1
  51. package/dist/headless-C15FmGco.js.map +0 -1
  52. package/dist/index-DgLlL4AT.d.ts.map +0 -1
package/dist/chat/pure.js CHANGED
@@ -1,3 +1,4 @@
1
- import { a as compactPath, c as formatTaskStatus, d as shortId, f as buildContextBreakdown, i as ageString, l as formatTaskSummary, o as fmtTokens, s as formatDuration, u as previewLine } from "../edit-utils-CzHl1ct_.js";
2
- import { A as splitLines, B as summarizeOutcomes, C as buildContextualDiff, D as extractEditPayload, E as computeLineDiff, G as createFilesCompletionProvider, H as createSkillsCompletionProvider, J as collectReferences, K as uniqueFilesFromReferences, M as tokenize, O as filetypeFromPath, Q as buildLinearRamp, S as applyEditPayload, T as computeInlineDiff, U as uniqueSkillNamesFromReferences, V as SKILLS_TRIGGER, W as FILES_TRIGGER, X as mergeReferences, Y as findActiveTrigger, Z as blendHsl, _ as isEditErrorResult, a as TOOL_DISPLAY, b as selectableTurnIds, c as finalizeStreamingMarkdown, d as turnContextSize, f as splitPromptSegments, g as EDIT_TOOL_NAMES, h as indexOfEntry, i as turnAsText, j as summarizeEditPayload, k as previewEditPayload, l as finalizeStreamingMarkdownForOwner, m as filterModelCatalog, n as deleteTurnSafely, o as displayNameFor, p as buildModelCatalog, q as applyInsert, r as truncateTurnsAt, s as formatToolCall, t as countNeighbors, v as isTurnHighlighted, w as buildUnifiedDiff, x as turnSelectionOwnership, y as isVisible } from "../turn-operations-CP8vfESx.js";
1
+ import { i as buildContextBreakdown } from "../edit-utils-BkPqw6WE.js";
2
+ import { a as formatTaskStatus, c as shortId, i as formatDuration, n as compactPath, o as formatTaskSummary, r as fmtTokens, s as previewLine, t as ageString } from "../format-BNOXpl-1.js";
3
+ import { A as splitLines, B as summarizeOutcomes, C as buildContextualDiff, D as extractEditPayload, E as computeLineDiff, G as createFilesCompletionProvider, H as createSkillsCompletionProvider, J as collectReferences, K as uniqueFilesFromReferences, M as tokenize, O as filetypeFromPath, Q as buildLinearRamp, S as applyEditPayload, T as computeInlineDiff, U as uniqueSkillNamesFromReferences, V as SKILLS_TRIGGER, W as FILES_TRIGGER, X as mergeReferences, Y as findActiveTrigger, Z as blendHsl, _ as isEditErrorResult, a as TOOL_DISPLAY, b as selectableTurnIds, c as finalizeStreamingMarkdown, d as turnContextSize, f as splitPromptSegments, g as EDIT_TOOL_NAMES, h as indexOfEntry, i as turnAsText, j as summarizeEditPayload, k as previewEditPayload, l as finalizeStreamingMarkdownForOwner, m as filterModelCatalog, n as deleteTurnSafely, o as displayNameFor, p as buildModelCatalog, q as applyInsert, r as truncateTurnsAt, s as formatToolCall, t as countNeighbors, v as isTurnHighlighted, w as buildUnifiedDiff, x as turnSelectionOwnership, y as isVisible } from "../turn-operations-BKg16YDb.js";
3
4
  export { EDIT_TOOL_NAMES, FILES_TRIGGER, SKILLS_TRIGGER, TOOL_DISPLAY, ageString, applyEditPayload, applyInsert, blendHsl, buildContextBreakdown, buildContextualDiff, buildLinearRamp, buildModelCatalog, buildUnifiedDiff, collectReferences, compactPath, computeInlineDiff, computeLineDiff, countNeighbors, createFilesCompletionProvider, createSkillsCompletionProvider, deleteTurnSafely, displayNameFor, extractEditPayload, filetypeFromPath, filterModelCatalog, finalizeStreamingMarkdown, finalizeStreamingMarkdownForOwner, findActiveTrigger, fmtTokens, formatDuration, formatTaskStatus, formatTaskSummary, formatToolCall, indexOfEntry, isEditErrorResult, isTurnHighlighted, isVisible, mergeReferences, previewEditPayload, previewLine, selectableTurnIds, shortId, splitLines, splitPromptSegments, summarizeEditPayload, summarizeOutcomes, tokenize, truncateTurnsAt, turnAsText, turnContextSize, turnSelectionOwnership, uniqueFilesFromReferences, uniqueSkillNamesFromReferences };
package/dist/chat.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { $n as buildContextBreakdown, Gn as ContextBreakdownOptions, Jn as ContextExactCounts, Kn as ContextCategory, M as SkillsConfig, O as SkillConfig, P as Session, Qn as ContextUsageSplit, Wn as ContextBreakdown, Xn as ContextMcpGroup, Yn as ContextItem, Zn as ContextSnapshot, en as McpServerConfig, gn as SessionTurn, nn as McpToolSchema, qn as ContextCategoryId, r as AgentHooks, ut as Provider } from "./agent-CYPEZ9i3.js";
2
- import { H as McpCredentialEntry, U as McpCredentialStore, t as Preset } from "./index-DgLlL4AT.js";
2
+ import { H as McpCredentialEntry, U as McpCredentialStore, t as Preset } from "./index-DutpkJJ7.js";
3
3
  import { m as SourcedScanPath } from "./index-BangznMk.js";
4
- import { $ as useInteractionsQueue, $t as parseBindingSpec, A as InteractionsProvider, At as marginTopFor, B as QuestionPayload, Bt as KEYBINDING_DEF_BY_ACTION, C as ASK_USER_TOOL, Ct as TuiState, D as InteractionRequest, Dt as lastContextSizeFromTurns, E as CreateInteractionToolsOptions, Et as eventsFromTurns, F as PlanRequest, Ft as toolCallPreview, G as TextQuestion, Gt as KeyBindings, H as QuestionResponse, Ht as KeyAction, I as PlanResponse, It as toolResultText, J as isInteractionTool, Jt as formatBindingForDisplay, K as buildResumedToolResultsTurn, Kt as ParsedBinding, L as PlanStep, Lt as updateToolEventOutcomes, M as PendingInteractionEntry, Mt as stripSpawnTokensLine, N as PlanDecision, Nt as sumRunCosts, O as InteractionResponse, Ot as listSessionMeta, P as PlanPayload, Pt as titleFromTurns, Q as useInteractionsActions, Qt as mergeKeybindings, R as Question, Rt as DEFAULT_KEYBINDINGS, S as splitMarkdownCodeBlocks, St as StateStoreApi, T as ConfirmQuestion, Tt as deriveSessionTitle, U as QuestionType, Ut as KeyBindingDef, V as QuestionRequest, Vt as KEYBINDING_KEY_COL_WIDTH, W as SelectQuestion, Wt as KeyBindingSection, X as pendingInteractionsFromTurns, Xt as keybindingsPath, Y as makeRequestInteraction, Yt as groupBindings, Z as serializeInteractionResponse, Zt as matchesBinding, _ as SessionExportTarget, _n as PLAN_AGENT, _t as ResolveStorageDirsOptions, a as ChipColorMap, an as Hint, at as DiscoveryResult, b as writeSessionExport, bn as singleAgentRegistry, bt as StorageSlot, c as SyntaxTokenStyle, cn as truncateTrailing, ct as discoverProjectMcps, d as ThemeSelect, dn as AgentRegistry, dt as ChatOptions, en as readKeybindings, et as EnabledAllowlistKey, f as ThemeSurfaces, fn as BUILD_AGENT, ft as ProviderRegistry, g as SessionExportFormat, gn as DEFAULT_PERSIST_EXCLUDE_TOOLS, gt as resolveStoragePaths, h as SessionExportAnchor, hn as DEFAULT_BUDGET_EXCLUDE_TOOLS, ht as resolveConfig, i as ChipColor, in as EMPTY_HINTS, it as DiscoveryError, j as PRESENT_PLAN_TOOL, jt as saveState, k as InteractionsActions, kt as loadState, l as Theme, ln as AgentAccent, lt as parseMcpsFile, m as resolveTheme, mn as DEFAULT_AGENT_ID, mt as ResolvedPaths, n as computeTurnAnchors, nn as CompletionState, nt as useEnabledToggleSet, o as DEFAULT_THEME, on as clipHintsToWidth, ot as buildMcpServers, p as resolveChipColor, pn as BUILTIN_AGENTS, pt as ResolvedConfig, q as createInteractionTools, qt as ensureKeybindingsFile, r as BUILTIN_THEMES, rn as useCompletion, rt as DiscoveredMcp, s as SyntaxStyles, sn as hintsLength, st as defaultMcpsConfigPaths, t as TranscriptItem, tn as stripJsonComments, tt as EnabledToggleSet, u as ThemeColors, un as AgentProfile, ut as AutoUpdateConfig, v as renderSession, vn as accentColor, vt as StorageDirs, w as AnswerValue, wt as createStateStore, x as MarkdownSegment, xt as resolveStorageDirs, y as resolveSessionExportTarget, yn as resolveAgentId, yt as StorageMode, z as QuestionChoice, zt as KEYBINDING_DEFS } from "./transcript-anchors-DELDp3Tl.js";
4
+ import { $ as useInteractionsQueue, $t as parseBindingSpec, A as InteractionsProvider, At as marginTopFor, B as QuestionPayload, Bt as KEYBINDING_DEF_BY_ACTION, C as ASK_USER_TOOL, Ct as TuiState, D as InteractionRequest, Dt as lastContextSizeFromTurns, E as CreateInteractionToolsOptions, Et as eventsFromTurns, F as PlanRequest, Ft as toolCallPreview, G as TextQuestion, Gt as KeyBindings, H as QuestionResponse, Ht as KeyAction, I as PlanResponse, It as toolResultText, J as isInteractionTool, Jt as formatBindingForDisplay, K as buildResumedToolResultsTurn, Kt as ParsedBinding, L as PlanStep, Lt as updateToolEventOutcomes, M as PendingInteractionEntry, Mt as stripSpawnTokensLine, N as PlanDecision, Nt as sumRunCosts, O as InteractionResponse, Ot as listSessionMeta, P as PlanPayload, Pt as titleFromTurns, Q as useInteractionsActions, Qt as mergeKeybindings, R as Question, Rt as DEFAULT_KEYBINDINGS, S as splitMarkdownCodeBlocks, St as StateStoreApi, T as ConfirmQuestion, Tt as deriveSessionTitle, U as QuestionType, Ut as KeyBindingDef, V as QuestionRequest, Vt as KEYBINDING_KEY_COL_WIDTH, W as SelectQuestion, Wt as KeyBindingSection, X as pendingInteractionsFromTurns, Xt as keybindingsPath, Y as makeRequestInteraction, Yt as groupBindings, Z as serializeInteractionResponse, Zt as matchesBinding, _ as SessionExportTarget, _n as PLAN_AGENT, _t as ResolveStorageDirsOptions, a as ChipColorMap, an as Hint, at as DiscoveryResult, b as writeSessionExport, bn as singleAgentRegistry, bt as StorageSlot, c as SyntaxTokenStyle, cn as truncateTrailing, ct as discoverProjectMcps, d as ThemeSelect, dn as AgentRegistry, dt as ChatOptions, en as readKeybindings, et as EnabledAllowlistKey, f as ThemeSurfaces, fn as BUILD_AGENT, ft as ProviderRegistry, g as SessionExportFormat, gn as DEFAULT_PERSIST_EXCLUDE_TOOLS, gt as resolveStoragePaths, h as SessionExportAnchor, hn as DEFAULT_BUDGET_EXCLUDE_TOOLS, ht as resolveConfig, i as ChipColor, in as EMPTY_HINTS, it as DiscoveryError, j as PRESENT_PLAN_TOOL, jt as saveState, k as InteractionsActions, kt as loadState, l as Theme, ln as AgentAccent, lt as parseMcpsFile, m as resolveTheme, mn as DEFAULT_AGENT_ID, mt as ResolvedPaths, n as computeTurnAnchors, nn as CompletionState, nt as useEnabledToggleSet, o as DEFAULT_THEME, on as clipHintsToWidth, ot as buildMcpServers, p as resolveChipColor, pn as BUILTIN_AGENTS, pt as ResolvedConfig, q as createInteractionTools, qt as ensureKeybindingsFile, r as BUILTIN_THEMES, rn as useCompletion, rt as DiscoveredMcp, s as SyntaxStyles, sn as hintsLength, st as defaultMcpsConfigPaths, t as TranscriptItem, tn as stripJsonComments, tt as EnabledToggleSet, u as ThemeColors, un as AgentProfile, ut as AutoUpdateConfig, v as renderSession, vn as accentColor, vt as StorageDirs, w as AnswerValue, wt as createStateStore, x as MarkdownSegment, xt as resolveStorageDirs, y as resolveSessionExportTarget, yn as resolveAgentId, yt as StorageMode, z as QuestionChoice, zt as KEYBINDING_DEFS } from "./transcript-anchors-D7Nc5Rmy.js";
5
5
  import { $ as anthropicDescriptor, A as SessionMeta, B as collectReferences, C as EditHunk, D as Owner, E as EditPayload, F as CompletionContext, G as ProviderKey, H as mergeReferences, I as CompletionItem, J as CustomField, K as detectAuth, L as CompletionProvider, M as StreamEvent, N as ToolCallDisplay, O as Picked, P as ActiveTrigger, Q as ProviderDescriptor, R as CompletionReference, S as EditDiffDisplay, T as EditOutcomeKind, U as AuthMethod, V as findActiveTrigger, W as ProviderAuth, X as ModelOption, Y as ModelInfo, Z as OUTPUT_RESERVE_TOKENS, _ as isEditErrorResult, a as formatToolCall, at as getModelInfo, b as selectableTurnIds, c as splitPromptSegments, ct as modelSupportsReasoning, d as RequestApproval, dt as openrouterDescriptor, et as cerebrasDescriptor, f as SafeModeActions, ft as piIdOf, h as useSafeModeQueue, i as displayNameFor, it as getContextWindow, j as Settings, k as Screen, l as ApprovalDecision, lt as modelsForDescriptor, m as useSafeModeActions, n as ToolDisplayMeta, nt as effectiveContextWindow, o as PromptSegment, ot as localDescriptor, p as SafeModeProvider, pt as restoreModelOptions, q as BUILTIN_PROVIDERS, r as ToolFormatLine, rt as enabledModelOptions, s as PromptSegmentRef, st as modelOptionsFor, t as TOOL_DISPLAY, tt as credKeyOf, u as ApprovalRequest, ut as openaiDescriptor, v as isTurnHighlighted, w as EditOutcome, x as turnSelectionOwnership, y as isVisible, z as applyInsert } from "./tool-formatters-COxisyPk.js";
6
6
  import { $ as uniqueFilesFromReferences, A as buildUnifiedDiff, B as buildEditOutcomesAnnotation, C as EditSummary, D as PreviewResult, E as InlineSegment, F as previewEditPayload, G as rewriteMultiEditHeader, H as mergeApprovalAndBodyOutcomes, I as splitLines, J as SKILLS_TRIGGER, K as stripEditOutcomesAnnotation, L as summarizeEditPayload, M as computeLineDiff, N as extractEditPayload, O as applyEditPayload, P as filetypeFromPath, Q as createFilesCompletionProvider, R as tokenize, S as EditHunkSummary, T as InlineDiff, U as parseEditOutcomesFromResult, V as maskToOutcomeKinds, W as resolveApprovalForPayload, X as uniqueSkillNamesFromReferences, Y as createSkillsCompletionProvider, Z as FILES_TRIGGER, _ as formatTaskSummary, a as finalizeStreamingMarkdown, b as DiffLine, c as CatalogEntry, d as indexOfEntry, et as FileEntry, f as ageString, g as formatTaskStatus, h as formatDuration, i as turnAsText, it as buildLinearRamp, j as computeInlineDiff, k as buildContextualDiff, l as buildModelCatalog, m as fmtTokens, n as deleteTurnSafely, nt as listProjectFiles, o as finalizeStreamingMarkdownForOwner, p as compactPath, q as summarizeOutcomes, r as truncateTurnsAt, rt as blendHsl, s as turnContextSize, t as countNeighbors, tt as ListProjectFilesOptions, u as filterModelCatalog, v as previewLine, w as HunkResolution, x as DiffOp, y as shortId, z as ResolvedApproval } from "./turn-operations-BzYtF4E8.js";
7
7
  import { Hookable } from "hookable";
package/dist/chat.js CHANGED
@@ -1,7 +1,8 @@
1
- import { $ as useMcpAuthDispatch, $n as BUILD_AGENT, $t as deriveSessionTitle, A as runOAuthLogin, An as buildUpdateHint, Ar as SUBAGENT_GUIDANCE, B as refreshMcpToolsCatalog, Bn as AUTO_COMPACT_MIN_GROWTH_FRACTION, Bt as CATPPUCCIN_LATTE, C as projectsFilePath, Cn as parseBindingSpec, Cr as COMMUNICATION_DOCTRINE, Ct as listProjectFiles, D as formatPathForCwd, Dn as tryOpenBrowser, Dr as INTERACTION_GUIDANCE_NO_PROMPTS, Dt as SETTINGS_CHOICES, E as writeProjects, En as useCompletion, Er as INTERACTION_GUIDANCE, Et as SETTINGS_CATEGORIES, F as parseMcpsFile, Fn as detectPackageManager, Ft as resolveTheme, G as useMcpToolToggleSet, Gn as readCredentials, Gt as useDiscovery, H as subscribeMcpToolsCache, Hn as detectAuth, Ht as CATPPUCCIN_MOCHA, I as projectUserPaths, In as parseSemver, It as VAPORWAVE_THEME, J as parentServerName, Jn as setProviderCredential, Jt as useConfig, K as buildVisibleMcpRows, Kn as readProviderCredential, Kt as useDiscoveryOptional, L as clearMcpToolsCache, Ln as performInPlaceSelfUpdate, Lt as GRUVBOX_DARK, M as buildMcpServers, Mn as checkForUpdate, Mr as buildBuildSystem, Mt as BUILTIN_THEMES, N as defaultMcpsConfigPaths, Nn as compareSemver, Nr as buildPlanSystem, Nt as DEFAULT_THEME, O as fetchOAuthRedirect, On as bootProfileEnabled, Or as PLAN_MODE_DOCTRINE, Ot as SETTINGS_TOGGLES, P as discoverProjectMcps, Pn as detectLibc, Pr as envSection, Pt as resolveChipColor, Q as McpAuthProvider, Qn as findGitRoot, Qt as createStateStore, R as loadMcpToolsCache, Rn as performSelfUpdate, Rt as GRUVBOX_LIGHT, S as matchesSafelistEntry, Sn as mergeKeybindings, Sr as ACTIONS_WITH_CARE_DOCTRINE, St as shortChord, T as suggestSafelistEntry, Tn as stripJsonComments, Tr as IDENTITY_PREFIX, Tt as DEFAULT_SETTINGS, U as buildToolToggle, Un as applyApiKeyEnv, Ut as createDiscoverySlot, V as saveMcpToolsCache, Vn as shouldAutoCompact, Vt as CATPPUCCIN_MACCHIATO, W as useMcpToolToggleMap, Wn as credentialsPath, Wt as DiscoveryProvider, X as mcpCredentialsPath, Xn as discoverAgentsMd, Xt as resolveStoragePaths, Y as createFileMcpCredentialStore, Yn as writeCredentials, Yt as resolveConfig, Z as patchMcpCredential, Zn as renderAgentsMdBlock, Zt as resolveStorageDirs, _ as useSafeModeQueue, _n as ensureKeybindingsFile, _r as pickActiveRunId, _t as hintsLength, a as useSurfaces, an as saveState, ar as accentColor, at as InteractionsProvider, b as getSafelist, bn as keybindingsPath, br as setTodosForRun, bt as generateSessionTitle, c as useStreamBuffer, cn as sumRunCosts, cr as TODOREAD_TOOL, ct as createInteractionTools, d as discoverProjectSkills, dn as toolResultText, dr as TODO_STATUS_GLYPHS, dt as pendingInteractionsFromTurns, en as eventsFromTurns, er as BUILTIN_AGENTS, et as useMcpAuthState, f as renderSession, fn as updateToolEventOutcomes, fr as TODO_WRITE_COUNTS_METADATA_KEY, ft as serializeInteractionResponse, g as useSafeModeActions, gn as KEYBINDING_KEY_COL_WIDTH, gr as isTodoTool, gt as clipHintsToWidth, h as SafeModeProvider, hn as KEYBINDING_DEF_BY_ACTION, hr as getTodosForRun, ht as EMPTY_HINTS, i as useSelectStyle, in as marginTopFor, ir as PLAN_AGENT, it as ASK_USER_TOOL, j as supportsOAuth, jn as useUpdateCheck, jr as TOKEN_DISCIPLINE_DOCTRINE, jt as useSettings, k as oauthUsesManualCodePaste, kn as bootTick, kr as PLAN_MODE_DOCTRINE_NO_PROMPTS, kt as SettingsProvider, l as buildSkillsConfig, ln as titleFromTurns, lr as TODOS_METADATA_KEY, lt as isInteractionTool, m as writeSessionExport, mn as KEYBINDING_DEFS, mr as getArchivedTodosForRun, mt as useInteractionsQueue, n as ThemeProvider, nn as listSessionMeta, nr as DEFAULT_BUDGET_EXCLUDE_TOOLS, nt as reduceMcpAuth, o as useSyntaxStyles, or as resolveAgentId, ot as PRESENT_PLAN_TOOL, p as resolveSessionExportTarget, pn as DEFAULT_KEYBINDINGS, pr as createTodoTools, pt as useInteractionsActions, q as indexOfServerRow, qn as removeProviderCredential, qt as ConfigProvider, r as useColors, rn as loadState, rr as DEFAULT_PERSIST_EXCLUDE_TOOLS, rt as splitMarkdownCodeBlocks, s as useTheme, sn as stripSpawnTokensLine, sr as singleAgentRegistry, st as buildResumedToolResultsTurn, t as computeTurnAnchors, tn as lastContextSizeFromTurns, tr as DEFAULT_AGENT_ID, tt as getMcpAuthStatus, u as defaultSkillScanPaths, un as toolCallPreview, ur as TODOWRITE_TOOL, ut as makeRequestInteraction, v as IMPLICITLY_SAFE_TOOLS, vn as formatBindingForDisplay, vr as pruneTodosByRun, vt as truncateTrailing, w as readProjects, wn as readKeybindings, wr as DOING_TASKS_DOCTRINE, wt as useEnabledToggleSet, x as isOnSafelist, xn as matchesBinding, xr as useActiveTodos, xt as buildHints, y as addToSafelist, yn as groupBindings, yr as selectActiveTodos, yt as cleanTitle, z as mcpToolsCachePath, zn as resolvePlatformPackage, zt as CATPPUCCIN_FRAPPE } from "./transcript-anchors-awh3E-cq.js";
2
- import { B as credKeyOf, G as localDescriptor, H as enabledModelOptions, I as BUILTIN_PROVIDERS, J as modelsForDescriptor, K as modelOptionsFor, L as OUTPUT_RESERVE_TOKENS, Q as restoreModelOptions, R as anthropicDescriptor, U as getContextWindow, V as effectiveContextWindow, W as getModelInfo, X as openrouterDescriptor, Y as openaiDescriptor, Z as piIdOf, q as modelSupportsReasoning, z as cerebrasDescriptor } from "./tools-BLAxircm.js";
3
- import { a as compactPath, c as formatTaskStatus, d as shortId, f as buildContextBreakdown, i as ageString, l as formatTaskSummary, o as fmtTokens, s as formatDuration, u as previewLine } from "./edit-utils-CzHl1ct_.js";
4
- import { A as splitLines, B as summarizeOutcomes, C as buildContextualDiff, D as extractEditPayload, E as computeLineDiff, F as mergeApprovalAndBodyOutcomes, G as createFilesCompletionProvider, H as createSkillsCompletionProvider, I as parseEditOutcomesFromResult, J as collectReferences, K as uniqueFilesFromReferences, L as resolveApprovalForPayload, M as tokenize, N as buildEditOutcomesAnnotation, O as filetypeFromPath, P as maskToOutcomeKinds, Q as buildLinearRamp, R as rewriteMultiEditHeader, S as applyEditPayload, T as computeInlineDiff, U as uniqueSkillNamesFromReferences, V as SKILLS_TRIGGER, W as FILES_TRIGGER, X as mergeReferences, Y as findActiveTrigger, Z as blendHsl, _ as isEditErrorResult, a as TOOL_DISPLAY, b as selectableTurnIds, c as finalizeStreamingMarkdown, d as turnContextSize, f as splitPromptSegments, h as indexOfEntry, i as turnAsText, j as summarizeEditPayload, k as previewEditPayload, l as finalizeStreamingMarkdownForOwner, m as filterModelCatalog, n as deleteTurnSafely, o as displayNameFor, p as buildModelCatalog, q as applyInsert, r as truncateTurnsAt, s as formatToolCall, t as countNeighbors, v as isTurnHighlighted, w as buildUnifiedDiff, x as turnSelectionOwnership, y as isVisible, z as stripEditOutcomesAnnotation } from "./turn-operations-CP8vfESx.js";
1
+ import { $ as useMcpAuthDispatch, $n as BUILD_AGENT, $t as deriveSessionTitle, A as runOAuthLogin, An as buildUpdateHint, Ar as SUBAGENT_GUIDANCE, B as refreshMcpToolsCatalog, Bn as AUTO_COMPACT_MIN_GROWTH_FRACTION, Bt as CATPPUCCIN_LATTE, C as projectsFilePath, Cn as parseBindingSpec, Cr as COMMUNICATION_DOCTRINE, Ct as listProjectFiles, D as formatPathForCwd, Dn as tryOpenBrowser, Dr as INTERACTION_GUIDANCE_NO_PROMPTS, Dt as SETTINGS_CHOICES, E as writeProjects, En as useCompletion, Er as INTERACTION_GUIDANCE, Et as SETTINGS_CATEGORIES, F as parseMcpsFile, Fn as detectPackageManager, Ft as resolveTheme, G as useMcpToolToggleSet, Gn as readCredentials, Gt as useDiscovery, H as subscribeMcpToolsCache, Hn as detectAuth, Ht as CATPPUCCIN_MOCHA, I as projectUserPaths, In as parseSemver, It as VAPORWAVE_THEME, J as parentServerName, Jn as setProviderCredential, Jt as useConfig, K as buildVisibleMcpRows, Kn as readProviderCredential, Kt as useDiscoveryOptional, L as clearMcpToolsCache, Ln as performInPlaceSelfUpdate, Lt as GRUVBOX_DARK, M as buildMcpServers, Mn as checkForUpdate, Mr as buildBuildSystem, Mt as BUILTIN_THEMES, N as defaultMcpsConfigPaths, Nn as compareSemver, Nr as buildPlanSystem, Nt as DEFAULT_THEME, O as fetchOAuthRedirect, On as bootProfileEnabled, Or as PLAN_MODE_DOCTRINE, Ot as SETTINGS_TOGGLES, P as discoverProjectMcps, Pn as detectLibc, Pr as envSection, Pt as resolveChipColor, Q as McpAuthProvider, Qn as findGitRoot, Qt as createStateStore, R as loadMcpToolsCache, Rn as performSelfUpdate, Rt as GRUVBOX_LIGHT, S as matchesSafelistEntry, Sn as mergeKeybindings, Sr as ACTIONS_WITH_CARE_DOCTRINE, St as shortChord, T as suggestSafelistEntry, Tn as stripJsonComments, Tr as IDENTITY_PREFIX, Tt as DEFAULT_SETTINGS, U as buildToolToggle, Un as applyApiKeyEnv, Ut as createDiscoverySlot, V as saveMcpToolsCache, Vn as shouldAutoCompact, Vt as CATPPUCCIN_MACCHIATO, W as useMcpToolToggleMap, Wn as credentialsPath, Wt as DiscoveryProvider, X as mcpCredentialsPath, Xn as discoverAgentsMd, Xt as resolveStoragePaths, Y as createFileMcpCredentialStore, Yn as writeCredentials, Yt as resolveConfig, Z as patchMcpCredential, Zn as renderAgentsMdBlock, Zt as resolveStorageDirs, _ as useSafeModeQueue, _n as ensureKeybindingsFile, _r as pickActiveRunId, _t as hintsLength, a as useSurfaces, an as saveState, ar as accentColor, at as InteractionsProvider, b as getSafelist, bn as keybindingsPath, br as setTodosForRun, bt as generateSessionTitle, c as useStreamBuffer, cn as sumRunCosts, cr as TODOREAD_TOOL, ct as createInteractionTools, d as discoverProjectSkills, dn as toolResultText, dr as TODO_STATUS_GLYPHS, dt as pendingInteractionsFromTurns, en as eventsFromTurns, er as BUILTIN_AGENTS, et as useMcpAuthState, f as renderSession, fn as updateToolEventOutcomes, fr as TODO_WRITE_COUNTS_METADATA_KEY, ft as serializeInteractionResponse, g as useSafeModeActions, gn as KEYBINDING_KEY_COL_WIDTH, gr as isTodoTool, gt as clipHintsToWidth, h as SafeModeProvider, hn as KEYBINDING_DEF_BY_ACTION, hr as getTodosForRun, ht as EMPTY_HINTS, i as useSelectStyle, in as marginTopFor, ir as PLAN_AGENT, it as ASK_USER_TOOL, j as supportsOAuth, jn as useUpdateCheck, jr as TOKEN_DISCIPLINE_DOCTRINE, jt as useSettings, k as oauthUsesManualCodePaste, kn as bootTick, kr as PLAN_MODE_DOCTRINE_NO_PROMPTS, kt as SettingsProvider, l as buildSkillsConfig, ln as titleFromTurns, lr as TODOS_METADATA_KEY, lt as isInteractionTool, m as writeSessionExport, mn as KEYBINDING_DEFS, mr as getArchivedTodosForRun, mt as useInteractionsQueue, n as ThemeProvider, nn as listSessionMeta, nr as DEFAULT_BUDGET_EXCLUDE_TOOLS, nt as reduceMcpAuth, o as useSyntaxStyles, or as resolveAgentId, ot as PRESENT_PLAN_TOOL, p as resolveSessionExportTarget, pn as DEFAULT_KEYBINDINGS, pr as createTodoTools, pt as useInteractionsActions, q as indexOfServerRow, qn as removeProviderCredential, qt as ConfigProvider, r as useColors, rn as loadState, rr as DEFAULT_PERSIST_EXCLUDE_TOOLS, rt as splitMarkdownCodeBlocks, s as useTheme, sn as stripSpawnTokensLine, sr as singleAgentRegistry, st as buildResumedToolResultsTurn, t as computeTurnAnchors, tn as lastContextSizeFromTurns, tr as DEFAULT_AGENT_ID, tt as getMcpAuthStatus, u as defaultSkillScanPaths, un as toolCallPreview, ur as TODOWRITE_TOOL, ut as makeRequestInteraction, v as IMPLICITLY_SAFE_TOOLS, vn as formatBindingForDisplay, vr as pruneTodosByRun, vt as truncateTrailing, w as readProjects, wn as readKeybindings, wr as DOING_TASKS_DOCTRINE, wt as useEnabledToggleSet, x as isOnSafelist, xn as matchesBinding, xr as useActiveTodos, xt as buildHints, y as addToSafelist, yn as groupBindings, yr as selectActiveTodos, yt as cleanTitle, z as mcpToolsCachePath, zn as resolvePlatformPackage, zt as CATPPUCCIN_FRAPPE } from "./transcript-anchors-NA-s8Ore.js";
2
+ import { B as credKeyOf, G as localDescriptor, H as enabledModelOptions, I as BUILTIN_PROVIDERS, J as modelsForDescriptor, K as modelOptionsFor, L as OUTPUT_RESERVE_TOKENS, Q as restoreModelOptions, R as anthropicDescriptor, U as getContextWindow, V as effectiveContextWindow, W as getModelInfo, X as openrouterDescriptor, Y as openaiDescriptor, Z as piIdOf, q as modelSupportsReasoning, z as cerebrasDescriptor } from "./tools-Cf5IsJEu.js";
3
+ import { i as buildContextBreakdown } from "./edit-utils-BkPqw6WE.js";
4
+ import { a as formatTaskStatus, c as shortId, i as formatDuration, n as compactPath, o as formatTaskSummary, r as fmtTokens, s as previewLine, t as ageString } from "./format-BNOXpl-1.js";
5
+ import { A as splitLines, B as summarizeOutcomes, C as buildContextualDiff, D as extractEditPayload, E as computeLineDiff, F as mergeApprovalAndBodyOutcomes, G as createFilesCompletionProvider, H as createSkillsCompletionProvider, I as parseEditOutcomesFromResult, J as collectReferences, K as uniqueFilesFromReferences, L as resolveApprovalForPayload, M as tokenize, N as buildEditOutcomesAnnotation, O as filetypeFromPath, P as maskToOutcomeKinds, Q as buildLinearRamp, R as rewriteMultiEditHeader, S as applyEditPayload, T as computeInlineDiff, U as uniqueSkillNamesFromReferences, V as SKILLS_TRIGGER, W as FILES_TRIGGER, X as mergeReferences, Y as findActiveTrigger, Z as blendHsl, _ as isEditErrorResult, a as TOOL_DISPLAY, b as selectableTurnIds, c as finalizeStreamingMarkdown, d as turnContextSize, f as splitPromptSegments, h as indexOfEntry, i as turnAsText, j as summarizeEditPayload, k as previewEditPayload, l as finalizeStreamingMarkdownForOwner, m as filterModelCatalog, n as deleteTurnSafely, o as displayNameFor, p as buildModelCatalog, q as applyInsert, r as truncateTurnsAt, s as formatToolCall, t as countNeighbors, v as isTurnHighlighted, w as buildUnifiedDiff, x as turnSelectionOwnership, y as isVisible, z as stripEditOutcomesAnnotation } from "./turn-operations-BKg16YDb.js";
5
6
  //#region src/chat/auto-update-cli.ts
6
7
  const UPGRADE_HELP = `Usage: zidane upgrade [options]
7
8
 
package/dist/chat.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"chat.js","names":[],"sources":["../src/chat/auto-update-cli.ts"],"sourcesContent":["// ---------------------------------------------------------------------------\n// `zidane upgrade` subcommand — drop-in handler for consumer CLIs.\n//\n// Wraps `checkForUpdate` + `performSelfUpdate` + `performInPlaceSelfUpdate`\n// into a single function the host's `cli.ts` can call. The behavior layers:\n//\n// - no flags → check + run the package manager\n// - `--check` → check only, print the latest version + bail\n// - `--in-place` → skip the PM, download + atomic-rename the binary\n// - `--dry-run` → resolve everything but don't actually swap\n// - `--channel <tag>` → override dist-tag (defaults to `'latest'`)\n// - `--registry <url>`→ override the npm registry URL\n//\n// Pure I/O — writes to stdout/stderr, returns the exit code the caller\n// should pass to `process.exit`. No React, no OpenTUI; safe to call\n// before / instead of `runTui`.\n// ---------------------------------------------------------------------------\n\nimport {\n checkForUpdate,\n compareSemver,\n detectPackageManager,\n performInPlaceSelfUpdate,\n performSelfUpdate,\n resolvePlatformPackage,\n} from './auto-update'\n\nexport interface RunUpdateCommandOptions {\n /** Top-level package the user installs (e.g. `'zidane-tui'`). */\n packageName: string\n /** Inlined at build time. */\n currentVersion: string\n /** Args passed after `upgrade` (typically `process.argv.slice(3)`). */\n argv: readonly string[]\n /** Where to persist the TTL cache. Usually `paths.userDir`. */\n cacheDir?: string\n /** Default channel when `--channel` isn't passed. Defaults to `'latest'`. */\n defaultChannel?: string\n /**\n * Override the platform-package-name prefix used by `--in-place`.\n * Defaults to `'<packageName>-'`, matching the `zidane-tui-<key>` layout.\n */\n platformPackagePrefix?: string\n /** Override registry. Defaults to npmjs. */\n registry?: string\n /** stdout. Defaults to `process.stdout`. */\n stdout?: NodeJS.WritableStream\n /** stderr. Defaults to `process.stderr`. */\n stderr?: NodeJS.WritableStream\n}\n\nexport interface RunUpdateCommandResult {\n exitCode: number\n}\n\nconst UPGRADE_HELP = `Usage: zidane upgrade [options]\n\nUpdate the zidane CLI to the latest release.\n\nOptions:\n --check Print the latest version and exit (no install).\n --in-place Download the platform binary directly from npm\n and atomic-rename over the running binary.\n Skips the package manager. Refused on Volta.\n --dry-run Resolve everything but don't actually install.\n --channel <tag> dist-tag to query (default: latest).\n --registry <url> Override the npm registry.\n --package-manager <pm> Force npm | pnpm | yarn | bun | volta.\n --force Run the install even if we're already on latest,\n or the registry check failed.\n -h, --help Print this help.\n\nEnvironment:\n NO_UPDATE_NOTIFIER Silence the background check (set to \"1\").\n ZIDANE_NO_UPDATE Same, project-specific.\n`\n\n/**\n * Run the `upgrade` subcommand. Exit code contract:\n * - `0` — update succeeded, `--check` reported no update, or `--check`\n * reported an update (informational only).\n * - `1` — update failed (PM exit non-zero, in-place download failed,\n * registry returned non-2xx).\n * - `2` — argv parse error (unknown flag).\n */\nexport async function runUpdateCommand(options: RunUpdateCommandOptions): Promise<RunUpdateCommandResult> {\n const out = options.stdout ?? process.stdout\n const err = options.stderr ?? process.stderr\n const parsed = parseArgs(options.argv)\n if (parsed.kind === 'error') {\n err.write(`zidane upgrade: ${parsed.message}\\n`)\n err.write(UPGRADE_HELP)\n return { exitCode: 2 }\n }\n if (parsed.help) {\n out.write(UPGRADE_HELP)\n return { exitCode: 0 }\n }\n\n const channel = parsed.channel ?? options.defaultChannel ?? 'latest'\n const registry = parsed.registry ?? options.registry\n\n // Always force the check — user typed `upgrade`, env opt-outs shouldn't\n // get in the way.\n const status = await checkForUpdate({\n packageName: options.packageName,\n currentVersion: options.currentVersion,\n channel,\n registry,\n cacheDir: options.cacheDir,\n force: true,\n timeoutMs: 8000,\n })\n\n // `--check` is informational — degrade gracefully on registry errors\n // (offline laptop, restricted proxy) and exit 0 so the user can script\n // around it without quoting tricks.\n if (parsed.check) {\n if (status.source === 'error') {\n err.write(`Could not check \\`${channel}\\` (${status.error ?? 'unknown error'}). Current: v${options.currentVersion}.\\n`)\n return { exitCode: 0 }\n }\n if (!status.latest) {\n err.write(`Could not determine latest version on \\`${channel}\\`. Current: v${options.currentVersion}.\\n`)\n return { exitCode: 0 }\n }\n const cmp = compareSemver(status.latest, options.currentVersion)\n if (cmp > 0)\n out.write(`v${status.latest} is available on \\`${channel}\\` (current: v${options.currentVersion}).\\n`)\n else\n out.write(`Already on v${options.currentVersion} (latest on \\`${channel}\\` is v${status.latest}).\\n`)\n return { exitCode: 0 }\n }\n\n // Install path — a registry error means we don't KNOW if we need an\n // update. Refuse to spawn the PM blindly unless the user explicitly\n // asks via `--force`.\n if (status.source === 'error') {\n err.write(`zidane upgrade: registry check failed (${status.error ?? 'unknown error'})\\n`)\n if (!parsed.force) {\n err.write('Pass --force to attempt the install anyway.\\n')\n return { exitCode: 1 }\n }\n }\n\n if (status.latest && !parsed.force) {\n const cmp = compareSemver(status.latest, options.currentVersion)\n if (cmp <= 0) {\n out.write(`Already on v${options.currentVersion} (latest on \\`${channel}\\` is v${status.latest}).\\n`)\n return { exitCode: 0 }\n }\n }\n\n // ---------------------------------------------------------------------\n // In-place path\n // ---------------------------------------------------------------------\n\n if (parsed.inPlace) {\n const platformPkg = resolvePlatformPackage({\n prefix: options.platformPackagePrefix ?? `${options.packageName}-`,\n })\n if (!platformPkg) {\n err.write(`No prebuilt binary for ${process.platform}/${process.arch}. Run \\`${options.packageName}-upgrade\\` via your package manager instead.\\n`)\n return { exitCode: 1 }\n }\n out.write(`Downloading ${platformPkg}@${channel}…\\n`)\n const result = await performInPlaceSelfUpdate({\n packageName: platformPkg,\n channel,\n registry,\n dryRun: parsed.dryRun,\n })\n if (result.status === 'success') {\n const verb = parsed.dryRun ? 'Would install' : 'Installed'\n out.write(`${verb} v${result.installedVersion} at ${result.binaryPath}.\\n`)\n return { exitCode: 0 }\n }\n err.write(`In-place update failed: ${result.reason ?? 'unknown error'}\\n`)\n if (result.status === 'refused')\n err.write('Falling back to package-manager path (drop --in-place to retry).\\n')\n return { exitCode: 1 }\n }\n\n // ---------------------------------------------------------------------\n // Package-manager path\n // ---------------------------------------------------------------------\n\n const detected = detectPackageManager({ packageName: options.packageName, channel })\n if (detected.note)\n out.write(`${detected.note}\\n`)\n out.write(`Running: ${detected.argv.join(' ')}\\n`)\n if (parsed.dryRun)\n return { exitCode: 0 }\n\n const result = await performSelfUpdate({\n packageName: options.packageName,\n channel,\n packageManager: parsed.packageManager ?? 'auto',\n })\n if (result.spawnError) {\n err.write(`Failed to launch \\`${result.command.argv[0]}\\`: ${result.spawnError}\\n`)\n err.write('Is the package manager installed and on $PATH?\\n')\n return { exitCode: 1 }\n }\n return { exitCode: result.exitCode ?? 1 }\n}\n\n// ---------------------------------------------------------------------------\n// Argv parser — minimal, just enough to drop into the consumer's `cli.ts`.\n// We deliberately don't pull in commander/yargs for a 5-flag surface.\n// ---------------------------------------------------------------------------\n\ntype ParseResult\n = | {\n kind: 'ok'\n check: boolean\n inPlace: boolean\n dryRun: boolean\n force: boolean\n help: boolean\n channel?: string\n registry?: string\n packageManager?: 'npm' | 'pnpm' | 'yarn' | 'bun' | 'volta'\n }\n | { kind: 'error', message: string }\n\nfunction parseArgs(argv: readonly string[]): ParseResult {\n let check = false\n let inPlace = false\n let dryRun = false\n let force = false\n let help = false\n let channel: string | undefined\n let registry: string | undefined\n let packageManager: 'npm' | 'pnpm' | 'yarn' | 'bun' | 'volta' | undefined\n\n for (let i = 0; i < argv.length; i++) {\n const a = argv[i]!\n switch (a) {\n case '--check': check = true; break\n case '--in-place':\n case '--inplace': inPlace = true; break\n case '--dry-run':\n case '--dryrun': dryRun = true; break\n case '--force': force = true; break\n case '-h':\n case '--help': help = true; break\n case '--channel':\n channel = argv[++i]\n if (!channel)\n return { kind: 'error', message: '--channel requires a value' }\n break\n case '--registry':\n registry = argv[++i]\n if (!registry)\n return { kind: 'error', message: '--registry requires a value' }\n break\n case '--package-manager':\n case '--pm': {\n const v = argv[++i]\n if (!v)\n return { kind: 'error', message: '--package-manager requires a value' }\n if (v !== 'npm' && v !== 'pnpm' && v !== 'yarn' && v !== 'bun' && v !== 'volta')\n return { kind: 'error', message: `unknown package manager: ${v}` }\n packageManager = v\n break\n }\n default:\n return { kind: 'error', message: `unknown argument: ${a}` }\n }\n }\n\n return { kind: 'ok', check, inPlace, dryRun, force, help, channel, registry, packageManager }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"chat.js","names":[],"sources":["../src/chat/auto-update-cli.ts"],"sourcesContent":["// ---------------------------------------------------------------------------\n// `zidane upgrade` subcommand — drop-in handler for consumer CLIs.\n//\n// Wraps `checkForUpdate` + `performSelfUpdate` + `performInPlaceSelfUpdate`\n// into a single function the host's `cli.ts` can call. The behavior layers:\n//\n// - no flags → check + run the package manager\n// - `--check` → check only, print the latest version + bail\n// - `--in-place` → skip the PM, download + atomic-rename the binary\n// - `--dry-run` → resolve everything but don't actually swap\n// - `--channel <tag>` → override dist-tag (defaults to `'latest'`)\n// - `--registry <url>`→ override the npm registry URL\n//\n// Pure I/O — writes to stdout/stderr, returns the exit code the caller\n// should pass to `process.exit`. No React, no OpenTUI; safe to call\n// before / instead of `runTui`.\n// ---------------------------------------------------------------------------\n\nimport {\n checkForUpdate,\n compareSemver,\n detectPackageManager,\n performInPlaceSelfUpdate,\n performSelfUpdate,\n resolvePlatformPackage,\n} from './auto-update'\n\nexport interface RunUpdateCommandOptions {\n /** Top-level package the user installs (e.g. `'zidane-tui'`). */\n packageName: string\n /** Inlined at build time. */\n currentVersion: string\n /** Args passed after `upgrade` (typically `process.argv.slice(3)`). */\n argv: readonly string[]\n /** Where to persist the TTL cache. Usually `paths.userDir`. */\n cacheDir?: string\n /** Default channel when `--channel` isn't passed. Defaults to `'latest'`. */\n defaultChannel?: string\n /**\n * Override the platform-package-name prefix used by `--in-place`.\n * Defaults to `'<packageName>-'`, matching the `zidane-tui-<key>` layout.\n */\n platformPackagePrefix?: string\n /** Override registry. Defaults to npmjs. */\n registry?: string\n /** stdout. Defaults to `process.stdout`. */\n stdout?: NodeJS.WritableStream\n /** stderr. Defaults to `process.stderr`. */\n stderr?: NodeJS.WritableStream\n}\n\nexport interface RunUpdateCommandResult {\n exitCode: number\n}\n\nconst UPGRADE_HELP = `Usage: zidane upgrade [options]\n\nUpdate the zidane CLI to the latest release.\n\nOptions:\n --check Print the latest version and exit (no install).\n --in-place Download the platform binary directly from npm\n and atomic-rename over the running binary.\n Skips the package manager. Refused on Volta.\n --dry-run Resolve everything but don't actually install.\n --channel <tag> dist-tag to query (default: latest).\n --registry <url> Override the npm registry.\n --package-manager <pm> Force npm | pnpm | yarn | bun | volta.\n --force Run the install even if we're already on latest,\n or the registry check failed.\n -h, --help Print this help.\n\nEnvironment:\n NO_UPDATE_NOTIFIER Silence the background check (set to \"1\").\n ZIDANE_NO_UPDATE Same, project-specific.\n`\n\n/**\n * Run the `upgrade` subcommand. Exit code contract:\n * - `0` — update succeeded, `--check` reported no update, or `--check`\n * reported an update (informational only).\n * - `1` — update failed (PM exit non-zero, in-place download failed,\n * registry returned non-2xx).\n * - `2` — argv parse error (unknown flag).\n */\nexport async function runUpdateCommand(options: RunUpdateCommandOptions): Promise<RunUpdateCommandResult> {\n const out = options.stdout ?? process.stdout\n const err = options.stderr ?? process.stderr\n const parsed = parseArgs(options.argv)\n if (parsed.kind === 'error') {\n err.write(`zidane upgrade: ${parsed.message}\\n`)\n err.write(UPGRADE_HELP)\n return { exitCode: 2 }\n }\n if (parsed.help) {\n out.write(UPGRADE_HELP)\n return { exitCode: 0 }\n }\n\n const channel = parsed.channel ?? options.defaultChannel ?? 'latest'\n const registry = parsed.registry ?? options.registry\n\n // Always force the check — user typed `upgrade`, env opt-outs shouldn't\n // get in the way.\n const status = await checkForUpdate({\n packageName: options.packageName,\n currentVersion: options.currentVersion,\n channel,\n registry,\n cacheDir: options.cacheDir,\n force: true,\n timeoutMs: 8000,\n })\n\n // `--check` is informational — degrade gracefully on registry errors\n // (offline laptop, restricted proxy) and exit 0 so the user can script\n // around it without quoting tricks.\n if (parsed.check) {\n if (status.source === 'error') {\n err.write(`Could not check \\`${channel}\\` (${status.error ?? 'unknown error'}). Current: v${options.currentVersion}.\\n`)\n return { exitCode: 0 }\n }\n if (!status.latest) {\n err.write(`Could not determine latest version on \\`${channel}\\`. Current: v${options.currentVersion}.\\n`)\n return { exitCode: 0 }\n }\n const cmp = compareSemver(status.latest, options.currentVersion)\n if (cmp > 0)\n out.write(`v${status.latest} is available on \\`${channel}\\` (current: v${options.currentVersion}).\\n`)\n else\n out.write(`Already on v${options.currentVersion} (latest on \\`${channel}\\` is v${status.latest}).\\n`)\n return { exitCode: 0 }\n }\n\n // Install path — a registry error means we don't KNOW if we need an\n // update. Refuse to spawn the PM blindly unless the user explicitly\n // asks via `--force`.\n if (status.source === 'error') {\n err.write(`zidane upgrade: registry check failed (${status.error ?? 'unknown error'})\\n`)\n if (!parsed.force) {\n err.write('Pass --force to attempt the install anyway.\\n')\n return { exitCode: 1 }\n }\n }\n\n if (status.latest && !parsed.force) {\n const cmp = compareSemver(status.latest, options.currentVersion)\n if (cmp <= 0) {\n out.write(`Already on v${options.currentVersion} (latest on \\`${channel}\\` is v${status.latest}).\\n`)\n return { exitCode: 0 }\n }\n }\n\n // ---------------------------------------------------------------------\n // In-place path\n // ---------------------------------------------------------------------\n\n if (parsed.inPlace) {\n const platformPkg = resolvePlatformPackage({\n prefix: options.platformPackagePrefix ?? `${options.packageName}-`,\n })\n if (!platformPkg) {\n err.write(`No prebuilt binary for ${process.platform}/${process.arch}. Run \\`${options.packageName}-upgrade\\` via your package manager instead.\\n`)\n return { exitCode: 1 }\n }\n out.write(`Downloading ${platformPkg}@${channel}…\\n`)\n const result = await performInPlaceSelfUpdate({\n packageName: platformPkg,\n channel,\n registry,\n dryRun: parsed.dryRun,\n })\n if (result.status === 'success') {\n const verb = parsed.dryRun ? 'Would install' : 'Installed'\n out.write(`${verb} v${result.installedVersion} at ${result.binaryPath}.\\n`)\n return { exitCode: 0 }\n }\n err.write(`In-place update failed: ${result.reason ?? 'unknown error'}\\n`)\n if (result.status === 'refused')\n err.write('Falling back to package-manager path (drop --in-place to retry).\\n')\n return { exitCode: 1 }\n }\n\n // ---------------------------------------------------------------------\n // Package-manager path\n // ---------------------------------------------------------------------\n\n const detected = detectPackageManager({ packageName: options.packageName, channel })\n if (detected.note)\n out.write(`${detected.note}\\n`)\n out.write(`Running: ${detected.argv.join(' ')}\\n`)\n if (parsed.dryRun)\n return { exitCode: 0 }\n\n const result = await performSelfUpdate({\n packageName: options.packageName,\n channel,\n packageManager: parsed.packageManager ?? 'auto',\n })\n if (result.spawnError) {\n err.write(`Failed to launch \\`${result.command.argv[0]}\\`: ${result.spawnError}\\n`)\n err.write('Is the package manager installed and on $PATH?\\n')\n return { exitCode: 1 }\n }\n return { exitCode: result.exitCode ?? 1 }\n}\n\n// ---------------------------------------------------------------------------\n// Argv parser — minimal, just enough to drop into the consumer's `cli.ts`.\n// We deliberately don't pull in commander/yargs for a 5-flag surface.\n// ---------------------------------------------------------------------------\n\ntype ParseResult\n = | {\n kind: 'ok'\n check: boolean\n inPlace: boolean\n dryRun: boolean\n force: boolean\n help: boolean\n channel?: string\n registry?: string\n packageManager?: 'npm' | 'pnpm' | 'yarn' | 'bun' | 'volta'\n }\n | { kind: 'error', message: string }\n\nfunction parseArgs(argv: readonly string[]): ParseResult {\n let check = false\n let inPlace = false\n let dryRun = false\n let force = false\n let help = false\n let channel: string | undefined\n let registry: string | undefined\n let packageManager: 'npm' | 'pnpm' | 'yarn' | 'bun' | 'volta' | undefined\n\n for (let i = 0; i < argv.length; i++) {\n const a = argv[i]!\n switch (a) {\n case '--check': check = true; break\n case '--in-place':\n case '--inplace': inPlace = true; break\n case '--dry-run':\n case '--dryrun': dryRun = true; break\n case '--force': force = true; break\n case '-h':\n case '--help': help = true; break\n case '--channel':\n channel = argv[++i]\n if (!channel)\n return { kind: 'error', message: '--channel requires a value' }\n break\n case '--registry':\n registry = argv[++i]\n if (!registry)\n return { kind: 'error', message: '--registry requires a value' }\n break\n case '--package-manager':\n case '--pm': {\n const v = argv[++i]\n if (!v)\n return { kind: 'error', message: '--package-manager requires a value' }\n if (v !== 'npm' && v !== 'pnpm' && v !== 'yarn' && v !== 'bun' && v !== 'volta')\n return { kind: 'error', message: `unknown package manager: ${v}` }\n packageManager = v\n break\n }\n default:\n return { kind: 'error', message: `unknown argument: ${a}` }\n }\n }\n\n return { kind: 'ok', check, inPlace, dryRun, force, help, channel, registry, packageManager }\n}\n"],"mappings":"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"}
@@ -171,139 +171,6 @@ function buildContextBreakdown(snapshot) {
171
171
  };
172
172
  }
173
173
  //#endregion
174
- //#region src/chat/format.ts
175
- /**
176
- * Resolve the user's home directory from env (no static os-module import),
177
- * so this module stays node-free and importable from a browser-context
178
- * renderer (Electron's renderer, Vite) via `zidane/chat/pure`. Reads the
179
- * platform env vars Node/Electron populate; returns '' when unavailable
180
- * (renderer), in which case `compactPath` falls back to the verbatim path.
181
- */
182
- function resolveHome() {
183
- const env = globalThis.process?.env;
184
- return env?.HOME ?? env?.USERPROFILE ?? "";
185
- }
186
- /** Compact token formatter — 12_415 → "12.4k", 1_234_567 → "1.23M". */
187
- function fmtTokens(n) {
188
- if (n < 1e3) return String(n);
189
- if (n < 1e6) return `${(n / 1e3).toFixed(n < 1e4 ? 2 : 1)}k`;
190
- return `${(n / 1e6).toFixed(2)}M`;
191
- }
192
- /** Compact relative-time formatter — "just now / 5m / 3h / 2d". */
193
- function ageString(ts, now = Date.now()) {
194
- const m = Math.floor((now - ts) / 6e4);
195
- if (m < 1) return "just now";
196
- if (m < 60) return `${m}m ago`;
197
- const h = Math.floor(m / 60);
198
- if (h < 24) return `${h}h ago`;
199
- return `${Math.floor(h / 24)}d ago`;
200
- }
201
- /** Six-char short form of a session id for headers and lists. */
202
- function shortId(id) {
203
- return id.replace(/-/g, "").slice(0, 6);
204
- }
205
- /**
206
- * Single-line preview of a multi-line string, capped at `max` chars and
207
- * ellipsis-terminated when truncated.
208
- *
209
- * Whitespace runs (newlines, tabs, multiple spaces) collapse into one
210
- * space so the rendered output stays on a single visual row no matter
211
- * how the input was shaped. Used by every transcript "preview" surface
212
- * (spawn-start task, `tool: shell (background): <command>`,
213
- * `<task-notification>` summary line, etc.) — without the whitespace
214
- * collapse, a 60-char `slice` on a string with an inline `\n\n` paints
215
- * the second paragraph below the first, producing the visible
216
- * "preview text spills onto multiple lines" bug (and, downstream,
217
- * misaligned spawn markers when the wrapped lines collide with
218
- * other events).
219
- *
220
- * Reserves one slot for the `…` so the displayed width is exactly
221
- * `max` when truncation kicks in.
222
- */
223
- function previewLine(s, max) {
224
- const single = s.replace(/\s+/g, " ").trim();
225
- if (single.length <= max) return single;
226
- return `${single.slice(0, max - 1)}…`;
227
- }
228
- /**
229
- * Compact human-readable duration formatter shared by background-task
230
- * surfaces (the `<task-notification>` summary, the TUI banner, the
231
- * `shell_kill` tool result, etc.).
232
- *
233
- * Format ladder:
234
- * - `< 1s` → `"Nms"`
235
- * - `< 10s` → `"N.Ns"` (one decimal)
236
- * - `< 1m` → `"Ns"` (whole seconds)
237
- * - `< 1h` → `"NmNs"` / `"Nm"` when seconds round to 0
238
- * - `≥ 1h` → `"NhNm"` / `"Nh"` when minutes round to 0
239
- *
240
- * Single source of truth so a 60s task renders the same across the
241
- * model-facing XML summary and the user-facing banner. Earlier
242
- * separate formatters disagreed (XML said `"60.0s"`, banner said `"1m"`)
243
- * which was confusing to the user reading both side by side.
244
- */
245
- function formatDuration(ms) {
246
- if (ms < 0) ms = 0;
247
- if (ms < 1e3) return `${ms}ms`;
248
- if (ms < 6e4) return `${(ms / 1e3).toFixed(ms < 1e4 ? 1 : 0)}s`;
249
- const minutes = Math.floor(ms / 6e4);
250
- const seconds = Math.floor(ms % 6e4 / 1e3);
251
- if (minutes < 60) return seconds > 0 ? `${minutes}m${seconds}s` : `${minutes}m`;
252
- const hours = Math.floor(minutes / 60);
253
- const remMinutes = minutes % 60;
254
- return remMinutes > 0 ? `${hours}h${remMinutes}m` : `${hours}h`;
255
- }
256
- /**
257
- * Status label for a terminated background task — `"exited <code>"`
258
- * for natural exits, `"killed"` (with the signal name when known)
259
- * for our-issued SIGTERMs.
260
- *
261
- * Pulled out as its own function so the `<task-notification>` XML
262
- * summary, the TUI banner header, the `shell_kill` tool result, and
263
- * future surfaces all read the same string.
264
- */
265
- function formatTaskStatus(info) {
266
- return info.status === "killed" ? `killed${info.signal ? ` (${info.signal})` : ""}` : `exited ${info.exitCode}`;
267
- }
268
- /**
269
- * One-line summary of a terminated background task — the shape used by
270
- * the `<task-notification>` XML's `<summary>` tag AND the TUI banner's
271
- * `event.text` fallback string. Three dot-separated segments:
272
- *
273
- * `<command preview · status · duration>`
274
- *
275
- * Centralizes the format so live + replay + wire all agree, and so a
276
- * future cosmetic tweak (separator glyph, segment ordering) lands in
277
- * exactly one place.
278
- */
279
- function formatTaskSummary(info, maxCommandChars = 80) {
280
- return `${previewLine(info.command, maxCommandChars)} · ${formatTaskStatus(info)} · ${formatDuration(info.durationMs)}`;
281
- }
282
- /**
283
- * Compact an absolute path for display: replace the user's `$HOME`
284
- * prefix with `~` (so `/Users/yael/Code/zidane` → `~/Code/zidane`),
285
- * and optionally left-truncate with an ellipsis when the result
286
- * still exceeds `maxWidth` (so the path's *tail* — the part the user
287
- * recognizes — stays visible: `…/zidane` rather than `/Users/yaeluil…`).
288
- *
289
- * `maxWidth` is the maximum *display width* in cells. Omit to skip
290
- * truncation. Paths outside `$HOME` are returned verbatim modulo
291
- * truncation. The ellipsis (`…`) counts as one cell.
292
- *
293
- * `home` overrides `os.homedir()` for tests; production callers leave
294
- * it undefined and pay the cheap one-syscall lookup per call.
295
- */
296
- function compactPath(path, maxWidth, home) {
297
- const h = home ?? resolveHome();
298
- let display = path;
299
- if (h) {
300
- if (path === h) display = "~";
301
- else if (path.startsWith(`${h}/`)) display = `~${path.slice(h.length)}`;
302
- }
303
- if (maxWidth !== void 0 && maxWidth > 1 && display.length > maxWidth) return `…${display.slice(display.length - maxWidth + 1)}`;
304
- return display;
305
- }
306
- //#endregion
307
174
  //#region src/tools/edit-utils.ts
308
175
  /**
309
176
  * Internal helpers shared between the `edit` and `multi_edit` tools.
@@ -519,6 +386,6 @@ function isOpeningContext(chars, i) {
519
386
  return prev === " " || prev === " " || prev === "\n" || prev === "\r" || prev === "(" || prev === "[" || prev === "{" || prev === "—" || prev === "–";
520
387
  }
521
388
  //#endregion
522
- export { compactPath as a, formatTaskStatus as c, shortId as d, buildContextBreakdown as f, ageString as i, formatTaskSummary as l, stripLineNumberPrefixes as n, fmtTokens as o, styleReplacementForVia as r, formatDuration as s, resolveOldString as t, previewLine as u };
389
+ export { buildContextBreakdown as i, stripLineNumberPrefixes as n, styleReplacementForVia as r, resolveOldString as t };
523
390
 
524
- //# sourceMappingURL=edit-utils-CzHl1ct_.js.map
391
+ //# sourceMappingURL=edit-utils-BkPqw6WE.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"edit-utils-BkPqw6WE.js","names":[],"sources":["../src/chat/context-breakdown.ts","../src/tools/edit-utils.ts"],"sourcesContent":["/**\n * Context-usage breakdown — pure transforms.\n *\n * Turns a {@link ContextSnapshot} (the raw pieces the agent assembled for a\n * run: system prompt, wire tools, deferred tools, MCP tools/instructions,\n * skills catalog, ...) plus the real last-turn token total into a categorized\n * {@link ContextBreakdown} the TUI panel / GUI popover render.\n *\n * No React, no node — a browser-context renderer imports these via\n * `zidane/chat/pure`. The snapshot is captured main-side (TUI direct, GUI in\n * `main/chat`) because building it reads provider/agent state; only the pure\n * shaping lives here.\n *\n * Accuracy: per-category counts are estimates when no provider `countTokens`\n * is available — the heuristic ({@link estimateTokens}, ~4 bytes/token) sizes\n * each static segment and the bar is reconciled so it always sums to the real\n * last-turn total (`conversation = realTotal - sum(static)`). When a provider\n * exposes exact counts (Anthropic, OpenAI), the caller passes them in via\n * {@link ContextSnapshot.exact} and the corresponding categories drop their\n * `estimated` flag. Exact buckets (free space, autocompact buffer) are never\n * estimated.\n */\n\nimport { estimateTokens } from '../compact/utils'\n\n/**\n * Stable identifiers for each breakdown category. Drives swatch color +\n * ordering in both UIs. `*Deferred` buckets are tools/MCP that exist but are\n * NOT currently on the wire (lazy disclosure); `autocompactBuffer` is the\n * reserved output headroom; `freeSpace` is the remaining window.\n */\nexport type ContextCategoryId\n = | 'systemPrompt'\n | 'rules'\n | 'tools'\n | 'mcpTools'\n | 'mcpInstructions'\n | 'skills'\n | 'subagentDefs'\n | 'conversation'\n | 'mcpToolsDeferred'\n | 'toolsDeferred'\n | 'autocompactBuffer'\n | 'freeSpace'\n\n/**\n * Exact last-turn token usage split (provider-reported — always exact). Drives\n * the cache breakdown shown below the categories. `cacheRead + cacheCreation +\n * input` equals the live context total (`used`).\n */\nexport interface ContextUsageSplit {\n /** Fresh, uncached input tokens this turn. */\n input: number\n /** Tokens served from the prompt cache (the cached prefix). */\n cacheRead: number\n /** Tokens written to the cache this turn. */\n cacheCreation: number\n /** Assistant output tokens (not part of the input window; informational). */\n output: number\n}\n\n/** One expandable child row under a category (e.g. a single MCP tool / memory file). */\nexport interface ContextItem {\n /** Stable-ish key for rendering (tool name, file path). */\n id: string\n /** Display label. */\n label: string\n /** Token count for this item. */\n tokens: number\n /** True when `tokens` came from the heuristic rather than an exact count. */\n estimated: boolean\n}\n\n/** One category row in the breakdown. */\nexport interface ContextCategory {\n id: ContextCategoryId\n /** Display label (e.g. \"Tool definitions\"). */\n label: string\n /** Token count for the category. */\n tokens: number\n /** True when `tokens` came from the heuristic rather than an exact count. */\n estimated: boolean\n /**\n * True for buckets that are NOT counted against the live window total\n * (deferred tools, free space, autocompact buffer) — the UI renders these\n * dimmed / below a divider, mirroring Claude Code's layout.\n */\n deferred?: boolean\n /** Optional expandable child rows (per MCP tool, per memory file, ...). */\n items?: ContextItem[]\n}\n\n/** The shaped, render-ready breakdown. */\nexport interface ContextBreakdown {\n /** Model id the snapshot was built for. */\n modelId: string\n /**\n * Real last-turn context size (provider-reported `input + cacheRead +\n * cacheCreation`) — the SAME number the footer/orb shows. The non-deferred\n * categories always sum to this.\n */\n used: number\n /** Effective window (raw - output reserve), the bar's denominator. */\n effectiveWindow: number\n /** `used / effectiveWindow`, clamped to [0, 1]. */\n fraction: number\n /** Live categories (sum to `used`) followed by deferred + free-space buckets. */\n categories: ContextCategory[]\n /** True when ANY live category is estimated (drives the panel's footnote). */\n hasEstimates: boolean\n /**\n * Exact last-turn usage split (cache read / write / fresh input / output),\n * when the host supplied it. Always exact — rendered as an informational\n * section below the categories. Absent when no usage is available yet.\n */\n usage?: ContextUsageSplit\n /**\n * Names of currently-active skills. Informational — an activated skill's body\n * lands in the conversation (tool-results), so its tokens are already counted\n * under Conversation; this just surfaces \"which skills are loaded\". Empty/absent\n * when none are active.\n */\n activeSkills?: string[]\n}\n\n/** Host-supplied options for `agent.getContextBreakdown`. */\nexport interface ContextBreakdownOptions {\n /**\n * Effective context window (`rawWindow - outputReserve`) for the active\n * model, resolved by the host via the chat model registry. Drives free-space\n * + fraction. When omitted, defaults to `used` (no headroom shown).\n */\n effectiveWindow?: number\n /**\n * Active model id — used for the exact `countTokens` call + the header label.\n * Only consulted on the PRE-RUN path (no snapshot yet); once a run has fired,\n * the snapshot's own model wins. When omitted, the provider default is used.\n */\n model?: string\n /** Tokens reserved for output (autocompact buffer). Defaults to 0. */\n autocompactBuffer?: number\n /**\n * Auto-compact threshold as a fraction of the window (0–1), when enabled.\n * When set, the \"Autocompact buffer\" bucket represents the ENTIRE tail from\n * the threshold to the end of the window (`(1 − threshold) × window`) rather\n * than just the reserved-output tokens — so the bar/row show exactly where\n * compaction fires. When omitted, `autocompactBuffer` is used as-is.\n */\n compactThreshold?: number\n /** Abort signal forwarded to the provider's `countTokens`. */\n signal?: AbortSignal\n}\n\n/** Tools grouped by MCP server, for the expandable per-server rows. */\nexport interface ContextMcpGroup {\n server: string\n /** Wire tool specs for this server (their JSON size is measured). */\n tools: { name: string, json: string }[]\n}\n\n/**\n * Exact per-segment counts from a provider's `countTokens`, when available.\n * Each field is the count of the cumulative payload up to and including that\n * segment, so categories are derived by differencing (see\n * {@link buildContextBreakdown}). Any subset may be present; missing fields\n * fall back to the heuristic for that category.\n */\nexport interface ContextExactCounts {\n /** Tokens for system prompt alone. */\n system?: number\n /** Tokens for system + tools (so tools = systemAndTools - system). */\n systemAndTools?: number\n /** Tokens for the full payload (system + tools + messages) = the real total. */\n full?: number\n}\n\n/**\n * Raw inputs captured at agent prompt-assembly time. Everything here is what\n * actually went on (or was withheld from) the wire for the last run.\n */\nexport interface ContextSnapshot {\n modelId: string\n /** Full rendered system prompt (marker-stripped, as sent). */\n system: string\n /**\n * Host-composed base system BEFORE the agent appended skills / searchable /\n * MCP-instructions catalogs. Includes the rules block. The \"System prompt\"\n * (base doctrine) bucket = base − rules − env-noise. Defaults to `system`\n * when not provided (back-compat).\n */\n baseSystem?: string\n /** Rendered AGENTS.md/CLAUDE.md rules block (a substring of `baseSystem`). */\n rulesBlock?: string\n /** Source files behind the rules block, for per-file rows. */\n rulesFiles?: { path: string, source: string }[]\n /** Wire tool specs currently disclosed to the model, as JSON strings. */\n toolsJson: string[]\n /** Lazy tool entries NOT currently disclosed (deferred), as JSON strings. */\n deferredToolsJson: string[]\n /** MCP tools grouped by server (disclosed ones). */\n mcpGroups: ContextMcpGroup[]\n /** Deferred (undisclosed) MCP tools grouped by server. */\n deferredMcpGroups: ContextMcpGroup[]\n /** Rendered MCP instructions block, if any. */\n mcpInstructions?: string\n /** Rendered skills catalog text, if any. */\n skillsCatalog?: string\n /** Searchable / subagent (spawn) tool definitions text, if any. */\n subagentDefs?: string\n /** Memory / rules files in context. */\n /** Real last-turn total (input + cacheRead + cacheCreation). */\n used: number\n /** Effective window (raw - output reserve). */\n effectiveWindow: number\n /** Tokens reserved for output (autocompact buffer). */\n autocompactBuffer: number\n /** Exact per-segment counts from the provider, when available. */\n exact?: ContextExactCounts\n /** Exact last-turn usage split, when available (passed straight through). */\n usage?: ContextUsageSplit\n /** Names of currently-active skills (passed straight through). */\n activeSkills?: string[]\n}\n\nconst LABELS: Record<ContextCategoryId, string> = {\n systemPrompt: 'System prompt',\n rules: 'Rules (AGENTS.md)',\n tools: 'Tool definitions',\n mcpTools: 'MCP tools',\n mcpInstructions: 'MCP instructions',\n skills: 'Skills',\n subagentDefs: 'Subagent definitions',\n conversation: 'Conversation',\n mcpToolsDeferred: 'MCP tools (deferred)',\n toolsDeferred: 'System tools (deferred)',\n autocompactBuffer: 'Autocompact buffer',\n freeSpace: 'Free space',\n}\n\n/** Sum the heuristic token sizes of a list of strings. */\nfunction sumEstimate(parts: readonly string[]): number {\n let total = 0\n for (const p of parts)\n total += estimateTokens(p)\n return total\n}\n\nfunction mcpGroupTokens(group: ContextMcpGroup): { total: number, items: ContextItem[] } {\n const items: ContextItem[] = group.tools.map(t => ({\n id: `${group.server}:${t.name}`,\n label: t.name,\n tokens: estimateTokens(t.json),\n estimated: true,\n }))\n let total = 0\n for (const it of items)\n total += it.tokens\n return { total, items }\n}\n\n/**\n * Shape a {@link ContextSnapshot} into a render-ready {@link ContextBreakdown}.\n *\n * Live categories (system prompt, tools, MCP tools/instructions, skills,\n * memory, subagent defs, conversation) sum to `snapshot.used` — `conversation`\n * absorbs the remainder so the bar matches the provider-reported total exactly.\n * Deferred + autocompact + free-space buckets follow.\n *\n * When `snapshot.exact` carries provider counts, the matching categories use\n * them (system, tools) and drop their `estimated` flag; everything else stays\n * on the heuristic.\n */\nexport function buildContextBreakdown(snapshot: ContextSnapshot): ContextBreakdown {\n const exact = snapshot.exact\n const systemExact = typeof exact?.system === 'number'\n\n // --- System-embedded sub-sections (heuristic) ----------------------------\n // The exact `count_tokens` system number covers the WHOLE system text. The\n // appended catalogs (rules / skills / MCP instructions / subagent defs) all\n // live inside it, so we size each heuristically and let the \"System prompt\"\n // (base doctrine) bucket absorb the remainder — keeping the system group's\n // sum exact while still attributing each section.\n const rulesTokens = snapshot.rulesBlock ? estimateTokens(snapshot.rulesBlock) : 0\n const rulesItems: ContextItem[] = (snapshot.rulesFiles ?? []).map(f => ({\n id: f.path,\n label: f.path,\n // Per-file size isn't separable from the rendered block; show the path only\n // (tokens 0, not estimated — there's nothing to estimate) so the row lists\n // sources without implying a per-file count or a `~` marker.\n tokens: 0,\n estimated: false,\n }))\n const skillsTokens = snapshot.skillsCatalog ? estimateTokens(snapshot.skillsCatalog) : 0\n const mcpInstructionsTokens = snapshot.mcpInstructions ? estimateTokens(snapshot.mcpInstructions) : 0\n const subagentTokens = snapshot.subagentDefs ? estimateTokens(snapshot.subagentDefs) : 0\n const embeddedSubsections = rulesTokens + skillsTokens + mcpInstructionsTokens + subagentTokens\n\n // System TOTAL (whole system text) — exact when available.\n const systemTotal = systemExact ? exact!.system! : estimateTokens(snapshot.system)\n // Base doctrine = system total minus the attributed sub-sections.\n const baseSystemTokens = Math.max(0, systemTotal - embeddedSubsections)\n\n // --- Native tool definitions (non-MCP, disclosed) ------------------------\n // When exact `systemAndTools` is available it covers BOTH native + MCP tools,\n // so we split that combined number proportionally by heuristic weight rather\n // than claiming exactness per sub-bucket.\n const nativeToolsEst = sumEstimate(snapshot.toolsJson)\n const mcpDisclosed = snapshot.mcpGroups.map(mcpGroupTokens)\n const mcpToolsEst = mcpDisclosed.reduce((a, g) => a + g.total, 0)\n\n let nativeToolsTokens = nativeToolsEst\n let mcpToolsTokens = mcpToolsEst\n let toolsEstimated = true\n if (systemExact && typeof exact?.systemAndTools === 'number') {\n const exactToolsTotal = Math.max(0, exact.systemAndTools - exact.system!)\n const estTotal = nativeToolsEst + mcpToolsEst\n if (estTotal > 0) {\n nativeToolsTokens = Math.round(exactToolsTotal * (nativeToolsEst / estTotal))\n mcpToolsTokens = exactToolsTotal - nativeToolsTokens\n }\n else {\n nativeToolsTokens = exactToolsTotal\n mcpToolsTokens = 0\n }\n toolsEstimated = false\n }\n\n // --- Live categories -----------------------------------------------------\n // Detailed split. The system-embedded sub-sections (rules / skills / MCP\n // instructions / subagent defs) are heuristic; the \"System prompt\" base\n // bucket carries the exact remainder so the whole system group still sums to\n // the exact system count. Tools/MCP-tools/conversation are split as before.\n const live: ContextCategory[] = []\n const push = (id: ContextCategoryId, tokens: number, estimated: boolean, items?: ContextItem[]) => {\n if (tokens <= 0 && !items?.length)\n return\n live.push({ id, label: LABELS[id], tokens: Math.max(0, tokens), estimated, ...(items?.length ? { items } : {}) })\n }\n\n // System group: base doctrine (exact remainder) + attributed sub-sections.\n push('systemPrompt', baseSystemTokens, !systemExact)\n push('rules', rulesTokens, true, rulesItems)\n push('skills', skillsTokens, true)\n push('mcpInstructions', mcpInstructionsTokens, true)\n push('subagentDefs', subagentTokens, true)\n // Tools.\n push('tools', nativeToolsTokens, toolsEstimated)\n push('mcpTools', mcpToolsTokens, toolsEstimated, mcpDisclosed.flatMap(g => g.items))\n\n // --- Conversation = remainder (keeps the bar summing to `used`) ----------\n const accountedStatic = live.reduce((a, c) => a + c.tokens, 0)\n const conversationTokens = Math.max(0, snapshot.used - accountedStatic)\n // Exact when both system AND tools were exactly counted — then the remainder\n // (used − exactSystem − exactTools) is itself exact, since `used` is the\n // provider-reported total.\n const conversationEstimated = !(systemExact && !toolsEstimated)\n push('conversation', conversationTokens, conversationEstimated)\n\n // --- Deferred buckets (not counted against `used`) -----------------------\n const deferred: ContextCategory[] = []\n const deferredNativeTools = sumEstimate(snapshot.deferredToolsJson)\n if (deferredNativeTools > 0) {\n deferred.push({ id: 'toolsDeferred', label: LABELS.toolsDeferred, tokens: deferredNativeTools, estimated: true, deferred: true })\n }\n const deferredMcp = snapshot.deferredMcpGroups.map(mcpGroupTokens)\n const deferredMcpTotal = deferredMcp.reduce((a, g) => a + g.total, 0)\n if (deferredMcpTotal > 0) {\n deferred.push({\n id: 'mcpToolsDeferred',\n label: LABELS.mcpToolsDeferred,\n tokens: deferredMcpTotal,\n estimated: true,\n deferred: true,\n items: deferredMcp.flatMap(g => g.items),\n })\n }\n\n // --- Autocompact buffer + free space (exact) -----------------------------\n if (snapshot.autocompactBuffer > 0) {\n deferred.push({ id: 'autocompactBuffer', label: LABELS.autocompactBuffer, tokens: snapshot.autocompactBuffer, estimated: false, deferred: true })\n }\n const free = Math.max(0, snapshot.effectiveWindow - snapshot.used)\n deferred.push({ id: 'freeSpace', label: LABELS.freeSpace, tokens: free, estimated: false, deferred: true })\n\n const categories = [...live, ...deferred]\n const hasEstimates = live.some(c => c.estimated && c.tokens > 0)\n const fraction = snapshot.effectiveWindow > 0\n ? Math.max(0, Math.min(1, snapshot.used / snapshot.effectiveWindow))\n : 0\n\n return {\n modelId: snapshot.modelId,\n used: snapshot.used,\n effectiveWindow: snapshot.effectiveWindow,\n fraction,\n categories,\n hasEstimates,\n ...(snapshot.usage ? { usage: snapshot.usage } : {}),\n ...(snapshot.activeSkills?.length ? { activeSkills: snapshot.activeSkills } : {}),\n }\n}\n","/**\n * Internal helpers shared between the `edit` and `multi_edit` tools.\n *\n * Not part of the public API — intentionally not re-exported from `tools/index.ts`\n * or the package barrel.\n */\n\n/**\n * Count exact (non-overlapping) occurrences of `needle` in `haystack`.\n * Returns 0 for an empty needle — both edit tools reject empty `old_string`\n * up front, so this branch is defensive rather than semantic.\n */\nexport function countExactMatches(haystack: string, needle: string): number {\n if (needle.length === 0)\n return 0\n let count = 0\n let idx = 0\n while (true) {\n const next = haystack.indexOf(needle, idx)\n if (next === -1)\n break\n count++\n idx = next + needle.length\n }\n return count\n}\n\n// ---------------------------------------------------------------------------\n// Curly-quote normalization + SDK-sanitization fallbacks\n// ---------------------------------------------------------------------------\n//\n// Models can't reliably emit Unicode curly quotes, and the Anthropic API\n// silently sanitizes a handful of XML-like tags before they hit the model\n// (`<name>` → `<n>`, etc.). When `old_string` doesn't match exactly, we retry\n// against the same content with both transforms applied so an \"old_string not\n// found\" failure that's only typographical resolves on the second pass.\n//\n// Mirrors the Claude Code Edit tool's recovery strategy. Verbatim port of the\n// quote constants and the desanitization table; the resolve loop below is\n// reorganized to share state between exact / quote-normalized / desanitized.\n\nexport const LEFT_SINGLE_CURLY_QUOTE = '\\u2018'\nexport const RIGHT_SINGLE_CURLY_QUOTE = '\\u2019'\nexport const LEFT_DOUBLE_CURLY_QUOTE = '\\u201C'\nexport const RIGHT_DOUBLE_CURLY_QUOTE = '\\u201D'\n\n/** Map curly quotes (any of the four) to their straight ASCII equivalents. */\nexport function normalizeQuotes(str: string): string {\n return str\n .replaceAll(LEFT_SINGLE_CURLY_QUOTE, '\\'')\n .replaceAll(RIGHT_SINGLE_CURLY_QUOTE, '\\'')\n .replaceAll(LEFT_DOUBLE_CURLY_QUOTE, '\"')\n .replaceAll(RIGHT_DOUBLE_CURLY_QUOTE, '\"')\n}\n\n/**\n * Substitutions Anthropic's API applies to assistant output before the model\n * sees it. The model emits the sanitized form; the file on disk contains the\n * unsanitized form. We undo the substitutions on `old_string` so the search\n * lands on the actual file contents.\n *\n * Verbatim from `claude-code/tools/FileEditTool/utils.ts`.\n */\nconst DESANITIZATIONS: ReadonlyArray<readonly [string, string]> = [\n ['<fnr>', '<function_results>'],\n ['<n>', '<name>'],\n ['</n>', '</name>'],\n ['<o>', '<output>'],\n ['</o>', '</output>'],\n ['<e>', '<error>'],\n ['</e>', '</error>'],\n ['<s>', '<system>'],\n ['</s>', '</system>'],\n ['<r>', '<result>'],\n ['</r>', '</result>'],\n ['< META_START >', '<META_START>'],\n ['< META_END >', '<META_END>'],\n ['< EOT >', '<EOT>'],\n ['< META >', '<META>'],\n ['< SOS >', '<SOS>'],\n ['\\n\\nH:', '\\n\\nHuman:'],\n ['\\n\\nA:', '\\n\\nAssistant:'],\n]\n\n/**\n * Apply the SDK desanitization table to a string. Exported so the edit tools\n * can apply it to `new_string` whenever `old_string` matched via a\n * desanitize-class fallback — keeps the file's unsanitized form on disk\n * instead of writing the model's abbreviated form back.\n */\nexport function desanitize(s: string): string {\n let out = s\n for (const [from, to] of DESANITIZATIONS)\n out = out.replaceAll(from, to)\n return out\n}\n\n/**\n * Strip line-number prefixes from each line of a needle, used as a recovery\n * fallback when the model pastes a `read_file` chunk verbatim into\n * `old_string` — the on-disk file doesn't carry the metadata prefix.\n *\n * Accepts three separator characters so a model that learned on a different\n * agent stack still works here: `\\t` (Claude Code compact, our default),\n * `|`, and `→`. Pattern: optional leading whitespace, 1-9 digits, then one\n * of `\\t | →`. The 9-digit ceiling covers files up to ~1B lines without\n * overshooting into legitimate `\\d{N}<sep>` content like Markdown table\n * cells with long numeric IDs.\n */\nconst LINE_NUMBER_PREFIX_RE = /^[ \\t]*\\d{1,9}[\\t|\\u2192]/gm\nexport function stripLineNumberPrefixes(s: string): string {\n return s.replace(LINE_NUMBER_PREFIX_RE, '')\n}\n\n/**\n * Locate the actual substring in `haystack` that corresponds to `needle`,\n * recovering from typographical mismatch on six escalating fallbacks:\n *\n * 1. Exact substring match (the happy path — no transformation).\n * 2. Curly-quote normalization on both sides — when the model emits straight\n * quotes but the file has curly ones (or vice versa), the slice of the\n * file at the matched position carries the file's actual typography.\n * 3. Anthropic-sanitization undo on the needle — the model's `<n>` becomes\n * the file's `<name>`, etc.\n * 4. Combined: desanitize + quote normalization on the needle.\n * 5. Line-number-prefix strip — when the model pasted a numbered `read_file`\n * chunk verbatim into `old_string` and the file carries no such prefix.\n * 6. Combined: line-number strip + quote normalization — paste-back of a\n * numbered chunk against a file whose typography differs from the model's.\n *\n * Returns `{ actual, occurrences }` — `actual` is the string that exists in\n * the file (use this to do the actual replace; preserves the file's\n * typography). `occurrences` is the count of those matches in the file.\n *\n * Returns `null` when no recovery worked.\n */\nexport interface ResolvedMatch {\n actual: string\n occurrences: number\n /** Recovery path — `'exact'` when no transformation was applied. */\n via: 'exact' | 'quotes' | 'desanitize' | 'quotes+desanitize' | 'line-numbers' | 'quotes+line-numbers'\n}\n\n/**\n * Search `target` in `normFile` and slice the matching span out of the\n * original `haystack`, counting all non-overlapping occurrences. `normFile`\n * is the haystack with whatever transform (quotes / desanitize / combined)\n * was applied to make the indices align — slicing the original haystack\n * preserves the file's actual typography so `replace_all` writes back the\n * file's form, not the model's.\n *\n * Pre-condition: `normFile.length === haystack.length` (every transform\n * we use is one-to-one). Returns null on miss.\n */\nfunction locateAndCount(\n haystack: string,\n normFile: string,\n target: string,\n via: ResolvedMatch['via'],\n): ResolvedMatch | null {\n const idx = normFile.indexOf(target)\n if (idx === -1)\n return null\n const actual = haystack.slice(idx, idx + target.length)\n let occ = 0\n let cursor = 0\n while (true) {\n const next = normFile.indexOf(target, cursor)\n if (next === -1)\n break\n occ++\n cursor = next + target.length\n }\n return { actual, occurrences: occ, via }\n}\n\nexport function resolveOldString(haystack: string, needle: string): ResolvedMatch | null {\n // 1. Exact match — happy path.\n const exact = countExactMatches(haystack, needle)\n if (exact > 0)\n return { actual: needle, occurrences: exact, via: 'exact' }\n\n // 2. Curly-quote normalization. Either side can carry curly quotes:\n // model emitted straight + file has curly, OR model emitted curly +\n // file has straight. Normalize both and look there. Slice the original\n // haystack to recover the actual file-side typography.\n const normNeedle = normalizeQuotes(needle)\n const normFile = normalizeQuotes(haystack)\n if (normNeedle !== needle || normFile !== haystack) {\n const m = locateAndCount(haystack, normFile, normNeedle, 'quotes')\n if (m)\n return m\n }\n\n // 3. Desanitize the needle — model-side substitution undo (`<n>` → `<name>`,\n // etc.) The file always has the unsanitized form; only the model emits\n // the abbreviated version.\n const desan = desanitize(needle)\n if (desan !== needle) {\n const desanCount = countExactMatches(haystack, desan)\n if (desanCount > 0)\n return { actual: desan, occurrences: desanCount, via: 'desanitize' }\n }\n\n // 4. Combined: desanitize + quote normalization. Hit when the model\n // emitted both sanitized tokens and straight quotes, but the file has\n // the unsanitized form with curly quotes.\n const combo = desanitize(normNeedle)\n if (combo !== needle) {\n const m = locateAndCount(haystack, normFile, combo, 'quotes+desanitize')\n if (m)\n return m\n }\n\n // 5. Line-number-prefix strip. When `read_file` returns line-numbered\n // output and the model pasted the chunk verbatim into `old_string`,\n // the on-disk file doesn't carry those prefixes. Strip them and\n // retry; the file-side `actual` is the prefix-free needle so the\n // replacement lands on real bytes.\n //\n // Guard against a needle that strips down to whitespace-only (e.g.\n // `1\\t\\n2\\t\\n3\\t` → `\\n\\n`). Searching for `\\n\\n` would match arbitrary\n // blank-line patterns anywhere in the file — a high false-positive risk.\n // Require the stripped needle to carry at least one non-whitespace\n // character before we trust the result.\n const stripped = stripLineNumberPrefixes(needle)\n if (stripped !== needle && stripped.trim().length > 0) {\n const count = countExactMatches(haystack, stripped)\n if (count > 0)\n return { actual: stripped, occurrences: count, via: 'line-numbers' }\n\n // 6. Combined: line-number strip + curly-quote normalization. The\n // typography mismatch may live in the file, the needle, or both.\n const strippedNorm = normalizeQuotes(stripped)\n if (strippedNorm !== stripped || normFile !== haystack) {\n const m = locateAndCount(haystack, normFile, strippedNorm, 'quotes+line-numbers')\n if (m)\n return m\n }\n }\n\n return null\n}\n\n/**\n * Apply the same recovery transforms used to find `old_string` to\n * `new_string`, so the file gets back its native form: desanitize when\n * the model emitted `<n>` for `<name>`, strip line-number prefixes when\n * the match required them, then re-curlify when the match required\n * quote normalization. Shared between `edit` and `multi_edit`.\n */\nexport function styleReplacementForVia(\n replacement: string,\n via: ResolvedMatch['via'],\n actual: string,\n): string {\n let out = replacement\n if (via === 'desanitize' || via === 'quotes+desanitize')\n out = desanitize(out)\n if (via === 'line-numbers' || via === 'quotes+line-numbers')\n out = stripLineNumberPrefixes(out)\n if (via === 'quotes' || via === 'quotes+desanitize' || via === 'quotes+line-numbers')\n out = preserveQuoteStyle(actual, out)\n return out\n}\n\n/**\n * When `old_string` matched via curly-quote normalization, re-style\n * `new_string` so the file's typography is preserved across the edit.\n * Detects whether the matched file region had curly singles, doubles, or\n * both, and applies the matching curlification to the replacement.\n *\n * Apostrophes in contractions (`don't`, `it's`) get the right-single curly\n * quote regardless of opening context — that's the canonical typographer's\n * convention for English. Other quotes use a simple\n * preceded-by-whitespace-or-opening-punctuation heuristic.\n */\nexport function preserveQuoteStyle(actual: string, replacement: string): string {\n const hasDouble = actual.includes(LEFT_DOUBLE_CURLY_QUOTE) || actual.includes(RIGHT_DOUBLE_CURLY_QUOTE)\n const hasSingle = actual.includes(LEFT_SINGLE_CURLY_QUOTE) || actual.includes(RIGHT_SINGLE_CURLY_QUOTE)\n if (!hasDouble && !hasSingle)\n return replacement\n\n let out = replacement\n if (hasDouble)\n out = applyCurly(out, '\"', LEFT_DOUBLE_CURLY_QUOTE, RIGHT_DOUBLE_CURLY_QUOTE, false)\n if (hasSingle)\n out = applyCurly(out, '\\'', LEFT_SINGLE_CURLY_QUOTE, RIGHT_SINGLE_CURLY_QUOTE, true)\n return out\n}\n\nfunction applyCurly(\n s: string,\n straight: string,\n left: string,\n right: string,\n contractionAware: boolean,\n): string {\n const chars = [...s]\n const result: string[] = []\n for (let i = 0; i < chars.length; i++) {\n if (chars[i] !== straight) {\n result.push(chars[i])\n continue\n }\n if (contractionAware) {\n const prev = i > 0 ? chars[i - 1] : ''\n const next = i < chars.length - 1 ? chars[i + 1] : ''\n // Letter-quote-letter is a contraction, not a quote — always right.\n if (/\\p{L}/u.test(prev) && /\\p{L}/u.test(next)) {\n result.push(right)\n continue\n }\n }\n result.push(isOpeningContext(chars, i) ? left : right)\n }\n return result.join('')\n}\n\nfunction isOpeningContext(chars: string[], i: number): boolean {\n if (i === 0)\n return true\n const prev = chars[i - 1]\n return prev === ' ' || prev === '\\t' || prev === '\\n' || prev === '\\r'\n || prev === '(' || prev === '[' || prev === '{'\n || prev === '\\u2014' || prev === '\\u2013' // em / en dash\n}\n"],"mappings":"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"}
package/dist/eval.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- import { $t as ReusableExecutionContext, An as statusCompleted, At as EvalDefinitionContext, Bt as EvalScorer, Cn as formatTrajectoryLine, Ct as EvalAgentRunResult, Dn as registerEvalTests, Dt as EvalCaseOptions, En as normalizeMetric, Et as EvalArtifacts, Ft as EvalRunReporterOptions, Gt as EvalWorkspaceSnapshot, Ht as EvalTestRunner, It as EvalRunSummary, Jt as MetricEmitter, Kt as LlmJudgeOptions, Lt as EvalRunSummaryCase, Mt as EvalMetricError, Nt as EvalRunMetricAggregate, On as relativeArtifactPath, Ot as EvalCaseResult, Pt as EvalRunReporter, Qt as RegisterEvalTestsOptions, Rt as EvalRunUsage, Sn as formatEvalRunSummary, St as EvalAgentRunOptions, Tn as llmJudge, Tt as EvalAgentStats, Ut as EvalWorkspaceFile, Vt as EvalScorerContext, Wt as EvalWorkspaceOptions, Xt as MetricSpecMap, Yt as MetricSpec, Zt as MetricStats, _n as fileContentQuality, an as buildRegisteredEvals, bn as finalizeEvalMetrics, bt as EvalAgent, cn as computeEvalTagScores, dn as createReusableExecutionContext, en as Trajectory, fn as defineEval, gn as fileContains, hn as emitEfficiencyMetrics, in as buildEvalRunSummary, jt as EvalMetric, kn as runEvalCase, kt as EvalDefinition, ln as createEvalAgent, mn as efficiencyMetricValues, nn as TrajectoryStepKind, on as buildTrajectory, pn as defineMetrics, qt as MetricDirection, rn as artifactPath, sn as clearRegisteredEvals, tn as TrajectoryStep, un as createEvalRunReporter, vn as fileExists, vt as CreateEvalAgentOptions, wn as functionalityMetric, wt as EvalAgentRunStats, xn as formatEvalCaseSummary, xt as EvalAgentMcpServers, yn as fileExistsOneOf, yt as EFFICIENCY_METRICS, zt as EvalScore } from "./index-DgLlL4AT.js";
1
+ import { $t as ReusableExecutionContext, An as statusCompleted, At as EvalDefinitionContext, Bt as EvalScorer, Cn as formatTrajectoryLine, Ct as EvalAgentRunResult, Dn as registerEvalTests, Dt as EvalCaseOptions, En as normalizeMetric, Et as EvalArtifacts, Ft as EvalRunReporterOptions, Gt as EvalWorkspaceSnapshot, Ht as EvalTestRunner, It as EvalRunSummary, Jt as MetricEmitter, Kt as LlmJudgeOptions, Lt as EvalRunSummaryCase, Mt as EvalMetricError, Nt as EvalRunMetricAggregate, On as relativeArtifactPath, Ot as EvalCaseResult, Pt as EvalRunReporter, Qt as RegisterEvalTestsOptions, Rt as EvalRunUsage, Sn as formatEvalRunSummary, St as EvalAgentRunOptions, Tn as llmJudge, Tt as EvalAgentStats, Ut as EvalWorkspaceFile, Vt as EvalScorerContext, Wt as EvalWorkspaceOptions, Xt as MetricSpecMap, Yt as MetricSpec, Zt as MetricStats, _n as fileContentQuality, an as buildRegisteredEvals, bn as finalizeEvalMetrics, bt as EvalAgent, cn as computeEvalTagScores, dn as createReusableExecutionContext, en as Trajectory, fn as defineEval, gn as fileContains, hn as emitEfficiencyMetrics, in as buildEvalRunSummary, jt as EvalMetric, kn as runEvalCase, kt as EvalDefinition, ln as createEvalAgent, mn as efficiencyMetricValues, nn as TrajectoryStepKind, on as buildTrajectory, pn as defineMetrics, qt as MetricDirection, rn as artifactPath, sn as clearRegisteredEvals, tn as TrajectoryStep, un as createEvalRunReporter, vn as fileExists, vt as CreateEvalAgentOptions, wn as functionalityMetric, wt as EvalAgentRunStats, xn as formatEvalCaseSummary, xt as EvalAgentMcpServers, yn as fileExistsOneOf, yt as EFFICIENCY_METRICS, zt as EvalScore } from "./index-DutpkJJ7.js";
2
2
  export { CreateEvalAgentOptions, EFFICIENCY_METRICS, EvalAgent, EvalAgentMcpServers, EvalAgentRunOptions, EvalAgentRunResult, EvalAgentRunStats, EvalAgentStats, EvalArtifacts, EvalCaseOptions, EvalCaseResult, EvalDefinition, EvalDefinitionContext, EvalMetric, EvalMetricError, EvalRunMetricAggregate, EvalRunReporter, EvalRunReporterOptions, EvalRunSummary, EvalRunSummaryCase, EvalRunUsage, EvalScore, EvalScorer, EvalScorerContext, EvalTestRunner, EvalWorkspaceFile, EvalWorkspaceOptions, EvalWorkspaceSnapshot, LlmJudgeOptions, MetricDirection, MetricEmitter, MetricSpec, MetricSpecMap, MetricStats, RegisterEvalTestsOptions, ReusableExecutionContext, Trajectory, TrajectoryStep, TrajectoryStepKind, artifactPath, buildEvalRunSummary, buildRegisteredEvals, buildTrajectory, clearRegisteredEvals, computeEvalTagScores, createEvalAgent, createEvalRunReporter, createReusableExecutionContext, defineEval, defineMetrics, efficiencyMetricValues, emitEfficiencyMetrics, fileContains, fileContentQuality, fileExists, fileExistsOneOf, finalizeEvalMetrics, formatEvalCaseSummary, formatEvalRunSummary, formatTrajectoryLine, functionalityMetric, llmJudge, normalizeMetric, registerEvalTests, relativeArtifactPath, runEvalCase, statusCompleted };
package/dist/eval.js CHANGED
@@ -1,6 +1,6 @@
1
- import { h as alwaysQuote } from "./tools-BLAxircm.js";
1
+ import { h as alwaysQuote } from "./tools-Cf5IsJEu.js";
2
2
  import { n as createProcessContext } from "./contexts-BD2U_xpi.js";
3
- import { a as headlessEventToJsonl, s as runHeadless } from "./headless-C15FmGco.js";
3
+ import { a as headlessEventToJsonl, c as runHeadless } from "./headless-DNBpUy-6.js";
4
4
  import { i as createMemoryStore, t as createSession } from "./session-SMszIfE6.js";
5
5
  import { join, relative, resolve } from "node:path";
6
6
  import { mkdir, mkdtemp, rm, writeFile } from "node:fs/promises";
@@ -0,0 +1,136 @@
1
+ //#region src/chat/format.ts
2
+ /**
3
+ * Resolve the user's home directory from env (no static os-module import),
4
+ * so this module stays node-free and importable from a browser-context
5
+ * renderer (Electron's renderer, Vite) via `zidane/chat/pure`. Reads the
6
+ * platform env vars Node/Electron populate; returns '' when unavailable
7
+ * (renderer), in which case `compactPath` falls back to the verbatim path.
8
+ */
9
+ function resolveHome() {
10
+ const env = globalThis.process?.env;
11
+ return env?.HOME ?? env?.USERPROFILE ?? "";
12
+ }
13
+ /** Compact token formatter — 12_415 → "12.4k", 1_234_567 → "1.23M". */
14
+ function fmtTokens(n) {
15
+ if (n < 1e3) return String(n);
16
+ if (n < 1e6) return `${(n / 1e3).toFixed(n < 1e4 ? 2 : 1)}k`;
17
+ return `${(n / 1e6).toFixed(2)}M`;
18
+ }
19
+ /** Compact relative-time formatter — "just now / 5m / 3h / 2d". */
20
+ function ageString(ts, now = Date.now()) {
21
+ const m = Math.floor((now - ts) / 6e4);
22
+ if (m < 1) return "just now";
23
+ if (m < 60) return `${m}m ago`;
24
+ const h = Math.floor(m / 60);
25
+ if (h < 24) return `${h}h ago`;
26
+ return `${Math.floor(h / 24)}d ago`;
27
+ }
28
+ /** Six-char short form of a session id for headers and lists. */
29
+ function shortId(id) {
30
+ return id.replace(/-/g, "").slice(0, 6);
31
+ }
32
+ /**
33
+ * Single-line preview of a multi-line string, capped at `max` chars and
34
+ * ellipsis-terminated when truncated.
35
+ *
36
+ * Whitespace runs (newlines, tabs, multiple spaces) collapse into one
37
+ * space so the rendered output stays on a single visual row no matter
38
+ * how the input was shaped. Used by every transcript "preview" surface
39
+ * (spawn-start task, `tool: shell (background): <command>`,
40
+ * `<task-notification>` summary line, etc.) — without the whitespace
41
+ * collapse, a 60-char `slice` on a string with an inline `\n\n` paints
42
+ * the second paragraph below the first, producing the visible
43
+ * "preview text spills onto multiple lines" bug (and, downstream,
44
+ * misaligned spawn markers when the wrapped lines collide with
45
+ * other events).
46
+ *
47
+ * Reserves one slot for the `…` so the displayed width is exactly
48
+ * `max` when truncation kicks in.
49
+ */
50
+ function previewLine(s, max) {
51
+ const single = s.replace(/\s+/g, " ").trim();
52
+ if (single.length <= max) return single;
53
+ return `${single.slice(0, max - 1)}…`;
54
+ }
55
+ /**
56
+ * Compact human-readable duration formatter shared by background-task
57
+ * surfaces (the `<task-notification>` summary, the TUI banner, the
58
+ * `shell_kill` tool result, etc.).
59
+ *
60
+ * Format ladder:
61
+ * - `< 1s` → `"Nms"`
62
+ * - `< 10s` → `"N.Ns"` (one decimal)
63
+ * - `< 1m` → `"Ns"` (whole seconds)
64
+ * - `< 1h` → `"NmNs"` / `"Nm"` when seconds round to 0
65
+ * - `≥ 1h` → `"NhNm"` / `"Nh"` when minutes round to 0
66
+ *
67
+ * Single source of truth so a 60s task renders the same across the
68
+ * model-facing XML summary and the user-facing banner. Earlier
69
+ * separate formatters disagreed (XML said `"60.0s"`, banner said `"1m"`)
70
+ * which was confusing to the user reading both side by side.
71
+ */
72
+ function formatDuration(ms) {
73
+ if (ms < 0) ms = 0;
74
+ if (ms < 1e3) return `${ms}ms`;
75
+ if (ms < 6e4) return `${(ms / 1e3).toFixed(ms < 1e4 ? 1 : 0)}s`;
76
+ const minutes = Math.floor(ms / 6e4);
77
+ const seconds = Math.floor(ms % 6e4 / 1e3);
78
+ if (minutes < 60) return seconds > 0 ? `${minutes}m${seconds}s` : `${minutes}m`;
79
+ const hours = Math.floor(minutes / 60);
80
+ const remMinutes = minutes % 60;
81
+ return remMinutes > 0 ? `${hours}h${remMinutes}m` : `${hours}h`;
82
+ }
83
+ /**
84
+ * Status label for a terminated background task — `"exited <code>"`
85
+ * for natural exits, `"killed"` (with the signal name when known)
86
+ * for our-issued SIGTERMs.
87
+ *
88
+ * Pulled out as its own function so the `<task-notification>` XML
89
+ * summary, the TUI banner header, the `shell_kill` tool result, and
90
+ * future surfaces all read the same string.
91
+ */
92
+ function formatTaskStatus(info) {
93
+ return info.status === "killed" ? `killed${info.signal ? ` (${info.signal})` : ""}` : `exited ${info.exitCode}`;
94
+ }
95
+ /**
96
+ * One-line summary of a terminated background task — the shape used by
97
+ * the `<task-notification>` XML's `<summary>` tag AND the TUI banner's
98
+ * `event.text` fallback string. Three dot-separated segments:
99
+ *
100
+ * `<command preview · status · duration>`
101
+ *
102
+ * Centralizes the format so live + replay + wire all agree, and so a
103
+ * future cosmetic tweak (separator glyph, segment ordering) lands in
104
+ * exactly one place.
105
+ */
106
+ function formatTaskSummary(info, maxCommandChars = 80) {
107
+ return `${previewLine(info.command, maxCommandChars)} · ${formatTaskStatus(info)} · ${formatDuration(info.durationMs)}`;
108
+ }
109
+ /**
110
+ * Compact an absolute path for display: replace the user's `$HOME`
111
+ * prefix with `~` (so `/Users/yael/Code/zidane` → `~/Code/zidane`),
112
+ * and optionally left-truncate with an ellipsis when the result
113
+ * still exceeds `maxWidth` (so the path's *tail* — the part the user
114
+ * recognizes — stays visible: `…/zidane` rather than `/Users/yaeluil…`).
115
+ *
116
+ * `maxWidth` is the maximum *display width* in cells. Omit to skip
117
+ * truncation. Paths outside `$HOME` are returned verbatim modulo
118
+ * truncation. The ellipsis (`…`) counts as one cell.
119
+ *
120
+ * `home` overrides `os.homedir()` for tests; production callers leave
121
+ * it undefined and pay the cheap one-syscall lookup per call.
122
+ */
123
+ function compactPath(path, maxWidth, home) {
124
+ const h = home ?? resolveHome();
125
+ let display = path;
126
+ if (h) {
127
+ if (path === h) display = "~";
128
+ else if (path.startsWith(`${h}/`)) display = `~${path.slice(h.length)}`;
129
+ }
130
+ if (maxWidth !== void 0 && maxWidth > 1 && display.length > maxWidth) return `…${display.slice(display.length - maxWidth + 1)}`;
131
+ return display;
132
+ }
133
+ //#endregion
134
+ export { formatTaskStatus as a, shortId as c, formatDuration as i, compactPath as n, formatTaskSummary as o, fmtTokens as r, previewLine as s, ageString as t };
135
+
136
+ //# sourceMappingURL=format-BNOXpl-1.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format-BNOXpl-1.js","names":[],"sources":["../src/chat/format.ts"],"sourcesContent":["/**\n * Resolve the user's home directory from env (no static os-module import),\n * so this module stays node-free and importable from a browser-context\n * renderer (Electron's renderer, Vite) via `zidane/chat/pure`. Reads the\n * platform env vars Node/Electron populate; returns '' when unavailable\n * (renderer), in which case `compactPath` falls back to the verbatim path.\n */\nfunction resolveHome(): string {\n const env = (globalThis as { process?: { env?: Record<string, string | undefined> } }).process?.env\n return env?.HOME ?? env?.USERPROFILE ?? ''\n}\n\n/** Compact token formatter — 12_415 → \"12.4k\", 1_234_567 → \"1.23M\". */\nexport function fmtTokens(n: number): string {\n if (n < 1000)\n return String(n)\n if (n < 1_000_000)\n return `${(n / 1000).toFixed(n < 10_000 ? 2 : 1)}k`\n return `${(n / 1_000_000).toFixed(2)}M`\n}\n\n/** Compact relative-time formatter — \"just now / 5m / 3h / 2d\". */\nexport function ageString(ts: number, now: number = Date.now()): string {\n const m = Math.floor((now - ts) / 60_000)\n if (m < 1)\n return 'just now'\n if (m < 60)\n return `${m}m ago`\n const h = Math.floor(m / 60)\n if (h < 24)\n return `${h}h ago`\n return `${Math.floor(h / 24)}d ago`\n}\n\n/** Six-char short form of a session id for headers and lists. */\nexport function shortId(id: string): string {\n return id.replace(/-/g, '').slice(0, 6)\n}\n\n/**\n * Single-line preview of a multi-line string, capped at `max` chars and\n * ellipsis-terminated when truncated.\n *\n * Whitespace runs (newlines, tabs, multiple spaces) collapse into one\n * space so the rendered output stays on a single visual row no matter\n * how the input was shaped. Used by every transcript \"preview\" surface\n * (spawn-start task, `tool: shell (background): <command>`,\n * `<task-notification>` summary line, etc.) — without the whitespace\n * collapse, a 60-char `slice` on a string with an inline `\\n\\n` paints\n * the second paragraph below the first, producing the visible\n * \"preview text spills onto multiple lines\" bug (and, downstream,\n * misaligned spawn markers when the wrapped lines collide with\n * other events).\n *\n * Reserves one slot for the `…` so the displayed width is exactly\n * `max` when truncation kicks in.\n */\nexport function previewLine(s: string, max: number): string {\n const single = s.replace(/\\s+/g, ' ').trim()\n if (single.length <= max)\n return single\n return `${single.slice(0, max - 1)}…`\n}\n\n/**\n * Compact human-readable duration formatter shared by background-task\n * surfaces (the `<task-notification>` summary, the TUI banner, the\n * `shell_kill` tool result, etc.).\n *\n * Format ladder:\n * - `< 1s` → `\"Nms\"`\n * - `< 10s` → `\"N.Ns\"` (one decimal)\n * - `< 1m` → `\"Ns\"` (whole seconds)\n * - `< 1h` → `\"NmNs\"` / `\"Nm\"` when seconds round to 0\n * - `≥ 1h` → `\"NhNm\"` / `\"Nh\"` when minutes round to 0\n *\n * Single source of truth so a 60s task renders the same across the\n * model-facing XML summary and the user-facing banner. Earlier\n * separate formatters disagreed (XML said `\"60.0s\"`, banner said `\"1m\"`)\n * which was confusing to the user reading both side by side.\n */\nexport function formatDuration(ms: number): string {\n if (ms < 0)\n ms = 0\n if (ms < 1000)\n return `${ms}ms`\n if (ms < 60_000)\n return `${(ms / 1000).toFixed(ms < 10_000 ? 1 : 0)}s`\n const minutes = Math.floor(ms / 60_000)\n const seconds = Math.floor((ms % 60_000) / 1000)\n if (minutes < 60)\n return seconds > 0 ? `${minutes}m${seconds}s` : `${minutes}m`\n const hours = Math.floor(minutes / 60)\n const remMinutes = minutes % 60\n return remMinutes > 0 ? `${hours}h${remMinutes}m` : `${hours}h`\n}\n\n/**\n * Status label for a terminated background task — `\"exited <code>\"`\n * for natural exits, `\"killed\"` (with the signal name when known)\n * for our-issued SIGTERMs.\n *\n * Pulled out as its own function so the `<task-notification>` XML\n * summary, the TUI banner header, the `shell_kill` tool result, and\n * future surfaces all read the same string.\n */\nexport function formatTaskStatus(info: {\n status: 'exited' | 'killed'\n exitCode: number\n signal?: NodeJS.Signals\n}): string {\n return info.status === 'killed'\n ? `killed${info.signal ? ` (${info.signal})` : ''}`\n : `exited ${info.exitCode}`\n}\n\n/**\n * One-line summary of a terminated background task — the shape used by\n * the `<task-notification>` XML's `<summary>` tag AND the TUI banner's\n * `event.text` fallback string. Three dot-separated segments:\n *\n * `<command preview · status · duration>`\n *\n * Centralizes the format so live + replay + wire all agree, and so a\n * future cosmetic tweak (separator glyph, segment ordering) lands in\n * exactly one place.\n */\nexport function formatTaskSummary(info: {\n command: string\n status: 'exited' | 'killed'\n exitCode: number\n signal?: NodeJS.Signals\n durationMs: number\n}, maxCommandChars = 80): string {\n return `${previewLine(info.command, maxCommandChars)} · ${formatTaskStatus(info)} · ${formatDuration(info.durationMs)}`\n}\n\n/**\n * Compact an absolute path for display: replace the user's `$HOME`\n * prefix with `~` (so `/Users/yael/Code/zidane` → `~/Code/zidane`),\n * and optionally left-truncate with an ellipsis when the result\n * still exceeds `maxWidth` (so the path's *tail* — the part the user\n * recognizes — stays visible: `…/zidane` rather than `/Users/yaeluil…`).\n *\n * `maxWidth` is the maximum *display width* in cells. Omit to skip\n * truncation. Paths outside `$HOME` are returned verbatim modulo\n * truncation. The ellipsis (`…`) counts as one cell.\n *\n * `home` overrides `os.homedir()` for tests; production callers leave\n * it undefined and pay the cheap one-syscall lookup per call.\n */\nexport function compactPath(path: string, maxWidth?: number, home?: string): string {\n const h = home ?? resolveHome()\n let display = path\n if (h) {\n if (path === h)\n display = '~'\n else if (path.startsWith(`${h}/`))\n display = `~${path.slice(h.length)}`\n }\n if (maxWidth !== undefined && maxWidth > 1 && display.length > maxWidth) {\n // Left-truncate: keep the rightmost `maxWidth - 1` chars and\n // prepend `…`. The right side of a path is the distinctive\n // bit (repo name, leaf folder); the left side is the boilerplate\n // (home, common parents) we're happy to drop.\n return `…${display.slice(display.length - maxWidth + 1)}`\n }\n return display\n}\n"],"mappings":";;;;;;;;AAOA,SAAS,cAAsB;CAC7B,MAAM,MAAO,WAA0E,SAAS;CAChG,OAAO,KAAK,QAAQ,KAAK,eAAe;AAC1C;;AAGA,SAAgB,UAAU,GAAmB;CAC3C,IAAI,IAAI,KACN,OAAO,OAAO,CAAC;CACjB,IAAI,IAAI,KACN,OAAO,IAAI,IAAI,KAAM,QAAQ,IAAI,MAAS,IAAI,CAAC,EAAE;CACnD,OAAO,IAAI,IAAI,KAAW,QAAQ,CAAC,EAAE;AACvC;;AAGA,SAAgB,UAAU,IAAY,MAAc,KAAK,IAAI,GAAW;CACtE,MAAM,IAAI,KAAK,OAAO,MAAM,MAAM,GAAM;CACxC,IAAI,IAAI,GACN,OAAO;CACT,IAAI,IAAI,IACN,OAAO,GAAG,EAAE;CACd,MAAM,IAAI,KAAK,MAAM,IAAI,EAAE;CAC3B,IAAI,IAAI,IACN,OAAO,GAAG,EAAE;CACd,OAAO,GAAG,KAAK,MAAM,IAAI,EAAE,EAAE;AAC/B;;AAGA,SAAgB,QAAQ,IAAoB;CAC1C,OAAO,GAAG,QAAQ,MAAM,EAAE,EAAE,MAAM,GAAG,CAAC;AACxC;;;;;;;;;;;;;;;;;;;AAoBA,SAAgB,YAAY,GAAW,KAAqB;CAC1D,MAAM,SAAS,EAAE,QAAQ,QAAQ,GAAG,EAAE,KAAK;CAC3C,IAAI,OAAO,UAAU,KACnB,OAAO;CACT,OAAO,GAAG,OAAO,MAAM,GAAG,MAAM,CAAC,EAAE;AACrC;;;;;;;;;;;;;;;;;;AAmBA,SAAgB,eAAe,IAAoB;CACjD,IAAI,KAAK,GACP,KAAK;CACP,IAAI,KAAK,KACP,OAAO,GAAG,GAAG;CACf,IAAI,KAAK,KACP,OAAO,IAAI,KAAK,KAAM,QAAQ,KAAK,MAAS,IAAI,CAAC,EAAE;CACrD,MAAM,UAAU,KAAK,MAAM,KAAK,GAAM;CACtC,MAAM,UAAU,KAAK,MAAO,KAAK,MAAU,GAAI;CAC/C,IAAI,UAAU,IACZ,OAAO,UAAU,IAAI,GAAG,QAAQ,GAAG,QAAQ,KAAK,GAAG,QAAQ;CAC7D,MAAM,QAAQ,KAAK,MAAM,UAAU,EAAE;CACrC,MAAM,aAAa,UAAU;CAC7B,OAAO,aAAa,IAAI,GAAG,MAAM,GAAG,WAAW,KAAK,GAAG,MAAM;AAC/D;;;;;;;;;;AAWA,SAAgB,iBAAiB,MAItB;CACT,OAAO,KAAK,WAAW,WACnB,SAAS,KAAK,SAAS,KAAK,KAAK,OAAO,KAAK,OAC7C,UAAU,KAAK;AACrB;;;;;;;;;;;;AAaA,SAAgB,kBAAkB,MAM/B,kBAAkB,IAAY;CAC/B,OAAO,GAAG,YAAY,KAAK,SAAS,eAAe,EAAE,KAAK,iBAAiB,IAAI,EAAE,KAAK,eAAe,KAAK,UAAU;AACtH;;;;;;;;;;;;;;;AAgBA,SAAgB,YAAY,MAAc,UAAmB,MAAuB;CAClF,MAAM,IAAI,QAAQ,YAAY;CAC9B,IAAI,UAAU;CACd,IAAI;MACE,SAAS,GACX,UAAU;OACP,IAAI,KAAK,WAAW,GAAG,EAAE,EAAE,GAC9B,UAAU,IAAI,KAAK,MAAM,EAAE,MAAM;CAAA;CAErC,IAAI,aAAa,KAAA,KAAa,WAAW,KAAK,QAAQ,SAAS,UAK7D,OAAO,IAAI,QAAQ,MAAM,QAAQ,SAAS,WAAW,CAAC;CAExD,OAAO;AACT"}