@kodax-ai/kodax 0.7.55 → 0.7.57

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 +50 -0
  2. package/README.md +22 -24
  3. package/README_CN.md +16 -18
  4. package/dist/builtin/code-review/SKILL.md +22 -3
  5. package/dist/chunks/agent-EHWQZA4C.js +2 -0
  6. package/dist/chunks/argument-completer-AYDAYGKL.js +2 -0
  7. package/dist/chunks/chunk-3WWPJGPQ.js +2 -0
  8. package/dist/chunks/chunk-4SHP3M67.js +2 -0
  9. package/dist/chunks/chunk-KN6IJMTB.js +636 -0
  10. package/dist/chunks/{chunk-ZBK3DZ3S.js → chunk-LZKGOR2C.js} +1 -1
  11. package/dist/chunks/chunk-MJFPFRGK.js +423 -0
  12. package/dist/chunks/chunk-N2N2W3AQ.js +584 -0
  13. package/dist/chunks/chunk-PCPFLPS4.js +5 -0
  14. package/dist/chunks/chunk-TCLSPUTR.js +31 -0
  15. package/dist/chunks/chunk-VACH6QWN.js +315 -0
  16. package/dist/chunks/chunk-YSVPF6SN.js +597 -0
  17. package/dist/chunks/{compaction-config-NAJEEPG5.js → compaction-config-TLDMFMZO.js} +1 -1
  18. package/dist/chunks/{construction-bootstrap-4CIVZMQ5.js → construction-bootstrap-55B7Q5RX.js} +4 -4
  19. package/dist/chunks/dist-IE4HVWP7.js +2 -0
  20. package/dist/chunks/dist-IKOK2MJQ.js +2 -0
  21. package/dist/chunks/paste-WTL2XN7P.js +2 -0
  22. package/dist/chunks/utils-EJ2VCRTC.js +2 -0
  23. package/dist/index.d.ts +21 -16
  24. package/dist/index.js +6 -6
  25. package/dist/kodax_cli.js +1128 -1099
  26. package/dist/provider-capabilities.json +986 -195
  27. package/dist/sdk-agent.d.ts +20 -12
  28. package/dist/sdk-agent.js +1 -1
  29. package/dist/sdk-coding.d.ts +223 -108
  30. package/dist/sdk-coding.js +1 -1
  31. package/dist/sdk-llm.d.ts +10 -5
  32. package/dist/sdk-llm.js +1 -1
  33. package/dist/sdk-mcp.d.ts +1 -1
  34. package/dist/sdk-mcp.js +1 -1
  35. package/dist/sdk-media.d.ts +142 -0
  36. package/dist/sdk-media.js +2 -0
  37. package/dist/sdk-repl.d.ts +106 -96
  38. package/dist/sdk-repl.js +1 -1
  39. package/dist/sdk-session.d.ts +6 -5
  40. package/dist/sdk-session.js +1 -1
  41. package/dist/sdk-skills.js +1 -1
  42. package/dist/semantic-worker.js +11 -0
  43. package/dist/types-chunks/base.d-BnjQrSVf.d.ts +301 -0
  44. package/dist/types-chunks/{bash-prefix-extractor.d-LUGkQHcd.d.ts → bash-prefix-extractor.d-BgvMbfq6.d.ts} +198 -139
  45. package/dist/types-chunks/{capsule.d-CNonpwAZ.d.ts → capsule.d-DwJp5r63.d.ts} +14 -11
  46. package/dist/types-chunks/{types.d-D4jL-gAA.d.ts → guardrail.d-BP3yyr6u.d.ts} +3 -121
  47. package/dist/types-chunks/{guardrail.d-B18oO1gt.d.ts → guardrail.d-C1DhxnvC.d.ts} +31 -9
  48. package/dist/types-chunks/{manager.d-DLmDhX3i.d.ts → manager.d-DBD7SOTT.d.ts} +7 -2
  49. package/dist/types-chunks/{process.d-Bj82oJhD.d.ts → process.d-BZncyzEj.d.ts} +2 -1
  50. package/dist/types-chunks/{resolver.d-CCX9NXWP.d.ts → resolver.d-ZvKQgl0X.d.ts} +82 -17
  51. package/dist/types-chunks/{sdk-session-SjrnWb4-.d.ts → sdk-session-DAScB0rW.d.ts} +6 -4
  52. package/dist/types-chunks/{storage.d-BAuJ0Ks7.d.ts → storage.d-CPvn9qI0.d.ts} +2 -2
  53. package/dist/types-chunks/{base.d-BBNUF9nz.d.ts → types.d-6VOXvF88.d.ts} +101 -290
  54. package/dist/types-chunks/types.d-D8WcfrOD.d.ts +143 -0
  55. package/dist/types-chunks/{utils.d-C9MUY8n3.d.ts → utils.d-CpgVIjYZ.d.ts} +16 -18
  56. package/package.json +15 -6
  57. package/dist/chunks/agent-PYSVWY7M.js +0 -2
  58. package/dist/chunks/argument-completer-CTDNNWV3.js +0 -2
  59. package/dist/chunks/chunk-7C2QUBLE.js +0 -31
  60. package/dist/chunks/chunk-EVIDQWMF.js +0 -5
  61. package/dist/chunks/chunk-FRI7UQSB.js +0 -2
  62. package/dist/chunks/chunk-HQCLPWRI.js +0 -551
  63. package/dist/chunks/chunk-JCDO2FR4.js +0 -584
  64. package/dist/chunks/chunk-MX4G42EV.js +0 -425
  65. package/dist/chunks/chunk-RGPPZOD5.js +0 -314
  66. package/dist/chunks/chunk-THAKTCPE.js +0 -652
  67. package/dist/chunks/dist-7KTO2PUU.js +0 -2
  68. package/dist/chunks/dist-BNKIZRCP.js +0 -2
  69. package/dist/chunks/paste-5DSTHQGK.js +0 -2
  70. package/dist/chunks/utils-2QXBKYPJ.js +0 -2
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * KodaX AI Types
3
3
  *
