@kodax-ai/kodax 0.7.50 → 0.7.52

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 (55) hide show
  1. package/CHANGELOG.md +1814 -1773
  2. package/README.md +1215 -1213
  3. package/README_CN.md +636 -634
  4. package/dist/chunks/agent-XXTR7T37.js +2 -0
  5. package/dist/chunks/argument-completer-VMH6VZ4X.js +2 -0
  6. package/dist/chunks/chunk-4RVSFOUT.js +420 -0
  7. package/dist/chunks/chunk-5USNUSTL.js +648 -0
  8. package/dist/chunks/chunk-7X7SOVER.js +492 -0
  9. package/dist/chunks/{chunk-HR64F32V.js → chunk-BFXFSEHK.js} +1 -1
  10. package/dist/chunks/chunk-HMATTIU6.js +574 -0
  11. package/dist/chunks/{chunk-SK4HOYT2.js → chunk-JJTUBNQX.js} +1 -1
  12. package/dist/chunks/chunk-LE6STNVN.js +31 -0
  13. package/dist/chunks/chunk-MFPYZT52.js +301 -0
  14. package/dist/chunks/{compaction-config-DDJSQ4OT.js → compaction-config-UBPCNGC2.js} +1 -1
  15. package/dist/chunks/{construction-bootstrap-4QNM2BVM.js → construction-bootstrap-BXRMA3KL.js} +1 -1
  16. package/dist/chunks/dist-IHH4BYIU.js +2 -0
  17. package/dist/chunks/{dist-OJSNNI7P.js → dist-Z6U7TWKJ.js} +1 -1
  18. package/dist/chunks/utils-6WZHBMCC.js +2 -0
  19. package/dist/index.d.ts +11 -11
  20. package/dist/index.js +4 -4
  21. package/dist/kodax_cli.js +1004 -978
  22. package/dist/provider-capabilities.json +2 -0
  23. package/dist/sdk-agent.d.ts +16 -10
  24. package/dist/sdk-agent.js +1 -1
  25. package/dist/sdk-coding.d.ts +32 -16
  26. package/dist/sdk-coding.js +1 -1
  27. package/dist/sdk-llm.d.ts +3 -5
  28. package/dist/sdk-llm.js +1 -1
  29. package/dist/sdk-mcp.js +1 -1
  30. package/dist/sdk-repl.d.ts +16 -727
  31. package/dist/sdk-repl.js +2 -2
  32. package/dist/sdk-session.d.ts +8 -224
  33. package/dist/sdk-session.js +1 -1
  34. package/dist/sdk-skills.js +1 -1
  35. package/dist/types-chunks/{types.d-rPRl2LSB.d.ts → base.d-BBNUF9nz.d.ts} +271 -3
  36. package/dist/types-chunks/{bash-prefix-extractor.d-B0CIb0N3.d.ts → bash-prefix-extractor.d-DBFZEwop.d.ts} +15 -521
  37. package/dist/types-chunks/{capsule.d-CwBEm6M-.d.ts → capsule.d-CNonpwAZ.d.ts} +3 -3
  38. package/dist/types-chunks/guardrail.d-B18oO1gt.d.ts +518 -0
  39. package/dist/types-chunks/{process.d-BbiXD24v.d.ts → process.d-Bj82oJhD.d.ts} +348 -275
  40. package/dist/types-chunks/{resolver.d-CQfaJbht.d.ts → resolver.d-CCX9NXWP.d.ts} +2 -2
  41. package/dist/types-chunks/sdk-session-D4tqRl0_.d.ts +977 -0
  42. package/dist/types-chunks/{storage.d-J2GqOgaX.d.ts → storage.d-CabW10Nt.d.ts} +78 -3
  43. package/dist/types-chunks/types.d-D4jL-gAA.d.ts +273 -0
  44. package/dist/types-chunks/{utils.d-D_-jrRku.d.ts → utils.d-23Gn14zP.d.ts} +7 -81
  45. package/package.json +3 -3
  46. package/dist/chunks/argument-completer-3WX5B42G.js +0 -2
  47. package/dist/chunks/chunk-5UJQ2GKJ.js +0 -574
  48. package/dist/chunks/chunk-MFOMFMSK.js +0 -1056
  49. package/dist/chunks/chunk-UB5IAZHF.js +0 -476
  50. package/dist/chunks/chunk-XZY4CIDV.js +0 -31
  51. package/dist/chunks/chunk-YJLRBIEW.js +0 -301
  52. package/dist/chunks/dist-T256OSDI.js +0 -2
  53. package/dist/chunks/utils-JHIEOX6Z.js +0 -2
  54. package/dist/types-chunks/base.d-C4jYVjJh.d.ts +0 -270
  55. package/dist/types-chunks/types.d-BnjX2Gn4.d.ts +0 -297
