open-multi-agent-kit 0.79.3 → 0.80.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (124) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/MATURITY.md +2 -2
  3. package/README.md +86 -39
  4. package/ROADMAP.md +20 -17
  5. package/dist/brand/night-city.theme.json +122 -24
  6. package/dist/brand/rust-forge.theme.json +1 -1
  7. package/dist/commands/chat/native-root-loop.d.ts +27 -3
  8. package/dist/commands/chat/native-root-loop.js +375 -49
  9. package/dist/commands/dag.js +45 -0
  10. package/dist/commands/init/content.d.ts +1 -1
  11. package/dist/commands/init/content.js +3 -3
  12. package/dist/commands/init.js +3 -3
  13. package/dist/commands/verify.js +59 -1
  14. package/dist/contracts/dag.d.ts +9 -1
  15. package/dist/evidence/graph-ontology-relation-gate.d.ts +10 -0
  16. package/dist/evidence/graph-ontology-relation-gate.js +46 -0
  17. package/dist/evidence/headroom-replay-verifier.d.ts +19 -0
  18. package/dist/evidence/headroom-replay-verifier.js +86 -0
  19. package/dist/memory/local-graph-memory-store.d.ts +75 -0
  20. package/dist/memory/local-graph-memory-store.js +570 -0
  21. package/dist/orchestration/dag.d.ts +22 -1
  22. package/dist/orchestration/evidence-gate.js +12 -0
  23. package/dist/orchestration/executor.js +108 -15
  24. package/dist/orchestration/loop-controller-headroom.d.ts +6 -0
  25. package/dist/orchestration/loop-controller-headroom.js +33 -0
  26. package/dist/orchestration/scheduler.d.ts +2 -0
  27. package/dist/orchestration/scheduler.js +3 -0
  28. package/dist/orchestration/task-graph.d.ts +17 -0
  29. package/dist/orchestration/task-graph.js +38 -0
  30. package/dist/providers/codex-cli-runner.js +17 -2
  31. package/dist/runtime/agent-runtime.d.ts +32 -3
  32. package/dist/runtime/agent-runtime.js +20 -7
  33. package/dist/runtime/authority-matrix.d.ts +23 -0
  34. package/dist/runtime/authority-matrix.js +159 -0
  35. package/dist/runtime/chat-advisory-runtime.js +3 -0
  36. package/dist/runtime/codex-cli-runtime.js +2 -0
  37. package/dist/runtime/codex-runtime.d.ts +4 -1
  38. package/dist/runtime/codex-runtime.js +34 -12
  39. package/dist/runtime/context-broker-converter.js +32 -2
  40. package/dist/runtime/context-broker.js +18 -0
  41. package/dist/runtime/contracts/evidence.d.ts +52 -0
  42. package/dist/runtime/contracts/evidence.js +128 -1
  43. package/dist/runtime/contracts/shared.d.ts +27 -0
  44. package/dist/runtime/data-retention-gate.d.ts +42 -0
  45. package/dist/runtime/data-retention-gate.js +123 -0
  46. package/dist/runtime/deepseek-runtime.d.ts +5 -1
  47. package/dist/runtime/deepseek-runtime.js +13 -7
  48. package/dist/runtime/external-cli-adapter.js +20 -7
  49. package/dist/runtime/freedomd-evidence-envelope.d.ts +57 -0
  50. package/dist/runtime/freedomd-evidence-envelope.js +110 -0
  51. package/dist/runtime/freedomd-exception.d.ts +32 -0
  52. package/dist/runtime/freedomd-exception.js +95 -0
  53. package/dist/runtime/freedomd-incidents.d.ts +23 -0
  54. package/dist/runtime/freedomd-incidents.js +103 -0
  55. package/dist/runtime/freedomd-policy.d.ts +35 -0
  56. package/dist/runtime/freedomd-policy.js +114 -0
  57. package/dist/runtime/freedomd-router.d.ts +66 -0
  58. package/dist/runtime/freedomd-router.js +433 -0
  59. package/dist/runtime/headroom-aware-loop-decision.d.ts +21 -0
  60. package/dist/runtime/headroom-aware-loop-decision.js +67 -0
  61. package/dist/runtime/headroom-loop-risk.d.ts +19 -0
  62. package/dist/runtime/headroom-loop-risk.js +43 -0
  63. package/dist/runtime/headroom-policy.d.ts +14 -1
  64. package/dist/runtime/headroom-policy.js +74 -12
  65. package/dist/runtime/kimi-api-runtime.d.ts +4 -1
  66. package/dist/runtime/kimi-api-runtime.js +35 -11
  67. package/dist/runtime/kimi-print-runtime.js +21 -0
  68. package/dist/runtime/kimi-wire-protocol-runtime.js +17 -1
  69. package/dist/runtime/local-llm-runtime.d.ts +5 -1
  70. package/dist/runtime/local-llm-runtime.js +14 -23
  71. package/dist/runtime/private-stderr.d.ts +13 -0
  72. package/dist/runtime/private-stderr.js +69 -0
  73. package/dist/runtime/prompt-envelope.d.ts +1 -1
  74. package/dist/runtime/provider-sovereignty.d.ts +81 -0
  75. package/dist/runtime/provider-sovereignty.js +285 -0
  76. package/dist/runtime/runtime-backed-task-runner.d.ts +1 -0
  77. package/dist/runtime/runtime-backed-task-runner.js +282 -10
  78. package/dist/runtime/runtime-bootstrap.d.ts +12 -0
  79. package/dist/runtime/runtime-bootstrap.js +56 -3
  80. package/dist/runtime/runtime-failure-classifier.d.ts +15 -0
  81. package/dist/runtime/runtime-failure-classifier.js +107 -0
  82. package/dist/runtime/runtime-health-probes.d.ts +30 -0
  83. package/dist/runtime/runtime-health-probes.js +102 -0
  84. package/dist/runtime/runtime-router.d.ts +6 -2
  85. package/dist/runtime/runtime-router.js +575 -53
  86. package/dist/runtime/structured-compaction.d.ts +107 -0
  87. package/dist/runtime/structured-compaction.js +414 -0
  88. package/dist/runtime/tool-dispatch-contracts.d.ts +7 -5
  89. package/dist/runtime/tool-dispatch-contracts.js +15 -4
  90. package/dist/runtime/tool-plane.d.ts +1 -1
  91. package/dist/runtime/tool-plane.js +49 -1
  92. package/dist/runtime/worker-manifest.js +1 -1
  93. package/dist/schema/evidence-bundle.schema.d.ts +8 -8
  94. package/dist/schema/proof-bundle.schema.d.ts +2 -2
  95. package/dist/util/hash.d.ts +2 -0
  96. package/dist/util/hash.js +13 -0
  97. package/dist/util/session.js +6 -5
  98. package/docs/2026-06-16/critical-issues.md +19 -0
  99. package/docs/2026-06-16/improvements.md +15 -0
  100. package/docs/2026-06-16/init-checklist.md +25 -0
  101. package/docs/2026-06-16/plan.md +20 -0
  102. package/docs/ARCHITECTURE_ANALYSIS_CODEGRAPH.md +2 -1
  103. package/docs/GSTACK_MIGRATION.md +1 -1
  104. package/docs/algorithm-hardening-playbook.md +219 -0
  105. package/docs/claims.md +1 -1
  106. package/docs/getting-started.md +1 -1
  107. package/docs/native-root-runtime-hardening.md +42 -32
  108. package/docs/post-0793-hardening-roadmap.md +123 -0
  109. package/docs/provider-maturity.md +18 -16
  110. package/docs/versioning.md +3 -3
  111. package/docs/what-is-omk.md +1 -1
  112. package/package.json +8 -4
  113. package/readmeasset/.npmignore +2 -0
  114. package/readmeasset/ASSET_INDEX.md +2 -0
  115. package/readmeasset/ASSET_PROVENANCE.md +40 -20
  116. package/readmeasset/omk-adaptorch-ouroboros-supermemory.svg +1 -1
  117. package/readmeasset/omk-control-surfaces.svg +1 -1
  118. package/readmeasset/omk-core-loop.svg +1 -1
  119. package/readmeasset/omk-freedomd-control-plane.svg +59 -0
  120. package/readmeasset/omk-freedomd-control-plane.webp +0 -0
  121. package/readmeasset/omk-init-control-loop.svg +1 -1
  122. package/readmeasset/omk-logo-mark.svg +1 -1
  123. package/readmeasset/omk-parallel-subagents.svg +1 -1
  124. package/readmeasset/omk-release-assertions.svg +1 -1
