open-multi-agent-kit 0.78.5 → 0.78.7
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/AGENTS.md +1 -1
- package/CHANGELOG.md +64 -0
- package/MATURITY.md +2 -2
- package/README.md +20 -5
- package/dist/brand/night-city.theme.json +80 -0
- package/dist/brand/palette.d.ts +73 -177
- package/dist/brand/palette.js +115 -39
- package/dist/brand/rust-forge.theme.json +216 -0
- package/dist/brand/theme-compiled.d.ts +61 -0
- package/dist/brand/theme-compiled.js +241 -0
- package/dist/brand/theme.js +50 -37
- package/dist/cli/release-promotion-gate.d.ts +8 -1
- package/dist/cli/release-promotion-gate.js +23 -11
- package/dist/cli/root.d.ts +1 -0
- package/dist/cli/root.js +2 -1
- package/dist/cli/theme/index.d.ts +11 -2
- package/dist/cli/theme/index.js +6 -1
- package/dist/cli/theme/oklab-quantize.d.ts +29 -0
- package/dist/cli/theme/oklab-quantize.js +105 -0
- package/dist/cli/theme/render-table.d.ts +59 -0
- package/dist/cli/theme/render-table.js +112 -0
- package/dist/cli/theme/status-frame.d.ts +10 -0
- package/dist/cli/theme/status-frame.js +22 -0
- package/dist/cli/theme/terminal-capability.d.ts +6 -1
- package/dist/cli/theme/terminal-capability.js +20 -4
- package/dist/cli/theme/theme-doc.d.ts +22 -0
- package/dist/cli/theme/theme-doc.js +97 -0
- package/dist/cli/theme/theme-registry.js +39 -18
- package/dist/cli/theme/tier-explain.d.ts +21 -0
- package/dist/cli/theme/tier-explain.js +60 -0
- package/dist/cli/ui/green-rain-renderer.js +3 -2
- package/dist/cli/ui/neon-grid-renderer.js +4 -3
- package/dist/cli/ui/rust-forge-renderer.js +17 -3
- package/dist/cli/ui/system24-renderer.d.ts +18 -1
- package/dist/cli/ui/system24-renderer.js +39 -16
- package/dist/cli/v2/chat-repl.js +3 -1
- package/dist/cli/v2/cli-v2-skeleton.d.ts +6 -0
- package/dist/cli/v2/cli-v2-skeleton.js +121 -9
- package/dist/cli/v2/interactive-prompt.d.ts +1 -0
- package/dist/cli/v2/interactive-prompt.js +6 -2
- package/dist/commands/chat/core.js +2 -2
- package/dist/commands/chat/runtime.js +2 -0
- package/dist/commands/chat/utils.js +12 -4
- package/dist/commands/cockpit/render.js +102 -64
- package/dist/commands/cockpit/utils.d.ts +2 -0
- package/dist/commands/design.js +18 -16
- package/dist/commands/doctor/checks.d.ts +0 -1
- package/dist/commands/doctor/checks.js +1 -36
- package/dist/commands/doctor/report.js +0 -11
- package/dist/commands/init/content.d.ts +1 -1
- package/dist/commands/init/content.js +3 -11
- package/dist/commands/init.js +2 -2
- package/dist/commands/mcp/config.d.ts +32 -0
- package/dist/commands/mcp/config.js +264 -0
- package/dist/commands/mcp/doctor-fix.d.ts +12 -0
- package/dist/commands/mcp/doctor-fix.js +261 -0
- package/dist/commands/mcp/doctor.d.ts +55 -0
- package/dist/commands/mcp/doctor.js +401 -0
- package/dist/commands/mcp/list.d.ts +1 -0
- package/dist/commands/mcp/list.js +56 -0
- package/dist/commands/mcp/shared.d.ts +47 -0
- package/dist/commands/mcp/shared.js +192 -0
- package/dist/commands/mcp/test.d.ts +5 -0
- package/dist/commands/mcp/test.js +457 -0
- package/dist/commands/mcp.d.ts +8 -104
- package/dist/commands/mcp.js +5 -1603
- package/dist/contracts/proof.d.ts +1 -1
- package/dist/goal/control-loop.d.ts +15 -0
- package/dist/goal/control-loop.js +39 -5
- package/dist/hud/render.d.ts +2 -0
- package/dist/hud/render.js +7 -1
- package/dist/mcp/secret-scanner.d.ts +6 -0
- package/dist/mcp/secret-scanner.js +44 -11
- package/dist/memory/graph-delta-log.d.ts +137 -0
- package/dist/memory/graph-delta-log.js +650 -0
- package/dist/memory/graph-viewer.js +13 -32
- package/dist/memory/local-graph-memory-store.d.ts +36 -3
- package/dist/memory/local-graph-memory-store.js +255 -10
- package/dist/orchestration/log-streamer.js +13 -8
- package/dist/orchestration/routing.d.ts +4 -0
- package/dist/orchestration/routing.js +28 -3
- package/dist/orchestration/state-persister.js +8 -1
- package/dist/providers/anthropic-messages-runner.d.ts +17 -0
- package/dist/providers/anthropic-messages-runner.js +197 -0
- package/dist/providers/model-registry.d.ts +1 -1
- package/dist/providers/model-registry.js +37 -3
- package/dist/providers/provider-runtime.js +27 -11
- package/dist/providers/thinking-levels.js +4 -1
- package/dist/providers/types.d.ts +3 -3
- package/dist/runtime/contracts/weakness-remediation.d.ts +11 -1
- package/dist/runtime/contracts/weakness-remediation.js +9 -1
- package/dist/runtime/router-v2-scoring.d.ts +8 -3
- package/dist/runtime/router-v2-scoring.js +27 -22
- package/dist/runtime/runtime-router.d.ts +5 -0
- package/dist/runtime/runtime-router.js +40 -8
- package/dist/runtime/sandbox-profile.d.ts +29 -0
- package/dist/runtime/sandbox-profile.js +101 -0
- package/dist/runtime/slash-commands.js +300 -2
- package/dist/runtime/tool-dispatch-contracts.d.ts +15 -0
- package/dist/runtime/tool-dispatch-contracts.js +12 -0
- package/dist/runtime/weights-config.d.ts +90 -0
- package/dist/runtime/weights-config.js +249 -0
- package/dist/schema/envelope.schema.d.ts +18 -18
- package/dist/schema/evidence.schema.d.ts +2 -2
- package/dist/schema/proof-bundle.schema.d.ts +6 -6
- package/dist/schema/proof-bundle.schema.js +0 -1
- package/dist/schema/provider.schema.d.ts +2 -2
- package/dist/schema/run-manifest.schema.d.ts +16 -16
- package/dist/theme/ansi.js +9 -2
- package/dist/theme/extended-palette.d.ts +85 -0
- package/dist/theme/extended-palette.js +108 -0
- package/dist/theme/layout.js +29 -8
- package/dist/theme/metrics.js +5 -5
- package/dist/theme/parallel.js +25 -15
- package/dist/ui/omk-sigil.js +5 -14
- package/dist/ui/omk-working-sweep.js +5 -15
- package/dist/util/chat-agent-mode.d.ts +11 -0
- package/dist/util/chat-agent-mode.js +41 -8
- package/dist/util/chat-cockpit.d.ts +9 -0
- package/dist/util/chat-cockpit.js +77 -20
- package/dist/util/fs/core.d.ts +5 -0
- package/dist/util/fs/core.js +35 -0
- package/dist/util/fs/internal.d.ts +14 -0
- package/dist/util/fs/internal.js +169 -0
- package/dist/util/fs/kimi-sync.d.ts +41 -0
- package/dist/util/fs/kimi-sync.js +495 -0
- package/dist/util/fs/logo.d.ts +2 -0
- package/dist/util/fs/logo.js +78 -0
- package/dist/util/fs/manifest.d.ts +6 -0
- package/dist/util/fs/manifest.js +40 -0
- package/dist/util/fs/mcp-diagnose.d.ts +15 -0
- package/dist/util/fs/mcp-diagnose.js +204 -0
- package/dist/util/fs/mcp-runtime-config.d.ts +23 -0
- package/dist/util/fs/mcp-runtime-config.js +412 -0
- package/dist/util/fs/paths.d.ts +13 -0
- package/dist/util/fs/paths.js +82 -0
- package/dist/util/fs/preflight.d.ts +27 -0
- package/dist/util/fs/preflight.js +271 -0
- package/dist/util/fs.d.ts +8 -128
- package/dist/util/fs.js +8 -1757
- package/dist/util/terminal-layout.js +5 -1
- package/dist/util/version.js +2 -1
- package/docs/2026-06-10/critical-issues.md +20 -0
- package/docs/2026-06-10/improvements.md +14 -0
- package/docs/2026-06-10/init-checklist.md +25 -0
- package/docs/2026-06-10/plan.md +20 -0
- package/docs/2026-06-11/critical-issues.md +20 -0
- package/docs/2026-06-11/improvements.md +14 -0
- package/docs/2026-06-11/init-checklist.md +25 -0
- package/docs/2026-06-11/plan.md +20 -0
- package/docs/ARCHITECTURE_ANALYSIS_CODEGRAPH.md +223 -0
- package/docs/adr/0001-no-native-rust-lane.md +52 -0
- package/docs/codex-oauth-setup.md +14 -0
- package/docs/decisions/2026-06-10-git-history-bloat.md +61 -0
- package/docs/decisions/ADR-theme-dark-only-assets.md +43 -0
- package/docs/getting-started.md +1 -1
- package/docs/headroom-omk-final-summary.md +188 -0
- package/docs/headroom-omk-integration.md +394 -0
- package/docs/headroom-omk-setup-guide.md +422 -0
- package/docs/headroom-omk-usage-examples.md +371 -0
- package/docs/provider-maturity.md +1 -1
- package/docs/versioning.md +3 -3
- package/package.json +10 -10
- package/readmeasset/.npmignore +2 -0
- package/readmeasset/ASSET_INDEX.md +7 -5
- package/readmeasset/ASSET_PROVENANCE.md +21 -5
- package/readmeasset/omk-control-surfaces.svg +55 -0
- package/readmeasset/omk-core-loop.svg +1 -0
- package/readmeasset/omk-logo-mark.svg +1 -0
- package/readmeasset/omk-release-assertions.svg +51 -0
- package/dist/native/linux-x64/omk-safety +0 -0
- package/dist/util/native-safety.d.ts +0 -28
- package/dist/util/native-safety.js +0 -118
- package/templates/skills/agents/omk-adaptorch-orchestration-review/SKILL.md +0 -52
- package/templates/skills/kimi/mcp-install/SKILL.md +0 -66
- package/templates/skills/kimi/omk-adaptorch-orchestration-review/SKILL.md +0 -52
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { OMK_PROOF_BUNDLE_SCHEMA_VERSION, OMK_RUNTIME_VERSION } from "../version.js";
|
|
2
|
-
export type ProofBundleScenario = "no-kimi-smoke" | "evidence-block" | "fallback-route" | "dag-dependent-block" | "replay-inspect" | "graph-audit" | "example-generation" | "doctor-provider" | "
|
|
2
|
+
export type ProofBundleScenario = "no-kimi-smoke" | "evidence-block" | "fallback-route" | "dag-dependent-block" | "replay-inspect" | "graph-audit" | "example-generation" | "doctor-provider" | "contract-version-smoke";
|
|
3
3
|
export type ProofBundleVerdict = "passed" | "failed" | "partial";
|
|
4
4
|
export type ProofBundleFiles = {
|
|
5
5
|
rawPrompt: string;
|
|
@@ -95,6 +95,21 @@ export interface NextPromptResult {
|
|
|
95
95
|
}
|
|
96
96
|
export declare function recallMemoryForGoal(goal: GoalSpec, root: string, runState?: RunState, signal?: AbortSignal): Promise<string>;
|
|
97
97
|
export declare function generateNextPrompt(goal: GoalSpec, evidence: GoalEvidence[], runState?: RunState, memorySummary?: string, root?: string): Promise<NextPromptResult>;
|
|
98
|
+
/** Buckets of run-state nodes grouped by lifecycle status. */
|
|
99
|
+
export interface RunStateNodeBuckets {
|
|
100
|
+
failed: RunState["nodes"];
|
|
101
|
+
blocked: RunState["nodes"];
|
|
102
|
+
running: RunState["nodes"];
|
|
103
|
+
pending: RunState["nodes"];
|
|
104
|
+
success: RunState["nodes"];
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Classify `runState.nodes` into status buckets in a SINGLE pass. Behavior-preserving
|
|
108
|
+
* replacement for five separate `.filter()` passes: each bucket holds exactly the nodes
|
|
109
|
+
* the matching `status === ...` filter would have selected, in the same order. `success`
|
|
110
|
+
* collects `status === "done"` nodes. Statuses outside these five are ignored.
|
|
111
|
+
*/
|
|
112
|
+
export declare function bucketRunStateNodesByStatus(runState: RunState | undefined): RunStateNodeBuckets;
|
|
98
113
|
/**
|
|
99
114
|
* Evaluate which success criteria still lack passing evidence.
|
|
100
115
|
* Returns ordered list with required criteria first, then by weight desc.
|
|
@@ -858,6 +858,41 @@ export async function generateNextPrompt(goal, evidence, runState, memorySummary
|
|
|
858
858
|
};
|
|
859
859
|
});
|
|
860
860
|
}
|
|
861
|
+
/**
|
|
862
|
+
* Classify `runState.nodes` into status buckets in a SINGLE pass. Behavior-preserving
|
|
863
|
+
* replacement for five separate `.filter()` passes: each bucket holds exactly the nodes
|
|
864
|
+
* the matching `status === ...` filter would have selected, in the same order. `success`
|
|
865
|
+
* collects `status === "done"` nodes. Statuses outside these five are ignored.
|
|
866
|
+
*/
|
|
867
|
+
export function bucketRunStateNodesByStatus(runState) {
|
|
868
|
+
const failed = [];
|
|
869
|
+
const blocked = [];
|
|
870
|
+
const running = [];
|
|
871
|
+
const pending = [];
|
|
872
|
+
const success = [];
|
|
873
|
+
for (const node of runState?.nodes ?? []) {
|
|
874
|
+
switch (node.status) {
|
|
875
|
+
case "failed":
|
|
876
|
+
failed.push(node);
|
|
877
|
+
break;
|
|
878
|
+
case "blocked":
|
|
879
|
+
blocked.push(node);
|
|
880
|
+
break;
|
|
881
|
+
case "running":
|
|
882
|
+
running.push(node);
|
|
883
|
+
break;
|
|
884
|
+
case "pending":
|
|
885
|
+
pending.push(node);
|
|
886
|
+
break;
|
|
887
|
+
case "done":
|
|
888
|
+
success.push(node);
|
|
889
|
+
break;
|
|
890
|
+
default:
|
|
891
|
+
break;
|
|
892
|
+
}
|
|
893
|
+
}
|
|
894
|
+
return { failed, blocked, running, pending, success };
|
|
895
|
+
}
|
|
861
896
|
async function generateNextPromptInner(goal, evidence, runState, memorySummary, root, signal) {
|
|
862
897
|
if (signal?.aborted)
|
|
863
898
|
throw signal.reason ?? new Error("Aborted");
|
|
@@ -880,11 +915,10 @@ async function generateNextPromptInner(goal, evidence, runState, memorySummary,
|
|
|
880
915
|
const ev = evidence.find((e) => e.criterionId === c.id);
|
|
881
916
|
return ev?.passed ?? false;
|
|
882
917
|
});
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
const
|
|
887
|
-
const successNodes = runState?.nodes.filter((n) => n.status === "done") ?? [];
|
|
918
|
+
// Single pass over runState.nodes replaces five separate .filter() passes per
|
|
919
|
+
// iteration. Bucket contents and order are identical to the prior per-status
|
|
920
|
+
// filters because nodes are appended in iteration order.
|
|
921
|
+
const { failed: failedNodes, blocked: blockedNodes, running: runningNodes, pending: pendingNodes, success: successNodes, } = bucketRunStateNodesByStatus(runState);
|
|
888
922
|
const proposedAction = suggestion.type === "close"
|
|
889
923
|
? "close"
|
|
890
924
|
: failedNodes.length > 0 || blockedNodes.length > 0
|
package/dist/hud/render.d.ts
CHANGED
|
@@ -29,6 +29,8 @@ export interface HudRenderOptions {
|
|
|
29
29
|
showUptime?: boolean;
|
|
30
30
|
systemRefreshMs?: number;
|
|
31
31
|
thinking?: import("./types.js").HudThinkingEntry[];
|
|
32
|
+
/** Optional live brand theme override; OMK_THEME is used when this is absent. */
|
|
33
|
+
theme?: string;
|
|
32
34
|
/** Current working phase for gradient-animated status line */
|
|
33
35
|
workingPhase?: import("../theme/working-indicator.js").WorkingPhase | null;
|
|
34
36
|
/** Spinner animation type (defaults to "braille") */
|
package/dist/hud/render.js
CHANGED
|
@@ -12,6 +12,8 @@ import { t } from "../util/i18n.js";
|
|
|
12
12
|
import { parseRunStateResult, buildRunViewModel, renderRunSummary, sanitizeForDisplay, } from "../util/run-view-model.js";
|
|
13
13
|
import { hudTheme } from "../util/theme.js";
|
|
14
14
|
import { renderWorkingIndicator } from "../theme/working-indicator.js";
|
|
15
|
+
import { setBrandPaletteTheme } from "../brand/palette.js";
|
|
16
|
+
import { getActiveBrandHudStatus } from "../brand/theme-compiled.js";
|
|
15
17
|
import { loadTodos } from "../util/todo-sync.js";
|
|
16
18
|
import { readSessionMeta } from "../util/session.js";
|
|
17
19
|
const theme = hudTheme;
|
|
@@ -254,7 +256,7 @@ function renderNeonControlHeader(runId, workingPhase, workingSpinner) {
|
|
|
254
256
|
const parts = [
|
|
255
257
|
"",
|
|
256
258
|
theme.style.phosphor("OMK//HUD") + " " + runLabel,
|
|
257
|
-
theme.style.gray(
|
|
259
|
+
theme.style.gray(getActiveBrandHudStatus()),
|
|
258
260
|
theme.style.gray("Route agents. Verify evidence. Control the loop."),
|
|
259
261
|
];
|
|
260
262
|
if (workingLine) {
|
|
@@ -940,6 +942,10 @@ async function renderSectionDashboard(options) {
|
|
|
940
942
|
return output.join("\n");
|
|
941
943
|
}
|
|
942
944
|
export async function renderHudDashboard(options = {}) {
|
|
945
|
+
const requestedBrandTheme = options.theme ?? process.env.OMK_THEME;
|
|
946
|
+
if (requestedBrandTheme !== undefined) {
|
|
947
|
+
setBrandPaletteTheme(requestedBrandTheme);
|
|
948
|
+
}
|
|
943
949
|
const width = options.terminalWidth ?? defaultHudTerminalWidth();
|
|
944
950
|
if (options.section) {
|
|
945
951
|
return renderSectionDashboard(options);
|
|
@@ -168,6 +168,12 @@ export declare class SecretScanner extends EventEmitter {
|
|
|
168
168
|
static severityIcon(severity: SecretSeverity): string;
|
|
169
169
|
private findInText;
|
|
170
170
|
private redactText;
|
|
171
|
+
/**
|
|
172
|
+
* Precompute the byte offset at which each line begins.
|
|
173
|
+
* lineStarts[0] is always 0; each subsequent entry is the index just after a
|
|
174
|
+
* "\n". Used to make getLineColumn O(log n) per lookup instead of O(offset).
|
|
175
|
+
*/
|
|
176
|
+
private computeLineStarts;
|
|
171
177
|
private getLineColumn;
|
|
172
178
|
private getContext;
|
|
173
179
|
private readFileSafe;
|
|
@@ -313,13 +313,14 @@ export class SecretScanner extends EventEmitter {
|
|
|
313
313
|
const findings = [];
|
|
314
314
|
let redacted = text;
|
|
315
315
|
const activePatterns = this.getActivePatterns();
|
|
316
|
+
const lineStarts = this.computeLineStarts(text);
|
|
316
317
|
for (const pattern of activePatterns) {
|
|
317
318
|
pattern.pattern.lastIndex = 0;
|
|
318
319
|
let match;
|
|
319
320
|
while ((match = pattern.pattern.exec(text)) !== null) {
|
|
320
321
|
const matchedText = match[0];
|
|
321
322
|
const offset = match.index;
|
|
322
|
-
const { line, column } = this.getLineColumn(text, offset);
|
|
323
|
+
const { line, column } = this.getLineColumn(text, offset, lineStarts);
|
|
323
324
|
const context = this.getContext(text, offset, matchedText.length);
|
|
324
325
|
findings.push({
|
|
325
326
|
id: this.generateId(),
|
|
@@ -519,13 +520,14 @@ export class SecretScanner extends EventEmitter {
|
|
|
519
520
|
findInText(text, sourceFile) {
|
|
520
521
|
const findings = [];
|
|
521
522
|
const activePatterns = this.getActivePatterns();
|
|
523
|
+
const lineStarts = this.computeLineStarts(text);
|
|
522
524
|
for (const pattern of activePatterns) {
|
|
523
525
|
pattern.pattern.lastIndex = 0;
|
|
524
526
|
let match;
|
|
525
527
|
while ((match = pattern.pattern.exec(text)) !== null) {
|
|
526
528
|
const matchedText = match[0];
|
|
527
529
|
const offset = match.index;
|
|
528
|
-
const { line, column } = this.getLineColumn(text, offset);
|
|
530
|
+
const { line, column } = this.getLineColumn(text, offset, lineStarts);
|
|
529
531
|
const context = this.getContext(text, offset, matchedText.length);
|
|
530
532
|
findings.push({
|
|
531
533
|
id: this.generateId(),
|
|
@@ -553,19 +555,50 @@ export class SecretScanner extends EventEmitter {
|
|
|
553
555
|
}
|
|
554
556
|
return result;
|
|
555
557
|
}
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
558
|
+
/**
|
|
559
|
+
* Precompute the byte offset at which each line begins.
|
|
560
|
+
* lineStarts[0] is always 0; each subsequent entry is the index just after a
|
|
561
|
+
* "\n". Used to make getLineColumn O(log n) per lookup instead of O(offset).
|
|
562
|
+
*/
|
|
563
|
+
computeLineStarts(text) {
|
|
564
|
+
const lineStarts = [0];
|
|
565
|
+
for (let i = 0; i < text.length; i++) {
|
|
566
|
+
if (text[i] === "\n")
|
|
567
|
+
lineStarts.push(i + 1);
|
|
568
|
+
}
|
|
569
|
+
return lineStarts;
|
|
570
|
+
}
|
|
571
|
+
getLineColumn(text, offset, lineStarts) {
|
|
572
|
+
// Backward-compatible fallback: original O(offset) scan when no precomputed
|
|
573
|
+
// index is supplied. Produces identical line/column numbers.
|
|
574
|
+
if (!lineStarts) {
|
|
575
|
+
let line = 1;
|
|
576
|
+
let column = 1;
|
|
577
|
+
for (let i = 0; i < offset && i < text.length; i++) {
|
|
578
|
+
if (text[i] === "\n") {
|
|
579
|
+
line++;
|
|
580
|
+
column = 1;
|
|
581
|
+
}
|
|
582
|
+
else {
|
|
583
|
+
column++;
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
return { line, column };
|
|
587
|
+
}
|
|
588
|
+
// Binary search for the rightmost line start that is <= offset.
|
|
589
|
+
let lo = 0;
|
|
590
|
+
let hi = lineStarts.length - 1;
|
|
591
|
+
while (lo < hi) {
|
|
592
|
+
const mid = (lo + hi + 1) >> 1;
|
|
593
|
+
if (lineStarts[mid] <= offset) {
|
|
594
|
+
lo = mid;
|
|
563
595
|
}
|
|
564
596
|
else {
|
|
565
|
-
|
|
597
|
+
hi = mid - 1;
|
|
566
598
|
}
|
|
567
599
|
}
|
|
568
|
-
|
|
600
|
+
const lineStartOffset = lineStarts[lo];
|
|
601
|
+
return { line: lo + 1, column: offset - lineStartOffset + 1 };
|
|
569
602
|
}
|
|
570
603
|
getContext(text, offset, matchLength) {
|
|
571
604
|
const ctxChars = this.contextChars;
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import type { LocalGraphState, LocalGraphNode, LocalGraphEdge } from "./local-graph-memory-store.js";
|
|
2
|
+
export interface DeltaRecord {
|
|
3
|
+
v: 2;
|
|
4
|
+
epoch: number;
|
|
5
|
+
seq: number;
|
|
6
|
+
ts: string;
|
|
7
|
+
meta: {
|
|
8
|
+
updatedAt: string;
|
|
9
|
+
project: {
|
|
10
|
+
key: string;
|
|
11
|
+
name: string;
|
|
12
|
+
root: string;
|
|
13
|
+
};
|
|
14
|
+
ontology: string;
|
|
15
|
+
};
|
|
16
|
+
nodes: {
|
|
17
|
+
del: string[];
|
|
18
|
+
put: LocalGraphNode[];
|
|
19
|
+
};
|
|
20
|
+
edges: {
|
|
21
|
+
del: string[];
|
|
22
|
+
put: LocalGraphEdge[];
|
|
23
|
+
};
|
|
24
|
+
crc: string;
|
|
25
|
+
}
|
|
26
|
+
export interface DeltaManifest {
|
|
27
|
+
formatVersion: 2;
|
|
28
|
+
snapshot: string;
|
|
29
|
+
snapshotEpoch: number;
|
|
30
|
+
delta: string;
|
|
31
|
+
deltaOpCount: number;
|
|
32
|
+
}
|
|
33
|
+
export type DurabilityMode = "legacy" | "delta";
|
|
34
|
+
export declare function resolveDurabilityMode(env?: NodeJS.ProcessEnv): DurabilityMode;
|
|
35
|
+
/**
|
|
36
|
+
* Compute an order-faithful delta between pre-mutation and post-mutation state.
|
|
37
|
+
* `put` entries are ordered by their index in the final array and repositioned
|
|
38
|
+
* entries are deleted-before-put, so Map-based replay reproduces the EXACT raw
|
|
39
|
+
* array order of the legacy full-rewrite (see `computeOrderedDelta`).
|
|
40
|
+
*/
|
|
41
|
+
export declare function computeDelta(preNodes: ReadonlyMap<string, LocalGraphNode>, preEdges: ReadonlyMap<string, LocalGraphEdge>, state: LocalGraphState): {
|
|
42
|
+
nodes: {
|
|
43
|
+
del: string[];
|
|
44
|
+
put: LocalGraphNode[];
|
|
45
|
+
};
|
|
46
|
+
edges: {
|
|
47
|
+
del: string[];
|
|
48
|
+
put: LocalGraphEdge[];
|
|
49
|
+
};
|
|
50
|
+
};
|
|
51
|
+
export declare function readManifest(graphPath: string): Promise<DeltaManifest | null>;
|
|
52
|
+
export declare function writeManifest(graphPath: string, manifest: DeltaManifest): Promise<void>;
|
|
53
|
+
/**
|
|
54
|
+
* Append a single delta record to the journal + fdatasync.
|
|
55
|
+
* Returns the seq number assigned to the record.
|
|
56
|
+
*/
|
|
57
|
+
export declare function appendDelta(graphPath: string, epoch: number, seq: number, ts: string, meta: DeltaRecord["meta"], nodesDelta: {
|
|
58
|
+
del: string[];
|
|
59
|
+
put: LocalGraphNode[];
|
|
60
|
+
}, edgesDelta: {
|
|
61
|
+
del: string[];
|
|
62
|
+
put: LocalGraphEdge[];
|
|
63
|
+
}): Promise<void>;
|
|
64
|
+
/**
|
|
65
|
+
* Load snapshot from disk plus replay all valid delta records.
|
|
66
|
+
*
|
|
67
|
+
* Replay correctness lemma:
|
|
68
|
+
* 1. Base: nodes/edges loaded from snapshot into insertion-ordered Map.
|
|
69
|
+
* 2. For each record with epoch === currentEpoch:
|
|
70
|
+
* a. Apply all `del` ids: Map.delete(key).
|
|
71
|
+
* b. Apply all `put` entries in array order: Map.set(key, entry).
|
|
72
|
+
* Map.set on existing key keeps position; on new/deleted key appends.
|
|
73
|
+
* 3. Materialize: `[...map.values()]` produces the exact same array order
|
|
74
|
+
* as the full-rewrite saveState().
|
|
75
|
+
*
|
|
76
|
+
* Crash recovery: the last line of the delta log may be torn. If JSON.parse
|
|
77
|
+
* fails AND it is the last line, we treat it as a torn tail and discard it.
|
|
78
|
+
* A CRC mismatch on a non-final line is corruption → throws in strict mode.
|
|
79
|
+
*/
|
|
80
|
+
export declare function replayDeltas(baseState: LocalGraphState, records: DeltaRecord[], epoch: number): LocalGraphState;
|
|
81
|
+
export interface DeltaParseResult {
|
|
82
|
+
records: DeltaRecord[];
|
|
83
|
+
/** Byte offset (exclusive end) of the last valid, newline-terminated record. */
|
|
84
|
+
validBytes: number;
|
|
85
|
+
/** True when a trailing, non-newline-terminated partial record was detected. */
|
|
86
|
+
torn: boolean;
|
|
87
|
+
}
|
|
88
|
+
export interface DeltaLoadResult {
|
|
89
|
+
state: LocalGraphState;
|
|
90
|
+
epoch: number;
|
|
91
|
+
lastSeq: number;
|
|
92
|
+
deltaOpCount: number;
|
|
93
|
+
/** Byte offset of the last valid record == where the next append lands. */
|
|
94
|
+
validBytes: number;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Full cold load in delta mode: manifest → snapshot → replay delta tail.
|
|
98
|
+
*
|
|
99
|
+
* Torn-tail recovery: if the log ends in a partial (non-newline-terminated)
|
|
100
|
+
* record, physically truncate the file to the last valid record boundary BEFORE
|
|
101
|
+
* returning, so the next O_APPEND write can never merge into the half-written
|
|
102
|
+
* line. Any cached append fd is closed first to drop the stale handle.
|
|
103
|
+
*/
|
|
104
|
+
export declare function loadStateViaDelta(graphPath: string, strict: boolean, emptyState: LocalGraphState): Promise<DeltaLoadResult>;
|
|
105
|
+
/**
|
|
106
|
+
* One-time setup: load legacy graph-state.json (or empty), write snapshot,
|
|
107
|
+
* write manifest, create empty delta log. Does NOT delete the legacy file.
|
|
108
|
+
* If manifest already exists, this is a no-op.
|
|
109
|
+
*/
|
|
110
|
+
export declare function setupDeltaMode(graphPath: string, legacyState: LocalGraphState): Promise<DeltaManifest>;
|
|
111
|
+
export interface CompactionThresholds {
|
|
112
|
+
maxBytes: number;
|
|
113
|
+
maxOps: number;
|
|
114
|
+
}
|
|
115
|
+
export declare function resolveCompactionThresholds(env?: NodeJS.ProcessEnv): CompactionThresholds;
|
|
116
|
+
/**
|
|
117
|
+
* Check if compaction is needed and perform it if so.
|
|
118
|
+
* Procedure: write snapshot → write new manifest (commit pivot) → truncate delta.
|
|
119
|
+
* The manifest is the single commit point; crash before manifest pivot is safe.
|
|
120
|
+
*/
|
|
121
|
+
export declare function compactIfNeeded(graphPath: string, state: LocalGraphState, currentEpoch: number, currentOpCount: number, thresholds: CompactionThresholds): Promise<{
|
|
122
|
+
compacted: boolean;
|
|
123
|
+
newEpoch: number;
|
|
124
|
+
newOpCount: number;
|
|
125
|
+
}>;
|
|
126
|
+
export interface DeltaFileStats {
|
|
127
|
+
snapshotMtimeMs: number;
|
|
128
|
+
snapshotSize: number;
|
|
129
|
+
snapshotCtimeMs: number;
|
|
130
|
+
snapshotIno: number;
|
|
131
|
+
deltaSize: number;
|
|
132
|
+
}
|
|
133
|
+
export declare function statDeltaFiles(graphPath: string): DeltaFileStats | null;
|
|
134
|
+
export declare function deltaStatsMatch(a: DeltaFileStats | null, b: DeltaFileStats | null): boolean;
|
|
135
|
+
export declare function acquireDeltaLock(graphPath: string, maxWaitMs?: number): Promise<void>;
|
|
136
|
+
export declare function releaseDeltaLock(graphPath: string): void;
|
|
137
|
+
export declare function withDeltaLock<T>(graphPath: string, fn: () => Promise<T>, env?: NodeJS.ProcessEnv, maxWaitMs?: number): Promise<T>;
|