@openclawbrain/openclaw 0.2.2 → 0.2.3
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/LICENSE +201 -0
- package/README.md +10 -0
- package/dist/src/cli.d.ts +61 -3
- package/dist/src/cli.js +1424 -167
- package/dist/src/cli.js.map +1 -1
- package/dist/src/daemon.js +55 -0
- package/dist/src/daemon.js.map +1 -1
- package/dist/src/index.d.ts +64 -3
- package/dist/src/index.js +399 -35
- package/dist/src/index.js.map +1 -1
- package/dist/src/local-session-passive-learning.d.ts +1 -0
- package/dist/src/local-session-passive-learning.js +97 -7
- package/dist/src/local-session-passive-learning.js.map +1 -1
- package/dist/src/resolve-activation-root.js +44 -21
- package/dist/src/resolve-activation-root.js.map +1 -1
- package/dist/src/session-store.d.ts +18 -0
- package/dist/src/session-store.js +40 -0
- package/dist/src/session-store.js.map +1 -1
- package/dist/src/session-tail.d.ts +6 -3
- package/dist/src/session-tail.js +35 -4
- package/dist/src/session-tail.js.map +1 -1
- package/extension/index.ts +69 -34
- package/extension/runtime-guard.ts +338 -0
- package/package.json +12 -13
package/dist/src/index.js
CHANGED
|
@@ -229,6 +229,19 @@ function cloneAlwaysOnLearningMaterializationJobOrNull(value) {
|
|
|
229
229
|
function cloneTeacherSupervisionArtifacts(value) {
|
|
230
230
|
return [...structuredClone(value)];
|
|
231
231
|
}
|
|
232
|
+
function cloneAsyncTeacherSnapshotState(value) {
|
|
233
|
+
if (value === undefined) {
|
|
234
|
+
return undefined;
|
|
235
|
+
}
|
|
236
|
+
return {
|
|
237
|
+
interactionEvents: [...structuredClone(value.interactionEvents)],
|
|
238
|
+
feedbackEvents: [...structuredClone(value.feedbackEvents)],
|
|
239
|
+
seenExportDigests: [...value.seenExportDigests]
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
function cloneAsyncTeacherSnapshotRuntime(value) {
|
|
243
|
+
return value === undefined ? undefined : { ...value };
|
|
244
|
+
}
|
|
232
245
|
function cloneCanonicalSupervision(value) {
|
|
233
246
|
return structuredClone(value);
|
|
234
247
|
}
|
|
@@ -548,6 +561,25 @@ export class AsyncTeacherLiveLoop {
|
|
|
548
561
|
if (!Number.isInteger(this.staleAfterMs) || this.staleAfterMs <= 0) {
|
|
549
562
|
throw new Error("staleAfterMs must be a positive integer");
|
|
550
563
|
}
|
|
564
|
+
const resumedSnapshot = input.resumeFromSnapshot;
|
|
565
|
+
if (resumedSnapshot !== undefined && resumedSnapshot !== null) {
|
|
566
|
+
if (resumedSnapshot.runtimeOwner !== "openclaw") {
|
|
567
|
+
throw new Error("async teacher resume snapshot runtimeOwner must be openclaw");
|
|
568
|
+
}
|
|
569
|
+
this.interactionEvents = [...structuredClone(resumedSnapshot.state?.interactionEvents ?? [])];
|
|
570
|
+
this.feedbackEvents = [...structuredClone(resumedSnapshot.state?.feedbackEvents ?? [])];
|
|
571
|
+
this.teacherArtifacts = cloneTeacherSupervisionArtifacts(resumedSnapshot.teacher.artifacts);
|
|
572
|
+
this.learnerState = structuredClone(resumedSnapshot.learner.state);
|
|
573
|
+
this.lastMaterialization = cloneAlwaysOnLearningMaterializationJobOrNull(resumedSnapshot.learner.lastMaterialization);
|
|
574
|
+
this.diagnostics = {
|
|
575
|
+
...structuredClone(resumedSnapshot.diagnostics),
|
|
576
|
+
notes: [...resumedSnapshot.diagnostics.notes]
|
|
577
|
+
};
|
|
578
|
+
for (const exportDigest of resumedSnapshot.state?.seenExportDigests ?? []) {
|
|
579
|
+
this.seenExportDigests.add(exportDigest);
|
|
580
|
+
}
|
|
581
|
+
this.refreshNotes();
|
|
582
|
+
}
|
|
551
583
|
}
|
|
552
584
|
enqueueNormalizedEventExport(normalizedEventExport, options = {}) {
|
|
553
585
|
const validationErrors = validateNormalizedEventExport(normalizedEventExport);
|
|
@@ -745,6 +777,11 @@ export class AsyncTeacherLiveLoop {
|
|
|
745
777
|
diagnostics: {
|
|
746
778
|
...this.diagnostics,
|
|
747
779
|
notes: [...this.diagnostics.notes]
|
|
780
|
+
},
|
|
781
|
+
state: {
|
|
782
|
+
interactionEvents: [...structuredClone(this.interactionEvents)],
|
|
783
|
+
feedbackEvents: [...structuredClone(this.feedbackEvents)],
|
|
784
|
+
seenExportDigests: [...this.seenExportDigests].sort()
|
|
748
785
|
}
|
|
749
786
|
};
|
|
750
787
|
}
|
|
@@ -781,6 +818,7 @@ export class AsyncTeacherLiveLoop {
|
|
|
781
818
|
const emittedArtifactCount = builtArtifacts.filter((artifact) => !currentDedupIds.has(artifact.dedupId)).length;
|
|
782
819
|
const dedupedArtifactCount = builtArtifacts.length - emittedArtifactCount;
|
|
783
820
|
this.teacherArtifacts = nextTeacherArtifacts;
|
|
821
|
+
const learnedRoutingState = this.input.resolveLearnedRoutingState?.() ?? {};
|
|
784
822
|
const learnerResult = advanceAlwaysOnLearningRuntime({
|
|
785
823
|
packLabel: this.input.packLabel,
|
|
786
824
|
workspace: this.input.workspace,
|
|
@@ -795,10 +833,17 @@ export class AsyncTeacherLiveLoop {
|
|
|
795
833
|
...(this.input.sparseFeedback !== undefined ? { sparseFeedback: this.input.sparseFeedback } : {}),
|
|
796
834
|
...(this.input.liveSliceSize !== undefined ? { liveSliceSize: this.input.liveSliceSize } : {}),
|
|
797
835
|
...(this.input.backfillSliceSize !== undefined ? { backfillSliceSize: this.input.backfillSliceSize } : {}),
|
|
798
|
-
...(this.input.cadence !== undefined ? { cadence: this.input.cadence } : {})
|
|
836
|
+
...(this.input.cadence !== undefined ? { cadence: this.input.cadence } : {}),
|
|
837
|
+
...(learnedRoutingState.pgVersion !== undefined ? { pgVersion: learnedRoutingState.pgVersion } : {}),
|
|
838
|
+
...(learnedRoutingState.serveTimeDecisions !== undefined ? { serveTimeDecisions: learnedRoutingState.serveTimeDecisions } : {}),
|
|
839
|
+
...(learnedRoutingState.baselineState !== undefined ? { baselineState: learnedRoutingState.baselineState } : {})
|
|
799
840
|
});
|
|
800
841
|
this.learnerState = structuredClone(learnerResult.state);
|
|
801
842
|
this.lastMaterialization = cloneAlwaysOnLearningMaterializationJobOrNull(learnerResult.materialization);
|
|
843
|
+
const updatedBaseline = learnerResult.materialization?.candidate.routingBuild.updatedBaseline ?? null;
|
|
844
|
+
if (updatedBaseline !== null) {
|
|
845
|
+
this.input.persistUpdatedBaseline?.(structuredClone(updatedBaseline));
|
|
846
|
+
}
|
|
802
847
|
this.diagnostics.processedExportCount += 1;
|
|
803
848
|
this.diagnostics.emittedArtifactCount += emittedArtifactCount;
|
|
804
849
|
this.diagnostics.dedupedArtifactCount += dedupedArtifactCount;
|
|
@@ -927,18 +972,53 @@ export function scanLiveEventExport(input) {
|
|
|
927
972
|
})
|
|
928
973
|
}
|
|
929
974
|
};
|
|
975
|
+
const labelFlow = summarizeNormalizedEventExportLabelFlow(normalizedEventExport, teacherArtifacts.length);
|
|
976
|
+
const learningPath = summarizeLearningPathFromMaterialization(learnerResult.materialization);
|
|
930
977
|
return {
|
|
931
978
|
runtimeOwner: "openclaw",
|
|
932
979
|
scanMode: "live",
|
|
933
980
|
observedAt,
|
|
934
981
|
packLabel,
|
|
935
982
|
supervision: buildCanonicalSupervision(normalizedEventExport),
|
|
936
|
-
snapshot
|
|
983
|
+
snapshot,
|
|
984
|
+
labelFlow,
|
|
985
|
+
learningPath
|
|
937
986
|
};
|
|
938
987
|
}
|
|
939
988
|
function readJsonFile(filePath) {
|
|
940
989
|
return JSON.parse(readFileSync(filePath, "utf8"));
|
|
941
990
|
}
|
|
991
|
+
export function resolveAsyncTeacherLiveLoopSnapshotPath(activationRoot) {
|
|
992
|
+
return path.join(path.resolve(normalizeNonEmptyString(activationRoot, "activationRoot")), "async-teacher-live-loop.snapshot.json");
|
|
993
|
+
}
|
|
994
|
+
export function loadAsyncTeacherLiveLoopSnapshot(snapshotPath) {
|
|
995
|
+
const snapshot = readJsonFile(path.resolve(snapshotPath));
|
|
996
|
+
if (snapshot.runtimeOwner !== "openclaw") {
|
|
997
|
+
throw new Error("async teacher snapshot runtimeOwner must be openclaw");
|
|
998
|
+
}
|
|
999
|
+
const cloned = {
|
|
1000
|
+
...snapshot,
|
|
1001
|
+
diagnostics: {
|
|
1002
|
+
...snapshot.diagnostics,
|
|
1003
|
+
notes: [...snapshot.diagnostics.notes]
|
|
1004
|
+
},
|
|
1005
|
+
teacher: {
|
|
1006
|
+
...snapshot.teacher,
|
|
1007
|
+
artifacts: cloneTeacherSupervisionArtifacts(snapshot.teacher.artifacts)
|
|
1008
|
+
},
|
|
1009
|
+
learner: {
|
|
1010
|
+
state: structuredClone(snapshot.learner.state),
|
|
1011
|
+
lastMaterialization: cloneAlwaysOnLearningMaterializationJobOrNull(snapshot.learner.lastMaterialization)
|
|
1012
|
+
}
|
|
1013
|
+
};
|
|
1014
|
+
if (snapshot.state !== undefined) {
|
|
1015
|
+
cloned.state = cloneAsyncTeacherSnapshotState(snapshot.state);
|
|
1016
|
+
}
|
|
1017
|
+
if (snapshot.runtime !== undefined) {
|
|
1018
|
+
cloned.runtime = cloneAsyncTeacherSnapshotRuntime(snapshot.runtime);
|
|
1019
|
+
}
|
|
1020
|
+
return cloned;
|
|
1021
|
+
}
|
|
942
1022
|
function resolveBundlePayloadPath(rootDir, payloadPath) {
|
|
943
1023
|
const resolved = path.resolve(rootDir, payloadPath);
|
|
944
1024
|
const relative = path.relative(rootDir, resolved);
|
|
@@ -1770,6 +1850,15 @@ function normalizeIsoTimestamp(value, fieldName, fallbackValue) {
|
|
|
1770
1850
|
function normalizeMode(value) {
|
|
1771
1851
|
return value ?? "heuristic";
|
|
1772
1852
|
}
|
|
1853
|
+
function normalizeCompileSelectionMode(value) {
|
|
1854
|
+
if (value === undefined) {
|
|
1855
|
+
return undefined;
|
|
1856
|
+
}
|
|
1857
|
+
if (value === "flat_rank_v1" || value === "graph_walk_v1") {
|
|
1858
|
+
return value;
|
|
1859
|
+
}
|
|
1860
|
+
throw new Error(`selectionMode must be flat_rank_v1 or graph_walk_v1, received ${String(value)}`);
|
|
1861
|
+
}
|
|
1773
1862
|
function normalizeRuntimeHints(value) {
|
|
1774
1863
|
if (value === undefined) {
|
|
1775
1864
|
return [];
|
|
@@ -1955,6 +2044,9 @@ export function formatPromptContext(compileResponse) {
|
|
|
1955
2044
|
lines.push("[/BRAIN_CONTEXT]");
|
|
1956
2045
|
return `${lines.join("\n")}\n`;
|
|
1957
2046
|
}
|
|
2047
|
+
function resolveActivationRootForFailure(value) {
|
|
2048
|
+
return path.resolve(normalizeOptionalString(value) ?? ".");
|
|
2049
|
+
}
|
|
1958
2050
|
function failOpenCompileResult(error, activationRoot) {
|
|
1959
2051
|
return {
|
|
1960
2052
|
ok: false,
|
|
@@ -1990,6 +2082,70 @@ function classifyCompileFailure(error, activationRoot) {
|
|
|
1990
2082
|
function uniqueNotes(notes) {
|
|
1991
2083
|
return [...new Set(notes.filter((note) => note.length > 0))];
|
|
1992
2084
|
}
|
|
2085
|
+
function buildServeRouteLogFailOpenWarning(scope, error) {
|
|
2086
|
+
return `learning spine serve route log failed open (${scope}): ${toErrorMessage(error)}`;
|
|
2087
|
+
}
|
|
2088
|
+
function buildServeRouteLogFailOpenNotes(scope, error) {
|
|
2089
|
+
return [
|
|
2090
|
+
"serve_route_log_status=fail_open",
|
|
2091
|
+
`serve_route_log_scope=${scope}`,
|
|
2092
|
+
`serve_route_log_error=${toErrorMessage(error)}`
|
|
2093
|
+
];
|
|
2094
|
+
}
|
|
2095
|
+
function normalizeServeRouteChannel(value) {
|
|
2096
|
+
if (typeof value !== "string") {
|
|
2097
|
+
return undefined;
|
|
2098
|
+
}
|
|
2099
|
+
const trimmed = value.trim();
|
|
2100
|
+
return trimmed.length > 0 ? trimmed : undefined;
|
|
2101
|
+
}
|
|
2102
|
+
function normalizeServeRouteMessage(value) {
|
|
2103
|
+
return typeof value === "string" ? value.trim() : "";
|
|
2104
|
+
}
|
|
2105
|
+
function appendCompileServeRouteDecisionLog(input) {
|
|
2106
|
+
if (input.compileInput._suppressServeLog) {
|
|
2107
|
+
return;
|
|
2108
|
+
}
|
|
2109
|
+
const recordedAt = new Date().toISOString();
|
|
2110
|
+
const sessionId = normalizeServeRouteChannel(input.compileInput.sessionId) ?? `ext-compile-${Date.now()}`;
|
|
2111
|
+
const channel = normalizeServeRouteChannel(input.compileInput.channel) ?? "extension";
|
|
2112
|
+
const syntheticTurn = {
|
|
2113
|
+
sessionId,
|
|
2114
|
+
channel,
|
|
2115
|
+
userMessage: input.userMessage,
|
|
2116
|
+
createdAt: recordedAt
|
|
2117
|
+
};
|
|
2118
|
+
if (input.compileInput.maxContextBlocks !== undefined) {
|
|
2119
|
+
syntheticTurn.maxContextBlocks = input.compileInput.maxContextBlocks;
|
|
2120
|
+
}
|
|
2121
|
+
if (input.compileInput.budgetStrategy === "fixed_v1" || input.compileInput.budgetStrategy === "empirical_v1") {
|
|
2122
|
+
syntheticTurn.budgetStrategy = input.compileInput.budgetStrategy;
|
|
2123
|
+
}
|
|
2124
|
+
if (input.compileInput.mode === "heuristic" || input.compileInput.mode === "learned") {
|
|
2125
|
+
syntheticTurn.mode = input.compileInput.mode;
|
|
2126
|
+
}
|
|
2127
|
+
if (input.compileInput.runtimeHints !== undefined) {
|
|
2128
|
+
syntheticTurn.runtimeHints = input.compileInput.runtimeHints;
|
|
2129
|
+
}
|
|
2130
|
+
try {
|
|
2131
|
+
appendServeTimeRouteDecisionLog({
|
|
2132
|
+
activationRoot: input.activationRoot,
|
|
2133
|
+
turn: syntheticTurn,
|
|
2134
|
+
compileResult: input.compileResult,
|
|
2135
|
+
recordedAt
|
|
2136
|
+
});
|
|
2137
|
+
}
|
|
2138
|
+
catch (error) {
|
|
2139
|
+
if (input.compileResult.ok) {
|
|
2140
|
+
input.compileResult.compileResponse.diagnostics.notes = uniqueNotes([
|
|
2141
|
+
...input.compileResult.compileResponse.diagnostics.notes,
|
|
2142
|
+
...buildServeRouteLogFailOpenNotes("compileRuntimeContext", error)
|
|
2143
|
+
]);
|
|
2144
|
+
}
|
|
2145
|
+
console.warn(`[openclawbrain] ${buildServeRouteLogFailOpenWarning("compileRuntimeContext", error)} ` +
|
|
2146
|
+
`(activationRoot=${input.activationRoot}, sessionId=${sessionId}, channel=${channel})`);
|
|
2147
|
+
}
|
|
2148
|
+
}
|
|
1993
2149
|
function roundMetric(value) {
|
|
1994
2150
|
return Math.round(value * 100) / 100;
|
|
1995
2151
|
}
|
|
@@ -2220,24 +2376,52 @@ export function resolveActivePackForCompile(activationRoot) {
|
|
|
2220
2376
|
};
|
|
2221
2377
|
}
|
|
2222
2378
|
export function compileRuntimeContext(input) {
|
|
2223
|
-
const
|
|
2224
|
-
|
|
2225
|
-
|
|
2379
|
+
const fallbackActivationRoot = resolveActivationRootForFailure(input.activationRoot);
|
|
2380
|
+
let activationRoot = fallbackActivationRoot;
|
|
2381
|
+
let agentId = process.env.OPENCLAWBRAIN_AGENT_ID ?? DEFAULT_AGENT_ID;
|
|
2382
|
+
let runtimeHints = [];
|
|
2383
|
+
let selectionMode;
|
|
2384
|
+
let userMessage = "";
|
|
2385
|
+
let maxContextChars;
|
|
2386
|
+
let mode = "heuristic";
|
|
2387
|
+
let result;
|
|
2388
|
+
try {
|
|
2389
|
+
activationRoot = path.resolve(normalizeNonEmptyString(input.activationRoot, "activationRoot"));
|
|
2390
|
+
agentId = normalizeOptionalString(input.agentId) ?? process.env.OPENCLAWBRAIN_AGENT_ID ?? DEFAULT_AGENT_ID;
|
|
2391
|
+
runtimeHints = normalizeRuntimeHints(input.runtimeHints);
|
|
2392
|
+
selectionMode = normalizeCompileSelectionMode(input.selectionMode);
|
|
2393
|
+
userMessage = normalizeNonEmptyString(input.message, "message");
|
|
2394
|
+
maxContextChars =
|
|
2395
|
+
input.maxContextChars !== undefined
|
|
2396
|
+
? normalizeNonNegativeInteger(input.maxContextChars, "maxContextChars", input.maxContextChars)
|
|
2397
|
+
: undefined;
|
|
2398
|
+
mode = normalizeMode(input.mode);
|
|
2399
|
+
}
|
|
2400
|
+
catch (error) {
|
|
2401
|
+
result = failOpenCompileResult(error, fallbackActivationRoot);
|
|
2402
|
+
appendCompileServeRouteDecisionLog({
|
|
2403
|
+
compileInput: input,
|
|
2404
|
+
activationRoot: result.activationRoot,
|
|
2405
|
+
compileResult: result,
|
|
2406
|
+
userMessage: normalizeServeRouteMessage(input.message)
|
|
2407
|
+
});
|
|
2408
|
+
return result;
|
|
2409
|
+
}
|
|
2226
2410
|
try {
|
|
2227
2411
|
const target = resolveActivePackForCompile(activationRoot);
|
|
2228
2412
|
const resolvedBudget = resolveCompileBudget(target, input);
|
|
2229
2413
|
const compile = compileRuntimeFromActivation(activationRoot, {
|
|
2230
2414
|
contract: CONTRACT_IDS.runtimeCompile,
|
|
2231
2415
|
agentId,
|
|
2232
|
-
userMessage
|
|
2416
|
+
userMessage,
|
|
2233
2417
|
maxContextBlocks: resolvedBudget.maxContextBlocks,
|
|
2234
|
-
...(
|
|
2235
|
-
|
|
2236
|
-
: {}),
|
|
2237
|
-
modeRequested: normalizeMode(input.mode),
|
|
2418
|
+
...(maxContextChars !== undefined ? { maxContextChars } : {}),
|
|
2419
|
+
modeRequested: mode,
|
|
2238
2420
|
activePackId: target.activePointer.packId,
|
|
2239
2421
|
...(input.compactionMode !== undefined ? { compactionMode: input.compactionMode } : {}),
|
|
2240
2422
|
...(runtimeHints.length > 0 ? { runtimeHints } : {})
|
|
2423
|
+
}, {
|
|
2424
|
+
...(selectionMode !== undefined ? { selectionMode } : {})
|
|
2241
2425
|
});
|
|
2242
2426
|
const compileResponse = {
|
|
2243
2427
|
...compile.response,
|
|
@@ -2246,7 +2430,7 @@ export function compileRuntimeContext(input) {
|
|
|
2246
2430
|
notes: uniqueNotes([...compile.response.diagnostics.notes, ...resolvedBudget.notes, "OpenClaw remains the runtime owner"])
|
|
2247
2431
|
}
|
|
2248
2432
|
};
|
|
2249
|
-
|
|
2433
|
+
result = {
|
|
2250
2434
|
ok: true,
|
|
2251
2435
|
fallbackToStaticContext: false,
|
|
2252
2436
|
hardRequirementViolated: false,
|
|
@@ -2258,8 +2442,15 @@ export function compileRuntimeContext(input) {
|
|
|
2258
2442
|
};
|
|
2259
2443
|
}
|
|
2260
2444
|
catch (error) {
|
|
2261
|
-
|
|
2445
|
+
result = classifyCompileFailure(error, activationRoot);
|
|
2262
2446
|
}
|
|
2447
|
+
appendCompileServeRouteDecisionLog({
|
|
2448
|
+
compileInput: input,
|
|
2449
|
+
activationRoot: result.activationRoot,
|
|
2450
|
+
compileResult: result,
|
|
2451
|
+
userMessage
|
|
2452
|
+
});
|
|
2453
|
+
return result;
|
|
2263
2454
|
}
|
|
2264
2455
|
function readDiagnosticNoteValue(notes, prefix) {
|
|
2265
2456
|
const note = notes.find((entry) => entry.startsWith(prefix));
|
|
@@ -3082,29 +3273,33 @@ export function writeScannedEventExportBundle(input) {
|
|
|
3082
3273
|
});
|
|
3083
3274
|
}
|
|
3084
3275
|
export function runRuntimeTurn(turn, options = {}) {
|
|
3276
|
+
const warnings = [];
|
|
3085
3277
|
const agentId = normalizeOptionalString(turn.agentId);
|
|
3086
3278
|
const compileInput = {
|
|
3087
|
-
activationRoot: options.activationRoot ??
|
|
3088
|
-
message:
|
|
3279
|
+
activationRoot: (options.activationRoot ?? turn.activationRoot),
|
|
3280
|
+
message: turn.userMessage,
|
|
3089
3281
|
...(agentId !== undefined ? { agentId } : {}),
|
|
3090
3282
|
...(turn.maxContextBlocks !== undefined ? { maxContextBlocks: turn.maxContextBlocks } : {}),
|
|
3091
3283
|
...(turn.budgetStrategy !== undefined ? { budgetStrategy: turn.budgetStrategy } : {}),
|
|
3092
3284
|
...(turn.mode !== undefined ? { mode: turn.mode } : {}),
|
|
3093
|
-
...(turn.
|
|
3285
|
+
...(turn.selectionMode !== undefined ? { selectionMode: turn.selectionMode } : {}),
|
|
3286
|
+
...(turn.runtimeHints !== undefined ? { runtimeHints: turn.runtimeHints } : {}),
|
|
3287
|
+
_suppressServeLog: true
|
|
3094
3288
|
};
|
|
3095
3289
|
const compileResult = compileRuntimeContext(compileInput);
|
|
3096
|
-
const warnings = [];
|
|
3097
3290
|
const serveLoggedAt = turn.compile?.createdAt ?? turn.createdAt ?? new Date().toISOString();
|
|
3098
3291
|
if (!compileResult.ok && compileResult.hardRequirementViolated) {
|
|
3099
3292
|
try {
|
|
3100
3293
|
appendServeTimeRouteDecisionLog({
|
|
3101
|
-
activationRoot:
|
|
3294
|
+
activationRoot: compileResult.activationRoot,
|
|
3102
3295
|
turn,
|
|
3103
3296
|
compileResult,
|
|
3104
3297
|
recordedAt: serveLoggedAt
|
|
3105
3298
|
});
|
|
3106
3299
|
}
|
|
3107
|
-
catch {
|
|
3300
|
+
catch (error) {
|
|
3301
|
+
console.warn(`[openclawbrain] serve-time route decision log failed before hard-fail throw: ${toErrorMessage(error)} ` +
|
|
3302
|
+
`(activationRoot=${compileResult.activationRoot}, sessionId=${turn.sessionId}, channel=${turn.channel})`);
|
|
3108
3303
|
}
|
|
3109
3304
|
throw new Error(compileResult.error);
|
|
3110
3305
|
}
|
|
@@ -3113,7 +3308,7 @@ export function runRuntimeTurn(turn, options = {}) {
|
|
|
3113
3308
|
try {
|
|
3114
3309
|
const compileEvent = normalizedEventExport.interactionEvents.find((event) => event.kind === "memory_compiled");
|
|
3115
3310
|
appendServeTimeRouteDecisionLog({
|
|
3116
|
-
activationRoot:
|
|
3311
|
+
activationRoot: compileResult.activationRoot,
|
|
3117
3312
|
turn,
|
|
3118
3313
|
compileResult,
|
|
3119
3314
|
normalizedEventExport,
|
|
@@ -3121,19 +3316,39 @@ export function runRuntimeTurn(turn, options = {}) {
|
|
|
3121
3316
|
});
|
|
3122
3317
|
}
|
|
3123
3318
|
catch (error) {
|
|
3124
|
-
warnings.push(
|
|
3319
|
+
warnings.push(buildServeRouteLogFailOpenWarning("runRuntimeTurn", error));
|
|
3320
|
+
if (compileResult.ok) {
|
|
3321
|
+
compileResult.compileResponse.diagnostics.notes = uniqueNotes([
|
|
3322
|
+
...compileResult.compileResponse.diagnostics.notes,
|
|
3323
|
+
...buildServeRouteLogFailOpenNotes("runRuntimeTurn", error)
|
|
3324
|
+
]);
|
|
3325
|
+
}
|
|
3326
|
+
}
|
|
3327
|
+
try {
|
|
3328
|
+
const eventExport = writeRuntimeEventExportBundle(turn, normalizedEventExport);
|
|
3329
|
+
return {
|
|
3330
|
+
...compileResult,
|
|
3331
|
+
eventExport,
|
|
3332
|
+
warnings
|
|
3333
|
+
};
|
|
3334
|
+
}
|
|
3335
|
+
catch (error) {
|
|
3336
|
+
if (options.failOpen === false) {
|
|
3337
|
+
throw error;
|
|
3338
|
+
}
|
|
3339
|
+
warnings.push(toErrorMessage(error));
|
|
3340
|
+
return {
|
|
3341
|
+
...compileResult,
|
|
3342
|
+
eventExport: {
|
|
3343
|
+
ok: false,
|
|
3344
|
+
wroteBundle: false,
|
|
3345
|
+
error: toErrorMessage(error)
|
|
3346
|
+
},
|
|
3347
|
+
warnings
|
|
3348
|
+
};
|
|
3125
3349
|
}
|
|
3126
|
-
const eventExport = writeRuntimeEventExportBundle(turn, normalizedEventExport);
|
|
3127
|
-
return {
|
|
3128
|
-
...compileResult,
|
|
3129
|
-
eventExport,
|
|
3130
|
-
warnings
|
|
3131
|
-
};
|
|
3132
3350
|
}
|
|
3133
3351
|
catch (error) {
|
|
3134
|
-
if (options.failOpen === false) {
|
|
3135
|
-
throw error;
|
|
3136
|
-
}
|
|
3137
3352
|
warnings.push(toErrorMessage(error));
|
|
3138
3353
|
return {
|
|
3139
3354
|
...compileResult,
|
|
@@ -4117,6 +4332,144 @@ function summarizeOperatorSlot(slot, updatedAt) {
|
|
|
4117
4332
|
findings: [...slot.findings]
|
|
4118
4333
|
};
|
|
4119
4334
|
}
|
|
4335
|
+
function buildMissingLabelFlowSummary(detail) {
|
|
4336
|
+
return {
|
|
4337
|
+
source: "missing",
|
|
4338
|
+
humanLabelCount: null,
|
|
4339
|
+
selfLabelCount: null,
|
|
4340
|
+
asyncTeacherArtifactCount: null,
|
|
4341
|
+
implicitPositiveCount: null,
|
|
4342
|
+
detail
|
|
4343
|
+
};
|
|
4344
|
+
}
|
|
4345
|
+
function buildMissingLearningPathSummary(detail) {
|
|
4346
|
+
return {
|
|
4347
|
+
available: false,
|
|
4348
|
+
source: "missing",
|
|
4349
|
+
policyGradientVersion: "unavailable",
|
|
4350
|
+
policyGradientMethod: null,
|
|
4351
|
+
objective: null,
|
|
4352
|
+
targetConstruction: null,
|
|
4353
|
+
connectOpsFired: null,
|
|
4354
|
+
reconstructedTrajectoryCount: null,
|
|
4355
|
+
detail
|
|
4356
|
+
};
|
|
4357
|
+
}
|
|
4358
|
+
function countTeacherArtifactBlocks(blocks) {
|
|
4359
|
+
return blocks.filter((block) => block.learning.role === "teacher_supervision" && !block.id.endsWith(":teacher-supervision-summary")).length;
|
|
4360
|
+
}
|
|
4361
|
+
function summarizePolicyGradientVersion(targetConstruction) {
|
|
4362
|
+
if (targetConstruction === "trajectory_reconstruction") {
|
|
4363
|
+
return "v2";
|
|
4364
|
+
}
|
|
4365
|
+
if (targetConstruction === "event_block_plus_related_interaction") {
|
|
4366
|
+
return "v1";
|
|
4367
|
+
}
|
|
4368
|
+
return "unavailable";
|
|
4369
|
+
}
|
|
4370
|
+
function summarizePackLabelFlow(source, pack) {
|
|
4371
|
+
const labelHarvest = pack.manifest.provenance.learningSurface.labelHarvest;
|
|
4372
|
+
return {
|
|
4373
|
+
source,
|
|
4374
|
+
humanLabelCount: labelHarvest.humanLabels,
|
|
4375
|
+
selfLabelCount: labelHarvest.selfLabels,
|
|
4376
|
+
asyncTeacherArtifactCount: countTeacherArtifactBlocks(pack.graph.blocks),
|
|
4377
|
+
implicitPositiveCount: labelHarvest.approvals,
|
|
4378
|
+
detail: source === "active_pack"
|
|
4379
|
+
? "active pack label harvest and teacher artifacts are visible"
|
|
4380
|
+
: source === "materialized_candidate"
|
|
4381
|
+
? "materialized candidate label harvest and teacher artifacts are visible"
|
|
4382
|
+
: "event export label harvest is visible"
|
|
4383
|
+
};
|
|
4384
|
+
}
|
|
4385
|
+
function summarizePackLearningPath(source, pack) {
|
|
4386
|
+
const targetConstruction = pack.router?.training.objective.profile.targetConstruction ?? null;
|
|
4387
|
+
const policyGradientVersion = summarizePolicyGradientVersion(targetConstruction);
|
|
4388
|
+
const reconstructedTrajectoryCount = policyGradientVersion === "v2"
|
|
4389
|
+
? pack.router?.training.routeTraceCount ?? 0
|
|
4390
|
+
: pack.router === null
|
|
4391
|
+
? null
|
|
4392
|
+
: 0;
|
|
4393
|
+
return {
|
|
4394
|
+
available: pack.router !== null,
|
|
4395
|
+
source,
|
|
4396
|
+
policyGradientVersion,
|
|
4397
|
+
policyGradientMethod: pack.router?.training.method ?? null,
|
|
4398
|
+
objective: pack.router?.training.objective.objective ?? null,
|
|
4399
|
+
targetConstruction,
|
|
4400
|
+
connectOpsFired: pack.manifest.graphDynamics.structuralOps.connect,
|
|
4401
|
+
reconstructedTrajectoryCount,
|
|
4402
|
+
detail: pack.router === null
|
|
4403
|
+
? "pack has no learned router artifact"
|
|
4404
|
+
: policyGradientVersion === "v2"
|
|
4405
|
+
? "learned routing uses trajectory-reconstruction PG"
|
|
4406
|
+
: policyGradientVersion === "v1"
|
|
4407
|
+
? "learned routing uses event-reconstruction PG"
|
|
4408
|
+
: "learned routing is present but the PG profile is not recognizable"
|
|
4409
|
+
};
|
|
4410
|
+
}
|
|
4411
|
+
function summarizePackObservability(source, pack) {
|
|
4412
|
+
return {
|
|
4413
|
+
labelFlow: summarizePackLabelFlow(source, pack),
|
|
4414
|
+
learningPath: summarizePackLearningPath(source, pack)
|
|
4415
|
+
};
|
|
4416
|
+
}
|
|
4417
|
+
export function summarizeNormalizedEventExportLabelFlow(normalizedEventExport, asyncTeacherArtifactCount = 0) {
|
|
4418
|
+
const labelHarvest = normalizedEventExport.provenance.learningSurface.labelHarvest;
|
|
4419
|
+
return {
|
|
4420
|
+
source: "event_export",
|
|
4421
|
+
humanLabelCount: labelHarvest.humanLabels,
|
|
4422
|
+
selfLabelCount: labelHarvest.selfLabels,
|
|
4423
|
+
asyncTeacherArtifactCount,
|
|
4424
|
+
implicitPositiveCount: labelHarvest.approvals,
|
|
4425
|
+
detail: "event export label harvest is visible"
|
|
4426
|
+
};
|
|
4427
|
+
}
|
|
4428
|
+
export function summarizeLearningPathFromMaterialization(materialization) {
|
|
4429
|
+
if (materialization === null) {
|
|
4430
|
+
return buildMissingLearningPathSummary("no candidate pack materialized during this learning pass");
|
|
4431
|
+
}
|
|
4432
|
+
return summarizePackLearningPath("materialized_candidate", {
|
|
4433
|
+
manifest: materialization.candidate.manifest,
|
|
4434
|
+
graph: materialization.candidate.payloads.graph,
|
|
4435
|
+
router: materialization.candidate.payloads.router
|
|
4436
|
+
});
|
|
4437
|
+
}
|
|
4438
|
+
function summarizeActivePackObservability(activationRoot, active) {
|
|
4439
|
+
if (active === null) {
|
|
4440
|
+
return {
|
|
4441
|
+
labelFlow: buildMissingLabelFlowSummary("no active pack is attached"),
|
|
4442
|
+
learningPath: buildMissingLearningPathSummary("no active pack is attached")
|
|
4443
|
+
};
|
|
4444
|
+
}
|
|
4445
|
+
if (!active.activationReady) {
|
|
4446
|
+
return {
|
|
4447
|
+
labelFlow: buildMissingLabelFlowSummary(`active pack ${active.packId} is not activation-ready`),
|
|
4448
|
+
learningPath: buildMissingLearningPathSummary(`active pack ${active.packId} is not activation-ready`)
|
|
4449
|
+
};
|
|
4450
|
+
}
|
|
4451
|
+
try {
|
|
4452
|
+
const pack = loadPackFromActivation(activationRoot, "active", { requireActivationReady: true });
|
|
4453
|
+
if (pack === null) {
|
|
4454
|
+
return {
|
|
4455
|
+
labelFlow: buildMissingLabelFlowSummary("active pack payloads are unavailable"),
|
|
4456
|
+
learningPath: buildMissingLearningPathSummary("active pack payloads are unavailable")
|
|
4457
|
+
};
|
|
4458
|
+
}
|
|
4459
|
+
return summarizePackObservability("active_pack", {
|
|
4460
|
+
manifest: pack.manifest,
|
|
4461
|
+
graph: pack.graph,
|
|
4462
|
+
router: pack.router
|
|
4463
|
+
});
|
|
4464
|
+
}
|
|
4465
|
+
catch (error) {
|
|
4466
|
+
const detail = `active pack observability could not be loaded: ${toErrorMessage(error)}`;
|
|
4467
|
+
return {
|
|
4468
|
+
labelFlow: buildMissingLabelFlowSummary(detail),
|
|
4469
|
+
learningPath: buildMissingLearningPathSummary(detail)
|
|
4470
|
+
};
|
|
4471
|
+
}
|
|
4472
|
+
}
|
|
4120
4473
|
function summarizeLastPromotion(inspection) {
|
|
4121
4474
|
if (inspection.active === null) {
|
|
4122
4475
|
return {
|
|
@@ -4532,11 +4885,7 @@ function loadTeacherSnapshot(input) {
|
|
|
4532
4885
|
if (teacherSnapshotPath === undefined) {
|
|
4533
4886
|
return null;
|
|
4534
4887
|
}
|
|
4535
|
-
|
|
4536
|
-
if (snapshot.runtimeOwner !== "openclaw") {
|
|
4537
|
-
throw new Error("teacher snapshot runtimeOwner must be openclaw");
|
|
4538
|
-
}
|
|
4539
|
-
return snapshot;
|
|
4888
|
+
return loadAsyncTeacherLiveLoopSnapshot(teacherSnapshotPath);
|
|
4540
4889
|
}
|
|
4541
4890
|
function summarizeTeacherLoop(input) {
|
|
4542
4891
|
const teacherSnapshotPath = normalizeOptionalString(input.teacherSnapshotPath);
|
|
@@ -4546,10 +4895,14 @@ function summarizeTeacherLoop(input) {
|
|
|
4546
4895
|
sourcePath: null,
|
|
4547
4896
|
lastNoOpReason: "unavailable",
|
|
4548
4897
|
latestFreshness: "unavailable",
|
|
4898
|
+
startedAt: null,
|
|
4899
|
+
lastHeartbeatAt: null,
|
|
4900
|
+
lastScanAt: null,
|
|
4549
4901
|
lastProcessedAt: null,
|
|
4550
4902
|
queueDepth: null,
|
|
4551
4903
|
queueCapacity: null,
|
|
4552
4904
|
running: null,
|
|
4905
|
+
lastAppliedMaterializationJobId: null,
|
|
4553
4906
|
lastMaterializedPackId: null,
|
|
4554
4907
|
notes: [],
|
|
4555
4908
|
detail: "no teacher snapshot path supplied"
|
|
@@ -4562,10 +4915,14 @@ function summarizeTeacherLoop(input) {
|
|
|
4562
4915
|
sourcePath: path.resolve(teacherSnapshotPath),
|
|
4563
4916
|
lastNoOpReason: "unavailable",
|
|
4564
4917
|
latestFreshness: "unavailable",
|
|
4918
|
+
startedAt: null,
|
|
4919
|
+
lastHeartbeatAt: null,
|
|
4920
|
+
lastScanAt: null,
|
|
4565
4921
|
lastProcessedAt: null,
|
|
4566
4922
|
queueDepth: null,
|
|
4567
4923
|
queueCapacity: null,
|
|
4568
4924
|
running: null,
|
|
4925
|
+
lastAppliedMaterializationJobId: null,
|
|
4569
4926
|
lastMaterializedPackId: null,
|
|
4570
4927
|
notes: [],
|
|
4571
4928
|
detail: "teacher snapshot could not be loaded"
|
|
@@ -4576,10 +4933,14 @@ function summarizeTeacherLoop(input) {
|
|
|
4576
4933
|
sourcePath: path.resolve(teacherSnapshotPath),
|
|
4577
4934
|
lastNoOpReason: snapshot.diagnostics.lastNoOpReason,
|
|
4578
4935
|
latestFreshness: snapshot.diagnostics.latestFreshness,
|
|
4936
|
+
startedAt: snapshot.runtime?.startedAt ?? null,
|
|
4937
|
+
lastHeartbeatAt: snapshot.runtime?.lastHeartbeatAt ?? null,
|
|
4938
|
+
lastScanAt: snapshot.runtime?.lastScanAt ?? null,
|
|
4579
4939
|
lastProcessedAt: snapshot.diagnostics.lastProcessedAt,
|
|
4580
4940
|
queueDepth: snapshot.queue.depth,
|
|
4581
4941
|
queueCapacity: snapshot.queue.capacity,
|
|
4582
4942
|
running: snapshot.queue.running,
|
|
4943
|
+
lastAppliedMaterializationJobId: snapshot.runtime?.lastAppliedMaterializationJobId ?? null,
|
|
4583
4944
|
lastMaterializedPackId: snapshot.learner.lastMaterialization?.candidate.summary.packId ?? null,
|
|
4584
4945
|
notes: [...snapshot.diagnostics.notes],
|
|
4585
4946
|
detail: "async teacher diagnostics loaded"
|
|
@@ -5066,6 +5427,7 @@ export function buildOperatorSurfaceReport(input) {
|
|
|
5066
5427
|
});
|
|
5067
5428
|
const attachStatus = describeAttachStatus({ activationRoot });
|
|
5068
5429
|
const active = summarizeOperatorSlot(inspection.active, inspection.pointers.active?.updatedAt ?? null);
|
|
5430
|
+
const activeObservability = summarizeActivePackObservability(activationRoot, active);
|
|
5069
5431
|
const reportBase = {
|
|
5070
5432
|
generatedAt: updatedAt,
|
|
5071
5433
|
activationRoot,
|
|
@@ -5078,6 +5440,8 @@ export function buildOperatorSurfaceReport(input) {
|
|
|
5078
5440
|
},
|
|
5079
5441
|
brain: summarizeBrainState(active, observability),
|
|
5080
5442
|
graph: summarizeGraphObservability(active, observability),
|
|
5443
|
+
labelFlow: activeObservability.labelFlow,
|
|
5444
|
+
learningPath: activeObservability.learningPath,
|
|
5081
5445
|
learnedRouting: {
|
|
5082
5446
|
required: observability.learnedRouteFn.required,
|
|
5083
5447
|
available: observability.learnedRouteFn.available,
|
|
@@ -5198,7 +5562,7 @@ export { describeNormalizedEventExportObservability } from "@openclawbrain/event
|
|
|
5198
5562
|
export { describeCompileFallbackUsage } from "@openclawbrain/compiler";
|
|
5199
5563
|
export { describeActivationObservability, inspectActivationState, rollbackActivePack } from "@openclawbrain/pack-format";
|
|
5200
5564
|
export { createOpenClawLocalSessionTail, OpenClawLocalSessionTail } from "./session-tail.js";
|
|
5201
|
-
export { discoverOpenClawMainSessionStores, loadOpenClawSessionIndex, readOpenClawAcpStreamFile, readOpenClawSessionFile } from "./session-store.js";
|
|
5565
|
+
export { discoverOpenClawMainSessionStores, discoverOpenClawSessionStores, loadOpenClawSessionIndex, readOpenClawAcpStreamFile, readOpenClawSessionFile } from "./session-store.js";
|
|
5202
5566
|
export { buildPassiveLearningSessionExportFromOpenClawSessionStore, buildPassiveLearningStoreExportFromOpenClawSessionIndex } from "./local-session-passive-learning.js";
|
|
5203
5567
|
export { resolveActivationRoot } from "./resolve-activation-root.js";
|
|
5204
5568
|
export { runDaemonCommand, parseDaemonArgs } from "./daemon.js";
|