zidane 6.1.13 → 6.2.0

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 (72) hide show
  1. package/dist/{acp-BqfKqQ9x.js → acp-0JO-UBEv.js} +2 -2
  2. package/dist/{acp-BqfKqQ9x.js.map → acp-0JO-UBEv.js.map} +1 -1
  3. package/dist/acp-cli.js +2 -2
  4. package/dist/acp.d.ts +1 -1
  5. package/dist/acp.js +1 -1
  6. package/dist/{agent-CZ3WSWqR.js → agent-25moybsj.js} +73 -11
  7. package/dist/agent-25moybsj.js.map +1 -0
  8. package/dist/agent.d.ts +1 -1
  9. package/dist/agent.js +1 -1
  10. package/dist/chat/pure.d.ts +3 -3
  11. package/dist/chat/pure.js +1 -1
  12. package/dist/chat.d.ts +5 -5
  13. package/dist/chat.d.ts.map +1 -1
  14. package/dist/chat.js +5 -5
  15. package/dist/{completion-core-CXYSVhZo.js → completion-core-BRo86R_L.js} +23 -10
  16. package/dist/completion-core-BRo86R_L.js.map +1 -0
  17. package/dist/contexts/daytona.d.ts +1 -1
  18. package/dist/contexts/e2b.d.ts +1 -1
  19. package/dist/eval.d.ts +1 -1
  20. package/dist/extensions.d.ts +2 -2
  21. package/dist/extensions.js +2 -2
  22. package/dist/headless.d.ts +1 -1
  23. package/dist/headless.js +1 -1
  24. package/dist/{index-X02SI0nt.d.ts → index-mUT8TI9j.d.ts} +248 -13
  25. package/dist/index-mUT8TI9j.d.ts.map +1 -0
  26. package/dist/index.d.ts +2 -2
  27. package/dist/index.js +4 -4
  28. package/dist/{generate-data-WL_yGVL6.js → inline-autocomplete-w_O3SVtN.js} +186 -6
  29. package/dist/inline-autocomplete-w_O3SVtN.js.map +1 -0
  30. package/dist/mcp.d.ts +1 -1
  31. package/dist/output/stream-json.d.ts +1 -1
  32. package/dist/output/terminal.d.ts +1 -1
  33. package/dist/presets.d.ts +1 -1
  34. package/dist/presets.js +1 -1
  35. package/dist/providers/anthropic.d.ts +1 -1
  36. package/dist/providers/arcee.d.ts +1 -1
  37. package/dist/providers/baseten.d.ts +1 -1
  38. package/dist/providers/cerebras.d.ts +1 -1
  39. package/dist/providers/local.d.ts +1 -1
  40. package/dist/providers/openai-compat.d.ts +1 -1
  41. package/dist/providers/openai.d.ts +1 -1
  42. package/dist/providers/openrouter.d.ts +1 -1
  43. package/dist/providers/xai.d.ts +1 -1
  44. package/dist/providers.d.ts +1 -1
  45. package/dist/restate.d.ts +1 -1
  46. package/dist/session/sqlite.d.ts +1 -1
  47. package/dist/session.d.ts +1 -1
  48. package/dist/skills.d.ts +1 -1
  49. package/dist/{tool-formatters-kg8O6wHZ.d.ts → tool-formatters-DOcJz_J9.d.ts} +2 -2
  50. package/dist/{tool-formatters-kg8O6wHZ.d.ts.map → tool-formatters-DOcJz_J9.d.ts.map} +1 -1
  51. package/dist/tools/fetch-url.d.ts +1 -1
  52. package/dist/tools/web-search.d.ts +1 -1
  53. package/dist/tools.d.ts +1 -1
  54. package/dist/tools.js +1 -1
  55. package/dist/{transcript-anchors-DAf0Mr_9.js → transcript-anchors-CO-WnuYQ.js} +13 -6
  56. package/dist/transcript-anchors-CO-WnuYQ.js.map +1 -0
  57. package/dist/{transcript-anchors-DAF4RbyU.d.ts → transcript-anchors-CzMMNrhJ.d.ts} +2 -2
  58. package/dist/{transcript-anchors-DAF4RbyU.d.ts.map → transcript-anchors-CzMMNrhJ.d.ts.map} +1 -1
  59. package/dist/tui.d.ts +11 -4
  60. package/dist/tui.d.ts.map +1 -1
  61. package/dist/tui.js +339 -31
  62. package/dist/tui.js.map +1 -1
  63. package/dist/{turn-operations-zkZ1L0eb.d.ts → turn-operations-CrCrJnvo.d.ts} +3 -3
  64. package/dist/{turn-operations-zkZ1L0eb.d.ts.map → turn-operations-CrCrJnvo.d.ts.map} +1 -1
  65. package/dist/types.d.ts +1 -1
  66. package/docs/EXTENSIONS.md +37 -1
  67. package/package.json +1 -1
  68. package/dist/agent-CZ3WSWqR.js.map +0 -1
  69. package/dist/completion-core-CXYSVhZo.js.map +0 -1
  70. package/dist/generate-data-WL_yGVL6.js.map +0 -1
  71. package/dist/index-X02SI0nt.d.ts.map +0 -1
  72. package/dist/transcript-anchors-DAf0Mr_9.js.map +0 -1