4
- * AI 层类型定义 - 所有 Provider 共享的类型接口
4
+ * AI 层类型定义 - 所有 Provider 共享的类型接口
5
5
  */
6
6
  interface KodaXTextBlock {
7
7
  type: 'text';
@@ -120,6 +120,57 @@ interface KodaXToolDefinition {
120
120
  };
121
121
  }
122
122
  type KodaXReasoningCapability = 'native-effort' | 'native-budget' | 'native-toggle' | 'native-adaptive' | 'none' | 'prompt-only' | 'unknown';
123
+ type KodaXStableEffortIntent = 'auto' | 'none' | 'low' | 'medium' | 'high';
124
+ type KodaXWireReasoningEffort = string;
125
+ type KodaXReasoningPresetName = 'zai-glm-5.2' | 'zai-glm-toggle' | 'deepseek-v4-openai' | 'deepseek-v4-anthropic' | 'deepseek-toggle' | 'kimi-k2.7-code' | 'kimi-hybrid-toggle' | 'minimax-m3' | 'minimax-m2-always' | 'mimo-v2.5-toggle' | 'qwen-hybrid-thinking' | 'openai-chat-reasoning' | 'openai-responses-reasoning' | 'codex-cli-effort' | 'claude-adaptive-xhigh' | 'claude-adaptive-max' | 'anthropic-budget' | 'generic-thinking-toggle' | 'none';
126
+ interface KodaXReasoningEffortRequest {
127
+ readonly value: KodaXWireReasoningEffort;
128
+ readonly isExplicit: boolean;
129
+ }
130
+ interface KodaXReasoningEffortPreset {
131
+ readonly value: KodaXWireReasoningEffort;
132
+ readonly description?: string;
133
+ readonly isDefault?: boolean;
134
+ readonly isUserVisible?: boolean;
135
+ }
136
+ type KodaXReasoningEffortWireStrategy = 'openai-responses-effort' | 'openai-chat-effort' | 'codex-cli-config' | 'anthropic-output-effort' | 'provider-budget' | 'provider-toggle' | 'prompt-only' | 'none';
137
+ type KodaXThinkingWireStrategy = 'anthropic-adaptive' | 'anthropic-budget' | 'provider-budget' | 'provider-toggle' | 'none';
138
+ interface KodaXReasoningProfile {
139
+ readonly reasoningPreset?: KodaXReasoningPresetName;
140
+ readonly effortStrategy: KodaXReasoningEffortWireStrategy;
141
+ readonly thinkingStrategy?: KodaXThinkingWireStrategy;
142
+ readonly defaultEffort?: KodaXWireReasoningEffort;
143
+ readonly supportedEfforts?: readonly KodaXReasoningEffortPreset[];
144
+ readonly effortAliases?: Partial<Record<KodaXWireReasoningEffort, KodaXWireReasoningEffort>>;
145
+ readonly disabledEfforts?: readonly KodaXWireReasoningEffort[];
146
+ readonly localRejectEfforts?: readonly KodaXWireReasoningEffort[];
147
+ readonly allowCustomEffort?: boolean;
148
+ readonly budgetByEffort?: Partial<Record<KodaXWireReasoningEffort, number>>;
149
+ readonly supportsReasoningEffort?: boolean;
150
+ readonly supportsReasoningSummary?: boolean;
151
+ readonly supportsEncryptedReasoningReplay?: boolean;
152
+ readonly supportsAdaptiveThinking?: boolean;
153
+ readonly supportsManualThinkingBudget?: boolean;
154
+ readonly supportsDisabledThinking?: boolean;
155
+ readonly requiresEffortBetaHeader?: boolean;
156
+ }
157
+ /**
158
+ * Friendly reasoning declaration for CUSTOM providers / models — the canonical
159
+ * user-facing form. List the effort rungs the model accepts (order = the Ctrl+T
160
+ * ladder; include `"off"` to allow disabling thinking) plus an optional
161
+ * `default`. The wire strategy (effortStrategy / thinkingStrategy) is derived
162
+ * from the provider `protocol`, so users never touch preset names or strategy
163
+ * enums. Use the string `"none"` for a model with no thinking capability. For
164
+ * full, explicit control fall back to `reasoningProfile`.
165
+ *
166
+ * Example: `"reasoning": { "efforts": ["off", "low", "high", "max"], "default": "high" }`
167
+ */
168
+ interface KodaXSimpleReasoningConfig {
169
+ readonly efforts: readonly string[];
170
+ readonly default?: string;
171
+ }
172
+ /** User-facing reasoning declaration: friendly form, `"none"`, or (advanced) a raw profile override. */
173
+ type KodaXReasoningConfig = KodaXSimpleReasoningConfig | 'none' | Partial<KodaXReasoningProfile>;
123
174
  type KodaXProviderTransport = 'native-api' | 'cli-bridge';
124
175
  type KodaXProviderConversationSemantics = 'full-history' | 'last-user-message';
125
176
  type KodaXProviderMcpSupport = 'native' | 'none';
@@ -140,7 +191,6 @@ interface KodaXProviderCapabilityProfile {
140
191
  multimodalSupport?: KodaXProviderMultimodalSupport;
141
192
  evidenceSupport?: KodaXProviderEvidenceSupport;
142
193
  }
143
- type KodaXReasoningOverride = 'budget' | 'effort' | 'toggle' | 'adaptive' | 'none';
144
194
  type KodaXReasoningMode = 'off' | 'auto' | 'quick' | 'balanced' | 'deep';
