autopilot-ai 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,743 @@
1
+ import { Readable, Writable } from 'node:stream';
2
+
3
+ type Mode = "edit" | "plan" | "auto" | "multi-agent-experimental";
4
+
5
+ type Role = "system" | "user" | "assistant" | "tool";
6
+ interface ToolCall {
7
+ id: string;
8
+ type: "function";
9
+ function: {
10
+ name: string;
11
+ arguments: string;
12
+ };
13
+ }
14
+ interface TextContentPart {
15
+ type: "text";
16
+ text: string;
17
+ }
18
+ interface ImageContentPart {
19
+ type: "image_url";
20
+ image_url: {
21
+ url: string;
22
+ };
23
+ }
24
+ type ContentPart = TextContentPart | ImageContentPart;
25
+ /**
26
+ * One structured reasoning block as OpenRouter reports it
27
+ * (`reasoning.text` / `reasoning.summary` / `reasoning.encrypted` / …).
28
+ * Opaque to us: stored as received and echoed back unchanged.
29
+ */
30
+ interface ReasoningDetail {
31
+ type: string;
32
+ index?: number;
33
+ id?: string | null;
34
+ format?: string;
35
+ text?: string | null;
36
+ summary?: string;
37
+ data?: string;
38
+ signature?: string | null;
39
+ [key: string]: unknown;
40
+ }
41
+ interface ChatMessage {
42
+ role: Role;
43
+ content: string | ContentPart[] | null;
44
+ reasoning_content?: string | null;
45
+ /** Structured reasoning to echo back to OpenRouter (Claude, GPT-5, Gemini). */
46
+ reasoning_details?: ReasoningDetail[];
47
+ tool_calls?: ToolCall[];
48
+ tool_call_id?: string;
49
+ name?: string;
50
+ }
51
+
52
+ /**
53
+ * Custom OpenAI-compatible endpoint routing.
54
+ *
55
+ * When `KIMIFLARE_BASE_URL` is set (or `baseUrl` in config), every model call
56
+ * — chat and embeddings — is sent to `<baseUrl>/chat/completions` (or
57
+ * `/embeddings`) with `Authorization: Bearer <KIMIFLARE_API_KEY>` instead of
58
+ * OpenRouter, and no OpenRouter key is needed.
59
+ *
60
+ * This is how a host application (e.g. an agents platform running kimiflare
61
+ * inside a container) points the CLI at its own gateway/broker instead of
62
+ * handing the process a raw provider key. The broker terminates the bearer it
63
+ * issued and forwards upstream with credentials that never enter this process.
64
+ *
65
+ * Precedence (per field): env var > config field. Model ids pass through to
66
+ * the body unchanged — no OpenRouter id-shape validation.
67
+ */
68
+ interface CustomEndpoint {
69
+ /** OpenAI-compatible base URL. `/chat/completions` is appended unless the URL already ends with it. */
70
+ baseUrl: string;
71
+ /** Bearer sent as `Authorization` to `baseUrl`. Omitted entirely when unset (unauthenticated local gateways). */
72
+ apiKey?: string;
73
+ }
74
+
75
+ /**
76
+ * OpenRouter `provider` routing object (subset we pass through). See
77
+ * https://openrouter.ai/docs/guides/routing/provider-selection. Setting
78
+ * `order` or `sort` disables sticky routing (prompt-cache locality) and
79
+ * load balancing, so they're opt-in only.
80
+ */
81
+ interface OpenRouterProviderPrefs {
82
+ order?: string[];
83
+ only?: string[];
84
+ ignore?: string[];
85
+ allow_fallbacks?: boolean;
86
+ require_parameters?: boolean;
87
+ data_collection?: "allow" | "deny";
88
+ zdr?: boolean;
89
+ quantizations?: string[];
90
+ sort?: "price" | "throughput" | "latency";
91
+ max_price?: Record<string, number>;
92
+ }
93
+
94
+ type ReasoningEffort = "low" | "medium" | "high";
95
+ interface McpServerConfig {
96
+ type: "local" | "remote";
97
+ command?: string[];
98
+ url?: string;
99
+ env?: Record<string, string>;
100
+ headers?: Record<string, string>;
101
+ enabled?: boolean;
102
+ /** Per-call timeout in milliseconds for tool invocations on this server. Default: 60000. */
103
+ timeoutMs?: number;
104
+ }
105
+ interface LspServerConfig {
106
+ command: string[];
107
+ env?: Record<string, string>;
108
+ enabled?: boolean;
109
+ rootPatterns?: string[];
110
+ /** Per-request timeout in milliseconds for LSP calls. Default: 10000. */
111
+ timeoutMs?: number;
112
+ /** Max auto-restart attempts after a crash. Default: 3. Set 0 to disable. */
113
+ maxRestartAttempts?: number;
114
+ }
115
+ /** Permission rule: allow, deny, or ask (default). */
116
+ type PermissionRule = "allow" | "deny" | "ask";
117
+ /** Per-tool permission rules keyed by glob pattern. */
118
+ type PermissionRules = Record<string, PermissionRule>;
119
+ interface KimiConfig {
120
+ /**
121
+ * The user's own OpenRouter API key (`sk-or-…`; env: OPENROUTER_API_KEY or
122
+ * KIMIFLARE_OPENROUTER_KEY, which win over the file). Every model call —
123
+ * chat, memory embeddings, plumbing side-calls — is billed to this key.
124
+ * Bring-your-own only: kimiflare never pays for or proxies model calls.
125
+ */
126
+ openrouterApiKey?: string;
127
+ /** OpenRouter model id, e.g. "moonshotai/kimi-k2.6". */
128
+ model: string;
129
+ /**
130
+ * Optional OpenRouter provider-routing preferences, merged into every
131
+ * request's `provider` object (kimiflare always sends
132
+ * `require_parameters: true`). E.g. `{ "ignore": ["SomeProvider"] }` or
133
+ * `{ "quantizations": ["fp8", "bf16"] }`. Avoid `order`/`sort` unless you
134
+ * need them: they disable OpenRouter's sticky routing, which is what keeps
135
+ * the prompt cache warm. See https://openrouter.ai/docs/guides/routing/provider-selection
136
+ */
137
+ openrouterProvider?: OpenRouterProviderPrefs;
138
+ /**
139
+ * Custom OpenAI-compatible endpoint base URL (env: KIMIFLARE_BASE_URL).
140
+ * For a host application that embeds kimiflare and owns its own broker:
141
+ * when set, ALL model calls go to `<baseUrl>/chat/completions` instead of
142
+ * OpenRouter and no OpenRouter key is needed. See src/agent/custom-endpoint.ts.
143
+ */
144
+ baseUrl?: string;
145
+ /**
146
+ * Bearer sent as `Authorization` to `baseUrl` (env: KIMIFLARE_API_KEY).
147
+ * Only used when `baseUrl` is set; omitted from the request entirely when
148
+ * unset (for unauthenticated local gateways).
149
+ */
150
+ apiKey?: string;
151
+ /**
152
+ * Cloudflare account id + API token (env: CLOUDFLARE_ACCOUNT_ID /
153
+ * CLOUDFLARE_API_TOKEN). Not used for model calls. Only `/multi-agent`
154
+ * Commute reads these, to deploy its Worker into the user's own account.
155
+ */
156
+ accountId?: string;
157
+ apiToken?: string;
158
+ reasoningEffort?: ReasoningEffort;
159
+ /**
160
+ * Feature flag for the plan / edit / auto permission modes. Off by default:
161
+ * every session runs in auto (tools run without per-call prompts) and the
162
+ * mode UI (Shift+Tab, /mode, /plan, /edit, /auto, the mode badge) is hidden.
163
+ * Turn on with `/settings modes on` to get the mode system back, starting
164
+ * in edit.
165
+ */
166
+ modesEnabled?: boolean;
167
+ coauthor?: boolean;
168
+ coauthorName?: string;
169
+ coauthorEmail?: string;
170
+ mcpServers?: Record<string, McpServerConfig>;
171
+ cacheStablePrompts?: boolean;
172
+ /** Enable compiled context (token-optimized state packet + artifact store). */
173
+ compiledContext?: boolean;
174
+ /** Number of recent user turns to retain image content; older images are dropped. */
175
+ imageHistoryTurns?: number;
176
+ /** Enable local structured memory (SQLite + embeddings). */
177
+ memoryEnabled?: boolean;
178
+ /** Path to memory database. Defaults to .kimiflare/memory.db in repo root, or ~/.local/share/kimiflare/memory.db. */
179
+ memoryDbPath?: string;
180
+ /** Max age of memories in days before cleanup. Default: 90. */
181
+ memoryMaxAgeDays?: number;
182
+ /** Max memories per repo. Default: 1000. */
183
+ memoryMaxEntries?: number;
184
+ /** Embedding model for memory vectors (OpenRouter id). Default: baai/bge-base-en-v1.5. */
185
+ memoryEmbeddingModel?: string;
186
+ /** Model for internal plumbing tasks (memory verification, hypothetical queries). Default: DEFAULT_PLUMBING_MODEL. */
187
+ plumbingModel?: string;
188
+ /** Model for auto-extracting high-signal edit events. Default: DEFAULT_PLUMBING_MODEL. */
189
+ memoryExtractionModel?: string;
190
+ /** Enable Code Mode: present tools as a TypeScript API and execute generated code in a sandbox. */
191
+ codeMode?: boolean;
192
+ /** Enable LSP integration. Default: false. */
193
+ lspEnabled?: boolean;
194
+ /** LSP server configurations. */
195
+ lspServers?: Record<string, LspServerConfig>;
196
+ /** Enable cost attribution by task type. Default: false. Once stable for 2 releases, consider defaulting to true. */
197
+ costAttribution?: boolean;
198
+ /** Enable @ file mention picker in chat input. Default: false. */
199
+ filePicker?: boolean;
200
+ /** UI theme name. Default: everforest-dark. */
201
+ theme?: string;
202
+ /** URL of the remote orchestrator Worker. */
203
+ remoteWorkerUrl?: string;
204
+ /** Shared secret for authenticating with the remote Worker. */
205
+ remoteAuthSecret?: string;
206
+ /** Configurable TTL for remote sessions in minutes (default: 30). */
207
+ remoteTtlMinutes?: number;
208
+ /** Max input token budget per remote job (default: 5_000_000). */
209
+ remoteMaxInputTokens?: number;
210
+ /** GitHub OAuth token for remote PR creation. */
211
+ githubOAuthToken?: string;
212
+ /** GitHub refresh token (if available). */
213
+ githubRefreshToken?: string;
214
+ /** GitHub token expiry timestamp. */
215
+ githubTokenExpiry?: number;
216
+ /** Default GitHub repo for remote sessions (owner/repo). */
217
+ githubRepo?: string;
218
+ /** Shell override for the bash tool. "auto" (default) detects the platform, or specify "bash", "cmd", "powershell", or an absolute path. */
219
+ shell?: string;
220
+ /**
221
+ * Deprecated/ignored. React Ink is always used. Camouflage UI access is
222
+ * temporarily disabled, so `--ui`, `KIMIFLARE_UI`, and this field have no
223
+ * effect. Kept in the type so existing configs do not break on load.
224
+ */
225
+ uiEngine?: "ink" | "camouflage";
226
+ /** Worker endpoint URL for spawning standalone research/executor workers. */
227
+ workerEndpoint?: string;
228
+ /** Max cost per worker in USD (default: 1.0). */
229
+ workerBudgetUsd?: number;
230
+ /** Hard ceiling for workerBudgetUsd. Any configured or programmatic value above this is silently capped. Default: 5.0. */
231
+ workerBudgetMaxUsd?: number;
232
+ /** Max workers to spawn in parallel (default: 3). */
233
+ workerMaxParallel?: number;
234
+ /** Timeout per worker in milliseconds (default: 300000 = 5 min). */
235
+ workerTimeoutMs?: number;
236
+ /** Enable multi-agent-experimental mode in the mode cycle. Default: false. */
237
+ multiAgentEnabled?: boolean;
238
+ /** Turn count at which KimiFlare suggests /fresh in auto/edit mode. 0 = disabled. Default: 30. */
239
+ autoFreshSuggestionTurns?: number;
240
+ /** If true, automatically execute /fresh when the threshold is hit instead of just suggesting it. Default: false. */
241
+ autoFreshEnabled?: boolean;
242
+ /** Estimated in-memory token threshold to trigger aggressive auto-compaction between turns. Default: 500_000. */
243
+ autoCompactTokenThreshold?: number;
244
+ /** Estimated in-memory token threshold to trigger auto-fresh when compaction cannot reduce below this. Default: 2_000_000. */
245
+ autoFreshTokenThreshold?: number;
246
+ /** Bearer/secret for the worker endpoint (sent as X-Worker-Api-Key). */
247
+ workerApiKey?: string;
248
+ /** Name of the deployed multi-agent Worker. Used for tear-down. */
249
+ workerName?: string;
250
+ /** When true, after plan workers synthesize, spawn one executor worker
251
+ * to implement the synthesized plan and open a PR. Off by default. */
252
+ autoExecute?: boolean;
253
+ /** Use shallow clone (`--depth 1`) for sandbox workers. Default: true. */
254
+ workerShallowClone?: boolean;
255
+ /** Enable repo caching / reuse hints for the Commute worker. Default: true. */
256
+ workerRepoCache?: boolean;
257
+ /** Forward memory context to multi-agent workers. Default: true. */
258
+ workerProxyMemory?: boolean;
259
+ /** Forward LSP context to multi-agent workers. Default: false. */
260
+ workerProxyLsp?: boolean;
261
+ /** Forward MCP context to multi-agent workers. Default: false. */
262
+ workerProxyMcp?: boolean;
263
+ /** Model used for LLM-based task decomposition in multi-agent mode.
264
+ * Default: DEFAULT_PLUMBING_MODEL (fast and cheap). */
265
+ decompositionModel?: string;
266
+ /** Strategy for decomposing heavy prompts into parallel research tasks.
267
+ * - "llm": use a lightweight LLM call (default)
268
+ * - "regex": pure regex heuristic (no LLM, fastest)
269
+ * - "hybrid": regex for explicit lists, LLM for prose */
270
+ decompositionStrategy?: "llm" | "regex" | "hybrid";
271
+ /** Model for synthesizing multi-agent findings.
272
+ * Default: DEFAULT_PLUMBING_MODEL (fast and cheap). */
273
+ synthesisModel?: string;
274
+ /** Strategy for synthesizing worker findings.
275
+ * - "llm": use a lightweight LLM call (default)
276
+ * - "heuristic": pure heuristic (no LLM, fastest)
277
+ * - "hybrid": try LLM, fall back to heuristic on failure */
278
+ synthesisStrategy?: "llm" | "heuristic" | "hybrid";
279
+ /** Explicit opt-out for LLM-based synthesis. When true, always uses heuristic. */
280
+ disableLlmSynthesis?: boolean;
281
+ /** Files to pre-read on the coordinator and inject into every worker's
282
+ * context. Saves redundant `read` tool calls across workers. Paths are
283
+ * relative to the repo root. */
284
+ workerPreReadFiles?: string[];
285
+ /** Max characters of pre-read content to inject per worker batch.
286
+ * Default: 50_000. */
287
+ workerPreReadMaxChars?: number;
288
+ /** Permission rules for headless/CI mode. Keys are tool names (e.g. "bash", "write").
289
+ * Values are glob-pattern → rule mappings. Patterns are matched against the
290
+ * target path (for file tools) or command string (for bash). */
291
+ permissions?: Record<string, PermissionRules>;
292
+ /** Prefer creating pull requests over pushing directly to the default branch.
293
+ * Injected into the system prompt. Default: true. */
294
+ preferPullRequests?: boolean;
295
+ /** Allow the bash tool to run `git push` directly to the repository's default
296
+ * branch. When false (default), such pushes are blocked and the model is
297
+ * directed to open a PR instead. */
298
+ allowDirectPush?: boolean;
299
+ }
300
+ declare const DEFAULT_MODEL = "moonshotai/kimi-k2.6";
301
+ declare const DEFAULT_REASONING_EFFORT: ReasoningEffort;
302
+ declare function loadConfig(): Promise<KimiConfig | null>;
303
+ declare function saveConfig(cfg: KimiConfig): Promise<string>;
304
+
305
+ /**
306
+ * The one place that turns config into model-call credentials.
307
+ *
308
+ * Every `runKimi` / `fetchEmbeddings` call site spreads `llmAuthFromConfig(cfg)`
309
+ * into its options instead of picking individual credential fields, so the
310
+ * main loop, side-calls (summaries, memory, decomposition, …), embeddings,
311
+ * print/emit/serve/SDK entry points all authenticate the same way — and a
312
+ * custom endpoint configured in the file (not just the env) applies to all
313
+ * of them.
314
+ */
315
+
316
+ interface LlmAuth {
317
+ /** The user's OpenRouter key. */
318
+ openrouterApiKey?: string;
319
+ /** Host-app broker endpoint; when set, used instead of OpenRouter. */
320
+ customEndpoint?: CustomEndpoint;
321
+ /** Extra OpenRouter provider-routing preferences. */
322
+ provider?: OpenRouterProviderPrefs;
323
+ }
324
+
325
+ type MemoryCategory = "fact" | "event" | "instruction" | "task" | "preference";
326
+ interface Memory {
327
+ id: string;
328
+ content: string;
329
+ embedding: Float32Array;
330
+ category: MemoryCategory;
331
+ sourceSessionId: string;
332
+ repoPath: string;
333
+ createdAt: number;
334
+ accessedAt: number;
335
+ importance: number;
336
+ relatedFiles: string[];
337
+ topicKey: string | null;
338
+ supersededBy: string | null;
339
+ forgotten: boolean;
340
+ vectorized: boolean;
341
+ /** Agent role that created this memory (plan, build, general). */
342
+ agentRole: string | null;
343
+ }
344
+ interface MemoryQuery {
345
+ text: string;
346
+ embedding?: Float32Array;
347
+ repoPath?: string;
348
+ category?: MemoryCategory;
349
+ limit?: number;
350
+ maxAgeDays?: number;
351
+ /** Filter recalled memories by the agent role that created them. */
352
+ agentRole?: string;
353
+ }
354
+ interface HybridResult {
355
+ memory: Memory;
356
+ ftsScore: number;
357
+ vectorScore: number;
358
+ exactScore: number;
359
+ topicKeyScore: number;
360
+ combinedScore: number;
361
+ }
362
+ interface MemoryStats {
363
+ totalCount: number;
364
+ dbSizeBytes: number;
365
+ lastCleanupAt: number | null;
366
+ byCategory: Record<MemoryCategory, number>;
367
+ }
368
+
369
+ interface MemoryManagerOpts {
370
+ dbPath: string;
371
+ openrouterApiKey?: string;
372
+ customEndpoint?: CustomEndpoint;
373
+ model?: string;
374
+ plumbingModel?: string;
375
+ extractionModel?: string;
376
+ embeddingModel?: string;
377
+ provider?: OpenRouterProviderPrefs;
378
+ maxAgeDays?: number;
379
+ maxEntries?: number;
380
+ redactSecrets?: boolean;
381
+ }
382
+ interface LlmOpts {
383
+ openrouterApiKey?: string;
384
+ customEndpoint?: CustomEndpoint;
385
+ model: string;
386
+ provider?: OpenRouterProviderPrefs;
387
+ signal?: AbortSignal;
388
+ }
389
+ declare class MemoryManager {
390
+ private db;
391
+ private opts;
392
+ constructor(opts: MemoryManagerOpts);
393
+ open(): void;
394
+ close(): void;
395
+ isOpen(): boolean;
396
+ private get llmOpts();
397
+ private get plumbingLlmOpts();
398
+ private get extractionLlmOpts();
399
+ /** Expose extraction LLM opts so the agent loop can pass them to extractors. */
400
+ getExtractionLlmOpts(): LlmOpts;
401
+ private shouldRedact;
402
+ /**
403
+ * Store a memory with verification, topic-key normalization, hypothetical queries,
404
+ * secret redaction, and supersession.
405
+ */
406
+ remember(content: string, category: MemoryCategory, importance: number, repoPath: string, sessionId: string, signal?: AbortSignal, agentRole?: string, topicKey?: string): Promise<{
407
+ id: string;
408
+ superseded?: string[];
409
+ }>;
410
+ /**
411
+ * Store a plan directly under a deterministic topic key.
412
+ * Skips embedding, verification, and hypothetical queries so it is fast and
413
+ * deterministic. Supersedes any previous plan stored under the same key.
414
+ */
415
+ rememberPlan(plan: string, repoPath: string, sessionId: string, topicKey?: string): Promise<{
416
+ id: string;
417
+ superseded?: string[];
418
+ }>;
419
+ /**
420
+ * Recall the latest memory for an exact topic key.
421
+ * Does not use embeddings; returns null if no matching memory exists.
422
+ */
423
+ getByTopicKey(repoPath: string, topicKey: string): Memory | null;
424
+ /**
425
+ * Count high-signal memories created since the given timestamp.
426
+ * Used for KIMI.md drift detection (Trigger A: session-start check).
427
+ */
428
+ countHighSignalMemoriesSince(repoPath: string, since: number): number;
429
+ /**
430
+ * Get the timestamp of the most recent KIMI.md refresh memory.
431
+ * Returns 0 if none exists.
432
+ */
433
+ getLastKimiMdRefreshTime(repoPath: string): number;
434
+ /**
435
+ * Record that KIMI.md was refreshed. Creates a lightweight memory
436
+ * so drift detection knows when the snapshot was last updated.
437
+ */
438
+ recordKimiMdRefresh(repoPath: string, sessionId: string): Promise<void>;
439
+ /**
440
+ * Recall memories using the full hybrid retrieval pipeline.
441
+ */
442
+ recall(query: MemoryQuery): Promise<HybridResult[]>;
443
+ /**
444
+ * Recall memories created by a specific agent role.
445
+ */
446
+ recallByRole(query: MemoryQuery, agentRole: string): Promise<HybridResult[]>;
447
+ /**
448
+ * Format recalled memories as a compact context block for injection into messages.
449
+ */
450
+ static formatRecalled(results: HybridResult[]): string;
451
+ /**
452
+ * Synthesize recalled memories into a dense prose paragraph.
453
+ * Uses the lightweight plumbing model (Scout) to keep costs low.
454
+ */
455
+ synthesizeRecalled(results: HybridResult[], signal?: AbortSignal): Promise<string>;
456
+ /**
457
+ * Soft-delete a memory by ID.
458
+ */
459
+ forget(id: string): Promise<boolean>;
460
+ /**
461
+ * Backfill un-vectorized memories at startup.
462
+ */
463
+ backfill(repoPath: string): Promise<number>;
464
+ cleanup(repoPath: string): Promise<{
465
+ oldDeleted: number;
466
+ excessDeleted: number;
467
+ duplicatesMerged: number;
468
+ }>;
469
+ getStats(): MemoryStats | null;
470
+ clearRepo(repoPath: string): number;
471
+ private verifyMemory;
472
+ private normalizeTopicKey;
473
+ private generateHypotheticalQueries;
474
+ }
475
+
476
+ interface PlanOption {
477
+ label: string;
478
+ plan: string;
479
+ }
480
+ interface ToolContext {
481
+ cwd: string;
482
+ signal?: AbortSignal;
483
+ onTasks?: (tasks: Task[]) => void;
484
+ onPlanOptions?: (options: PlanOption[]) => void;
485
+ coauthor?: {
486
+ name: string;
487
+ email: string;
488
+ };
489
+ memoryManager?: MemoryManager | null;
490
+ sessionId?: string;
491
+ githubToken?: string;
492
+ /** Shell override for the bash tool. If omitted, the tool auto-detects based on platform. */
493
+ shell?: string;
494
+ /**
495
+ * Intent tier classified for this turn, when known. Carried into
496
+ * hook payloads (PreToolUse / PostToolUse) so user hooks can branch
497
+ * on tier — e.g. skip auto-format for light-tier turns, or audit
498
+ * every heavy-tier action. Optional because code-mode sub-calls
499
+ * and SDK consumers may not have a tier.
500
+ */
501
+ intentTier?: "light" | "medium" | "heavy";
502
+ /** Credentials for tools that need to call an LLM (see llm-auth.ts). */
503
+ llmAuth?: LlmAuth;
504
+ /** Model id for tools that need to call an LLM. */
505
+ model?: string;
506
+ /** When false (default), the bash tool blocks `git push` to the repository's
507
+ * default branch and directs the model to open a PR instead. */
508
+ allowDirectPush?: boolean;
509
+ }
510
+ interface ToolRender {
511
+ title: string;
512
+ body?: string;
513
+ diff?: {
514
+ path: string;
515
+ before: string;
516
+ after: string;
517
+ };
518
+ }
519
+ interface ToolOutput {
520
+ content: string;
521
+ rawBytes: number;
522
+ reducedBytes: number;
523
+ }
524
+ interface ToolSpec<Args = any> {
525
+ name: string;
526
+ description: string;
527
+ parameters: Record<string, unknown>;
528
+ needsPermission: boolean;
529
+ /** When true, the tool only reads state and never mutates the workspace.
530
+ * Read-only tools within a single turn may be executed in parallel. */
531
+ isReadOnly?: boolean;
532
+ render?: (args: Args) => ToolRender;
533
+ run: (args: Args, ctx: ToolContext) => Promise<string | ToolOutput>;
534
+ }
535
+ type TaskStatus = "pending" | "in_progress" | "completed";
536
+ interface Task {
537
+ id: string;
538
+ title: string;
539
+ status: TaskStatus;
540
+ }
541
+
542
+ /**
543
+ * Whether the user said yes or no.
544
+ *
545
+ * NOTE on naming: the legacy `PermissionDecision` string type
546
+ * (`"allow" | "allow_session" | "deny"`) also lives below as a
547
+ * deprecated back-compat alias. New callers should return the typed
548
+ * `PermissionDecisionResult` shape; the executor normalizes either at
549
+ * the boundary so existing SDK callers keep working unchanged.
550
+ */
551
+ type PermissionDecisionKind = "allow" | "deny";
552
+ /**
553
+ * How broadly an allow applies. M2.1's enum overloaded this with the
554
+ * decision — `"allow_session"` meant "allow + cache for the session" —
555
+ * which made the new `"pattern"` scope from M6.2 impossible to express.
556
+ *
557
+ * - `once` — approved this single call. The executor will ask
558
+ * again next time the same tool is requested.
559
+ * - `session` — approved for the rest of the session (existing
560
+ * `"allow_session"` behavior).
561
+ * - `pattern` — approved because the call matched a pre-configured
562
+ * glob in settings.json (M6.2). The executor does NOT
563
+ * cache pattern-allow decisions — the pattern itself
564
+ * is the durable record and lives in the config file.
565
+ *
566
+ * `scope` is meaningful only when `decision === "allow"`; for `deny`
567
+ * it's ignored, but we keep it required so the shape stays uniform.
568
+ */
569
+ type PermissionScope = "once" | "session" | "pattern";
570
+ interface PermissionDecisionResult {
571
+ decision: PermissionDecisionKind;
572
+ scope: PermissionScope;
573
+ }
574
+ /**
575
+ * Legacy single-string decision. Kept for SDK back-compat — callers can
576
+ * still return `"allow" | "allow_session" | "deny"` and the executor
577
+ * normalizes via `toPermissionResult`. Prefer
578
+ * `PermissionDecisionResult` in new code.
579
+ *
580
+ * @deprecated since M2.2. Use `PermissionDecisionResult` instead.
581
+ */
582
+ type PermissionDecisionLegacy = "allow" | "allow_session" | "deny";
583
+ /**
584
+ * Union of the new typed result and the legacy string. Both shapes are
585
+ * accepted by `PermissionAsker`; the executor calls
586
+ * `toPermissionResult` to normalize.
587
+ */
588
+ type PermissionDecision = PermissionDecisionLegacy | PermissionDecisionResult;
589
+ interface PermissionRequest {
590
+ tool: ToolSpec;
591
+ args: Record<string, unknown>;
592
+ sessionKey: string;
593
+ }
594
+
595
+ interface CreateSessionOptions {
596
+ /** Working directory for the agent. Defaults to process.cwd(). */
597
+ cwd?: string;
598
+ /** Override config. If omitted, loads from ~/.config/kimiflare/config.json */
599
+ config?: Partial<KimiConfig>;
600
+ /** Session ID for persistence. If omitted, creates a new session. */
601
+ sessionId?: string;
602
+ /** Which tools to enable. Defaults to ALL_TOOLS. */
603
+ tools?: ToolSpec[];
604
+ /** Enable local structured memory. Defaults to config value. */
605
+ memoryEnabled?: boolean;
606
+ /** Enable LSP integration. Defaults to config value. */
607
+ lspEnabled?: boolean;
608
+ /** Enable cost attribution. Defaults to config value. */
609
+ costAttribution?: boolean;
610
+ /** OpenRouter provider-routing preferences for this session (merged over config.openrouterProvider). */
611
+ provider?: OpenRouterProviderPrefs;
612
+ /** Custom permission handler. Defaults to auto-deny in plan mode, ask callback in edit mode. */
613
+ permissionHandler?: PermissionHandler;
614
+ /** Called when the agent detects KIMI.md drift. */
615
+ onKimiMdStale?: () => void;
616
+ /**
617
+ * M6.1: enable user-configured lifecycle hooks loaded from
618
+ * `~/.config/kimiflare/settings.json` + `<cwd>/.kimiflare/settings.json`.
619
+ * Default `false` (SDK is a primitive; opt in if you want the
620
+ * TUI's hook behavior).
621
+ */
622
+ enableHooks?: boolean;
623
+ }
624
+ interface PromptOptions {
625
+ /** Attach images to the prompt. */
626
+ images?: Array<{
627
+ path: string;
628
+ } | {
629
+ data: string;
630
+ mimeType: string;
631
+ }>;
632
+ /** Override mode for this prompt only. */
633
+ mode?: "plan" | "edit" | "auto";
634
+ /** Override max tool iterations for this prompt only. */
635
+ maxToolIterations?: number;
636
+ }
637
+ type SessionEvent = {
638
+ type: "session.start";
639
+ sessionId: string;
640
+ cwd: string;
641
+ } | {
642
+ type: "session.end";
643
+ reason: "complete" | "aborted" | "error";
644
+ error?: string;
645
+ } | {
646
+ type: "message.start";
647
+ messageId: string;
648
+ role: "user" | "assistant";
649
+ } | {
650
+ type: "message.delta";
651
+ messageId: string;
652
+ text: string;
653
+ } | {
654
+ type: "message.reasoning";
655
+ messageId: string;
656
+ text: string;
657
+ } | {
658
+ type: "message.end";
659
+ messageId: string;
660
+ } | {
661
+ type: "tool.start";
662
+ toolCallId: string;
663
+ toolName: string;
664
+ args: unknown;
665
+ } | {
666
+ type: "tool.result";
667
+ toolCallId: string;
668
+ toolName: string;
669
+ result: string;
670
+ isError: boolean;
671
+ } | {
672
+ type: "usage";
673
+ inputTokens: number;
674
+ outputTokens: number;
675
+ reasoningTokens?: number;
676
+ cost?: number;
677
+ } | {
678
+ type: "permission.request";
679
+ requestId: string;
680
+ toolName: string;
681
+ args: unknown;
682
+ } | {
683
+ type: "permission.resolved";
684
+ requestId: string;
685
+ decision: PermissionDecision;
686
+ } | {
687
+ type: "tasks.update";
688
+ tasks: Task[];
689
+ } | {
690
+ type: "warning";
691
+ message: string;
692
+ } | {
693
+ type: "status";
694
+ status: "idle" | "streaming" | "tool_executing" | "compacting" | "error";
695
+ };
696
+ interface SessionUsage {
697
+ totalInputTokens: number;
698
+ totalOutputTokens: number;
699
+ totalCost: number;
700
+ turnCount: number;
701
+ }
702
+ interface SessionStatus {
703
+ isStreaming: boolean;
704
+ isCompacting: boolean;
705
+ pendingSteer: string[];
706
+ pendingFollowUp: string[];
707
+ currentMode: Mode;
708
+ }
709
+ type PermissionHandler = (req: PermissionRequest) => Promise<PermissionDecision>;
710
+ interface KimiFlareSession {
711
+ readonly sessionId: string;
712
+ readonly cwd: string;
713
+ readonly isStreaming: boolean;
714
+ readonly messages: ChatMessage[];
715
+ prompt(text: string, options?: PromptOptions): Promise<void>;
716
+ steer(text: string): Promise<void>;
717
+ followUp(text: string): Promise<void>;
718
+ abort(): Promise<void>;
719
+ setModel(modelId: string): void;
720
+ setMode(mode: "plan" | "edit" | "auto"): void;
721
+ setReasoningEffort(level: "low" | "medium" | "high"): void;
722
+ resolvePermission(requestId: string, decision: PermissionDecision): void;
723
+ subscribe(listener: (event: SessionEvent) => void): () => void;
724
+ getUsage(): SessionUsage;
725
+ getStatus(): SessionStatus;
726
+ save(): Promise<void>;
727
+ dispose(): void;
728
+ }
729
+
730
+ declare function createAgentSession(opts: CreateSessionOptions): Promise<{
731
+ session: KimiFlareSession;
732
+ }>;
733
+
734
+ declare function createDefaultPermissionHandler(options: {
735
+ mode: Mode;
736
+ onRequest?: (req: PermissionRequest) => void;
737
+ }): PermissionHandler;
738
+
739
+ declare function startRpcServer(input?: Readable, output?: Writable, createSession?: typeof createAgentSession): Promise<void>;
740
+
741
+ declare function resolveSdkConfig(opts: CreateSessionOptions): Promise<KimiConfig>;
742
+
743
+ export { type ChatMessage, type CreateSessionOptions, DEFAULT_MODEL, DEFAULT_REASONING_EFFORT, type KimiConfig, type KimiFlareSession, type PermissionDecision, type PermissionHandler, type PermissionRequest, type PromptOptions, type SessionEvent, type SessionStatus, type SessionUsage, type Task, type ToolSpec, createAgentSession, createDefaultPermissionHandler, loadConfig, resolveSdkConfig, saveConfig, startRpcServer };