package/dist/tui.js CHANGED
@@ -1,5 +1,5 @@
1
- import { $ as useMcpAuthState, $n as buildPlanSystem, $t as restoreChainFallbacks, A as runOAuthLogin, Bt as createDiscoverySlot, Ct as SETTINGS_CHOICES, D as formatPathForCwd, Dt as clampFps, Et as SettingsProvider, G as buildVisibleMcpRows, Gt as useConfig, Ht as useDiscovery, J as createFileMcpCredentialStore, Jt as buildRunModel, K as indexOfServerRow, Kt as resolveConfig, L as loadMcpToolsCache, M as buildMcpServers, Mt as resolveTheme, O as fetchOAuthRedirect, Ot as useSettings, P as discoverProjectMcps, Q as useMcpAuthDispatch, Qn as buildBuildSystem, Qt as providerKeySetChanged, R as mcpToolsCachePath, St as SETTINGS_CATEGORIES, T as suggestSafelistEntries, Tn as accentColor, Tt as SETTINGS_TOGGLES, U as useMcpToolToggleMap, Ut as useDiscoveryOptional, V as subscribeMcpToolsCache, Vn as useActiveTodos, Vt as DiscoveryProvider, Wt as ConfigProvider, Xt as chainsEqual, Yt as chainPositionOf, Z as McpAuthProvider, Zt as filterChainFallbacks, _ as useSafeModeQueue, _n as discoverAgentsMd, _r as toolCallPreview, _t as buildHints, a as useSurfaces, an as bootTick, at as buildResumedToolResultsTurn, b as getSafelist, br as usageByModel, bt as useEnabledToggleSet, c as useStreamBuffer, cr as lastContextSizeFromTurns, ct as makeRequestInteraction, d as discoverProjectSkills, dr as marginTopFor, dt as useInteractionsActions, er as envSection, et as getMcpAuthStatus, ft as useInteractionsQueue, g as useSafeModeActions, gn as chatAutoCompactBehavior, gt as truncateTrailing, h as SafeModeProvider, hr as sumRunCosts, ht as hintsLength, i as useSelectStyle, ir as compactSummaryEvent, it as PRESENT_PLAN_TOOL, j as supportsOAuth, jn as TODO_STATUS_GLYPHS, jt as resolveChipColor, k as oauthUsesManualCodePaste, l as buildSkillsConfig, lr as listSessionMeta, lt as pendingInteractionsFromTurns, m as writeSessionExport, mr as stripSpawnTokensLine, mt as clipHintsToWidth, n as ThemeProvider, nn as useCompletion, nr as createChatTurnsReadTool, nt as ASK_USER_TOOL, on as buildUpdateHint, or as deriveSessionTitle, ot as createInteractionTools, pr as serverToolResultSummary, pt as EMPTY_HINTS, q as parentServerName, qt as resolveStoragePaths, r as useColors, rn as tryOpenBrowser, rt as InteractionsProvider, s as useTheme, sn as useUpdateCheck, sr as eventsFromTurns, t as computeTurnAnchors, tn as toggleChainEntry, tr as chatReferenceTokensForPrompt, u as defaultSkillScanPaths, ur as loadState, vr as toolResultText, wt as SETTINGS_INPUTS, x as isOnSafelist, xt as DEFAULT_SETTINGS, y as addToSafelist, yr as updateToolEventOutcomes, yt as listProjectFiles, z as refreshMcpToolsCatalog } from "./transcript-anchors-DAf0Mr_9.js";
2
- import { $ as composeExtensionPreset, B as ExtensionInstallError, Bt as ensureKeybindingsFile, Et as createModelSearchTool, H as installExtensionFromSpec, Ht as groupBindings, J as createExtensionHud, K as removeInstalledExtension, P as summaryToTurn, St as tailTruncate, Ut as keybindingsPath, Vt as formatBindingForDisplay, Wt as matchesBinding, X as discoverAndBuildExtensionRegistry, Y as registerExtensionHostModules, Yt as resolveExtensionKeybindings, _ as buildPostCompactAttachments, c as applyCompactSummaryCutoff, en as inlineLoadedExtension, et as disposeExtensionRegistry, f as cleanupPersistedSession, g as resolveTasksDir, h as resolvePersistDir, ht as isSpawnTool, it as createExtensionHostRuntimeBridge, lt as basic_default, m as resolveMcpWarningsDir, mn as effectiveContextWindow, nn as parseExtensionScanPathEnv, on as coerceExtensionConfigInput, pn as OUTPUT_RESERVE_TOKENS, q as updateInstalledExtension, rn as scanExtensionDirectories, rt as partitionExtensionCatalog, t as createAgent, tt as filterExtensionRegistry, un as resolveExtensionConfigValue, wt as looksBinary, x as compactConversation, y as selectFilesFromSession, z as createExtensionPromptBridge, zt as KEYBINDING_KEY_COL_WIDTH } from "./agent-CZ3WSWqR.js";
1
+ import { $ as useMcpAuthState, $n as buildPlanSystem, $t as restoreChainFallbacks, A as runOAuthLogin, Bt as createDiscoverySlot, Ct as SETTINGS_CHOICES, D as formatPathForCwd, Dt as clampFps, Et as SettingsProvider, G as buildVisibleMcpRows, Gt as useConfig, Ht as useDiscovery, J as createFileMcpCredentialStore, Jt as buildRunModel, K as indexOfServerRow, Kt as resolveConfig, L as loadMcpToolsCache, M as buildMcpServers, Mt as resolveTheme, O as fetchOAuthRedirect, Ot as useSettings, P as discoverProjectMcps, Q as useMcpAuthDispatch, Qn as buildBuildSystem, Qt as providerKeySetChanged, R as mcpToolsCachePath, St as SETTINGS_CATEGORIES, T as suggestSafelistEntries, Tn as accentColor, Tt as SETTINGS_TOGGLES, U as useMcpToolToggleMap, Ut as useDiscoveryOptional, V as subscribeMcpToolsCache, Vn as useActiveTodos, Vt as DiscoveryProvider, Wt as ConfigProvider, Xt as chainsEqual, Yt as chainPositionOf, Z as McpAuthProvider, Zt as filterChainFallbacks, _ as useSafeModeQueue, _n as discoverAgentsMd, _r as toolCallPreview, _t as buildHints, a as useSurfaces, an as bootTick, at as buildResumedToolResultsTurn, b as getSafelist, br as usageByModel, bt as useEnabledToggleSet, c as useStreamBuffer, cr as lastContextSizeFromTurns, ct as makeRequestInteraction, d as discoverProjectSkills, dr as marginTopFor, dt as useInteractionsActions, er as envSection, et as getMcpAuthStatus, ft as useInteractionsQueue, g as useSafeModeActions, gn as chatAutoCompactBehavior, gt as truncateTrailing, h as SafeModeProvider, hr as sumRunCosts, ht as hintsLength, i as useSelectStyle, ir as compactSummaryEvent, it as PRESENT_PLAN_TOOL, j as supportsOAuth, jn as TODO_STATUS_GLYPHS, jt as resolveChipColor, k as oauthUsesManualCodePaste, l as buildSkillsConfig, lr as listSessionMeta, lt as pendingInteractionsFromTurns, m as writeSessionExport, mr as stripSpawnTokensLine, mt as clipHintsToWidth, n as ThemeProvider, nn as useCompletion, nr as createChatTurnsReadTool, nt as ASK_USER_TOOL, on as buildUpdateHint, or as deriveSessionTitle, ot as createInteractionTools, pr as serverToolResultSummary, pt as EMPTY_HINTS, q as parentServerName, qt as resolveStoragePaths, r as useColors, rn as tryOpenBrowser, rt as InteractionsProvider, s as useTheme, sn as useUpdateCheck, sr as eventsFromTurns, t as computeTurnAnchors, tn as toggleChainEntry, tr as chatReferenceTokensForPrompt, u as defaultSkillScanPaths, ur as loadState, vr as toolResultText, wt as SETTINGS_INPUTS, x as isOnSafelist, xt as DEFAULT_SETTINGS, y as addToSafelist, yr as updateToolEventOutcomes, yt as listProjectFiles, z as refreshMcpToolsCatalog } from "./transcript-anchors-CO-WnuYQ.js";
2
+ import { $ as composeExtensionPreset, B as ExtensionInstallError, Bt as ensureKeybindingsFile, Et as createModelSearchTool, H as installExtensionFromSpec, Ht as groupBindings, J as createExtensionHud, K as removeInstalledExtension, P as summaryToTurn, St as tailTruncate, Ut as keybindingsPath, Vt as formatBindingForDisplay, Wt as matchesBinding, X as discoverAndBuildExtensionRegistry, Y as registerExtensionHostModules, Yt as resolveExtensionKeybindings, _ as buildPostCompactAttachments, c as applyCompactSummaryCutoff, dn as sanitizeExtensionConfigActionPatch, en as inlineLoadedExtension, et as disposeExtensionRegistry, f as cleanupPersistedSession, g as resolveTasksDir, h as resolvePersistDir, hn as effectiveContextWindow, ht as isSpawnTool, it as createExtensionHostRuntimeBridge, lt as basic_default, m as resolveMcpWarningsDir, mn as OUTPUT_RESERVE_TOKENS, nn as parseExtensionScanPathEnv, on as coerceExtensionConfigInput, q as updateInstalledExtension, rn as scanExtensionDirectories, rt as partitionExtensionCatalog, t as createAgent, tt as filterExtensionRegistry, un as resolveExtensionConfigValue, wt as looksBinary, x as compactConversation, y as selectFilesFromSession, z as createExtensionPromptBridge, zt as KEYBINDING_KEY_COL_WIDTH } from "./agent-25moybsj.js";
3
3
  import { a as formatDuration, c as previewLine, i as fmtTokens, l as shortId, n as compactPath, o as formatTaskStatus, r as fmtCost, s as formatTaskSummary, t as ageString } from "./format-BF745pLL.js";