@@ -134,8 +134,25 @@ async function resolveAutoProvider(env) {
134
134
  export async function resolveRuntimeBootstrap(options) {
135
135
  const providerPolicy = options.provider.trim().toLowerCase() || "auto";
136
136
  const env = options.env ?? process.env;
137
- const authorityProvider = resolveAuthorityProviderPolicy(providerPolicy, env);
138
- const effectiveProviderPolicy = authorityProvider ?? providerPolicy;
137
+ const resolvedPolicy = await resolveProviderPolicy(providerPolicy, env);
138
+ if (!resolvedPolicy.ok) {
139
+ return {
140
+ ok: false,
141
+ provider: providerPolicy,
142
+ providerPolicy,
143
+ selectedProvider: providerPolicy,
144
+ selectedRuntimeId: "unresolved",
145
+ selectedModel: options.model,
146
+ sessionMode: "advisory-only",
147
+ authOk: false,
148
+ modelOk: false,
149
+ runtimeOk: false,
150
+ reason: resolvedPolicy.reason,
151
+ setupHints: resolvedPolicy.remediation,
152
+ };
153
+ }
154
+ const authorityProvider = resolvedPolicy.provider;
155
+ const effectiveProviderPolicy = authorityProvider;
139
156
  const autoSelection = effectiveProviderPolicy === "auto" ? await resolveAutoProvider(env) : undefined;
140
157
  const selectedProvider = autoSelection?.provider ?? effectiveProviderPolicy;
141
158
  const info = detectProvider(selectedProvider, env);
@@ -185,7 +202,7 @@ export async function resolveRuntimeBootstrap(options) {
185
202
  provider: selectedProvider,
186
203
  providerPolicy,
187
204
  selectedProvider,
188
- selectedRuntimeId: autoSelection?.runtimeId ?? info.bin ?? info.envKey ?? "auto",
205
+ selectedRuntimeId: autoSelection?.runtimeId ?? resolvedPolicy.runtimeId ?? info.bin ?? info.envKey ?? "auto",
189
206
  selectedModel: options.model ?? info.modelHint,
190
207
  sessionMode: info.sessionMode,
191
208
  authOk,
@@ -212,6 +229,42 @@ function providerConfigHasApiKey(configContent, provider) {
212
229
  function escapeRegExp(value) {
213
230
  return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
214
231
  }
232
+ export async function resolveProviderPolicy(providerPolicy, env) {
233
+ const normalized = providerPolicy.trim().toLowerCase() || "auto";
234
+ if (!["authority", "primary", "omk"].includes(normalized)) {
235
+ return { ok: true, provider: normalized };
236
+ }
237
+ const configured = env.OMK_AUTHORITY_PROVIDER?.trim().toLowerCase()
238
+ || env.OMK_DEFAULT_PROVIDER?.trim().toLowerCase();
239
+ if (configured && !["authority", "primary", "omk"].includes(configured)) {
240
+ return { ok: true, provider: configured, reason: `resolved from OMK_AUTHORITY_PROVIDER` };
241
+ }
242
+ // Default authority chain: mimo > kimi > auto
243
+ if (env.MIMO_API_KEY || (await hasProviderConfigApiKey(env, "mimo"))) {
244
+ return { ok: true, provider: "mimo", runtimeId: "mimo-api", reason: "default authority resolved to mimo" };
245
+ }
246
+ if (env.KIMI_API_KEY || (await hasProviderConfigApiKey(env, "kimi"))) {
247
+ return { ok: true, provider: "kimi", runtimeId: "kimi-api", reason: "default authority resolved to kimi" };
248
+ }
249
+ const auto = await resolveAutoProvider(env);
250
+ if (auto) {
251
+ return { ok: true, provider: auto.provider, runtimeId: auto.runtimeId, reason: "authority fell back to auto-selected provider" };
252
+ }
253
+ return {
254
+ ok: false,
255
+ provider: normalized,
256
+ reason: "no authority provider is configured or healthy",
257
+ remediation: [
258
+ "Set OMK_AUTHORITY_PROVIDER to a concrete provider (e.g. mimo, kimi, codex).",
259
+ "Set the provider API key env var (e.g. MIMO_API_KEY, KIMI_API_KEY).",
260
+ "Or configure [providers.<name>] api_key in ~/.omk/config.toml.",
261
+ ],
262
+ };
263
+ }
264
+ async function hasProviderConfigApiKey(env, provider) {
265
+ const configContent = readHomeProviderConfig(env, ".omk");
266
+ return configContent ? providerConfigHasApiKey(configContent, provider) : false;
267
+ }
215
268
  function resolveAuthorityProviderPolicy(providerPolicy, env) {
216
269
  if (providerPolicy !== "authority" && providerPolicy !== "primary" && providerPolicy !== "omk")
217
270
  return undefined;
@@ -0,0 +1,15 @@
1
+ export type RuntimeFailureClass = "none" | "runtime" | "auth" | "model" | "quota" | "rate_limit" | "timeout" | "authority" | "abort" | "transient" | "unknown";
2
+ export interface RuntimeFailureClassification {
3
+ readonly failureClass: RuntimeFailureClass;
4
+ readonly retryable: boolean;
5
+ readonly circuitBreaker: boolean;
6
+ readonly cooldownMs: number;
7
+ readonly reason: string;
8
+ }
9
+ export interface RuntimeFailureInput {
10
+ readonly exitCode?: number;
11
+ readonly stdout?: string;
12
+ readonly stderr?: string;
13
+ readonly metadata?: Readonly<Record<string, unknown>>;
14
+ }
15
+ export declare function classifyRuntimeFailure(input: RuntimeFailureInput): RuntimeFailureClassification;
@@ -0,0 +1,107 @@
1
+ import { maskSensitiveText } from "../util/secret-mask.js";
2
+ const DEFAULT_COOLDOWNS = {
3
+ runtime: 120_000,
4
+ auth: 300_000,
5
+ model: 300_000,
6
+ quota: 300_000,
7
+ rate_limit: 60_000,
8
+ timeout: 45_000,
9
+ authority: 120_000,
10
+ abort: 0,
11
+ transient: 30_000,
12
+ unknown: 0,
13
+ };
14
+ const RETRYABLE_FAILURES = new Set(["runtime", "rate_limit", "timeout", "transient"]);
15
+ const CIRCUIT_BREAKER_FAILURES = new Set([
16
+ "runtime",
17
+ "auth",
18
+ "model",
19
+ "quota",
20
+ "rate_limit",
21
+ "timeout",
22
+ "authority",
23
+ "transient",
24
+ ]);
25
+ export function classifyRuntimeFailure(input) {
26
+ const metadataClass = normalizeFailureClass(input.metadata?.failureClass ?? input.metadata?.failureKind ?? nestedFailureKind(input.metadata?.providerFallback));
27
+ const failureClass = metadataClass ?? classifyRuntimeFailureFromSignals(input);
28
+ if (failureClass === "none") {
29
+ return { failureClass, retryable: false, circuitBreaker: false, cooldownMs: 0, reason: "runtime result succeeded" };
30
+ }
31
+ return {
32
+ failureClass,
33
+ retryable: RETRYABLE_FAILURES.has(failureClass),
34
+ circuitBreaker: CIRCUIT_BREAKER_FAILURES.has(failureClass),
35
+ cooldownMs: DEFAULT_COOLDOWNS[failureClass],
36
+ reason: reasonForFailureClass(failureClass),
37
+ };
38
+ }
39
+ function classifyRuntimeFailureFromSignals(input) {
40
+ if (input.exitCode === 0)
41
+ return "none";
42
+ if (input.exitCode === 130)
43
+ return "abort";
44
+ if (input.exitCode === 78)
45
+ return "authority";
46
+ const text = maskSensitiveText(`${input.stderr ?? ""}\n${input.stdout ?? ""}`).toLowerCase();
47
+ if (/\b(unauthorized|forbidden|invalid api key|api key|authentication|auth failed|permission denied|401|403)\b/.test(text))
48
+ return "auth";
49
+ if (/\b(insufficient balance|quota|billing|payment required|402|credit exhausted)\b/.test(text))
50
+ return "quota";
51
+ if (/\b(rate[-\s_]*limit|too many requests|429)\b/.test(text))
52
+ return "rate_limit";
53
+ if (/\b(timeout|timed out|etimedout|deadline exceeded)\b/.test(text))
54
+ return "timeout";
55
+ if (/\b(model not found|unknown model|invalid model|model unavailable|404 model)\b/.test(text))
56
+ return "model";
57
+ if (/\b(command not found|enoent|spawn .* failed|runtime unavailable|binary missing|not installed)\b/.test(text))
58
+ return "runtime";
59
+ if (/\b(econnreset|econnrefused|network|temporarily unavailable|503|502|504|5\d\d)\b/.test(text))
60
+ return "transient";
61
+ return "unknown";
62
+ }
63
+ function normalizeFailureClass(value) {
64
+ if (typeof value !== "string")
65
+ return undefined;
66
+ const normalized = value.trim().toLowerCase().replace(/[\s-]+/g, "_");
67
+ switch (normalized) {
68
+ case "none":
69
+ case "runtime":
70
+ case "auth":
71
+ case "model":
72
+ case "quota":
73
+ case "rate_limit":
74
+ case "timeout":
75
+ case "authority":
76
+ case "abort":
77
+ case "transient":
78
+ case "unknown":
79
+ return normalized;
80
+ case "availability":
81
+ return "runtime";
82
+ case "policy":
83
+ return "authority";
84
+ default:
85
+ return undefined;
86
+ }
87
+ }
88
+ function nestedFailureKind(value) {
89
+ if (!value || typeof value !== "object")
90
+ return undefined;
91
+ return value.failureKind;
92
+ }
93
+ function reasonForFailureClass(failureClass) {
94
+ switch (failureClass) {
95
+ case "runtime": return "runtime unavailable or adapter launch failed";
96
+ case "auth": return "runtime authentication failed";
97
+ case "model": return "runtime model is unavailable or invalid";
98
+ case "quota": return "runtime quota or billing is exhausted";
99
+ case "rate_limit": return "runtime rate limit was reached";
100
+ case "timeout": return "runtime timed out";
101
+ case "authority": return "runtime authority or policy boundary blocked execution";
102
+ case "abort": return "runtime execution was aborted";
103
+ case "transient": return "transient runtime or network failure";
104
+ case "unknown": return "unclassified runtime failure";
105
+ case "none": return "runtime result succeeded";
106
+ }
107
+ }
@@ -0,0 +1,30 @@
1
+ import type { RuntimeHealth, RuntimeHealthProbeKind } from "./contracts/shared.js";
2
+ export interface RuntimeHealthProbeInput {
3
+ readonly probeKind?: RuntimeHealthProbeKind;
4
+ readonly timeoutMs?: number;
5
+ readonly highRisk?: boolean;
6
+ }
7
+ export interface StaticHealthInput {
8
+ readonly runtimeId: string;
9
+ readonly available: boolean;
10
+ readonly reason?: string;
11
+ readonly authOk?: boolean;
12
+ readonly modelOk?: boolean;
13
+ readonly runtimeOk?: boolean;
14
+ readonly quotaOk?: boolean;
15
+ readonly rateLimitOk?: boolean;
16
+ readonly probeKind?: RuntimeHealthProbeKind;
17
+ readonly ttlMs?: number;
18
+ readonly latencyMs?: number;
19
+ }
20
+ export declare function staticRuntimeHealth(input: StaticHealthInput): RuntimeHealth;
21
+ export declare function probeOpenAiCompatibleModels(input: {
22
+ readonly runtimeId: string;
23
+ readonly baseUrl: string;
24
+ readonly apiKey?: string;
25
+ readonly apiKeyName: string;
26
+ readonly model: string;
27
+ readonly providerName: string;
28
+ readonly probeKind: RuntimeHealthProbeKind;
29
+ readonly timeoutMs?: number;
30
+ }): Promise<RuntimeHealth>;
@@ -0,0 +1,102 @@
1
+ import { maskSensitiveText } from "../util/secret-mask.js";
2
+ export function staticRuntimeHealth(input) {
3
+ const now = new Date();
4
+ const runtimeOk = input.runtimeOk ?? input.available;
5
+ const authOk = input.authOk ?? input.available;
6
+ const modelOk = input.modelOk ?? input.available;
7
+ const quotaOk = input.quotaOk ?? true;
8
+ const rateLimitOk = input.rateLimitOk ?? true;
9
+ return {
10
+ runtimeId: input.runtimeId,
11
+ available: input.available,
12
+ reason: input.reason,
13
+ checkedAt: now.toISOString(),
14
+ vector: {
15
+ runtimeOk,
16
+ authOk,
17
+ modelOk,
18
+ quotaOk,
19
+ rateLimitOk,
20
+ runtime: runtimeOk ? "pass" : "fail",
21
+ auth: authOk ? "pass" : "fail",
22
+ model: modelOk ? "pass" : "fail",
23
+ quota: quotaOk ? "unknown" : "fail",
24
+ rateLimit: rateLimitOk ? "unknown" : "fail",
25
+ ...(input.latencyMs !== undefined && { latencyMs: input.latencyMs }),
26
+ lastProbeKind: input.probeKind ?? "static",
27
+ checkedAt: now.toISOString(),
28
+ expiresAt: new Date(now.getTime() + (input.ttlMs ?? 60_000)).toISOString(),
29
+ },
30
+ };
31
+ }
32
+ export async function probeOpenAiCompatibleModels(input) {
33
+ const staticAuthOk = Boolean(input.apiKey);
34
+ const staticModelOk = input.model.trim().length > 0 && input.model !== "default";
35
+ if (!staticAuthOk || !staticModelOk || input.probeKind === "static" || input.probeKind === "none") {
36
+ const reason = !staticAuthOk
37
+ ? `${input.apiKeyName} is not set`
38
+ : !staticModelOk
39
+ ? `${input.providerName} model is not configured`
40
+ : undefined;
41
+ return staticRuntimeHealth({
42
+ runtimeId: input.runtimeId,
43
+ available: staticAuthOk && staticModelOk,
44
+ reason,
45
+ authOk: staticAuthOk,
46
+ modelOk: staticModelOk,
47
+ runtimeOk: true,
48
+ probeKind: input.probeKind === "none" ? "static" : input.probeKind,
49
+ });
50
+ }
51
+ const started = Date.now();
52
+ const controller = new AbortController();
53
+ const timeout = setTimeout(() => controller.abort(), input.timeoutMs ?? 5000);
54
+ try {
55
+ const response = await fetch(`${input.baseUrl.replace(/\/+$/, "")}/models`, {
56
+ method: "GET",
57
+ headers: { Authorization: `Bearer ${input.apiKey}` },
58
+ signal: controller.signal,
59
+ });
60
+ const latencyMs = Date.now() - started;
61
+ const authOk = response.status !== 401 && response.status !== 403;
62
+ const rateLimitOk = response.status !== 429;
63
+ const quotaOk = response.status !== 402;
64
+ const modelOk = staticModelOk && response.status !== 404;
65
+ const runtimeOk = response.status < 500;
66
+ const available = response.ok && authOk && modelOk && quotaOk && rateLimitOk;
67
+ const reason = available ? undefined : `${input.providerName} health probe returned ${response.status}`;
68
+ return staticRuntimeHealth({
69
+ runtimeId: input.runtimeId,
70
+ available,
71
+ reason,
72
+ authOk,
73
+ modelOk,
74
+ runtimeOk,
75
+ quotaOk,
76
+ rateLimitOk,
77
+ latencyMs,
78
+ probeKind: input.probeKind,
79
+ ttlMs: 30_000,
80
+ });
81
+ }
82
+ catch (err) {
83
+ const latencyMs = Date.now() - started;
84
+ const reason = maskSensitiveText(err instanceof Error ? err.message : String(err));
85
+ return staticRuntimeHealth({
86
+ runtimeId: input.runtimeId,
87
+ available: false,
88
+ reason: `${input.providerName} health probe failed: ${reason}`,
89
+ authOk: staticAuthOk,
90
+ modelOk: staticModelOk,
91
+ runtimeOk: false,
92
+ quotaOk: true,
93
+ rateLimitOk: true,
94
+ latencyMs,
95
+ probeKind: input.probeKind,
96
+ ttlMs: 30_000,
97
+ });
98
+ }
99
+ finally {
100
+ clearTimeout(timeout);
101
+ }
102
+ }
@@ -7,16 +7,20 @@
7
7
  * 3. Historical evidence pass rates from graph-state memory
8
8
  * 4. Fallback chain with runtime.supports() check
9
9
  */
10
- import type { AgentRuntime, AgentRunResult, AgentTask } from "./agent-runtime.js";
10
+ import type { AgentRuntime, AgentRunResult, AgentTask, RuntimeHealth } from "./agent-runtime.js";
11
11
  import type { ContextCapsule } from "./context-capsule.js";
12
+ import type { RuntimeHealthProbeKind } from "./contracts/shared.js";
12
13
  export type NodeIntent = "research" | "planning" | "coding" | "debugging" | "refactor" | "review" | "test-generation" | "documentation" | "shell-operation";
13
14
  export interface RuntimeScore {
14
15
  readonly runtime: string;
15
16
  readonly qualityScore: number;
16
17
  readonly costScore: number;
17
18
  readonly latencyScore: number;
19
+ readonly healthScore: number;
18
20
  readonly evidencePassRate: number;
19
21
  readonly recentFailurePenalty: number;
22
+ readonly healthAvailable?: boolean;
23
+ readonly healthReason?: string;
20
24
  }
21
25
  export interface RuntimeRouterOptions {
22
26
  readonly runtimes?: AgentRuntime[];
@@ -39,7 +43,7 @@ interface EvidenceHistoryEntry {
39
43
  }
40
44
  export declare function createRuntimeRouter(options?: RuntimeRouterOptions): {
41
45
  select: (capsule: ContextCapsule) => RuntimeRouteDecision;
42
- selectByIntent: (capsule: ContextCapsule, history: EvidenceHistoryEntry[]) => RuntimeRouteDecision;
46
+ selectByIntent: (capsule: ContextCapsule, history: EvidenceHistoryEntry[], healthMap?: ReadonlyMap<string, RuntimeHealth>, probeKind?: RuntimeHealthProbeKind) => RuntimeRouteDecision;
43
47
  runNode: (capsule: ContextCapsule, signal: AbortSignal) => Promise<AgentRunResult>;
44
48
  execute: (task: AgentTask, signal?: AbortSignal) => Promise<AgentRunResult>;
45
49
  executeTask: (task: AgentTask, capsule: ContextCapsule, signal: AbortSignal) => Promise<AgentRunResult>;