145
195
  type KodaXThinkingDepth = 'off' | 'low' | 'medium' | 'high';
146
196
  type KodaXTaskType = 'conversation' | 'lookup' | 'review' | 'bugfix' | 'edit' | 'refactor' | 'plan' | 'qa' | 'unknown';
@@ -155,23 +205,7 @@ type KodaXMutationSurface = 'read-only' | 'docs-only' | 'code' | 'system';
155
205
  type KodaXAssuranceIntent = 'default' | 'explicit-check';
156
206
  type KodaXHarnessProfile = 'H0_DIRECT' | 'H1_EXECUTE_EVAL' | 'H2_PLAN_EXECUTE_EVAL' | 'PLANNED';
157
207
  type KodaXReviewScale = 'small' | 'large' | 'massive';
158
- type KodaXAmaProfile = 'tactical' | 'managed';
159
- type KodaXAmaTactic = 'direct' | 'child-fanout' | 'planning-pass' | 'verification-pass' | 'repair-loop';
160
- type KodaXAmaFanoutClass = 'finding-validation' | 'evidence-scan' | 'module-triage' | 'hypothesis-check';
161
- interface KodaXAmaFanoutPolicy {
162
- admissible: boolean;
163
- class?: KodaXAmaFanoutClass;
164
- reason: string;
165
- maxChildren?: number;
166
- requiresReadOnly?: boolean;
167
- }
168
- interface KodaXAmaControllerDecision {
169
- profile: KodaXAmaProfile;
170
- tactics: KodaXAmaTactic[];
171
- fanout: KodaXAmaFanoutPolicy;
172
- reason: string;
173
- upgradeTriggers: string[];
174
- }
208
+ type KodaXChildFanoutClass = 'finding-validation' | 'evidence-scan' | 'module-triage' | 'hypothesis-check';
175
209
  interface KodaXTaskRoutingDecision {
176
210
  primaryTask: KodaXTaskType;
177
211
  secondaryTask?: KodaXTaskType;
@@ -207,18 +241,40 @@ interface KodaXThinkingBudgetMap {
207
241
  type KodaXTaskBudgetOverrides = Partial<Record<KodaXTaskType, Partial<KodaXThinkingBudgetMap>>>;
208
242
  interface KodaXReasoningRequest {
209
243
  enabled?: boolean;
210
- mode?: KodaXReasoningMode;
211
- depth?: KodaXThinkingDepth;
244
+ /**
245
+ * Canonical reasoning control. Reasoning single-tracking removed the legacy
246
+ * `mode` (KodaXReasoningMode) + `depth` (KodaXThinkingDepth) request fields —
247
+ * callers pass `effort` (or `enabled` as a boolean shorthand). Providers
248
+ * derive any thinking budget from the effort via `effortToThinkingDepth`.
249
+ */
250
+ effort?: KodaXWireReasoningEffort;
212
251
  taskType?: KodaXTaskType;
213
252
  executionMode?: KodaXExecutionMode;
214
253
  }
254
+ interface KodaXNormalizedReasoningRequest {
255
+ enabled: boolean;
256
+ effort: KodaXWireReasoningEffort;
257
+ effortSource?: 'explicit' | 'legacy';
258
+ taskType: KodaXTaskType;
259
+ executionMode: KodaXExecutionMode;
260
+ }
215
261
  interface KodaXModelDescriptor {
216
262
  id: string;
217
263
  displayName?: string;
218
264
  contextWindow?: number;
219
265
  maxOutputTokens?: number;
220
266
  thinkingBudgetCap?: number;
267
+ /** @deprecated Auto-migrated on load. Prefer `reasoning: { efforts, default }`. */
221
268
  reasoningCapability?: KodaXReasoningCapability;
269
+ /** @deprecated Internal preset name; auto-migrated on load. Prefer `reasoning`. */
270
+ reasoningPreset?: KodaXReasoningPresetName;
271
+ /**
272
+ * Canonical reasoning declaration: friendly `{ efforts, default }`, `"none"`,
273
+ * or (advanced) a raw `Partial<KodaXReasoningProfile>` override. See
274
+ * `KodaXReasoningConfig`.
275
+ */
276
+ reasoning?: KodaXReasoningConfig;
277
+ reasoningProfile?: KodaXReasoningProfile;
222
278
  /**
223
279
  * Per-model override for `replayReasoningContent`. Falls through to the
224
280
  * provider-level flag when undefined. Lets a single gateway endpoint
@@ -309,6 +365,14 @@ interface KodaXCustomProviderConfig {
309
365
  baseUrl: string;
310
366
  apiKeyEnv: string;
311
367
  model: string;
368
+ /** @deprecated Internal preset name; auto-migrated on load. Prefer `reasoning`. */
369
+ reasoningPreset?: KodaXReasoningPresetName;
370
+ /**
371
+ * Canonical reasoning declaration for this provider: friendly
372
+ * `{ efforts, default }`, `"none"`, or (advanced) a raw profile override.
373
+ * See `KodaXReasoningConfig`.
374
+ */
375
+ reasoning?: KodaXReasoningConfig;
312
376
  /**
313
377
  * Additional available models beyond the default. Accepts either a
314
378
  * plain model id string (legacy) or a KodaXModelDescriptor object
@@ -322,8 +386,11 @@ interface KodaXCustomProviderConfig {
322
386
  * - sdk: keep the upstream SDK default User-Agent
323
387
  */
324
388
  userAgentMode?: KodaXProviderUserAgentMode;
389
+ /** @deprecated Auto-migrated on load. Prefer `reasoning: "none"` (off) or `reasoning: { efforts, default }`. */
325
390
  supportsThinking?: boolean;
391
+ /** @deprecated Auto-migrated on load. Prefer `reasoning: { efforts, default }`. */
326
392
  reasoningCapability?: KodaXReasoningCapability;
393
+ reasoningProfile?: KodaXReasoningProfile;
327
394
  capabilityProfile?: KodaXProviderCapabilityProfile;
328
395
  contextWindow?: number;
329
396
  maxOutputTokens?: number;
@@ -370,6 +437,7 @@ interface KodaXProviderConfig {
370
437
  userAgentMode?: KodaXProviderUserAgentMode;
371
438
  supportsThinking: boolean;
372
439
  reasoningCapability?: KodaXReasoningCapability;
440
+ reasoningProfile?: KodaXReasoningProfile;
373
441
  capabilityProfile?: KodaXProviderCapabilityProfile;
374
442
  /** 模型的上下文窗口大小 (tokens) */
375
443
  contextWindow?: number;
@@ -471,6 +539,17 @@ interface KodaXProviderStreamOptions {
471
539
  maxAttempts: number;
472
540
  }) => void;
473
541
  /** 会话标识,用于多轮对话上下文恢复 */
542
+ /**
543
+ * Passive capability learning — fired when a provider HARD-rejects a
544
+ * reasoning-effort value (400/422 naming the param). The REPL records it in
545
+ * `capability-cache.json` so the rung is removed from the ladder and never
546
+ * offered or sent again (see `classifyReasoningEffortRejection`).
547
+ */
548
+ onReasoningEffortRejected?: (event: {
549
+ provider: string;
550
+ model: string;
551
+ effort: string;
552
+ }) => void;
474
553
  sessionId?: string;
475
554
  /** Override the provider's default model for a single request */
476
555
  modelOverride?: string;
@@ -482,272 +561,4 @@ interface KodaXProviderStreamOptions {
482
561
  signal?: AbortSignal;
483
562
  }
484
563
 
485
- /**
486
- * Retry-After header parsing — FEATURE_130 (v0.7.36).
487
- *
488
- * Handles the four forms KodaX's 12 provider adapters encounter when a
489
- * model returns 429 (rate limit) or 503/529 (overloaded):
490
- *
491
- * 1. `Retry-After: 120` — integer seconds (HTTP 7231 standard)
492
- * 2. `Retry-After: <HTTP-date>` — RFC 7231 IMF-fixdate
493
- * e.g. "Wed, 21 Oct 2026 07:28:00 GMT"
494
- * 3. `retry-after-ms: 45000` — Anthropic millisecond extension
495
- * 4. (no Retry-After header present) — falls back to exponential backoff
496
- * capped at `maxBackoffMs`, with optional jitter for the
497
- * "thundering herd" protection.
498
- *
499
- * All return values are normalized to whole milliseconds and clamped to
500
- * a sensible upper bound — never block the user for more than 120s, and
501
- * never honor a header advertising a wait longer than `maxHeaderWaitMs`
502
- * (default 120s). Beyond that limit we still extract the header but cap
503
- * it; the calling provider can check `cappedFromHeader` to decide
504
- * whether to surface a "rate limit exceeded — please wait" error to the
505
- * user instead of silently sleeping for two minutes.
506
- *
507
- * Pattern-B (FEATURE_119) interaction: the helper is referentially
508
- * transparent and stateless — it can be invoked concurrently by N
509
- * parallel children without coordination. The retry loop in each
510
- * provider holds its own attempt counter; this helper only translates
511
- * headers/attempts into wait durations.
512
- *
513
- * Reference: opencode session/retry.ts:14-123 (4-form coverage).
514
- */
515
- type RetryAfterSource = 'retry-after-seconds' | 'retry-after-date' | 'retry-after-ms' | 'exponential-backoff';
516
- type RetryAfterResult = {
517
- readonly type: 'header';
518
- readonly waitMs: number;
519
- readonly source: 'retry-after-seconds' | 'retry-after-date' | 'retry-after-ms';
520
- /** True when the header value exceeded `maxHeaderWaitMs` and was clamped. */
521
- readonly cappedFromHeader: boolean;
522
- } | {
523
- readonly type: 'backoff';
524
- readonly waitMs: number;
525
- readonly source: 'exponential-backoff';
526
- readonly attempt: number;
527
- };
528
- interface ParseRetryAfterOptions {
529
- /** Zero-based attempt index used by the backoff branch (0 = first retry). */
530
- readonly attempt: number;
531
- /** Base delay for exponential backoff. Default 1000ms. */
532
- readonly baseBackoffMs?: number;
533
- /** Maximum exponential backoff cap. Default 30000ms. */
534
- readonly maxBackoffMs?: number;
535
- /** Maximum wait honored from a header. Default 120000ms. */
536
- readonly maxHeaderWaitMs?: number;
537
- /**
538
- * Override the "now" reference used by the HTTP-date branch.
539
- * Test-only escape hatch — production code should leave this undefined.
540
- */
541
- readonly now?: () => number;
542
- /**
543
- * Whether the backoff branch adds 0-25% jitter on top of the base
544
- * exponential. Default true (matches the legacy `withRateLimit`
545
- * jitter contract). Tests can pass `false` for deterministic output.
546
- */
547
- readonly withJitter?: boolean;
548
- }
549
- type HeadersLike = Headers | Record<string, string | string[] | undefined> | undefined;
550
- /**
551
- * Parse rate-limit/overload retry-after headers (4 forms) and decide
552
- * how long the caller should sleep before retrying. Returns either:
553
- *
554
- * - `{type: 'header', ...}` when one of the supported headers was found
555
- * and converted into a wait duration; OR
556
- * - `{type: 'backoff', ...}` falling back to exponential backoff for
557
- * the given `attempt` index when no header is present.
558
- */
559
- declare function parseRetryAfter(headers: HeadersLike, options: ParseRetryAfterOptions): RetryAfterResult;
560
- /**
561
- * Pull headers off a thrown error in the various shapes produced across
562
- * provider SDKs (Anthropic, OpenAI, fetch-based custom providers).
563
- * Returns `undefined` when no headers can be located — the helper then
564
- * falls through to exponential backoff.
565
- */
566
- declare function extractHeadersFromError(error: unknown): HeadersLike;
567
-
568
- /**
569
- * KodaX Base Provider
570
- *
571
- * Provider 抽象基类 - 所有 Provider 的公共基础
572
- */
573
-
574
- /**
575
- * FEATURE_130 (v0.7.36): structured payload fired through
576
- * `KodaXEvents.onRetryAfter` whenever a provider's `withRateLimit`
577
- * loop catches a 429 / 503 / 529 response and decides to wait. The
578
- * `source` field carries which retry-after header form (or fallback)
579
- * produced the wait duration so UI surfaces can show "provider asked
580
- * us to wait 45s" vs "no header, exp-backoff guess of 4s".
581
- */
582
- interface KodaXRetryAfterEvent {
583
- readonly provider: string;
584
- readonly waitMs: number;
585
- readonly reason: 'rate-limit' | 'overloaded';
586
- readonly source: RetryAfterSource;
587
- readonly attempt: number;
588
- readonly maxAttempts: number;
589
- }
590
- type KodaXOnRetryAfterCallback = (event: KodaXRetryAfterEvent) => void;
591
- declare abstract class KodaXBaseProvider {
592
- abstract readonly name: string;
593
- abstract readonly supportsThinking: boolean;
594
- protected abstract readonly config: KodaXProviderConfig;
595
- /**
596
- * Per-request override for `max_tokens` in the next provider call. Consumed
597
- * once and cleared in `withRateLimit` after the next successful response.
598
- * Two callers set this:
599
- * 1. Context-overflow recovery inside `withRateLimit` (reduces budget
600
- * when the model reports "prompt too long").
601
- * 2. The agent loop's max_tokens escalation path, which flips this to
602
- * `KODAX_ESCALATED_MAX_OUTPUT_TOKENS` when a capped-budget turn
603
- * returns `stop_reason: max_tokens`. See `coding/src/agent.ts`.
604
- */
605
- protected maxOutputTokensOverride?: number;
606
- /**
607
- * Public setter for the one-shot override above. Callers outside the
608
- * provider package (notably the agent loop's escalation branch) use this
609
- * to stage a larger budget for the next stream call in the same logical
610
- * turn. Pass `undefined` to clear a stale override explicitly.
611
- */
612
- setMaxOutputTokensOverride(value: number | undefined): void;
613
- /**
614
- * Returns the max_tokens value the provider will currently use on its
615
- * next request. Precedence (highest to lowest):
616
- * 1. One-shot override (agent escalation, context-overflow recovery)
617
- * 2. User env var `KODAX_MAX_OUTPUT_TOKENS` (explicit user intent)
618
- * 3. Active model descriptor's `maxOutputTokens` (FEATURE_098)
619
- * 4. Provider config default
620
- * 5. Global `KODAX_MAX_TOKENS` fallback
621
- * Used by provider stream() paths and by the agent loop to decide
622
- * whether escalation is applicable (see `coding/src/agent.ts`).
623
- */
624
- getEffectiveMaxOutputTokens(model?: string): number;
625
- /**
626
- * Hard cap on a single streaming request's wall-clock duration (ms).
627
- * Returns undefined when no cap is configured. Consumed by the
628
- * resilience layer to abort a doomed stream before the server-side
629
- * kill window fires; routed through `non_streaming_fallback`.
630
- *
631
- * Cascade (highest to lowest):
632
- * 1. Active model descriptor's `streamMaxDurationMs`
633
- * 2. Provider config default
634
- * 3. undefined (watchdog disabled)
635
- */
636
- getStreamMaxDurationMs(model?: string): number | undefined;
637
- /**
638
- * Resolves whether OpenAI-compat `reasoning_content` should echo back
639
- * on replayed assistant messages for the given model. Same cascade as
640
- * `getStreamMaxDurationMs`. Defaults to false when neither layer sets it.
641
- */
642
- getEffectiveReplayReasoningContent(model?: string): boolean;
643
- /**
644
- * Resolves whether Anthropic-style thinking signatures must verify
645
- * strictly (Anthropic proper only). Same cascade as
646
- * `getStreamMaxDurationMs`. Defaults to false (lenient) when neither
647
- * layer sets it — matches third-party Anthropic-compat behavior.
648
- */
649
- getEffectiveStrictThinkingSignature(model?: string): boolean;
650
- abstract stream(messages: KodaXMessage[], tools: KodaXToolDefinition[], system: string, reasoning?: boolean | KodaXReasoningRequest, streamOptions?: KodaXProviderStreamOptions, signal?: AbortSignal): Promise<KodaXStreamResult>;
651
- supportsNonStreamingFallback(): boolean;
652
- complete(_messages: KodaXMessage[], _tools: KodaXToolDefinition[], _system: string, _reasoning?: boolean | KodaXReasoningRequest, _streamOptions?: KodaXProviderStreamOptions, _signal?: AbortSignal): Promise<KodaXStreamResult>;
653
- isConfigured(): boolean;
654
- /**
655
- * FEATURE_216 v0.7.45 — Lightweight credential verification. Returns
656
- * a never-throws envelope with `ok` + categorized `error`. Concrete
657
- * compat base classes (`KodaXAnthropicCompatProvider`,
658
- * `KodaXOpenAICompatProvider`) override this to dispatch by the
659
- * `verifyStrategy` field. The default here returns `unsupported` so
660
- * Provider classes that don't extend a compat base — or future ones
661
- * yet to be wired — fail safely instead of throwing.
662
- *
663
- * Distinct from `isConfigured()`: that one is env-only (no network);
664
- * this one hits the wire (zero or ~7 tokens depending on strategy)
665
- * and verifies the key is actually accepted by the upstream.
666
- */
667
- verifyCredential(_opts?: {
668
- timeoutMs?: number;
669
- signal?: AbortSignal;
670
- }): Promise<KodaXVerifyCredentialResult>;
671
- getModel(): string;
672
- getAvailableModels(): string[];
673
- getModelDescriptor(modelId?: string): KodaXModelDescriptor | undefined;
674
- getBaseUrl(): string | undefined;
675
- getApiKeyEnv(): string;
676
- getCapabilityProfile(): KodaXProviderCapabilityProfile;
677
- getConfiguredReasoningCapability(modelOverride?: string): KodaXReasoningCapability;
678
- getReasoningCapability(modelOverride?: string): KodaXReasoningCapability;
679
- getReasoningOverride(modelOverride?: string): KodaXReasoningOverride | undefined;
680
- getReasoningOverrideKey(modelOverride?: string): string;
681
- protected persistReasoningCapabilityOverride(capability: KodaXReasoningCapability, modelOverride?: string): void;
682
- protected shouldFallbackForReasoningError(error: unknown, ...terms: string[]): boolean;
683
- protected shouldFallbackForSpecificReasoningError(error: unknown, ...terms: string[]): boolean;
684
- protected shouldFallbackForForcedToolChoiceError(error: unknown): boolean;
685
- protected isServerError(error: unknown): boolean;
686
- protected getReasoningFallbackChain(capability: KodaXReasoningCapability): KodaXReasoningCapability[];
687
- /**
688
- * 获取模型的上下文窗口大小
689
- *
690
- * Backwards-compatible no-arg form: resolves against the provider's
691
- * default model descriptor. New call sites that know the active
692
- * model should use `getEffectiveContextWindow(model)` directly.
693
- * @returns 上下文窗口大小 (tokens)
694
- */
695
- getContextWindow(): number;
696
- /**
697
- * Resolves the context window for a specific model.
698
- * Precedence (highest to lowest):
699
- * 1. Active model descriptor's `contextWindow` (FEATURE_098)
700
- * 2. Provider config default
701
- * 3. 200_000 fallback
702
- * The user-level `compaction.contextWindow` is layered on top of
703
- * this at the call site, so it remains the highest-priority manual
704
- * override.
705
- */
706
- getEffectiveContextWindow(model?: string): number;
707
- protected getApiKey(): string;
708
- protected shouldLogStreamDiagnostics(): boolean;
709
- protected logStreamDiagnostic(...args: unknown[]): void;
710
- protected normalizeReasoning(reasoning?: boolean | KodaXReasoningRequest): Required<KodaXReasoningRequest>;
711
- /**
712
- * Called when ECONNRESET/EPIPE is detected, indicating a stale keep-alive
713
- * socket. Subclasses should override to rebuild their HTTP client with a
714
- * fresh connection pool so the next retry uses a new TCP connection.
715
- */
716
- protected onStaleConnection(): void;
717
- protected isRateLimitError(error: unknown): boolean;
718
- /**
719
- * FEATURE_130: classify a rate-limit error as either a 429-style
720
- * "rate-limit" or a 503/529-style "overloaded" condition. The
721
- * distinction matters for UI: "rate-limit" usually surfaces a
722
- * provider-supplied retry-after window; "overloaded" tends to fall
723
- * through to exponential backoff with no header. Both flow through
724
- * the same retry path; this only labels the event.
725
- */
726
- protected classifyRateLimitReason(error: unknown): 'rate-limit' | 'overloaded';
727
- /**
728
- * Extract Retry-After delay from error headers (429/529 responses).
729
- * Returns milliseconds, or undefined when no usable header is present.
730
- *
731
- * FEATURE_130 (v0.7.36): now delegates to the shared `parseRetryAfter`
732
- * helper so all 12 provider adapters get 4-form coverage without each
733
- * adapter rolling its own parser. The 4 forms supported are:
734
- * - `Retry-After: <integer-seconds>`
735
- * - `Retry-After: <HTTP-date>`
736
- * - `retry-after-ms: <milliseconds>` (Anthropic extension)
737
- * - exponential-backoff fallback (returned via `withRateLimit`,
738
- * not through this helper — it is `undefined` here when no
739
- * header is present, which the caller then resolves to backoff)
740
- */
741
- protected extractRetryAfterMs(error: unknown): number | undefined;
742
- /**
743
- * Detect "prompt too long / context window exceeded" errors and compute
744
- * a reduced max_tokens for retry. Returns undefined if not a context
745
- * overflow error.
746
- */
747
- protected parseContextOverflow(error: unknown): number | undefined;
748
- protected isContextOverflowError(error: unknown): boolean;
749
- protected withRateLimit<T>(fn: () => Promise<T>, signal?: AbortSignal, retries?: number, onRateLimit?: (attempt: number, maxRetries: number, delayMs: number) => void, onRetryAfter?: KodaXOnRetryAfterCallback): Promise<T>;
750
- }
751
-
752
- export { extractHeadersFromError as aa, parseRetryAfter as ab, KodaXBaseProvider as f };
753
- export type { KodaXToolDefinition as $, KodaXProviderMultimodalSupport as A, KodaXProviderSessionSupport as B, KodaXProviderStreamOptions as C, KodaXProviderToolCallingFidelity as D, KodaXProviderTransport as E, KodaXReasoningCapability as F, KodaXReasoningMode as G, KodaXReasoningOverride as H, KodaXReasoningRequest as I, KodaXRedactedThinkingBlock as J, KodaXAmaControllerDecision as K, KodaXRetryAfterEvent as L, KodaXReviewScale as M, KodaXRiskLevel as N, KodaXStreamResult as O, KodaXTaskActionability as P, KodaXTaskBudgetOverrides as Q, KodaXTaskComplexity as R, KodaXTaskFamily as S, KodaXTaskRoutingDecision as T, KodaXTaskType as U, KodaXTaskWorkIntent as V, KodaXTextBlock as W, KodaXThinkingBlock as X, KodaXThinkingBudgetMap as Y, KodaXThinkingDepth as Z, KodaXTokenUsage as _, KodaXAmaFanoutClass as a, KodaXToolResultBlock as a0, KodaXToolResultContentItem as a1, KodaXToolResultImageItem as a2, KodaXToolResultTextItem as a3, KodaXToolUseBlock as a4, KodaXVerifyCredentialResult as a5, KodaXVerifyStrategy as a6, ParseRetryAfterOptions as a7, RetryAfterResult as a8, RetryAfterSource as a9, KodaXAmaFanoutPolicy as b, KodaXAmaProfile as c, KodaXAmaTactic as d, KodaXAssuranceIntent as e, KodaXCacheBoundary as g, KodaXContentBlock as h, KodaXCustomProviderConfig as i, KodaXExecutionMode as j, KodaXExecutionPattern as k, KodaXHarnessProfile as l, KodaXImageBlock as m, KodaXListModelsResult as n, KodaXMessage as o, KodaXModelDescriptor as p, KodaXMutationSurface as q, KodaXOnRetryAfterCallback as r, KodaXProtocolFamily as s, KodaXProviderCapabilityProfile as t, KodaXProviderConfig as u, KodaXProviderContextFidelity as v, KodaXProviderConversationSemantics as w, KodaXProviderEvidenceSupport as x, KodaXProviderLongRunningSupport as y, KodaXProviderMcpSupport as z };
564
+ export type { KodaXToolResultBlock as $, KodaXReasoningCapability as A, KodaXReasoningEffortPreset as B, KodaXReasoningEffortRequest as C, KodaXReasoningEffortWireStrategy as D, KodaXReasoningMode as E, KodaXReasoningProfile as F, KodaXReasoningRequest as G, KodaXRedactedThinkingBlock as H, KodaXReviewScale as I, KodaXRiskLevel as J, KodaXAssuranceIntent as K, KodaXStableEffortIntent as L, KodaXStreamResult as M, KodaXTaskActionability as N, KodaXTaskBudgetOverrides as O, KodaXTaskComplexity as P, KodaXTaskFamily as Q, KodaXTaskRoutingDecision as R, KodaXTaskType as S, KodaXTaskWorkIntent as T, KodaXTextBlock as U, KodaXThinkingBlock as V, KodaXThinkingBudgetMap as W, KodaXThinkingDepth as X, KodaXThinkingWireStrategy as Y, KodaXTokenUsage as Z, KodaXToolDefinition as _, KodaXCacheBoundary as a, KodaXToolResultContentItem as a0, KodaXToolResultImageItem as a1, KodaXToolResultTextItem as a2, KodaXToolUseBlock as a3, KodaXVerifyCredentialResult as a4, KodaXVerifyStrategy as a5, KodaXWireReasoningEffort as a6, KodaXChildFanoutClass as b, KodaXContentBlock as c, KodaXCustomProviderConfig as d, KodaXExecutionMode as e, KodaXExecutionPattern as f, KodaXHarnessProfile as g, KodaXImageBlock as h, KodaXListModelsResult as i, KodaXMessage as j, KodaXModelDescriptor as k, KodaXMutationSurface as l, KodaXNormalizedReasoningRequest as m, KodaXProtocolFamily as n, KodaXProviderCapabilityProfile as o, KodaXProviderConfig as p, KodaXProviderContextFidelity as q, KodaXProviderConversationSemantics as r, KodaXProviderEvidenceSupport as s, KodaXProviderLongRunningSupport as t, KodaXProviderMcpSupport as u, KodaXProviderMultimodalSupport as v, KodaXProviderSessionSupport as w, KodaXProviderStreamOptions as x, KodaXProviderToolCallingFidelity as y, KodaXProviderTransport as z };
@@ -0,0 +1,143 @@
1
+ /**
2
+ * @kodax-ai/agent/messaging — Message queue types
3
+ *
4
+ * FEATURE_115 (v0.7.36): agentId-scoped 2-tier priority queue infrastructure.
5
+ *
6
+ * Per ADR-021: messaging is a generic agent-platform primitive (not coding-
7
+ * specific). Downstream consumers:
8
+ * - @kodax-ai/coding runner-driven mid-turn drain
9
+ * - @kodax-ai/repl InkREPL ESC soft-pause + text injection (FEATURE_111 absorbed)
10
+ * - subagent task-notification routing (FEATURE_155 idle-yield wakeup)
11
+ *
12
+ * Phase 0.6 study (`c:/tmp/claude-code-actual-usage.md`): Claude Code's
13
+ * `'now'` priority has zero production usage; KodaX simplifies to 2 tiers.
14
+ */
15
+ type MessagePriority = 'user' | 'background';
16
+ type MessageMode = 'prompt' | 'task-notification' | 'system-reminder';
17
+ type QueuedInputArtifact = {
18
+ readonly kind: 'image';
19
+ readonly path: string;
20
+ readonly mediaType?: string;
21
+ readonly source?: string;
22
+ readonly description?: string;
23
+ } | {
24
+ readonly kind: 'file';
25
+ readonly path: string;
26
+ readonly mediaType?: string;
27
+ readonly mimeType?: string;
28
+ readonly name?: string;
29
+ readonly source?: string;
30
+ readonly description?: string;
31
+ } | {
32
+ readonly kind: 'video';
33
+ readonly path: string;
34
+ readonly mediaType: string;
35
+ readonly name?: string;
36
+ readonly source?: string;
37
+ readonly description?: string;
38
+ };
39
+ interface QueuedMessage {
40
+ /** Stable id for tracing / dedup. Format: `msg-<sequence>`. */
41
+ readonly id: string;
42
+ readonly priority: MessagePriority;
43
+ /**
44
+ * Routing key:
45
+ * undefined = main thread / coordinator agent
46
+ * 'agent-id-XYZ' = subagent / specific consumer
47
+ *
48
+ * Drain consumers MUST filter by agentId match — undefined matches only
49
+ * undefined-agentId messages, not "any agent".
50
+ */
51
+ readonly agentId?: string;
52
+ readonly mode: MessageMode;
53
+ readonly content: string;
54
+ readonly inputArtifacts?: readonly QueuedInputArtifact[];
55
+ /** Wall-clock timestamp (`Date.now()`) for tracing only — not used for ordering. */
56
+ readonly enqueuedAt: number;
57
+ }
58
+ interface DequeueFilter {
59
+ /**
60
+ * Only return messages with this agentId.
61
+ * undefined matches messages with no agentId (main-thread messages only).
62
+ */
63
+ readonly agentId?: string;
64
+ /**
65
+ * Highest priority level included in the drain.
66
+ * 'user' → only user priority drained, background stays queued
67
+ * 'background' → both user + background drained (Sleep-gated case)
68
+ */
69
+ readonly maxPriority: MessagePriority;
70
+ /**
71
+ * Optional cap on number of messages drained in this call.
72
+ * Defaults to unlimited (drains all matching).
73
+ */
74
+ readonly limit?: number;
75
+ /**
76
+ * FEATURE_159 (v0.7.40) — optional mode filter. Lets REPL split the
77
+ * single queue into mode-typed views (e.g. `mode:'prompt'` for user
78
+ * input vs `mode:'task-notification'` for child completion banners)
79
+ * without separate queues. When omitted, all modes match.
80
+ */
81
+ readonly mode?: MessageMode;
82
+ /**
83
+ * FEATURE_159 (v0.7.40) — optional precise-id filter. Single-message
84
+ * targeted removal — drives Esc-pop-this-uuid in REPL. When set, all
85
+ * other filters still apply (agentId / priority / mode mismatches still
86
+ * skip the message), so callers can't accidentally remove a message
87
+ * outside their scope.
88
+ */
89
+ readonly id?: string;
90
+ /**
91
+ * FEATURE_159 (v0.7.40) — optional escape-hatch predicate, AND-ed with
92
+ * the structured filters. Lets SDK consumers express conditions the
93
+ * typed fields don't cover (e.g. timestamp ranges, content-match) without
94
+ * forcing every new use case to extend `DequeueFilter`. KodaX-internal
95
+ * code should prefer the typed fields for readability; this is the
96
+ * "data-driven main path + predicate escape" pattern.
97
+ *
98
+ * Evaluated AFTER the typed filters succeed — so a `predicate` that
99
+ * inspects `message.content` never runs on messages outside the
100
+ * caller's `agentId` / `mode` / `id` scope.
101
+ */
102
+ readonly predicate?: (message: QueuedMessage) => boolean;
103
+ }
104
+ /**
105
+ * FEATURE_159 (v0.7.40) — structured queue event emitted to subscribers.
106
+ *
107
+ * Replaces the prior `() => void` bare-notify signal. Carries the kind +
108
+ * affected messages so SDK observability consumers (logging, tracing,
109
+ * metrics) can react per-event without re-diffing snapshots.
110
+ *
111
+ * Event granularity rules:
112
+ * - `enqueued` fires ONCE per `enqueue()` call (always 1 message).
113
+ * - `dequeued` fires ONCE per `dequeue()` call that removed ≥1 message,
114
+ * carrying ALL drained messages in priority+FIFO order. No-op drains
115
+ * (filter matched nothing) fire no event — quiet by design so the
116
+ * `waitForWakeEvent` 100ms poll doesn't spam idle subscribers.
117
+ * - `cleared` fires ONCE per `clear()` call that removed ≥1 message,
118
+ * carrying the pre-clear messages. Empty-queue clear fires nothing.
119
+ *
120
+ * The `useSyncExternalStore` React hook ignores the event payload (it
121
+ * only needs the change signal); SDK / tracer consumers read the event.
122
+ */
123
+ type QueueEvent = {
124
+ readonly kind: 'enqueued';
125
+ readonly message: QueuedMessage;
126
+ } | {
127
+ readonly kind: 'dequeued';
128
+ readonly messages: readonly QueuedMessage[];
129
+ } | {
130
+ readonly kind: 'cleared';
131
+ readonly messages: readonly QueuedMessage[];
132
+ };
133
+ /** FEATURE_159 — `MessageQueue.subscribe` listener signature. */
134
+ type QueueEventListener = (event: QueueEvent) => void;
135
+ interface EnqueueInput {
136
+ readonly priority: MessagePriority;
137
+ readonly mode: MessageMode;
138
+ readonly content: string;
139
+ readonly agentId?: string;
140
+ readonly inputArtifacts?: readonly QueuedInputArtifact[];
141
+ }
142
+
143
+ export type { DequeueFilter as D, EnqueueInput as E, MessageMode as M, QueueEventListener as Q, MessagePriority as a, QueuedInputArtifact as b, QueuedMessage as c };