4
4
  import { n as appendCapped } from "./output-cap-kBUHBlnq.js";
5
5
  import { i as killProcessGroup, n as SUPPORTS_PROCESS_GROUPS, r as createProcessContext } from "./contexts-A4ep-iJs.js";
@@ -12,8 +12,8 @@ import { replaceDynamicSection } from "./prompt.js";
12
12
  import { a as getExtensionSessionState, i as demoteStaleRunningStatus, o as loadSession, s as setExtensionSessionState, t as createSession } from "./session-D7JSEMME.js";
13
13
  import { o as withTimeout } from "./timeout-BDetbuN6.js";
14
14
  import { n as connectMcpServers, u as McpOAuthProvider } from "./mcp-CkHUripi.js";
15
- import { c as commandBlockToEvent, d as executeCommand, f as parseCommandInvocation, i as shouldAutoGenerateTitle, l as commandBlocksToContent, r as generateSessionTitle, t as generateStructuredData } from "./generate-data-WL_yGVL6.js";
16
- import { s as resolveCompletionSubmit } from "./completion-core-CXYSVhZo.js";
15
+ import { a as generateStructuredData, c as shouldAutoGenerateTitle, f as commandBlockToEvent, g as parseCommandInvocation, h as executeCommand, n as patchInlineGhost, p as commandBlocksToContent, r as resolveInlineSuggestion, s as generateSessionTitle, t as createPathAutocompleteProvider } from "./inline-autocomplete-w_O3SVtN.js";
16
+ import { s as resolveCompletionSubmit } from "./completion-core-BRo86R_L.js";
17
17
  import { i as installSkillFromSpec, r as SkillInstallError } from "./skills-BlmY7QhV.js";
18
18
  import { i as ZIDANE_EXTENSION_SKILL_NAME, l as withZidaneExtensionSkill, o as extensionDirForCwd, r as EXTENSION_EDIT_METADATA_KEY, s as extensionScaffold, t as loginMcpServer } from "./login-Bp_tRj_e.js";
19
19
  import { C as restoreModelOptions, S as piIdOf, _ as modelOptionsFor, m as getContextWindow, p as enabledModelOptions, s as setProviderCredential, t as detectAuth, v as modelSupportsReasoning } from "./auth-D5FfJtLf.js";
