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.
- package/CHANGELOG.md +22 -0
- package/MATURITY.md +2 -2
- package/README.md +86 -39
- package/ROADMAP.md +20 -17
- package/dist/brand/night-city.theme.json +122 -24
- package/dist/brand/rust-forge.theme.json +1 -1
- package/dist/commands/chat/native-root-loop.d.ts +27 -3
- package/dist/commands/chat/native-root-loop.js +375 -49
- package/dist/commands/dag.js +45 -0
- package/dist/commands/init/content.d.ts +1 -1
- package/dist/commands/init/content.js +3 -3
- package/dist/commands/init.js +3 -3
- package/dist/commands/verify.js +59 -1
- package/dist/contracts/dag.d.ts +9 -1
- package/dist/evidence/graph-ontology-relation-gate.d.ts +10 -0
- package/dist/evidence/graph-ontology-relation-gate.js +46 -0
- package/dist/evidence/headroom-replay-verifier.d.ts +19 -0
- package/dist/evidence/headroom-replay-verifier.js +86 -0
- package/dist/memory/local-graph-memory-store.d.ts +75 -0
- package/dist/memory/local-graph-memory-store.js +570 -0
- package/dist/orchestration/dag.d.ts +22 -1
- package/dist/orchestration/evidence-gate.js +12 -0
- package/dist/orchestration/executor.js +108 -15
- package/dist/orchestration/loop-controller-headroom.d.ts +6 -0
- package/dist/orchestration/loop-controller-headroom.js +33 -0
- package/dist/orchestration/scheduler.d.ts +2 -0
- package/dist/orchestration/scheduler.js +3 -0
- package/dist/orchestration/task-graph.d.ts +17 -0
- package/dist/orchestration/task-graph.js +38 -0
- package/dist/providers/codex-cli-runner.js +17 -2
- package/dist/runtime/agent-runtime.d.ts +32 -3
- package/dist/runtime/agent-runtime.js +20 -7
- package/dist/runtime/authority-matrix.d.ts +23 -0
- package/dist/runtime/authority-matrix.js +159 -0
- package/dist/runtime/chat-advisory-runtime.js +3 -0
- package/dist/runtime/codex-cli-runtime.js +2 -0
- package/dist/runtime/codex-runtime.d.ts +4 -1
- package/dist/runtime/codex-runtime.js +34 -12
- package/dist/runtime/context-broker-converter.js +32 -2
- package/dist/runtime/context-broker.js +18 -0
- package/dist/runtime/contracts/evidence.d.ts +52 -0
- package/dist/runtime/contracts/evidence.js +128 -1
- package/dist/runtime/contracts/shared.d.ts +27 -0
- package/dist/runtime/data-retention-gate.d.ts +42 -0
- package/dist/runtime/data-retention-gate.js +123 -0
- package/dist/runtime/deepseek-runtime.d.ts +5 -1
- package/dist/runtime/deepseek-runtime.js +13 -7
- package/dist/runtime/external-cli-adapter.js +20 -7
- package/dist/runtime/freedomd-evidence-envelope.d.ts +57 -0
- package/dist/runtime/freedomd-evidence-envelope.js +110 -0
- package/dist/runtime/freedomd-exception.d.ts +32 -0
- package/dist/runtime/freedomd-exception.js +95 -0
- package/dist/runtime/freedomd-incidents.d.ts +23 -0
- package/dist/runtime/freedomd-incidents.js +103 -0
- package/dist/runtime/freedomd-policy.d.ts +35 -0
- package/dist/runtime/freedomd-policy.js +114 -0
- package/dist/runtime/freedomd-router.d.ts +66 -0
- package/dist/runtime/freedomd-router.js +433 -0
- package/dist/runtime/headroom-aware-loop-decision.d.ts +21 -0
- package/dist/runtime/headroom-aware-loop-decision.js +67 -0
- package/dist/runtime/headroom-loop-risk.d.ts +19 -0
- package/dist/runtime/headroom-loop-risk.js +43 -0
- package/dist/runtime/headroom-policy.d.ts +14 -1
- package/dist/runtime/headroom-policy.js +74 -12
- package/dist/runtime/kimi-api-runtime.d.ts +4 -1
- package/dist/runtime/kimi-api-runtime.js +35 -11
- package/dist/runtime/kimi-print-runtime.js +21 -0
- package/dist/runtime/kimi-wire-protocol-runtime.js +17 -1
- package/dist/runtime/local-llm-runtime.d.ts +5 -1
- package/dist/runtime/local-llm-runtime.js +14 -23
- package/dist/runtime/private-stderr.d.ts +13 -0
- package/dist/runtime/private-stderr.js +69 -0
- package/dist/runtime/prompt-envelope.d.ts +1 -1
- package/dist/runtime/provider-sovereignty.d.ts +81 -0
- package/dist/runtime/provider-sovereignty.js +285 -0
- package/dist/runtime/runtime-backed-task-runner.d.ts +1 -0
- package/dist/runtime/runtime-backed-task-runner.js +282 -10
- package/dist/runtime/runtime-bootstrap.d.ts +12 -0
- package/dist/runtime/runtime-bootstrap.js +56 -3
- package/dist/runtime/runtime-failure-classifier.d.ts +15 -0
- package/dist/runtime/runtime-failure-classifier.js +107 -0
- package/dist/runtime/runtime-health-probes.d.ts +30 -0
- package/dist/runtime/runtime-health-probes.js +102 -0
- package/dist/runtime/runtime-router.d.ts +6 -2
- package/dist/runtime/runtime-router.js +575 -53
- package/dist/runtime/structured-compaction.d.ts +107 -0
- package/dist/runtime/structured-compaction.js +414 -0
- package/dist/runtime/tool-dispatch-contracts.d.ts +7 -5
- package/dist/runtime/tool-dispatch-contracts.js +15 -4
- package/dist/runtime/tool-plane.d.ts +1 -1
- package/dist/runtime/tool-plane.js +49 -1
- package/dist/runtime/worker-manifest.js +1 -1
- package/dist/schema/evidence-bundle.schema.d.ts +8 -8
- package/dist/schema/proof-bundle.schema.d.ts +2 -2
- package/dist/util/hash.d.ts +2 -0
- package/dist/util/hash.js +13 -0
- package/dist/util/session.js +6 -5
- package/docs/2026-06-16/critical-issues.md +19 -0
- package/docs/2026-06-16/improvements.md +15 -0
- package/docs/2026-06-16/init-checklist.md +25 -0
- package/docs/2026-06-16/plan.md +20 -0
- package/docs/ARCHITECTURE_ANALYSIS_CODEGRAPH.md +2 -1
- package/docs/GSTACK_MIGRATION.md +1 -1
- package/docs/algorithm-hardening-playbook.md +219 -0
- package/docs/claims.md +1 -1
- package/docs/getting-started.md +1 -1
- package/docs/native-root-runtime-hardening.md +42 -32
- package/docs/post-0793-hardening-roadmap.md +123 -0
- package/docs/provider-maturity.md +18 -16
- package/docs/versioning.md +3 -3
- package/docs/what-is-omk.md +1 -1
- package/package.json +8 -4
- package/readmeasset/.npmignore +2 -0
- package/readmeasset/ASSET_INDEX.md +2 -0
- package/readmeasset/ASSET_PROVENANCE.md +40 -20
- package/readmeasset/omk-adaptorch-ouroboros-supermemory.svg +1 -1
- package/readmeasset/omk-control-surfaces.svg +1 -1
- package/readmeasset/omk-core-loop.svg +1 -1
- package/readmeasset/omk-freedomd-control-plane.svg +59 -0
- package/readmeasset/omk-freedomd-control-plane.webp +0 -0
- package/readmeasset/omk-init-control-loop.svg +1 -1
- package/readmeasset/omk-logo-mark.svg +1 -1
- package/readmeasset/omk-parallel-subagents.svg +1 -1
- package/readmeasset/omk-release-assertions.svg +1 -1
|
@@ -6,7 +6,8 @@
|
|
|
6
6
|
* a configurable threshold (default 90%).
|
|
7
7
|
*
|
|
8
8
|
* Prefers the external `headroom` CLI compressor when available;
|
|
9
|
-
* falls back to
|
|
9
|
+
* falls back to caller-provided structured text and finally to legacy
|
|
10
|
+
* side-effect optimizers when not.
|
|
10
11
|
*
|
|
11
12
|
* Deterministic except for the injectable `runHeadroom` runner.
|
|
12
13
|
*/
|
|
@@ -18,9 +19,20 @@ export interface HeadroomDecision {
|
|
|
18
19
|
readonly contextWindow: number;
|
|
19
20
|
readonly reason: string;
|
|
20
21
|
}
|
|
22
|
+
export type HeadroomBackend = "headroom" | "structured-fallback" | "side-effect-fallback" | "none";
|
|
21
23
|
export interface HeadroomCompactResult {
|
|
24
|
+
/** Backward-compatible summary: a backend produced compacted text or completed a legacy fallback. */
|
|
22
25
|
readonly compacted: boolean;
|
|
26
|
+
/** Backward-compatible backend family. */
|
|
23
27
|
readonly via: "headroom" | "fallback" | "none";
|
|
28
|
+
readonly compactedText?: string;
|
|
29
|
+
readonly reason?: string;
|
|
30
|
+
/** Whether a compaction attempt was made because the policy threshold was crossed. */
|
|
31
|
+
readonly attempted: boolean;
|
|
32
|
+
/** Specific backend that produced this result. */
|
|
33
|
+
readonly backend: HeadroomBackend;
|
|
34
|
+
/** Whether a textual backend produced non-empty compacted text. */
|
|
35
|
+
readonly compactedTextProduced: boolean;
|
|
24
36
|
}
|
|
25
37
|
export declare function resolveHeadroomThreshold(env?: NodeJS.ProcessEnv | Record<string, string | undefined>): number;
|
|
26
38
|
export declare function isHeadroomEnabled(env?: NodeJS.ProcessEnv | Record<string, string | undefined>): boolean;
|
|
@@ -34,4 +46,5 @@ export declare function maybeCompactWithHeadroom(args: {
|
|
|
34
46
|
text?: string;
|
|
35
47
|
runHeadroom?: (text: string) => Promise<string | null>;
|
|
36
48
|
fallback?: () => Promise<void>;
|
|
49
|
+
fallbackText?: () => string | null | Promise<string | null>;
|
|
37
50
|
}): Promise<HeadroomCompactResult>;
|
|
@@ -6,7 +6,8 @@
|
|
|
6
6
|
* a configurable threshold (default 90%).
|
|
7
7
|
*
|
|
8
8
|
* Prefers the external `headroom` CLI compressor when available;
|
|
9
|
-
* falls back to
|
|
9
|
+
* falls back to caller-provided structured text and finally to legacy
|
|
10
|
+
* side-effect optimizers when not.
|
|
10
11
|
*
|
|
11
12
|
* Deterministic except for the injectable `runHeadroom` runner.
|
|
12
13
|
*/
|
|
@@ -50,14 +51,14 @@ export function evaluateHeadroom(input) {
|
|
|
50
51
|
reason: "headroom disabled via OMK_HEADROOM",
|
|
51
52
|
};
|
|
52
53
|
}
|
|
53
|
-
if (contextWindow <= 0) {
|
|
54
|
+
if (!Number.isFinite(contextWindow) || contextWindow <= 0) {
|
|
54
55
|
return {
|
|
55
56
|
shouldCompact: false,
|
|
56
57
|
utilization: 0,
|
|
57
58
|
threshold,
|
|
58
59
|
usedTokens,
|
|
59
60
|
contextWindow,
|
|
60
|
-
reason:
|
|
61
|
+
reason: `context window size unknown (${String(contextWindow)})`,
|
|
61
62
|
};
|
|
62
63
|
}
|
|
63
64
|
const utilization = usedTokens / contextWindow;
|
|
@@ -93,30 +94,91 @@ async function defaultRunHeadroom(text) {
|
|
|
93
94
|
}
|
|
94
95
|
export async function maybeCompactWithHeadroom(args) {
|
|
95
96
|
if (!args.decision.shouldCompact) {
|
|
96
|
-
return {
|
|
97
|
+
return {
|
|
98
|
+
compacted: false,
|
|
99
|
+
via: "none",
|
|
100
|
+
attempted: false,
|
|
101
|
+
backend: "none",
|
|
102
|
+
compactedTextProduced: false,
|
|
103
|
+
reason: args.decision.reason,
|
|
104
|
+
};
|
|
97
105
|
}
|
|
98
|
-
// Try headroom first
|
|
106
|
+
// Try headroom first.
|
|
99
107
|
if (args.text) {
|
|
100
108
|
try {
|
|
101
109
|
const runner = args.runHeadroom ?? defaultRunHeadroom;
|
|
102
110
|
const result = await runner(args.text);
|
|
103
|
-
if (result
|
|
104
|
-
return {
|
|
111
|
+
if (typeof result === "string" && result.trim().length > 0) {
|
|
112
|
+
return {
|
|
113
|
+
compacted: true,
|
|
114
|
+
via: "headroom",
|
|
115
|
+
backend: "headroom",
|
|
116
|
+
compactedText: result,
|
|
117
|
+
attempted: true,
|
|
118
|
+
compactedTextProduced: true,
|
|
119
|
+
reason: "headroom CLI compaction produced text",
|
|
120
|
+
};
|
|
105
121
|
}
|
|
106
122
|
}
|
|
107
123
|
catch {
|
|
108
|
-
// Headroom threw — fall through to fallback
|
|
124
|
+
// Headroom threw — fall through to fallback.
|
|
109
125
|
}
|
|
110
126
|
}
|
|
111
|
-
// Fall back to
|
|
127
|
+
// Fall back to a caller-provided textual compaction. This keeps autocompact
|
|
128
|
+
// effective even when the installed headroom CLI exposes proxy/MCP commands
|
|
129
|
+
// but no direct `compact --stdin` subcommand.
|
|
130
|
+
if (args.fallbackText) {
|
|
131
|
+
try {
|
|
132
|
+
const text = await args.fallbackText();
|
|
133
|
+
if (typeof text === "string" && text.trim().length > 0) {
|
|
134
|
+
return {
|
|
135
|
+
compacted: true,
|
|
136
|
+
via: "fallback",
|
|
137
|
+
backend: "structured-fallback",
|
|
138
|
+
compactedText: text,
|
|
139
|
+
attempted: true,
|
|
140
|
+
compactedTextProduced: true,
|
|
141
|
+
reason: "headroom CLI compaction unavailable; used structured fallback text",
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
if (typeof text === "string") {
|
|
145
|
+
return {
|
|
146
|
+
compacted: false,
|
|
147
|
+
via: "none",
|
|
148
|
+
backend: "none",
|
|
149
|
+
attempted: true,
|
|
150
|
+
compactedTextProduced: false,
|
|
151
|
+
reason: "empty fallback text",
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
catch {
|
|
156
|
+
// Text fallback failed — try side-effect fallback below.
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
// Fall back to built-in optimizer side effects when supplied by older callers.
|
|
112
160
|
if (args.fallback) {
|
|
113
161
|
try {
|
|
114
162
|
await args.fallback();
|
|
115
|
-
return {
|
|
163
|
+
return {
|
|
164
|
+
compacted: true,
|
|
165
|
+
via: "fallback",
|
|
166
|
+
backend: "side-effect-fallback",
|
|
167
|
+
attempted: true,
|
|
168
|
+
compactedTextProduced: false,
|
|
169
|
+
reason: "side-effect fallback completed",
|
|
170
|
+
};
|
|
116
171
|
}
|
|
117
172
|
catch {
|
|
118
|
-
// Fallback also failed — graceful degradation
|
|
173
|
+
// Fallback also failed — graceful degradation.
|
|
119
174
|
}
|
|
120
175
|
}
|
|
121
|
-
return {
|
|
176
|
+
return {
|
|
177
|
+
compacted: false,
|
|
178
|
+
via: "none",
|
|
179
|
+
backend: "none",
|
|
180
|
+
attempted: true,
|
|
181
|
+
compactedTextProduced: false,
|
|
182
|
+
reason: "no compaction backend succeeded",
|
|
183
|
+
};
|
|
122
184
|
}
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
* Calls https://api.moonshot.cn/v1/chat/completions directly.
|
|
6
6
|
*/
|
|
7
7
|
import type { AgentRuntime, AgentRunResult, AgentResult, AgentTask, RuntimeCapabilities, RuntimeHealth } from "./agent-runtime.js";
|
|
8
|
+
import type { RuntimeHealthProbeRequest } from "./contracts/shared.js";
|
|
8
9
|
import type { ContextCapsule } from "./context-capsule.js";
|
|
9
10
|
export interface KimiApiRuntimeOptions {
|
|
10
11
|
id?: string;
|
|
@@ -37,6 +38,7 @@ export declare function createKimiApiRuntime(options?: KimiApiRuntimeOptions): A
|
|
|
37
38
|
export declare const createKimiWireRuntime: typeof createKimiApiRuntime;
|
|
38
39
|
export declare class KimiApiRuntime implements AgentRuntime {
|
|
39
40
|
readonly id: string;
|
|
41
|
+
readonly advisory = true;
|
|
40
42
|
readonly providerId: string;
|
|
41
43
|
readonly legacy = false;
|
|
42
44
|
readonly runtimeMode = "api";
|
|
@@ -50,8 +52,9 @@ export declare class KimiApiRuntime implements AgentRuntime {
|
|
|
50
52
|
private readonly baseUrl;
|
|
51
53
|
constructor(options?: KimiApiRuntimeOptions);
|
|
52
54
|
supports(capsule: ContextCapsule): boolean;
|
|
53
|
-
health(): Promise<RuntimeHealth>;
|
|
55
|
+
health(input?: RuntimeHealthProbeRequest): Promise<RuntimeHealth>;
|
|
54
56
|
runNode(capsule: ContextCapsule, signal: AbortSignal): Promise<AgentRunResult>;
|
|
55
57
|
execute(task: AgentTask): Promise<AgentResult>;
|
|
58
|
+
private consumeCompactionContext;
|
|
56
59
|
private parseStreamResponse;
|
|
57
60
|
}
|
|
@@ -9,6 +9,7 @@ import { resolve } from "node:path";
|
|
|
9
9
|
import { capsuleToTask } from "./context-broker-converter.js";
|
|
10
10
|
import { buildProviderToolPayload } from "./provider-tool-contracts.js";
|
|
11
11
|
import { repairToolCalls } from "./tool-call-repair.js";
|
|
12
|
+
import { probeOpenAiCompatibleModels } from "./runtime-health-probes.js";
|
|
12
13
|
/**
|
|
13
14
|
* Detect "Image file: <path>" patterns in the prompt text (inserted by /paste
|
|
14
15
|
* or Ctrl+V clipboard image) and load the referenced images as base64 data URIs
|
|
@@ -86,6 +87,7 @@ export function createKimiApiRuntime(options = {}) {
|
|
|
86
87
|
export const createKimiWireRuntime = createKimiApiRuntime;
|
|
87
88
|
export class KimiApiRuntime {
|
|
88
89
|
id;
|
|
90
|
+
advisory = true;
|
|
89
91
|
providerId;
|
|
90
92
|
legacy = false;
|
|
91
93
|
runtimeMode = "api";
|
|
@@ -133,14 +135,16 @@ export class KimiApiRuntime {
|
|
|
133
135
|
return false;
|
|
134
136
|
return true;
|
|
135
137
|
}
|
|
136
|
-
async health() {
|
|
137
|
-
|
|
138
|
-
return {
|
|
138
|
+
async health(input = { probeKind: "static", highRisk: false }) {
|
|
139
|
+
return probeOpenAiCompatibleModels({
|
|
139
140
|
runtimeId: this.id,
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
141
|
+
baseUrl: this.baseUrl,
|
|
142
|
+
apiKey: this.apiKey,
|
|
143
|
+
apiKeyName: this.apiKeyEnvName,
|
|
144
|
+
model: this.model,
|
|
145
|
+
providerName: this.providerName,
|
|
146
|
+
probeKind: input.probeKind,
|
|
147
|
+
});
|
|
144
148
|
}
|
|
145
149
|
async runNode(capsule, signal) {
|
|
146
150
|
try {
|
|
@@ -172,12 +176,13 @@ export class KimiApiRuntime {
|
|
|
172
176
|
}
|
|
173
177
|
}
|
|
174
178
|
async execute(task) {
|
|
179
|
+
const compactionMeta = this.consumeCompactionContext(task);
|
|
175
180
|
if (!this.apiKey) {
|
|
176
181
|
return {
|
|
177
182
|
output: "",
|
|
178
183
|
exitCode: 1,
|
|
179
184
|
thinking: "",
|
|
180
|
-
metadata: { error: `${this.apiKeyEnvName} is not set
|
|
185
|
+
metadata: { error: `${this.apiKeyEnvName} is not set`, ...compactionMeta },
|
|
181
186
|
};
|
|
182
187
|
}
|
|
183
188
|
if (task.capabilities.write ||
|
|
@@ -192,6 +197,7 @@ export class KimiApiRuntime {
|
|
|
192
197
|
metadata: {
|
|
193
198
|
error: `${this.id} is advisory/read-only and does not receive write, shell, MCP, merge, or patch authority`,
|
|
194
199
|
authorityMode: "advisory",
|
|
200
|
+
...compactionMeta,
|
|
195
201
|
},
|
|
196
202
|
};
|
|
197
203
|
}
|
|
@@ -252,13 +258,14 @@ export class KimiApiRuntime {
|
|
|
252
258
|
output: "",
|
|
253
259
|
exitCode: 1,
|
|
254
260
|
thinking: "",
|
|
255
|
-
metadata: { error: `${this.providerName} API error ${response.status}: ${errorText}
|
|
261
|
+
metadata: { error: `${this.providerName} API error ${response.status}: ${errorText}`, ...compactionMeta },
|
|
256
262
|
};
|
|
257
263
|
}
|
|
258
264
|
if (useStreaming) {
|
|
259
265
|
return this.parseStreamResponse(response, {
|
|
260
266
|
toolPlaneHash: providerTools.toolPlaneHash,
|
|
261
267
|
toolContracts: providerTools.contracts,
|
|
268
|
+
compactionMeta,
|
|
262
269
|
});
|
|
263
270
|
}
|
|
264
271
|
const contentType = response.headers.get("content-type") ?? "";
|
|
@@ -266,6 +273,7 @@ export class KimiApiRuntime {
|
|
|
266
273
|
return this.parseStreamResponse(response, {
|
|
267
274
|
toolPlaneHash: providerTools.toolPlaneHash,
|
|
268
275
|
toolContracts: providerTools.contracts,
|
|
276
|
+
compactionMeta,
|
|
269
277
|
});
|
|
270
278
|
}
|
|
271
279
|
const payload = (await response.json());
|
|
@@ -297,6 +305,7 @@ export class KimiApiRuntime {
|
|
|
297
305
|
toolPlaneHash: providerTools.toolPlaneHash,
|
|
298
306
|
toolContracts: providerTools.contracts,
|
|
299
307
|
toolCallRepair: mappedToolCalls.repair,
|
|
308
|
+
...compactionMeta,
|
|
300
309
|
},
|
|
301
310
|
};
|
|
302
311
|
}
|
|
@@ -306,17 +315,31 @@ export class KimiApiRuntime {
|
|
|
306
315
|
output: "",
|
|
307
316
|
exitCode: 130,
|
|
308
317
|
thinking: "",
|
|
309
|
-
metadata: { error: "Request aborted" },
|
|
318
|
+
metadata: { error: "Request aborted", ...compactionMeta },
|
|
310
319
|
};
|
|
311
320
|
}
|
|
312
321
|
return {
|
|
313
322
|
output: "",
|
|
314
323
|
exitCode: 1,
|
|
315
324
|
thinking: "",
|
|
316
|
-
metadata: { error: String(err) },
|
|
325
|
+
metadata: { error: String(err), ...compactionMeta },
|
|
317
326
|
};
|
|
318
327
|
}
|
|
319
328
|
}
|
|
329
|
+
consumeCompactionContext(task) {
|
|
330
|
+
const compaction = task.context.compaction;
|
|
331
|
+
if (!compaction || compaction.schemaVersion !== "omk.task-compaction.v1") {
|
|
332
|
+
return { compactionConsumed: false };
|
|
333
|
+
}
|
|
334
|
+
return {
|
|
335
|
+
compactionConsumed: true,
|
|
336
|
+
compactionContract: typeof compaction.contract.schemaVersion === "string"
|
|
337
|
+
? compaction.contract.schemaVersion
|
|
338
|
+
: "unknown",
|
|
339
|
+
compactionArtifactRef: compaction.artifactRef,
|
|
340
|
+
compactionQualityScore: compaction.diagnostics?.qualityScore,
|
|
341
|
+
};
|
|
342
|
+
}
|
|
320
343
|
async parseStreamResponse(response, metadata) {
|
|
321
344
|
const reader = response.body?.getReader();
|
|
322
345
|
if (!reader) {
|
|
@@ -424,6 +447,7 @@ export class KimiApiRuntime {
|
|
|
424
447
|
model,
|
|
425
448
|
finishReason,
|
|
426
449
|
...metadata,
|
|
450
|
+
...(metadata.compactionMeta ?? {}),
|
|
427
451
|
toolCallRepair: mappedToolCalls.repair,
|
|
428
452
|
},
|
|
429
453
|
};
|
|
@@ -30,6 +30,25 @@ export function createKimiPrintRuntime(options = {}) {
|
|
|
30
30
|
metadata: { runtime: "kimi-print", error: errorMsg },
|
|
31
31
|
};
|
|
32
32
|
}
|
|
33
|
+
const routing = capsule.node?.routing;
|
|
34
|
+
const approvalPolicy = routing?.approvalPolicy ?? routing?.executionPrompt;
|
|
35
|
+
const sandboxMode = routing?.sandboxMode;
|
|
36
|
+
const capabilities = routing?.assignedProviderCapabilities ?? [];
|
|
37
|
+
const isAdvisory = sandboxMode === "read-only" ||
|
|
38
|
+
capabilities.length === 0 ||
|
|
39
|
+
capabilities.every((c) => ["read", "review"].includes(c));
|
|
40
|
+
const requiresWriteShellMerge = capabilities.some((c) => ["write", "patch", "shell", "merge"].includes(c));
|
|
41
|
+
if (requiresWriteShellMerge && isAdvisory) {
|
|
42
|
+
const errorMsg = `[omk] kimi-print runtime is advisory/read-only and does not receive write, patch, shell, or merge authority`;
|
|
43
|
+
process.stderr.write(`${errorMsg}\n`);
|
|
44
|
+
return {
|
|
45
|
+
success: false,
|
|
46
|
+
exitCode: 1,
|
|
47
|
+
stdout: `[ERROR] ${errorMsg}`,
|
|
48
|
+
stderr: errorMsg,
|
|
49
|
+
metadata: { runtime: "kimi-print", error: errorMsg, authorityMode: "advisory" },
|
|
50
|
+
};
|
|
51
|
+
}
|
|
33
52
|
const runner = createKimiTaskRunner(options);
|
|
34
53
|
const resources = await getOmkResourceSettings();
|
|
35
54
|
const env = {
|
|
@@ -41,6 +60,8 @@ export function createKimiPrintRuntime(options = {}) {
|
|
|
41
60
|
OMK_HOOKS_ENABLED: resources.hooksScope === "none" ? "false" : "true",
|
|
42
61
|
OMK_CONTEXT_BUDGET: capsule.budget.compression,
|
|
43
62
|
OMK_TOTAL_TOKENS: String(capsule.budget.maxInputTokens),
|
|
63
|
+
OMK_APPROVAL_POLICY: approvalPolicy ?? "",
|
|
64
|
+
OMK_SANDBOX_MODE: sandboxMode ?? (isAdvisory ? "read-only" : "workspace-write"),
|
|
44
65
|
...(capsule.node ? dagNodeRoutingEnv(capsule.node) : {}),
|
|
45
66
|
};
|
|
46
67
|
const node = {
|
|
@@ -66,11 +66,27 @@ export class KimiWireProtocolRuntime {
|
|
|
66
66
|
const kimiBin = resolveKimiBin();
|
|
67
67
|
const available = await checkCommand(kimiBin);
|
|
68
68
|
this.kimiAvailable = available;
|
|
69
|
+
const now = new Date();
|
|
69
70
|
return {
|
|
70
71
|
runtimeId: this.id,
|
|
71
72
|
available,
|
|
72
73
|
reason: available ? undefined : "`kimi` command not found in PATH",
|
|
73
|
-
checkedAt:
|
|
74
|
+
checkedAt: now.toISOString(),
|
|
75
|
+
vector: {
|
|
76
|
+
runtimeOk: available,
|
|
77
|
+
authOk: available,
|
|
78
|
+
modelOk: true,
|
|
79
|
+
quotaOk: true,
|
|
80
|
+
rateLimitOk: true,
|
|
81
|
+
runtime: available ? "pass" : "fail",
|
|
82
|
+
auth: available ? "unknown" : "fail",
|
|
83
|
+
model: "unknown",
|
|
84
|
+
quota: "unknown",
|
|
85
|
+
rateLimit: "unknown",
|
|
86
|
+
lastProbeKind: "static",
|
|
87
|
+
checkedAt: now.toISOString(),
|
|
88
|
+
expiresAt: new Date(now.getTime() + 60_000).toISOString(),
|
|
89
|
+
},
|
|
74
90
|
};
|
|
75
91
|
}
|
|
76
92
|
async runNode(capsule, signal) {
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
* Supports SSE streaming and reasoning_content.
|
|
7
7
|
*/
|
|
8
8
|
import type { AgentRuntime, AgentRunResult, AgentResult, AgentTask, RuntimeCapabilities, RuntimeHealth } from "./agent-runtime.js";
|
|
9
|
+
import type { RuntimeHealthProbeRequest } from "./contracts/shared.js";
|
|
9
10
|
import type { ContextCapsule } from "./context-capsule.js";
|
|
10
11
|
export interface LocalLlmRuntimeOptions {
|
|
11
12
|
apiKey?: string;
|
|
@@ -14,6 +15,9 @@ export interface LocalLlmRuntimeOptions {
|
|
|
14
15
|
}
|
|
15
16
|
export declare class LocalLlmRuntime implements AgentRuntime {
|
|
16
17
|
readonly id = "local-llm";
|
|
18
|
+
readonly providerId = "local-llm";
|
|
19
|
+
readonly advisory = true;
|
|
20
|
+
readonly runtimeMode = "api";
|
|
17
21
|
readonly kind = "api";
|
|
18
22
|
readonly priority = 35;
|
|
19
23
|
readonly capabilities: RuntimeCapabilities;
|
|
@@ -22,7 +26,7 @@ export declare class LocalLlmRuntime implements AgentRuntime {
|
|
|
22
26
|
private readonly baseUrl;
|
|
23
27
|
constructor(options?: LocalLlmRuntimeOptions);
|
|
24
28
|
supports(capsule: ContextCapsule): boolean;
|
|
25
|
-
health(): Promise<RuntimeHealth>;
|
|
29
|
+
health(input?: RuntimeHealthProbeRequest): Promise<RuntimeHealth>;
|
|
26
30
|
runNode(capsule: ContextCapsule, signal: AbortSignal): Promise<AgentRunResult>;
|
|
27
31
|
execute(task: AgentTask): Promise<AgentResult>;
|
|
28
32
|
private parseStreamResponse;
|
|
@@ -7,8 +7,12 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import { capsuleToTask } from "./context-broker-converter.js";
|
|
9
9
|
import { sanitizeUserVisibleOutput } from "../util/user-visible-output.js";
|
|
10
|
+
import { probeOpenAiCompatibleModels } from "./runtime-health-probes.js";
|
|
10
11
|
export class LocalLlmRuntime {
|
|
11
12
|
id = "local-llm";
|
|
13
|
+
providerId = "local-llm";
|
|
14
|
+
advisory = true;
|
|
15
|
+
runtimeMode = "api";
|
|
12
16
|
kind = "api";
|
|
13
17
|
priority = 35;
|
|
14
18
|
capabilities = {
|
|
@@ -40,29 +44,16 @@ export class LocalLlmRuntime {
|
|
|
40
44
|
return false;
|
|
41
45
|
return true;
|
|
42
46
|
}
|
|
43
|
-
async health() {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
available: resp.ok,
|
|
54
|
-
reason: resp.ok ? undefined : `Local LLM returned ${resp.status}`,
|
|
55
|
-
checkedAt: new Date().toISOString(),
|
|
56
|
-
};
|
|
57
|
-
}
|
|
58
|
-
catch (err) {
|
|
59
|
-
return {
|
|
60
|
-
runtimeId: this.id,
|
|
61
|
-
available: false,
|
|
62
|
-
reason: `Local LLM not reachable: ${err instanceof Error ? err.message : String(err)}`,
|
|
63
|
-
checkedAt: new Date().toISOString(),
|
|
64
|
-
};
|
|
65
|
-
}
|
|
47
|
+
async health(input = { probeKind: "static", highRisk: false }) {
|
|
48
|
+
return probeOpenAiCompatibleModels({
|
|
49
|
+
runtimeId: this.id,
|
|
50
|
+
baseUrl: this.baseUrl,
|
|
51
|
+
apiKey: this.apiKey,
|
|
52
|
+
apiKeyName: "LOCAL_LLM_API_KEY",
|
|
53
|
+
model: this.model,
|
|
54
|
+
providerName: "Local LLM",
|
|
55
|
+
probeKind: input.probeKind === "static" ? "static" : input.probeKind,
|
|
56
|
+
});
|
|
66
57
|
}
|
|
67
58
|
async runNode(capsule, signal) {
|
|
68
59
|
try {
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface PrivateStderrRetentionOptions {
|
|
2
|
+
readonly runId?: string;
|
|
3
|
+
readonly nodeId?: string;
|
|
4
|
+
readonly runtimeId?: string;
|
|
5
|
+
readonly root?: string;
|
|
6
|
+
readonly env?: Record<string, string | undefined>;
|
|
7
|
+
}
|
|
8
|
+
export interface StderrSanitizableResult {
|
|
9
|
+
readonly stderr: string;
|
|
10
|
+
readonly metadata?: Record<string, unknown>;
|
|
11
|
+
}
|
|
12
|
+
export declare function privateStderrRetentionEnabled(env?: Record<string, string | undefined>): boolean;
|
|
13
|
+
export declare function sanitizeRuntimeStderrResult<T extends StderrSanitizableResult>(result: T, options?: PrivateStderrRetentionOptions): T;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { mkdirSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { dirname } from "node:path";
|
|
4
|
+
import { getRunArtifactPath } from "../util/run-store.js";
|
|
5
|
+
import { maskSensitiveText } from "../util/secret-mask.js";
|
|
6
|
+
export function privateStderrRetentionEnabled(env) {
|
|
7
|
+
const value = env?.OMK_PRIVATE_STDERR_ARTIFACTS ?? env?.OMK_DEBUG;
|
|
8
|
+
return /^(1|true|yes|on)$/i.test(value ?? "");
|
|
9
|
+
}
|
|
10
|
+
export function sanitizeRuntimeStderrResult(result, options = {}) {
|
|
11
|
+
const originalStderr = result.stderr ?? "";
|
|
12
|
+
const sanitizedStderr = maskSensitiveText(originalStderr);
|
|
13
|
+
const redacted = sanitizedStderr !== originalStderr;
|
|
14
|
+
const privateArtifact = writePrivateStderrArtifact(sanitizedStderr, originalStderr, options);
|
|
15
|
+
if (!redacted && !privateArtifact && sanitizedStderr === result.stderr)
|
|
16
|
+
return result;
|
|
17
|
+
return {
|
|
18
|
+
...result,
|
|
19
|
+
stderr: sanitizedStderr,
|
|
20
|
+
metadata: {
|
|
21
|
+
...(result.metadata ?? {}),
|
|
22
|
+
stderrRedacted: true,
|
|
23
|
+
secretLikeContentRedacted: redacted,
|
|
24
|
+
stderrPreview: sanitizedStderr.slice(0, 500),
|
|
25
|
+
...(privateArtifact && {
|
|
26
|
+
stderrPrivateArtifact: privateArtifact.path,
|
|
27
|
+
stderrPrivateArtifactSha256: privateArtifact.sha256,
|
|
28
|
+
stderrRetainedPrivately: true,
|
|
29
|
+
}),
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
function writePrivateStderrArtifact(sanitizedStderr, originalStderr, options) {
|
|
34
|
+
if (!privateStderrRetentionEnabled(options.env))
|
|
35
|
+
return undefined;
|
|
36
|
+
if (sanitizedStderr.trim().length === 0)
|
|
37
|
+
return undefined;
|
|
38
|
+
const runId = options.runId;
|
|
39
|
+
if (!runId || runId.startsWith("local-"))
|
|
40
|
+
return undefined;
|
|
41
|
+
try {
|
|
42
|
+
const node = safeArtifactSegment(options.nodeId, "node");
|
|
43
|
+
const runtime = safeArtifactSegment(options.runtimeId, "runtime");
|
|
44
|
+
const sha256 = createHash("sha256").update(sanitizedStderr).digest("hex");
|
|
45
|
+
const rel = `private/stderr/${node}-${runtime}-${sha256.slice(0, 12)}.json`;
|
|
46
|
+
const full = getRunArtifactPath(runId, rel, options.root);
|
|
47
|
+
mkdirSync(dirname(full), { recursive: true });
|
|
48
|
+
writeFileSync(full, JSON.stringify({
|
|
49
|
+
schemaVersion: "omk.private-stderr.v1",
|
|
50
|
+
runId,
|
|
51
|
+
nodeId: options.nodeId,
|
|
52
|
+
runtimeId: options.runtimeId,
|
|
53
|
+
redaction: "secret-like-content-masked-before-retention",
|
|
54
|
+
publicPreviewLength: 500,
|
|
55
|
+
sha256,
|
|
56
|
+
rawSha256: createHash("sha256").update(originalStderr).digest("hex"),
|
|
57
|
+
stderr: sanitizedStderr,
|
|
58
|
+
timestamp: new Date().toISOString(),
|
|
59
|
+
}, null, 2), "utf-8");
|
|
60
|
+
return { path: rel, sha256 };
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
return undefined;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
function safeArtifactSegment(value, fallback) {
|
|
67
|
+
const sanitized = (value ?? fallback).replace(/[^A-Za-z0-9._-]/g, "-").slice(0, 48);
|
|
68
|
+
return sanitized.length > 0 ? sanitized : fallback;
|
|
69
|
+
}
|
|
@@ -9,7 +9,7 @@ export interface PromptEnvelopeInput {
|
|
|
9
9
|
readonly nodeId?: string;
|
|
10
10
|
readonly runId?: string;
|
|
11
11
|
readonly executionPrompt?: string;
|
|
12
|
-
readonly turnRisk?: "read" | "write" | "shell" | "merge";
|
|
12
|
+
readonly turnRisk?: "read" | "write" | "shell" | "merge" | "ask";
|
|
13
13
|
readonly sandboxMode?: "read-only" | "workspace-write";
|
|
14
14
|
}
|
|
15
15
|
export interface PromptEnvelopeSection {
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provider sovereignty scoring for Freedomd.
|
|
3
|
+
*
|
|
4
|
+
* Translates provider jurisdiction, retention, cutoff/portability, and locality
|
|
5
|
+
* properties into a normalized score that feeds runtime routing. The score is
|
|
6
|
+
* intentionally conservative: unknowns are treated as risk.
|
|
7
|
+
*/
|
|
8
|
+
import type { AgentRuntime, AgentTask } from "./agent-runtime.js";
|
|
9
|
+
import type { RuntimeHealth } from "./contracts/shared.js";
|
|
10
|
+
export type ExportPolicy = "open" | "restricted" | "controlled" | "unknown";
|
|
11
|
+
export interface ProviderSovereigntyProfile {
|
|
12
|
+
readonly providerId: string;
|
|
13
|
+
readonly runtimeMode: string;
|
|
14
|
+
readonly providerCountry: string;
|
|
15
|
+
readonly exportPolicy: ExportPolicy;
|
|
16
|
+
readonly retentionDays: number;
|
|
17
|
+
readonly zeroDataRetention: boolean;
|
|
18
|
+
readonly trainingUse: boolean;
|
|
19
|
+
readonly supportsSelfHosted: boolean;
|
|
20
|
+
readonly openApiCompatible: boolean;
|
|
21
|
+
readonly policyInstabilityScore: number;
|
|
22
|
+
readonly exportControlExposure: number;
|
|
23
|
+
readonly accountDependency: number;
|
|
24
|
+
readonly metadataEvidenceSupport: boolean;
|
|
25
|
+
}
|
|
26
|
+
export interface ProviderIncidentState {
|
|
27
|
+
readonly providerId: string;
|
|
28
|
+
readonly runtimeMode?: string;
|
|
29
|
+
readonly kind: "availability" | "policy" | "export-control" | "retention" | "jurisdiction";
|
|
30
|
+
readonly severity: "info" | "warn" | "block";
|
|
31
|
+
readonly reason: string;
|
|
32
|
+
readonly updatedAt: string;
|
|
33
|
+
}
|
|
34
|
+
export interface SovereigntyDiagnostics {
|
|
35
|
+
readonly jurisdictionRisk: number;
|
|
36
|
+
readonly retentionRisk: number;
|
|
37
|
+
readonly cutoffRisk: number;
|
|
38
|
+
readonly localityScore: number;
|
|
39
|
+
readonly portabilityScore: number;
|
|
40
|
+
readonly incidentSeverity?: string;
|
|
41
|
+
readonly reason: string;
|
|
42
|
+
}
|
|
43
|
+
export interface SovereigntyScore {
|
|
44
|
+
readonly score: number;
|
|
45
|
+
readonly diagnostics: SovereigntyDiagnostics;
|
|
46
|
+
}
|
|
47
|
+
export interface ComputeSovereigntyOptions {
|
|
48
|
+
readonly profile: ProviderSovereigntyProfile;
|
|
49
|
+
readonly userCountry?: string;
|
|
50
|
+
readonly taskRisk?: string;
|
|
51
|
+
readonly incidents?: readonly ProviderIncidentState[];
|
|
52
|
+
readonly localAvailable?: boolean;
|
|
53
|
+
}
|
|
54
|
+
export declare function assessJurisdictionRisk(options: {
|
|
55
|
+
readonly providerCountry: string;
|
|
56
|
+
readonly userCountry?: string;
|
|
57
|
+
readonly taskRisk?: string;
|
|
58
|
+
readonly exportPolicy: ExportPolicy;
|
|
59
|
+
readonly incidents?: readonly ProviderIncidentState[];
|
|
60
|
+
}): number;
|
|
61
|
+
export declare function assessRetentionRisk(options: {
|
|
62
|
+
readonly retentionDays: number;
|
|
63
|
+
readonly zeroDataRetention: boolean;
|
|
64
|
+
readonly trainingUse: boolean;
|
|
65
|
+
readonly maxRetentionDays?: number;
|
|
66
|
+
}): number;
|
|
67
|
+
export declare function assessCutoffRisk(options: {
|
|
68
|
+
readonly health?: RuntimeHealth;
|
|
69
|
+
readonly policyInstabilityScore: number;
|
|
70
|
+
readonly exportControlExposure: number;
|
|
71
|
+
readonly accountDependency: number;
|
|
72
|
+
readonly incidents?: readonly ProviderIncidentState[];
|
|
73
|
+
}): number;
|
|
74
|
+
export declare function assessPortability(options: {
|
|
75
|
+
readonly supportsOpenApiCompat: boolean;
|
|
76
|
+
readonly supportsToolContract: boolean;
|
|
77
|
+
readonly supportsEvidenceReturn: boolean;
|
|
78
|
+
}): number;
|
|
79
|
+
export declare function computeProviderSovereigntyScore(runtime: AgentRuntime, task: AgentTask, options: ComputeSovereigntyOptions): SovereigntyScore;
|
|
80
|
+
export declare function buildProviderSovereigntyProfiles(): Readonly<Record<string, ProviderSovereigntyProfile>>;
|
|
81
|
+
export declare function lookupSovereigntyProfile(runtime: AgentRuntime, profiles?: Readonly<Record<string, ProviderSovereigntyProfile>>): ProviderSovereigntyProfile | undefined;
|