@@ -0,0 +1,518 @@
1
+ import { M as McpConnectMode, a as McpServerConfig, b as McpServersConfig, c as McpTransportKind } from './config.d-CJy1WENT.js';
2
+ import { f as KodaXBaseProvider } from './base.d-BBNUF9nz.js';
3
+ import { a as CostTracker } from './cost-tracker.d-wRtyEW9d.js';
4
+ import { aG as RunnerToolCall } from './process.d-Bj82oJhD.js';
5
+ import { f as ToolGuardrail } from './types.d-D4jL-gAA.js';
6
+
7
+ /**
8
+ * FEATURE_200 Phase F (v0.7.45) — MCP domain types extracted from types.ts.
9
+ * Thin KodaX-facing aliases over the @kodax-ai/agent MCP types. Re-exported
10
+ * from ../types.ts so all `../types` importers are unaffected.
11
+ */
12
+
13
+ type KodaXMcpTransport = McpTransportKind;
14
+ type KodaXMcpConnectMode = McpConnectMode;
15
+ type KodaXMcpServerConfig = McpServerConfig;
16
+ /** Flat map of MCP server configs, keyed under `mcpServers` in config.json. */
17
+ type KodaXMcpServersConfig = McpServersConfig;
18
+
19
+ /**
20
+ * AGENTS.md - Project-level AI Context Rules Loader
21
+ *
22
+ * This module implements loading of project-level context rules from AGENTS.md files,
23
+ * inspired by pi-mono's implementation.
24
+ *
25
+ * Priority: global < root < ... < current directory < .kodax/
26
+ */
27
+ interface AgentsFile {
28
+ path: string;
29
+ content: string;
30
+ scope: 'global' | 'project' | 'directory';
31
+ }
32
+ interface LoadAgentsOptions {
33
+ /** Pass cwd explicitly for deterministic prompt building; process.cwd() is only a legacy fallback. */
34
+ cwd?: string;
35
+ kodaxDir?: string;
36
+ projectRoot?: string;
37
+ }
38
+ /**
39
+ * Get KodaX global directory.
40
+ *
41
+ * Routes through {@link getAgentConfigHome} (v0.7.35.1 FEATURE_145 3-tier
42
+ * resolution: programmatic override > KODAX_HOME env > ~/.kodax default).
43
+ */
44
+ declare function getKodaxGlobalDir(): string;
45
+ /**
46
+ * Load all AGENTS files
47
+ * Priority: global < root < ... < current directory < .kodax/
48
+ */
49
+ declare function loadAgentsFiles(options?: LoadAgentsOptions): AgentsFile[];
50
+ /**
51
+ * Format AGENTS files for system prompt
52
+ */
53
+ declare function formatAgentsForPrompt(files: AgentsFile[]): string;
54
+
55
+ /**
56
+ * Auto-Mode Rules Loader — FEATURE_092 Phase 2b.2 (v0.7.33).
57
+ *
58
+ * Three-layer trust model for `auto-rules.jsonc` files consumed by the
59
+ * auto-mode classifier:
60
+ *
61
+ * 1. ~/.kodax/auto-rules.jsonc — user-level, always trusted
62
+ * 2. <project>/.kodax/auto-rules.jsonc — shared, opt-in (sha256 fingerprint)
63
+ * 3. <project>/.kodax/auto-rules.local.jsonc — workspace-local, gitignored, trusted
64
+ *
65
+ * Why opt-in for the shared file: a malicious PR could land an
66
+ * `auto-rules.jsonc` claiming "allow any curl" and the user wouldn't
67
+ * notice. First-checkout opt-in via fingerprint forces the user to
68
+ * acknowledge the file by content. If the fingerprint changes later,
69
+ * the file is silently skipped until re-trusted — failures favor safety.
70
+ *
71
+ * Schema (each field optional, defaults to []):
72
+ * {
73
+ * "allow": string[], // patterns the classifier defaults to allowing
74
+ * "soft_deny": string[], // patterns the classifier defaults to blocking
75
+ * "environment": string[] // background context the classifier sees verbatim
76
+ * }
77
+ *
78
+ * Merge: layers concatenated in order (user → project → local). Identical
79
+ * strings deduplicated by stable insertion (later layers win position only
80
+ * when the string is unique per layer).
81
+ */
82
+ interface AutoRules {
83
+ readonly allow: readonly string[];
84
+ readonly soft_deny: readonly string[];
85
+ readonly environment: readonly string[];
86
+ }
87
+ type RulesOrigin = 'user' | 'project' | 'local';
88
+ interface LoadedRulesSource {
89
+ readonly origin: RulesOrigin;
90
+ readonly path: string;
91
+ readonly fingerprint: string;
92
+ }
93
+ interface SkippedRulesSource {
94
+ readonly origin: 'project';
95
+ readonly path: string;
96
+ readonly fingerprint: string;
97
+ readonly reason: 'untrusted' | 'fingerprint-changed';
98
+ }
99
+ interface RulesLoadError {
100
+ readonly path: string;
101
+ readonly message: string;
102
+ }
103
+ interface RulesLoadResult {
104
+ readonly merged: AutoRules;
105
+ readonly sources: readonly LoadedRulesSource[];
106
+ readonly skipped: readonly SkippedRulesSource[];
107
+ readonly errors: readonly RulesLoadError[];
108
+ }
109
+ interface LoadAutoRulesOptions {
110
+ readonly userKodaxDir: string;
111
+ readonly projectRoot: string;
112
+ }
113
+ interface TrustState {
114
+ readonly trusted: Readonly<Record<string, string>>;
115
+ }
116
+ declare function computeRulesFingerprint(content: string): string;
117
+ declare function readTrustState(userKodaxDir: string): Promise<TrustState>;
118
+ interface TrustOptions {
119
+ readonly userKodaxDir: string;
120
+ }
121
+ declare function trustProjectRules(rulesPath: string, fingerprint: string, opts: TrustOptions): Promise<void>;
122
+ type ParseAutoRulesResult = {
123
+ readonly ok: true;
124
+ readonly rules: AutoRules;
125
+ } | {
126
+ readonly ok: false;
127
+ readonly error: string;
128
+ };
129
+ declare function parseAutoRules(src: string): ParseAutoRulesResult;
130
+ declare function loadAutoRules(opts: LoadAutoRulesOptions): Promise<RulesLoadResult>;
131
+
132
+ /**
133
+ * Tool-Call Signals — FEATURE_158 Step 2 (v0.7.39).
134
+ *
135
+ * Mechanical pattern matches over a tool call. Signals are NOT verdicts;
136
+ * the classifier consumes them as informational input alongside transcript
137
+ * + user rules and produces the final decision (allow / block / escalate).
138
+ *
139
+ * Two invariants the producers must hold:
140
+ *
141
+ * 1. **Pure**: same `call` + `projectRoot` ⇒ same signals. No I/O, no
142
+ * timestamps, no env reads inside collectors. Collectors run on every
143
+ * non-Tier-1 tool call, so they must be cheap and deterministic.
144
+ *
145
+ * 2. **Fact-only**: a `protected_path` signal says "this command names
146
+ * path X which is under ~/.kodax/", not "this should be blocked".
147
+ * Severity stays on the producer side (e.g. `dangerous_pattern.severity`)
148
+ * so the classifier can weight signals, but the verdict is not encoded
149
+ * here.
150
+ *
151
+ * Tier 0 (absolute deny) is a separate module — signals are pre-verdict
152
+ * material consumed by Tier 2 (LLM classifier). The two paths are not
153
+ * coupled: Tier 0 catches a fixed catastrophic-pattern set; signals
154
+ * describe a wider surface for the classifier to reason about.
155
+ *
156
+ * Design ref: ADR-025, FEATURE_158 (docs/features/v0.7.39.md).
157
+ */
158
+
159
+ /**
160
+ * One mechanical signal about a tool call. Discriminated union — consumers
161
+ * narrow on `kind` to access the kind-specific fields.
162
+ */
163
+ type ToolCallSignal = {
164
+ readonly kind: 'dangerous_pattern';
165
+ /** Pattern source (e.g. regex .source) that matched. */
166
+ readonly pattern: string;
167
+ /**
168
+ * Severity hint for the classifier.
169
+ * `high` — destructive intent typical (e.g. `git push --force`,
170
+ * `chmod 777`, `curl | bash`). Classifier should lean
171
+ * toward escalate/block.
172
+ * `medium` — risk-shaped but contextual (e.g. broad `rm`, `sudo`).
173
+ * Classifier weighs against transcript context.
174
+ */
175
+ readonly severity: 'high' | 'medium';
176
+ } | {
177
+ readonly kind: 'protected_path';
178
+ /** Path token that triggered the match (as it appeared in the call). */
179
+ readonly path: string;
180
+ /**
181
+ * `project-kodax` — under `<projectRoot>/.kodax/`
182
+ * `user-kodax` — under `~/.kodax/` (credentials zone)
183
+ */
184
+ readonly zone: 'project-kodax' | 'user-kodax';
185
+ } | {
186
+ readonly kind: 'outside_project';
187
+ readonly path: string;
188
+ } | {
189
+ readonly kind: 'shell_redirect_outside';
190
+ /** Redirection target path (`>`, `>>`, `tee` etc.). */
191
+ readonly target: string;
192
+ } | {
193
+ readonly kind: 'package_install';
194
+ readonly manager: 'npm' | 'pnpm' | 'yarn' | 'pip' | 'cargo' | 'apt' | 'brew';
195
+ } | {
196
+ readonly kind: 'git_write';
197
+ readonly verb: 'commit' | 'push' | 'reset' | 'clean' | 'rebase' | 'cherry-pick' | 'revert';
198
+ } | {
199
+ readonly kind: 'network';
200
+ readonly tool: 'curl' | 'wget' | 'fetch';
201
+ } | {
202
+ readonly kind: 'file_modification';
203
+ readonly targets: readonly string[];
204
+ };
205
+ /**
206
+ * Pulls signals from one tool call. A collector declares which tool names
207
+ * it applies to via `toolNames`; the dispatcher in `collectAllSignals`
208
+ * skips non-matching collectors so each one only sees calls it was
209
+ * designed for.
210
+ *
211
+ * `collect` returns the signals; an empty array is fine and the common
212
+ * case for benign calls.
213
+ */
214
+ interface SignalCollector {
215
+ /**
216
+ * Tool names this collector reacts to (lowercase). Other tool names
217
+ * never reach `collect`. Empty set = matches nothing (effectively
218
+ * disabled — useful only for tests).
219
+ */
220
+ readonly toolNames: ReadonlySet<string>;
221
+ /**
222
+ * Inspect the call and produce zero or more signals.
223
+ *
224
+ * Must be pure: no I/O, no timing, no global state reads. The
225
+ * `projectRoot` argument is the only environmental context — pass
226
+ * the same value through every call site to keep results stable.
227
+ */
228
+ collect(call: RunnerToolCall, projectRoot: string): readonly ToolCallSignal[];
229
+ }
230
+ /**
231
+ * Run every applicable collector on `call` and return the merged signal
232
+ * list. Order preserved: collectors run in array order; per-collector
233
+ * signal order preserved within their slice.
234
+ *
235
+ * Duplicates intentionally not deduped here — different collectors may
236
+ * legitimately surface the same kind for different reasons (e.g. a
237
+ * `protected_path` from a bash redirect target AND a `protected_path`
238
+ * from an argv token in the same command). The classifier prompt
239
+ * tolerates duplicates; dedup would risk dropping load-bearing context.
240
+ */
241
+ declare function collectAllSignals(call: RunnerToolCall, projectRoot: string, collectors: readonly SignalCollector[]): readonly ToolCallSignal[];
242
+
243
+ /**
244
+ * Denial Tracker — FEATURE_092 Phase 2b.4 (v0.7.33).
245
+ *
246
+ * Tracks classifier blocks per session. When either threshold is crossed,
247
+ * the auto-mode engine downgrades from `llm` to `rules` (mode stays `auto`).
248
+ *
249
+ * - 3 consecutive blocks → likely an unproductive loop (agent not adapting)
250
+ * - 20 cumulative blocks → broader classifier-noise pattern in this session
251
+ *
252
+ * Both are session-scoped, shared with subagents (per design doc, to defend
253
+ * against threshold-bypass via spawning).
254
+ *
255
+ * Pure functional API: each operation returns a new tracker. No mutation.
256
+ */
257
+ declare const CONSECUTIVE_THRESHOLD = 3;
258
+ declare const CUMULATIVE_THRESHOLD = 20;
259
+ interface DenialTracker {
260
+ readonly consecutive: number;
261
+ readonly cumulative: number;
262
+ }
263
+ declare function createDenialTracker(): DenialTracker;
264
+ declare function recordBlock(t: DenialTracker): DenialTracker;
265
+ declare function recordAllow(t: DenialTracker): DenialTracker;
266
+ declare function shouldFallback$1(t: DenialTracker): boolean;
267
+
268
+ /**
269
+ * Circuit Breaker — FEATURE_092 Phase 2b.4 (v0.7.33).
270
+ *
271
+ * Sliding-window error counter for classifier failures (timeouts, 5xx, 429,
272
+ * unparseable outputs). When ≥ 5 errors land within a 10-minute window, the
273
+ * auto-mode engine downgrades from `llm` to `rules` (mode stays `auto`) so
274
+ * the user is not blocked by a degraded classifier path.
275
+ *
276
+ * Pure functional API: each operation returns a new breaker. No mutation.
277
+ * Memory bound: stale timestamps are pruned on each recordError call so
278
+ * the timestamps array never grows unbounded.
279
+ */
280
+ declare const ERROR_THRESHOLD = 5;
281
+ declare const WINDOW_MS: number;
282
+ interface CircuitBreaker {
283
+ readonly timestamps: readonly number[];
284
+ }
285
+ declare function createCircuitBreaker(): CircuitBreaker;
286
+ declare function recordError(b: CircuitBreaker, now: number): CircuitBreaker;
287
+ declare function shouldFallback(b: CircuitBreaker, now: number): boolean;
288
+
289
+ /**
290
+ * AutoModeToolGuardrail — FEATURE_092 Phase 2b.6 (v0.7.33).
291
+ *
292
+ * Assembles the auto-mode classifier modules (rules + projection +
293
+ * classify + denial-tracker + circuit-breaker + model-resolver) into a
294
+ * `ToolGuardrail` that the Runner calls via `beforeTool` on every
295
+ * tool invocation.
296
+ *
297
+ * Decision flow (per design doc "三层权限金字塔"):
298
+ *
299
+ * 1. Tool projection is '' (Tier 1) → allow (zero token cost)
300
+ * 2. Engine has been downgraded to rules → escalate (user confirms)
301
+ * 3. denialTracker.shouldFallback (3/20) → engine downgrade, then escalate
302
+ * 4. circuitBreaker.shouldFallback (5/10m) → engine downgrade, then escalate
303
+ * 5. classify(...) sideQuery
304
+ * allow → allow (record allow → reset consecutive)
305
+ * block → block + reason (record block)
306
+ * escalate → escalate + reason (record error)
307
+ * AbortError thrown → re-throw (propagate user cancel)
308
+ *
309
+ * State (mutable, session-scoped):
310
+ * - engine: 'llm' | 'rules' (starts at 'llm', downgrades on threshold)
311
+ * - denialTracker (immutable type, swapped on each event)
312
+ * - circuitBreaker (immutable type, swapped on each event)
313
+ *
314
+ * Subagent sharing:
315
+ * The factory accepts an optional `sharedState` ref; passing the same ref
316
+ * to a subagent's guardrail means denial / circuit / engine state is
317
+ * shared (per design doc "防绕阈值"). Without it each guardrail is
318
+ * independent.
319
+ *
320
+ * Capability check, Tier 2 path-shortcuts, and the explicit
321
+ * `supportsAutoModeClassifier` provider flag are deferred to follow-up
322
+ * phases — v1 of the guardrail relies on Tier 1 (projection==='') as the
323
+ * structural opt-out and forwards everything else to the classifier.
324
+ */
325
+
326
+ type AutoModeEngine = 'llm' | 'rules';
327
+ interface AutoModeSharedState {
328
+ engine: AutoModeEngine;
329
+ denials: DenialTracker;
330
+ breaker: CircuitBreaker;
331
+ }
332
+ /**
333
+ * User answer for an escalated tool-call. The guardrail translates this into
334
+ * the actual `GuardrailVerdict` returned to the Runner. `'block'` preserves
335
+ * the original escalation reason as the verdict reason so downstream consumers
336
+ * see why the tool was blocked.
337
+ */
338
+ type AutoModeAskUserVerdict = 'allow' | 'block';
339
+ /**
340
+ * Optional REPL-supplied prompt callback for the 6 escalate paths in
341
+ * `beforeTool` (engine-downgraded, denial-threshold-just-crossed,
342
+ * breaker-just-tripped, classifier-error, classifier-decision-escalate,
343
+ * provider-not-configured). When supplied, the guardrail calls this and
344
+ * translates the user's answer into `'allow'` or `'block'`. When NOT
345
+ * supplied, the guardrail returns `'escalate'` as before — the Runner will
346
+ * then throw `GuardrailEscalateError` (preserves backward compat with
347
+ * SDK-side guardrail consumers that have no askUser surface).
348
+ *
349
+ * Rejection propagates: if the user cancels (Ctrl-C in the prompt), throw
350
+ * an AbortError-shaped exception and the Runner aborts the run cleanly.
351
+ */
352
+ type AutoModeAskUser = (call: RunnerToolCall, reason: string,
353
+ /**
354
+ * FEATURE_158 (v0.7.39): static-analysis signals collected for this tool
355
+ * call. Optional + readonly so existing callers without signal-aware UI
356
+ * keep working. REPL uses these to render Scope/Risk labels on the
357
+ * confirm dialog (replacing the input-marker path from FEATURE_066).
358
+ */
359
+ signals?: readonly ToolCallSignal[]) => Promise<AutoModeAskUserVerdict>;
360
+ interface AutoModeGuardrailConfig {
361
+ readonly rules: AutoRules;
362
+ readonly claudeMd?: string;
363
+ /**
364
+ * FEATURE_092 phase 2b.7b: optional user-prompt callback for escalate
365
+ * paths. See `AutoModeAskUser` for semantics.
366
+ */
367
+ readonly askUser?: AutoModeAskUser;
368
+ /**
369
+ * Look up a tool's `toClassifierInput` projection by tool name.
370
+ * Returns `undefined` when the tool isn't in the registry — guardrail
371
+ * treats that as "no projection ⇒ Tier 1 skip" (conservative for
372
+ * unknown tools is debatable; v1 favors not blocking on noise).
373
+ */
374
+ readonly getToolProjection: (toolName: string) => ((input: unknown) => string) | undefined;
375
+ /**
376
+ * Resolve a provider name to an instance. Returns `undefined` when
377
+ * unconfigured / unknown — the guardrail then escalates.
378
+ */
379
+ readonly resolveProvider: (providerName: string) => KodaXBaseProvider | undefined;
380
+ readonly defaultProvider: string;
381
+ readonly defaultModel: string;
382
+ /**
383
+ * FEATURE_092 v0.7.34 hotfix-3 — defaultProvider/defaultModel staleness fix.
384
+ *
385
+ * When supplied, these are called on EVERY classify() invocation, so the
386
+ * classifier follows the user's current main session provider/model even
387
+ * after `/model` or `/provider` mid-session swaps. Falls back to
388
+ * `defaultProvider` / `defaultModel` (static strings) when unset, preserving
389
+ * backward compatibility for SDK consumers that pass string literals.
390
+ */
391
+ readonly getDefaultProvider?: () => string;
392
+ readonly getDefaultModel?: () => string;
393
+ readonly cliFlag?: string;
394
+ readonly envVar?: string;
395
+ readonly sessionOverride?: string;
396
+ readonly userSettings?: string;
397
+ /**
398
+ * Optional cost-tracker accessors. The classifier writes its tokens to
399
+ * the tracker under `querySource: 'auto_mode'` (handled inside sideQuery).
400
+ */
401
+ readonly getCostTracker?: () => CostTracker | undefined;
402
+ readonly setCostTracker?: (t: CostTracker) => void;
403
+ /** Optional logger for engine-downgrade and config warnings. */
404
+ readonly log?: (level: 'info' | 'warn', msg: string) => void;
405
+ /**
406
+ * Fired whenever the active engine changes — both on automatic downgrades
407
+ * (denial threshold / circuit breaker) AND on manual `setEngine(...)`
408
+ * calls. UI surfaces (status bar engine indicator, slash-command
409
+ * confirmations) subscribe here so the displayed engine stays in sync
410
+ * with the guardrail's internal state without the user having to trigger
411
+ * another mode toggle just to refresh the bar.
412
+ */
413
+ readonly onEngineChange?: (engine: AutoModeEngine) => void;
414
+ /**
415
+ * Optional shared state for subagent threshold-bypass defense
416
+ * (design doc "防绕阈值"). When supplied, the parent and child
417
+ * guardrails reference the SAME object — engine downgrades and
418
+ * tracker advances are visible across the session boundary.
419
+ */
420
+ readonly sharedState?: AutoModeSharedState;
421
+ /**
422
+ * FEATURE_092 phase 2b.7b slice C: starting engine. Defaults to `'llm'`.
423
+ * Set to `'rules'` to skip the classifier entirely from session start
424
+ * (the rules-mode escalate path runs immediately on the first non-Tier-1
425
+ * tool call). Resolved by the REPL from `~/.kodax/config.json`
426
+ * `autoMode.engine` and the `KODAX_AUTO_MODE_ENGINE` env var.
427
+ */
428
+ readonly initialEngine?: AutoModeEngine;
429
+ /**
430
+ * FEATURE_092 phase 2b.7b slice C: classifier sideQuery timeout in ms.
431
+ * Defaults to 8000. Resolved by the REPL from `~/.kodax/config.json`
432
+ * `autoMode.timeoutMs`.
433
+ */
434
+ readonly timeoutMs?: number;
435
+ /**
436
+ * Project root for signal collectors. File-tool collector uses this to
437
+ * detect `outside_project` vs project-relative paths. Bash collector
438
+ * doesn't use it (command-string-level) but threads it for uniform
439
+ * collector contract.
440
+ *
441
+ * Required by FEATURE_158: if omitted, the default coding-side
442
+ * collectors produce no `outside_project` signal (degrades gracefully),
443
+ * but **REPL-injected `extraCollectors` will likely require it**.
444
+ * SDK consumers without a project root should set `projectRoot: ''`
445
+ * and supply no `extraCollectors`.
446
+ */
447
+ readonly projectRoot?: string;
448
+ /**
449
+ * Override the default signal-collector set. When unset, defaults to
450
+ * `[bashSignalCollector, fileSignalCollector]` — coding-side
451
+ * command-string + file-tool collectors that don't depend on REPL
452
+ * path utilities.
453
+ *
454
+ * Use `extraCollectors` instead if you want to **add** collectors
455
+ * without replacing the defaults.
456
+ */
457
+ readonly signalCollectors?: readonly SignalCollector[];
458
+ /**
459
+ * Additional signal collectors to merge with `signalCollectors`.
460
+ * Primary use: REPL injects a path-aware bash collector built on its
461
+ * own `extractPathsFromCommand` / `isAlwaysConfirmPath` utilities
462
+ * (those live in `@kodax/repl` for historical reasons; lifting them
463
+ * is out-of-scope for FEATURE_158 — see design doc layer-boundary
464
+ * decision).
465
+ *
466
+ * Order: defaults run first, then extras (preserves per-collector
467
+ * signal order).
468
+ */
469
+ readonly extraCollectors?: readonly SignalCollector[];
470
+ /**
471
+ * Speculative-classify quiet window (ms). When a classifier promise
472
+ * settles within this window, the guardrail uses the verdict directly
473
+ * (no confirm dialog). When the window expires, the call escalates to
474
+ * the user; the background classifier is left running for cost-tracker
475
+ * settlement but its eventual result is discarded in v1 (UI doesn't
476
+ * adopt late verdicts yet).
477
+ *
478
+ * Precedence: explicit arg > `KODAX_AUTO_SPECULATIVE_WINDOW_MS` env >
479
+ * `DEFAULT_WINDOW_MS = 500`. Set to 0 to disable speculative race
480
+ * (degrades to synchronous classify).
481
+ */
482
+ readonly speculativeWindowMs?: number;
483
+ }
484
+ /**
485
+ * Snapshot of the auto-mode guardrail's session-scoped state. Returned by
486
+ * `getStats()` for diagnostic surfaces (`/auto-denials`) and the status bar
487
+ * engine indicator. The DenialTracker / CircuitBreaker types are immutable
488
+ * value objects, so this is a copy of the references — caller cannot mutate
489
+ * guardrail state through it.
490
+ */
491
+ interface AutoModeStats {
492
+ readonly engine: AutoModeEngine;
493
+ readonly denials: DenialTracker;
494
+ readonly breaker: CircuitBreaker;
495
+ }
496
+ interface AutoModeToolGuardrail extends ToolGuardrail {
497
+ /** Current engine for this session. */
498
+ getEngine(): AutoModeEngine;
499
+ /** Snapshot of engine + denial tracker + circuit breaker. */
500
+ getStats(): AutoModeStats;
501
+ /**
502
+ * Manually set the engine. Used by `/auto-engine` slash command to flip
503
+ * back to 'llm' after an automatic downgrade or to flip to 'rules' for
504
+ * manual testing. The downgrade thresholds still operate normally — a
505
+ * subsequent threshold cross will downgrade again.
506
+ */
507
+ setEngine(engine: AutoModeEngine): void;
508
+ /** Test-only alias for getEngine(). Backward-compat for test files. */
509
+ getEngineForTest(): AutoModeEngine;
510
+ /** Test-only alias for getStats(). Backward-compat for test files. */
511
+ getStatsForTest(): AutoModeStats;
512
+ /** Test-only override: swap the provider mid-test (for downgrade scenarios). */
513
+ setProviderForTest(provider: KodaXBaseProvider): void;
514
+ }
515
+ declare function createAutoModeToolGuardrail(config: AutoModeGuardrailConfig): AutoModeToolGuardrail;
516
+
517
+ export { parseAutoRules as B, CONSECUTIVE_THRESHOLD as C, ERROR_THRESHOLD as E, readTrustState as F, recordAllow as G, recordBlock as H, recordError as I, shouldFallback$1 as J, shouldFallback as M, trustProjectRules as N, WINDOW_MS as W, CUMULATIVE_THRESHOLD as i, collectAllSignals as r, computeRulesFingerprint as s, createAutoModeToolGuardrail as t, createCircuitBreaker as u, createDenialTracker as v, formatAgentsForPrompt as w, getKodaxGlobalDir as x, loadAgentsFiles as y, loadAutoRules as z };
518
+ export type { AgentsFile as A, DenialTracker as D, KodaXMcpConnectMode as K, LoadAgentsOptions as L, RulesLoadError as R, SignalCollector as S, ToolCallSignal as T, AutoModeAskUser as a, AutoModeAskUserVerdict as b, AutoModeEngine as c, AutoModeGuardrailConfig as d, AutoModeSharedState as e, AutoModeStats as f, AutoModeToolGuardrail as g, AutoRules as h, CircuitBreaker as j, KodaXMcpServerConfig as k, KodaXMcpServersConfig as l, KodaXMcpTransport as m, LoadedRulesSource as n, RulesLoadResult as o, SkippedRulesSource as p, TrustState as q };