@@ -50,16 +50,18 @@ function scoreCommands(catalog, query) {
50
50
  const scored = [];
51
51
  for (const command of catalog) {
52
52
  const name = command.name.toLowerCase();
53
+ const aliases = (command.aliases ?? []).map((a) => a.toLowerCase());
54
+ const group = command.group?.toLowerCase();
53
55
  const desc = command.description.toLowerCase();
54
56
  if (q.length === 0) scored.push({
55
57
  command,
56
58
  rank: 4
57
59
  });
58
- else if (name.startsWith(q)) scored.push({
60
+ else if (name.startsWith(q) || aliases.some((a) => a.startsWith(q))) scored.push({
59
61
  command,
60
62
  rank: 0
61
63
  });
62
- else if (name.includes(q)) scored.push({
64
+ else if (name.includes(q) || aliases.some((a) => a.includes(q)) || group !== void 0 && q.length >= 2 && group.startsWith(q)) scored.push({
63
65
  command,
64
66
  rank: 1
65
67
  });
@@ -76,7 +78,7 @@ function scoreCommands(catalog, query) {
76
78
  return scored.map(({ command }) => ({
77
79
  id: command.name,
78
80
  label: command.name,
79
- description: command.description,
81
+ description: command.aliases?.length ? `${command.description} (alias: ${command.aliases.map((a) => `/${a}`).join(", ")})` : command.description,
80
82
  insertText: `/${command.name} `,
81
83
  data: command
82
84
  }));
@@ -97,7 +99,7 @@ function createCommandsCompletionProvider(opts) {
97
99
  if (spaceIdx !== -1) {
98
100
  if (ctx.text.trimStart()[0] !== "/") return [];
99
101
  const typed = query.slice(0, spaceIdx).toLowerCase();
100
- const command = opts.getCommands().find((c) => c.name.toLowerCase() === typed);
102
+ const command = opts.getCommands().find((c) => c.name.toLowerCase() === typed || c.aliases?.some((a) => a.toLowerCase() === typed));
101
103
  if (!command?.completeArgs) return [];
102
104
  const argsPrefix = query.slice(spaceIdx + 1).replace(/^\s+/, "");
103
105
  return Promise.resolve(command.completeArgs(argsPrefix)).then((suggestions) => (suggestions ?? []).map((s) => ({
@@ -5998,17 +6000,48 @@ function CompletionPopup({ state, visibleRows = 6 }) {
5998
6000
  });
5999
6001
  height = 3;
6000
6002
  } else {
6001
- const rows = Math.min(state.items.length, visibleRows);
6003
+ const showSections = state.items.some((it) => it.section);
6004
+ const displayRows = [];
6005
+ let prevSection;
6006
+ for (const [index, item] of state.items.entries()) {
6007
+ if (showSections && item.section && item.section !== prevSection) {
6008
+ displayRows.push({
6009
+ kind: "header",
6010
+ section: item.section
6011
+ });
6012
+ prevSection = item.section;
6013
+ }
6014
+ displayRows.push({
6015
+ kind: "item",
6016
+ item,
6017
+ index
6018
+ });
6019
+ }
6020
+ const rows = Math.min(displayRows.length, visibleRows);
6021
+ const selectedRow = displayRows.findIndex((r) => r.kind === "item" && r.index === state.selectedIndex);
6002
6022
  const half = Math.floor(rows / 2);
6003
- let start = Math.max(0, state.selectedIndex - half);
6004
- if (start + rows > state.items.length) start = state.items.length - rows;
6005
- const slice = state.items.slice(start, start + rows);
6006
- const showSections = new Set(state.items.map((it) => it.section).filter(Boolean)).size > 1;
6023
+ let start = Math.max(0, selectedRow - half);
6024
+ if (start + rows > displayRows.length) start = displayRows.length - rows;
6025
+ const slice = displayRows.slice(start, start + rows);
6007
6026
  height = 2 + rows + 1;
6008
6027
  body = /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx$1("box", {
6009
6028
  style: { flexDirection: "column" },
6010
- children: slice.map((item, i) => {
6011
- const focused = start + i === state.selectedIndex;
6029
+ children: slice.map((row, i) => {
6030
+ if (row.kind === "header") return /* @__PURE__ */ jsx$1("box", {
6031
+ style: {
6032
+ height: 1,
6033
+ overflow: "hidden",
6034
+ flexShrink: 0
6035
+ },
6036
+ children: /* @__PURE__ */ jsx$1("text", {
6037
+ fg: COLOR.mute,
6038
+ wrapMode: "none",
6039
+ children: `── ${row.section} ${"─".repeat(200)}`
6040
+ })
6041
+ }, `header:${row.section}:${start + i}`);
6042
+ const { item, index } = row;
6043
+ const focused = index === state.selectedIndex;
6044
+ const titleFg = (item.providerId !== void 0 ? SURFACE.chips[item.providerId] : void 0)?.bg ?? (item.providerId === "commands" ? COLOR.accent : SELECT.textColor);
6012
6045
  return /* @__PURE__ */ jsx$1("box", {
6013
6046
  style: {
6014
6047
  height: 1,
@@ -6024,12 +6057,8 @@ function CompletionPopup({ state, visibleRows = 6 }) {
6024
6057
  fg: focused ? COLOR.brand : COLOR.mute,
6025
6058
  children: focused ? "▶ " : " "
6026
6059
  }),
6027
- showSections && item.section && /* @__PURE__ */ jsxs("span", {
6028
- fg: COLOR.mute,
6029
- children: [item.section, " "]
6030
- }),
6031
6060
  /* @__PURE__ */ jsx$1("span", {
6032
- fg: focused ? COLOR.brand : SELECT.textColor,
6061
+ fg: focused ? COLOR.brand : titleFg,
6033
6062
  children: item.label
6034
6063
  }),
6035
6064
  item.description && /* @__PURE__ */ jsxs("span", {
@@ -9463,7 +9492,7 @@ const MIME_BY_EXT = {
9463
9492
  * default-value reference at the prop destructure.
9464
9493
  */
9465
9494
  const EMPTY_QUEUED_MESSAGES = [];
9466
- function ChatScreen({ cwd, events, busy, compacting = false, queuedMessages = EMPTY_QUEUED_MESSAGES, queueSelectionIndex = null, queueShortcuts, onEnterQueueFromEmptyPrompt, settings, onSubmit, session, pending, onApproval, pendingInteraction, onInteraction, completionProviders, onCompletionTab, enterSelectsCompletion, onPopupOpenChange, selectedTurnId, promptTriggerHints, attachImageBinding, editorBinding, sessionDetailsBinding, liveSession = null }) {
9495
+ function ChatScreen({ cwd, events, busy, compacting = false, queuedMessages = EMPTY_QUEUED_MESSAGES, queueSelectionIndex = null, queueShortcuts, onEnterQueueFromEmptyPrompt, settings, onSubmit, session, pending, onApproval, pendingInteraction, onInteraction, completionProviders, inlineAutocompleteProviders, onCompletionTab, enterSelectsCompletion, onPopupOpenChange, selectedTurnId, promptTriggerHints, attachImageBinding, editorBinding, sessionDetailsBinding, liveSession = null }) {
9467
9496
  const COLOR = useColors();
9468
9497
  const titleText = session?.title ?? "New session";
9469
9498
  const sessionShortcutKey = formatBindingForDisplay(sessionDetailsBinding);
@@ -9577,6 +9606,7 @@ function ChatScreen({ cwd, events, busy, compacting = false, queuedMessages = EM
9577
9606
  userPrompts,
9578
9607
  onSubmit,
9579
9608
  completionProviders,
9609
+ inlineAutocompleteProviders,
9580
9610
  onCompletionTab,
9581
9611
  enterSelectsCompletion,
9582
9612
  onPopupOpenChange: handlePopupOpenChange,
@@ -9898,7 +9928,15 @@ function previewText(text) {
9898
9928
  }
9899
9929
  /** Stable empty providers reference — avoids `useCompletion` rerun on every render when no providers are wired. */
9900
9930
  const EMPTY_PROVIDERS = [];
9901
- function PromptBlock({ userPrompts, onSubmit, completionProviders, onCompletionTab, enterSelectsCompletion, onPopupOpenChange, selectMode = null, triggerHints, busy = false, onEnterQueueFromEmpty, attachImageBinding, editorBinding }) {
9931
+ /** Stable empty reference for the inline-autocomplete effect's dep array. */
9932
+ const EMPTY_INLINE_PROVIDERS = [];
9933
+ /**
9934
+ * Debounce before querying inline-autocomplete providers. Long enough to
9935
+ * skip intermediate keystrokes while typing a path, short enough that the
9936
+ * ghost feels immediate on a pause.
9937
+ */
9938
+ const INLINE_GHOST_DEBOUNCE_MS = 120;
9939
+ function PromptBlock({ userPrompts, onSubmit, completionProviders, inlineAutocompleteProviders, onCompletionTab, enterSelectsCompletion, onPopupOpenChange, selectMode = null, triggerHints, busy = false, onEnterQueueFromEmpty, attachImageBinding, editorBinding }) {
9902
9940
  const focused = useModalAwareFocus();
9903
9941
  const renderer = useRenderer();
9904
9942
  const COLOR = useColors();
@@ -9984,6 +10022,9 @@ function PromptBlock({ userPrompts, onSubmit, completionProviders, onCompletionT
9984
10022
  shellModeRef.current = on;
9985
10023
  setShellMode(on);
9986
10024
  }, []);
10025
+ const [ghost, setGhost] = useState(null);
10026
+ const ghostRef = useRef(null);
10027
+ ghostRef.current = ghost;
9987
10028
  /**
9988
10029
  * Pull the latest buffer state from the OpenTUI textarea ref. Called from
9989
10030
  * `onContentChange` + `onKeyDown` so cursor moves (without text changes)
@@ -10001,9 +10042,49 @@ function PromptBlock({ userPrompts, onSubmit, completionProviders, onCompletionT
10001
10042
  text: ta.plainText,
10002
10043
  cursor: ta.cursorOffset
10003
10044
  });
10045
+ setGhost((prev) => patchInlineGhost(prev, ta.plainText, ta.cursorOffset));
10004
10046
  const total = ta.editorView.getTotalVirtualLineCount();
10005
10047
  setContentLines(Math.max(MIN_CONTENT_LINES, total));
10006
10048
  }, []);
10049
+ const inlineProviders = inlineAutocompleteProviders ?? EMPTY_INLINE_PROVIDERS;
10050
+ const inlineEnabled = settings.inlineAutocomplete && inlineProviders.length > 0;
10051
+ useEffect(() => {
10052
+ const atWordBoundary = bufferState.cursor === bufferState.text.length || /\s/.test(bufferState.text[bufferState.cursor]);
10053
+ if (!inlineEnabled || popupOpen || selectMode !== null || shellMode || bufferState.text.length === 0 || !atWordBoundary) {
10054
+ setGhost(null);
10055
+ return;
10056
+ }
10057
+ const controller = new AbortController();
10058
+ const { text, cursor } = bufferState;
10059
+ const timer = setTimeout(() => {
10060
+ resolveInlineSuggestion(inlineProviders, {
10061
+ text,
10062
+ cursor,
10063
+ cwd: process.cwd(),
10064
+ signal: controller.signal
10065
+ }).then((res) => {
10066
+ if (controller.signal.aborted) return;
10067
+ const suffixes = (res?.suffixes ?? []).map((s) => s.split("\n")[0]).filter((s) => s.length > 0);
10068
+ setGhost(suffixes.length > 0 ? {
10069
+ suffixes,
10070
+ index: 0,
10071
+ text,
10072
+ cursor
10073
+ } : null);
10074
+ });
10075
+ }, INLINE_GHOST_DEBOUNCE_MS);
10076
+ return () => {
10077
+ controller.abort();
10078
+ clearTimeout(timer);
10079
+ };
10080
+ }, [
10081
+ bufferState,
10082
+ inlineEnabled,
10083
+ popupOpen,
10084
+ selectMode,
10085
+ shellMode,
10086
+ inlineProviders
10087
+ ]);
10007
10088
  /**
10008
10089
  * Open the current prompt in `$EDITOR` (git-style round-trip). The
10009
10090
  * external-editor module is pure; the TUI handoff is owned here — suspend
@@ -10255,6 +10336,30 @@ function PromptBlock({ userPrompts, onSubmit, completionProviders, onCompletionT
10255
10336
  return;
10256
10337
  }
10257
10338
  if (event.ctrl || event.shift || event.meta) return;
10339
+ if (ghostRef.current) {
10340
+ const g = ghostRef.current;
10341
+ if (event.name === "tab") {
10342
+ const ta = textareaRef.current;
10343
+ if (ta && ta.plainText === g.text && ta.cursorOffset === g.cursor) {
10344
+ event.preventDefault();
10345
+ ta.insertText(g.suffixes[g.index]);
10346
+ setGhost(null);
10347
+ syncBuffer();
10348
+ return;
10349
+ }
10350
+ }
10351
+ if ((event.name === "up" || event.name === "down") && g.suffixes.length > 1) {
10352
+ event.preventDefault();
10353
+ const delta = event.name === "down" ? 1 : -1;
10354
+ setGhost({
10355
+ ...g,
10356
+ index: (g.index + delta + g.suffixes.length) % g.suffixes.length
10357
+ });
10358
+ return;
10359
+ }
10360
+ if (event.name === "escape") setGhost(null);
10361
+ else if (event.name === "left" || event.name === "right" || event.name === "home" || event.name === "end" || event.name === "pageup" || event.name === "pagedown" || event.name === "up" || event.name === "down") setGhost(null);
10362
+ }
10258
10363
  if (event.name !== "up" && event.name !== "down") return;
10259
10364
  const buffer = textareaRef.current;
10260
10365
  if (!buffer) return;
@@ -10292,6 +10397,27 @@ function PromptBlock({ userPrompts, onSubmit, completionProviders, onCompletionT
10292
10397
  attachments,
10293
10398
  showNotice
10294
10399
  ]);
10400
+ const ghostPosition = useMemo(() => {
10401
+ if (!ghost) return null;
10402
+ const ta = textareaRef.current;
10403
+ if (!ta || ta.plainText !== ghost.text || ta.cursorOffset !== ghost.cursor) return null;
10404
+ const cursor = ta.visualCursor;
10405
+ if (cursor.visualRow < 0 || cursor.visualRow >= Math.min(MAX_CONTENT_LINES, contentLines)) return null;
10406
+ return {
10407
+ row: cursor.visualRow,
10408
+ col: cursor.visualCol
10409
+ };
10410
+ }, [
10411
+ ghost,
10412
+ contentLines,
10413
+ bufferState
10414
+ ]);
10415
+ const ghostTail = useMemo(() => {
10416
+ if (!ghost) return "";
10417
+ const rest = ghost.text.slice(ghost.cursor);
10418
+ const nl = rest.indexOf("\n");
10419
+ return nl === -1 ? rest : rest.slice(0, nl);
10420
+ }, [ghost]);
10295
10421
  const boxHeight = Math.min(MAX_CONTENT_LINES, contentLines) + 2;
10296
10422
  return /* @__PURE__ */ jsxs("box", {
10297
10423
  style: {
@@ -10347,7 +10473,7 @@ function PromptBlock({ userPrompts, onSubmit, completionProviders, onCompletionT
10347
10473
  flexDirection: "column",
10348
10474
  flexShrink: 0
10349
10475
  },
10350
- children: [/* @__PURE__ */ jsx$1("box", {
10476
+ children: [/* @__PURE__ */ jsxs("box", {
10351
10477
  style: {
10352
10478
  border: true,
10353
10479
  borderColor: selectMode ? COLOR.warn : shellMode ? COLOR.accent : COLOR.borderActive,
@@ -10356,7 +10482,7 @@ function PromptBlock({ userPrompts, onSubmit, completionProviders, onCompletionT
10356
10482
  height: boxHeight,
10357
10483
  flexDirection: "column"
10358
10484
  },
10359
- children: /* @__PURE__ */ jsx$1("textarea", {
10485
+ children: [/* @__PURE__ */ jsx$1("textarea", {
10360
10486
  ref: textareaRef,
10361
10487
  focused: focused && !selectMode,
10362
10488
  keyBindings: TEXTAREA_BINDINGS,
@@ -10371,7 +10497,24 @@ function PromptBlock({ userPrompts, onSubmit, completionProviders, onCompletionT
10371
10497
  onContentChange: syncBuffer,
10372
10498
  onKeyDown,
10373
10499
  onPaste
10374
- })
10500
+ }), ghostPosition !== null && ghost !== null && /* @__PURE__ */ jsx$1("box", {
10501
+ style: {
10502
+ position: "absolute",
10503
+ top: ghostPosition.row,
10504
+ left: 1 + ghostPosition.col,
10505
+ right: 1,
10506
+ height: 1,
10507
+ overflow: "hidden",
10508
+ backgroundColor: SURFACE.background
10509
+ },
10510
+ children: /* @__PURE__ */ jsxs("text", {
10511
+ wrapMode: "none",
10512
+ children: [/* @__PURE__ */ jsx$1("span", {
10513
+ fg: COLOR.dim,
10514
+ children: ghost.suffixes[ghost.index]
10515
+ }), ghostTail.length > 0 && /* @__PURE__ */ jsx$1("span", { children: ghostTail })]
10516
+ })
10517
+ })]
10375
10518
  }), /* @__PURE__ */ jsx$1(PromptHints, {
10376
10519
  selectMode,
10377
10520
  triggerHints,
@@ -12009,7 +12152,68 @@ function SettingsModal({ skillsCatalog: skillsCatalogProp, mcpsCatalog: mcpsCata
12009
12152
  }
12010
12153
  });
12011
12154
  }, [settings.extensionConfig, setSetting]);
12155
+ const writeConfigValues = useCallback((extName, values) => {
12156
+ const prev = settings.extensionConfig ?? {};
12157
+ const prevExt = prev[extName] ?? {};
12158
+ setSetting("extensionConfig", {
12159
+ ...prev,
12160
+ [extName]: {
12161
+ ...prevExt,
12162
+ ...values
12163
+ }
12164
+ });
12165
+ }, [settings.extensionConfig, setSetting]);
12166
+ const [configAction, setConfigAction] = useState(null);
12167
+ const writeConfigValuesRef = useRef(writeConfigValues);
12168
+ writeConfigValuesRef.current = writeConfigValues;
12169
+ const extensionConfigItemsRef = useRef(extensionConfigItems);
12170
+ extensionConfigItemsRef.current = extensionConfigItems;
12171
+ const [actionProbes, setActionProbes] = useState({});
12172
+ const [actionProbeNonce, setActionProbeNonce] = useState(0);
12173
+ const configActionBusyRef = useRef(false);
12174
+ const runConfigAction = useCallback((extName, item) => {
12175
+ if (configActionBusyRef.current) return;
12176
+ configActionBusyRef.current = true;
12177
+ setConfigAction({
12178
+ extName,
12179
+ key: item.key,
12180
+ state: "busy"
12181
+ });
12182
+ (async () => {
12183
+ try {
12184
+ const result = await item.run() ?? void 0;
12185
+ const { accepted, rejected } = sanitizeExtensionConfigActionPatch(extensionConfigItemsRef.current[extName], result?.config);
12186
+ const acceptedKeys = Object.keys(accepted);
12187
+ if (acceptedKeys.length > 0) writeConfigValuesRef.current(extName, accepted);
12188
+ const parts = [];
12189
+ if (result?.message) parts.push(result.message);
12190
+ else if (acceptedKeys.length > 0) parts.push(`updated ${acceptedKeys.join(", ")}`);
12191
+ else parts.push("done");
12192
+ if (rejected.length > 0) parts.push(`(ignored invalid: ${rejected.join(", ")})`);
12193
+ setConfigAction({
12194
+ extName,
12195
+ key: item.key,
12196
+ state: "done",
12197
+ text: parts.join(" ")
12198
+ });
12199
+ } catch (err) {
12200
+ setConfigAction({
12201
+ extName,
12202
+ key: item.key,
12203
+ state: "error",
12204
+ text: errorMessage(err)
12205
+ });
12206
+ } finally {
12207
+ configActionBusyRef.current = false;
12208
+ }
12209
+ setActionProbeNonce((n) => n + 1);
12210
+ })();
12211
+ }, []);
12012
12212
  const activateConfigRow = useCallback((extName, item) => {
12213
+ if (item.type === "action") {
12214
+ runConfigAction(extName, item);
12215
+ return;
12216
+ }
12013
12217
  const current = resolveExtensionConfigValue(item, settings.extensionConfig?.[extName]?.[item.key]);
12014
12218
  if (item.type === "boolean") {
12015
12219
  writeConfigValue(extName, item.key, !current);
@@ -12031,7 +12235,8 @@ function SettingsModal({ skillsCatalog: skillsCatalogProp, mcpsCatalog: mcpsCata
12031
12235
  }, [
12032
12236
  settings.extensionConfig,
12033
12237
  writeConfigValue,
12034
- modelCatalog
12238
+ modelCatalog,
12239
+ runConfigAction
12035
12240
  ]);
12036
12241
  const applyModelEdit = useCallback((ids) => {
12037
12242
  if (configEdit) writeConfigValue(configEdit.extName, configEdit.key, ids.join(", "));
@@ -12073,6 +12278,40 @@ function SettingsModal({ skillsCatalog: skillsCatalogProp, mcpsCatalog: mcpsCata
12073
12278
  logs
12074
12279
  ]);
12075
12280
  const [activeTab, setActiveTab] = useState(tabOrder[0]);
12281
+ useEffect(() => {
12282
+ if (activeTab !== "extensions") return;
12283
+ let cancelled = false;
12284
+ for (const [extName, byKey] of Object.entries(extensionConfigItems)) for (const item of Object.values(byKey)) {
12285
+ if (item.type !== "action" || typeof item.status !== "function") continue;
12286
+ (async () => {
12287
+ let status;
12288
+ try {
12289
+ status = await Promise.race([Promise.resolve(item.status()), new Promise((resolve) => setTimeout(resolve, 3e3))]);
12290
+ } catch {
12291
+ status = void 0;
12292
+ }
12293
+ if (cancelled) return;
12294
+ const mapKey = `${extName}:${item.key}`;
12295
+ setActionProbes((prev) => {
12296
+ if (status && typeof status.message === "string") return {
12297
+ ...prev,
12298
+ [mapKey]: status
12299
+ };
12300
+ if (!(mapKey in prev)) return prev;
12301
+ const next = { ...prev };
12302
+ delete next[mapKey];
12303
+ return next;
12304
+ });
12305
+ })();
12306
+ }
12307
+ return () => {
12308
+ cancelled = true;
12309
+ };
12310
+ }, [
12311
+ activeTab,
12312
+ extensionConfigItems,
12313
+ actionProbeNonce
12314
+ ]);
12076
12315
  const [extEditNotice, setExtEditNotice] = useState(null);
12077
12316
  const [extOp, setExtOp] = useState(null);
12078
12317
  const [removeArmed, setRemoveArmed] = useState(null);
@@ -12785,7 +13024,9 @@ function SettingsModal({ skillsCatalog: skillsCatalogProp, mcpsCatalog: mcpsCata
12785
13024
  onCommitEdit: commitConfigEdit,
12786
13025
  modelCatalog,
12787
13026
  onApplyModelEdit: applyModelEdit,
12788
- onCancelEdit: cancelConfigEdit
13027
+ onCancelEdit: cancelConfigEdit,
13028
+ actionStatus: configAction,
13029
+ actionProbes
12789
13030
  }),
12790
13031
  activeTab === "mcps" && /* @__PURE__ */ jsx$1(McpsList, {
12791
13032
  rows: mcpVisibleRows,
@@ -13059,7 +13300,7 @@ function GeneralList({ items, cursor, highlightBg, query, contentCols, editingKe
13059
13300
  });
13060
13301
  }
13061
13302
  const EXTENSION_CONFIG_INDENT = 0;
13062
- function ExtensionsList({ rows, enabledSet, extensionConfig, categories, totalCount, cursor, highlightBg, query, contentCols, editing, inputRef, onCommitEdit, modelCatalog, onApplyModelEdit, onCancelEdit }) {
13303
+ function ExtensionsList({ rows, enabledSet, extensionConfig, categories, totalCount, cursor, highlightBg, query, contentCols, editing, inputRef, onCommitEdit, modelCatalog, onApplyModelEdit, onCancelEdit, actionStatus, actionProbes }) {
13063
13304
  const COLOR = useColors();
13064
13305
  const home = homedir();
13065
13306
  if (totalCount === 0) return /* @__PURE__ */ jsxs("box", {
@@ -13206,7 +13447,19 @@ function ExtensionsList({ rows, enabledSet, extensionConfig, categories, totalCo
13206
13447
  const childBg = childFocused ? highlightBg : void 0;
13207
13448
  const value = resolveExtensionConfigValue(item, extensionConfig?.[group.ext.name]?.[item.key]);
13208
13449
  const childDesc = truncateToCols(item.description ?? "", descCols);
13209
- if (item.type === "boolean") childEls.push(/* @__PURE__ */ jsx$1(ToggleRow, {
13450
+ if (item.type === "action") {
13451
+ const status = actionStatus && actionStatus.extName === group.ext.name && actionStatus.key === item.key ? actionStatus : null;
13452
+ childEls.push(/* @__PURE__ */ jsx$1(ConfigActionRow, {
13453
+ id: anchorIdFor(index),
13454
+ indent: EXTENSION_CONFIG_INDENT,
13455
+ label: item.label,
13456
+ description: childDesc,
13457
+ status,
13458
+ probe: actionProbes[`${group.ext.name}:${item.key}`] ?? null,
13459
+ focused: childFocused,
13460
+ bg: childBg
13461
+ }, item.key));
13462
+ } else if (item.type === "boolean") childEls.push(/* @__PURE__ */ jsx$1(ToggleRow, {
13210
13463
  id: anchorIdFor(index),
13211
13464
  indent: EXTENSION_CONFIG_INDENT,
13212
13465
  label: item.label,
@@ -13345,6 +13598,53 @@ function CreateExtensionButton() {
13345
13598
  })]
13346
13599
  });
13347
13600
  }
13601
+ function ConfigActionRow({ id, label, description, status, probe, focused, bg, indent = 0 }) {
13602
+ const COLOR = useColors();
13603
+ const statusText = (status?.state === "busy" ? "running…" : status?.text) ?? probe?.message;
13604
+ const statusColor = status ? status.state === "error" ? COLOR.error : status.state === "busy" ? COLOR.mute : COLOR.accent : probe ? probe.state === "error" ? COLOR.error : probe.state === "off" ? COLOR.mute : COLOR.accent : COLOR.mute;
13605
+ return /* @__PURE__ */ jsxs("box", {
13606
+ id,
13607
+ style: {
13608
+ flexDirection: "column",
13609
+ flexShrink: 0,
13610
+ paddingLeft: 1 + indent,
13611
+ paddingRight: 1,
13612
+ backgroundColor: bg
13613
+ },
13614
+ children: [/* @__PURE__ */ jsxs("text", {
13615
+ wrapMode: "none",
13616
+ children: [
13617
+ /* @__PURE__ */ jsx$1("span", {
13618
+ fg: focused ? COLOR.brand : COLOR.mute,
13619
+ children: focused ? "▶ " : " "
13620
+ }),
13621
+ /* @__PURE__ */ jsx$1("span", {
13622
+ fg: COLOR.mute,
13623
+ children: SPACER_CHECKBOX_WIDTH
13624
+ }),
13625
+ /* @__PURE__ */ jsx$1("span", {
13626
+ fg: focused ? COLOR.brand : COLOR.dim,
13627
+ children: label
13628
+ }),
13629
+ statusText && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx$1("span", {
13630
+ fg: COLOR.mute,
13631
+ children: ": "
13632
+ }), /* @__PURE__ */ jsx$1("span", {
13633
+ fg: statusColor,
13634
+ children: statusText
13635
+ })] }),
13636
+ focused && status?.state !== "busy" && /* @__PURE__ */ jsx$1("span", {
13637
+ fg: COLOR.brand,
13638
+ children: " ↵ run"
13639
+ })
13640
+ ]
13641
+ }), description && /* @__PURE__ */ jsx$1("text", {
13642
+ wrapMode: "none",
13643
+ fg: COLOR.mute,
13644
+ children: `${COL_TITLE}${description}`
13645
+ })]
13646
+ });
13647
+ }
13348
13648
  function ConfigInputRow({ id, label, description, value, editing, initial, inputRef, onCommit, focused, bg, indent = 0 }) {
13349
13649
  const COLOR = useColors();
13350
13650
  return /* @__PURE__ */ jsxs("box", {
@@ -15917,6 +16217,11 @@ function AppShell() {
15917
16217
  const [showQuitConfirm, setShowQuitConfirm] = useState(false);
15918
16218
  const showQuitConfirmRef = useRef(false);
15919
16219
  showQuitConfirmRef.current = showQuitConfirm;
16220
+ useEffect(() => {
16221
+ if (!showQuitConfirm) return;
16222
+ modal.lock();
16223
+ return () => modal.unlock();
16224
+ }, [showQuitConfirm, modal]);
15920
16225
  const [quitConfirmSelected, setQuitConfirmSelected] = useState("cancel");
15921
16226
  const quitConfirmSelectedRef = useRef("cancel");
15922
16227
  quitConfirmSelectedRef.current = quitConfirmSelected;
@@ -16059,6 +16364,7 @@ function AppShell() {
16059
16364
  const key = command.name.toLowerCase();
16060
16365
  if (seen.has(key)) continue;
16061
16366
  seen.add(key);
16367
+ for (const alias of command.aliases ?? []) seen.add(alias.toLowerCase());
16062
16368
  merged.push(command);
16063
16369
  }
16064
16370
  return merged;
@@ -16093,6 +16399,7 @@ function AppShell() {
16093
16399
  visibleChatCatalog,
16094
16400
  liveExtensionCompletionProviders
16095
16401
  ]);
16402
+ const inlineAutocompleteProviders = useMemo(() => [createPathAutocompleteProvider({ cwd: () => process.cwd() }), ...extensionRegistry.inlineAutocompleteProviders], [extensionRegistry.inlineAutocompleteProviders]);
16096
16403
  useEffect(() => {
16097
16404
  const handle = agentRef.current?.handle;
16098
16405
  if (handle) handle.cwd = cwd;
@@ -18330,7 +18637,7 @@ function AppShell() {
18330
18637
  /** Route a submitted prompt to the command executor when it's a `/cmd`, otherwise to the model. */
18331
18638
  const runPromptOrCommand = useCallback(async (prompt, references, attachments, opts) => {
18332
18639
  if (!opts?.wake) {
18333
- const invocation = parseCommandInvocation(prompt, commandsRef.current.map((c) => c.name));
18640
+ const invocation = parseCommandInvocation(prompt, commandsRef.current);
18334
18641
  if (invocation) {
18335
18642
  await runCommand(invocation);
18336
18643
  return;
@@ -18401,7 +18708,7 @@ function AppShell() {
18401
18708
  suppressWakeRef.current = false;
18402
18709
  (async () => {
18403
18710
  let effectivePrompt = prompt;
18404
- if (parseCommandInvocation(prompt, commandsRef.current.map((c) => c.name)) === null && parseBashInvocation(prompt) === null) for (const contribution of extensionRegistry.promptTransforms) try {
18711
+ if (parseCommandInvocation(prompt, commandsRef.current) === null && parseBashInvocation(prompt) === null) for (const contribution of extensionRegistry.promptTransforms) try {
18405
18712
  const out = await contribution.value(effectivePrompt);
18406
18713
  if (out === void 0) continue;
18407
18714
  if (typeof out === "string") {
@@ -19667,6 +19974,7 @@ function AppShell() {
19667
19974
  pendingInteraction,
19668
19975
  onInteraction: onInteractionResolve,
19669
19976
  completionProviders,
19977
+ inlineAutocompleteProviders,
19670
19978
  onCompletionTab: (providerId) => {
19671
19979
  if (providerId !== "chats") return false;
19672
19980
  toggleChatReferenceScope();