@noopolis/daimon 0.2.0 → 0.2.1
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/README.md +6 -0
- package/dist/contracts/attentionContract.d.ts +25 -0
- package/dist/contracts/attentionContract.d.ts.map +1 -1
- package/dist/contracts/attentionContract.js +8 -1
- package/dist/contracts/grokBrokerTaskClock.d.ts +18 -0
- package/dist/contracts/grokBrokerTaskClock.d.ts.map +1 -0
- package/dist/contracts/grokBrokerTaskClock.js +16 -0
- package/dist/contracts/organizationRuntimeContract.d.ts +76 -0
- package/dist/contracts/organizationRuntimeContract.d.ts.map +1 -1
- package/dist/contracts/organizationRuntimeContract.js +2 -0
- package/dist/contracts/runtimeContractManifest.d.ts +222 -15
- package/dist/contracts/runtimeContractManifest.d.ts.map +1 -1
- package/dist/contracts/runtimeContractManifest.js +35 -10
- package/dist/contracts/shellEnvironmentPolicy.d.ts +3 -0
- package/dist/contracts/shellEnvironmentPolicy.d.ts.map +1 -0
- package/dist/contracts/shellEnvironmentPolicy.js +5 -0
- package/dist/contracts/wakeMomentContract.d.ts +61 -0
- package/dist/contracts/wakeMomentContract.d.ts.map +1 -0
- package/dist/contracts/wakeMomentContract.js +27 -0
- package/dist/core/types.d.ts +2 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/examples/jungianPlayAgent.d.ts +1 -0
- package/dist/examples/jungianPlayAgent.d.ts.map +1 -1
- package/dist/examples/jungianPlayAgent.js +6 -2
- package/dist/observability/causalEvents.d.ts +3 -3
- package/dist/observability/causalEvents.d.ts.map +1 -1
- package/dist/observability/causalEvents.js +4 -4
- package/dist/pi/cliEngineSpawn.d.ts +2 -2
- package/dist/pi/cliEngineSpawn.d.ts.map +1 -1
- package/dist/pi/cliEngineSpawn.js +7 -2
- package/dist/pi/cliEnvironment.d.ts.map +1 -1
- package/dist/pi/cliEnvironment.js +2 -0
- package/dist/pi/cliMcpRegistration.d.ts +1 -1
- package/dist/pi/cliMcpRegistration.d.ts.map +1 -1
- package/dist/pi/cliMcpRegistration.js +1 -1
- package/dist/pi/cliSession.d.ts +2 -0
- package/dist/pi/cliSession.d.ts.map +1 -1
- package/dist/pi/cliSession.js +3 -80
- package/dist/pi/cliSessionMcp.d.ts +9 -0
- package/dist/pi/cliSessionMcp.d.ts.map +1 -0
- package/dist/pi/cliSessionMcp.js +80 -0
- package/dist/pi/engineTaskClock.d.ts +9 -0
- package/dist/pi/engineTaskClock.d.ts.map +1 -0
- package/dist/pi/engineTaskClock.js +28 -0
- package/dist/pi/grokHomeMcpRegistration.d.ts.map +1 -1
- package/dist/pi/grokHomeMcpRegistration.js +2 -1
- package/dist/pi/grokSandbox.js +1 -1
- package/dist/pi/memoryClock.d.ts +25 -0
- package/dist/pi/memoryClock.d.ts.map +1 -0
- package/dist/pi/memoryClock.js +18 -0
- package/dist/pi/piAgentHandle.d.ts +3 -1
- package/dist/pi/piAgentHandle.d.ts.map +1 -1
- package/dist/pi/piAgentHandle.js +5 -2
- package/dist/pi/piHarness.d.ts +8 -2
- package/dist/pi/piHarness.d.ts.map +1 -1
- package/dist/pi/piHarness.js +28 -12
- package/dist/pi/taskClockProcess.d.ts +6 -0
- package/dist/pi/taskClockProcess.d.ts.map +1 -0
- package/dist/pi/taskClockProcess.js +8 -0
- package/dist/pi/turnCausal.d.ts +4 -2
- package/dist/pi/turnCausal.d.ts.map +1 -1
- package/dist/pi/turnCausal.js +4 -4
- package/dist/pi/wakeAcceptance.d.ts +1 -1
- package/dist/pi/wakeAcceptance.d.ts.map +1 -1
- package/dist/pi/wakeAcceptance.js +2 -2
- package/dist/runtime/agySubscriptionBootstrap.js +1 -1
- package/dist/runtime/agySubscriptionRealm.js +1 -1
- package/dist/runtime/attention.d.ts +5 -0
- package/dist/runtime/attention.d.ts.map +1 -1
- package/dist/runtime/attention.js +14 -1
- package/dist/runtime/attentionDispatcher.d.ts +14 -2
- package/dist/runtime/attentionDispatcher.d.ts.map +1 -1
- package/dist/runtime/attentionDispatcher.js +127 -33
- package/dist/runtime/cli.js +5 -0
- package/dist/runtime/contract-manifest.json +1 -1
- package/dist/runtime/contract-manifest.sha256 +1 -1
- package/dist/runtime/engineBrokerCapabilities.d.ts +10 -0
- package/dist/runtime/engineBrokerCapabilities.d.ts.map +1 -1
- package/dist/runtime/engineBrokerCapabilities.js +10 -0
- package/dist/runtime/engineBrokerControlClient.d.ts +12 -1
- package/dist/runtime/engineBrokerControlClient.d.ts.map +1 -1
- package/dist/runtime/engineBrokerControlClient.js +139 -43
- package/dist/runtime/engineBrokerCredentialJournal.d.ts +2 -0
- package/dist/runtime/engineBrokerCredentialJournal.d.ts.map +1 -1
- package/dist/runtime/engineBrokerCredentialJournal.js +9 -0
- package/dist/runtime/engineBrokerInferenceProtocol.d.ts +3 -2
- package/dist/runtime/engineBrokerInferenceProtocol.d.ts.map +1 -1
- package/dist/runtime/engineBrokerInferenceProtocol.js +4 -4
- package/dist/runtime/engineBrokerMcpCallLog.d.ts +11 -0
- package/dist/runtime/engineBrokerMcpCallLog.d.ts.map +1 -1
- package/dist/runtime/engineBrokerMcpCallLog.js +13 -1
- package/dist/runtime/engineBrokerMcpFacade.d.ts +5 -2
- package/dist/runtime/engineBrokerMcpFacade.d.ts.map +1 -1
- package/dist/runtime/engineBrokerMcpFacade.js +5 -2
- package/dist/runtime/engineBrokerNativeClient.js +2 -2
- package/dist/runtime/engineBrokerProtocol.d.ts +42 -10
- package/dist/runtime/engineBrokerProtocol.d.ts.map +1 -1
- package/dist/runtime/engineBrokerProtocol.js +97 -14
- package/dist/runtime/engineBrokerSealLedger.d.ts.map +1 -1
- package/dist/runtime/engineBrokerSealLedger.js +9 -0
- package/dist/runtime/engineBrokerService.d.ts +8 -2
- package/dist/runtime/engineBrokerService.d.ts.map +1 -1
- package/dist/runtime/engineBrokerService.js +95 -37
- package/dist/runtime/engineBrokerServiceCli.js +1 -1
- package/dist/runtime/engineBrokerServiceConfig.d.ts +5 -0
- package/dist/runtime/engineBrokerServiceConfig.d.ts.map +1 -1
- package/dist/runtime/engineBrokerServiceConfig.js +47 -9
- package/dist/runtime/engineBrokerTurnRegistry.d.ts +1 -1
- package/dist/runtime/engineBrokerTurnRegistry.d.ts.map +1 -1
- package/dist/runtime/engineBrokerTurnRegistry.js +7 -6
- package/dist/runtime/engineDispatcher.d.ts +2 -0
- package/dist/runtime/engineDispatcher.d.ts.map +1 -1
- package/dist/runtime/engineDispatcher.js +14 -2
- package/dist/runtime/engineReadiness.js +1 -1
- package/dist/runtime/grokBrokerCredentialAuthority.d.ts +1 -0
- package/dist/runtime/grokBrokerCredentialAuthority.d.ts.map +1 -1
- package/dist/runtime/grokBrokerCredentialAuthority.js +48 -22
- package/dist/runtime/grokBrokerCredentialReader.d.ts +1 -0
- package/dist/runtime/grokBrokerCredentialReader.d.ts.map +1 -1
- package/dist/runtime/grokBrokerCredentialReader.js +2 -1
- package/dist/runtime/grokBrokerProjection.d.ts +9 -1
- package/dist/runtime/grokBrokerProjection.d.ts.map +1 -1
- package/dist/runtime/grokBrokerProjection.js +11 -4
- package/dist/runtime/grokBrokerProviderClock.d.ts +26 -0
- package/dist/runtime/grokBrokerProviderClock.d.ts.map +1 -0
- package/dist/runtime/grokBrokerProviderClock.js +133 -0
- package/dist/runtime/grokBrokerProxy.d.ts +17 -3
- package/dist/runtime/grokBrokerProxy.d.ts.map +1 -1
- package/dist/runtime/grokBrokerProxy.js +73 -9
- package/dist/runtime/grokBrokerProxyJson.d.ts +10 -0
- package/dist/runtime/grokBrokerProxyJson.d.ts.map +1 -0
- package/dist/runtime/grokBrokerProxyJson.js +31 -0
- package/dist/runtime/grokBrokerProxyRequest.d.ts.map +1 -1
- package/dist/runtime/grokBrokerProxyRequest.js +17 -6
- package/dist/runtime/grokBrokerRealmLease.js +1 -1
- package/dist/runtime/grokBrokerRefresh.js +1 -1
- package/dist/runtime/grokBrokerRunBudget.d.ts +20 -0
- package/dist/runtime/grokBrokerRunBudget.d.ts.map +1 -0
- package/dist/runtime/grokBrokerRunBudget.js +85 -0
- package/dist/runtime/grokBrokerSlot.d.ts +6 -0
- package/dist/runtime/grokBrokerSlot.d.ts.map +1 -0
- package/dist/runtime/grokBrokerSlot.js +21 -0
- package/dist/runtime/grokBrokerTaskClock.d.ts +32 -0
- package/dist/runtime/grokBrokerTaskClock.d.ts.map +1 -0
- package/dist/runtime/grokBrokerTaskClock.js +120 -0
- package/dist/runtime/grokBrokerTurnMeter.d.ts +55 -3
- package/dist/runtime/grokBrokerTurnMeter.d.ts.map +1 -1
- package/dist/runtime/grokBrokerTurnMeter.js +90 -4
- package/dist/runtime/grokBrokerWorkerConfig.d.ts +5 -2
- package/dist/runtime/grokBrokerWorkerConfig.d.ts.map +1 -1
- package/dist/runtime/grokBrokerWorkerConfig.js +22 -3
- package/dist/runtime/grokEngineBroker.d.ts +43 -3
- package/dist/runtime/grokEngineBroker.d.ts.map +1 -1
- package/dist/runtime/grokEngineBroker.js +159 -71
- package/dist/runtime/grokEngineBrokerTurn.d.ts +32 -8
- package/dist/runtime/grokEngineBrokerTurn.d.ts.map +1 -1
- package/dist/runtime/grokEngineBrokerTurn.js +204 -21
- package/dist/runtime/grokEngineBrokerTurnEnd.d.ts +88 -0
- package/dist/runtime/grokEngineBrokerTurnEnd.d.ts.map +1 -0
- package/dist/runtime/grokEngineBrokerTurnEnd.js +148 -0
- package/dist/runtime/grokInferenceProxy.d.ts.map +1 -1
- package/dist/runtime/grokInferenceProxy.js +3 -0
- package/dist/runtime/grokSubscriptionRealm.js +1 -1
- package/dist/runtime/grokWorkerAttestation.d.ts +9 -4
- package/dist/runtime/grokWorkerAttestation.d.ts.map +1 -1
- package/dist/runtime/grokWorkerAttestation.js +2 -2
- package/dist/runtime/grokWorkerHomeAttestation.d.ts +4 -2
- package/dist/runtime/grokWorkerHomeAttestation.d.ts.map +1 -1
- package/dist/runtime/grokWorkerHomeAttestation.js +10 -4
- package/dist/runtime/index.d.ts +7 -2
- package/dist/runtime/index.d.ts.map +1 -1
- package/dist/runtime/index.js +5 -1
- package/dist/runtime/native/daimon-engine-broker +0 -0
- package/dist/runtime/organizationRuntime.d.ts +3 -0
- package/dist/runtime/organizationRuntime.d.ts.map +1 -1
- package/dist/runtime/organizationRuntimeAdmission.d.ts +6 -0
- package/dist/runtime/organizationRuntimeAdmission.d.ts.map +1 -0
- package/dist/runtime/organizationRuntimeAdmission.js +22 -0
- package/dist/runtime/organizationRuntimeControl.d.ts +9 -0
- package/dist/runtime/organizationRuntimeControl.d.ts.map +1 -1
- package/dist/runtime/organizationRuntimeControl.js +72 -24
- package/dist/runtime/organizationRuntimeHost.d.ts.map +1 -1
- package/dist/runtime/organizationRuntimeHost.js +13 -4
- package/dist/runtime/organizationRuntimeParsing.d.ts.map +1 -1
- package/dist/runtime/organizationRuntimeParsing.js +4 -1
- package/dist/runtime/organizationRuntimeReadiness.d.ts.map +1 -1
- package/dist/runtime/organizationRuntimeReadiness.js +8 -0
- package/dist/runtime/organizationRuntimeRecording.d.ts +7 -0
- package/dist/runtime/organizationRuntimeRecording.d.ts.map +1 -0
- package/dist/runtime/organizationRuntimeRecording.js +58 -0
- package/dist/runtime/physicalReadiness.d.ts +12 -0
- package/dist/runtime/physicalReadiness.d.ts.map +1 -1
- package/dist/runtime/physicalReadiness.js +43 -9
- package/dist/runtime/productionAgentTools.d.ts.map +1 -1
- package/dist/runtime/productionAgentTools.js +13 -5
- package/dist/runtime/relocateRuntimeConfig.d.ts +14 -0
- package/dist/runtime/relocateRuntimeConfig.d.ts.map +1 -0
- package/dist/runtime/relocateRuntimeConfig.js +38 -0
- package/dist/runtime/schedule.d.ts.map +1 -1
- package/dist/runtime/schedule.js +12 -7
- package/dist/runtime/storeCoordination.d.ts +10 -0
- package/dist/runtime/storeCoordination.d.ts.map +1 -1
- package/dist/runtime/storeCoordination.js +23 -0
- package/dist/runtime/taskClock.d.ts +42 -0
- package/dist/runtime/taskClock.d.ts.map +1 -0
- package/dist/runtime/taskClock.js +102 -0
- package/dist/runtime/taskClockProcess.d.ts +17 -0
- package/dist/runtime/taskClockProcess.d.ts.map +1 -0
- package/dist/runtime/taskClockProcess.js +58 -0
- package/dist/runtime/turnRequestLedger.d.ts +0 -5
- package/dist/runtime/turnRequestLedger.d.ts.map +1 -1
- package/dist/runtime/turnRequestLedger.js +23 -21
- package/dist/runtime/wakeAcceptanceClaimDiagnostics.d.ts +34 -0
- package/dist/runtime/wakeAcceptanceClaimDiagnostics.d.ts.map +1 -0
- package/dist/runtime/wakeAcceptanceClaimDiagnostics.js +79 -0
- package/dist/runtime/wakeAcceptanceIndex.d.ts +55 -0
- package/dist/runtime/wakeAcceptanceIndex.d.ts.map +1 -0
- package/dist/runtime/wakeAcceptanceIndex.js +158 -0
- package/dist/runtime/wakeAcceptanceProcessIdentity.d.ts +9 -1
- package/dist/runtime/wakeAcceptanceProcessIdentity.d.ts.map +1 -1
- package/dist/runtime/wakeAcceptanceProcessIdentity.js +5 -1
- package/dist/runtime/wakeAcceptanceRecord.d.ts +2 -0
- package/dist/runtime/wakeAcceptanceRecord.d.ts.map +1 -1
- package/dist/runtime/wakeAcceptanceRecord.js +4 -2
- package/dist/runtime/wakeAcceptanceRetention.d.ts +25 -1
- package/dist/runtime/wakeAcceptanceRetention.d.ts.map +1 -1
- package/dist/runtime/wakeAcceptanceRetention.js +28 -2
- package/dist/runtime/wakeAcceptanceStore.d.ts +8 -8
- package/dist/runtime/wakeAcceptanceStore.d.ts.map +1 -1
- package/dist/runtime/wakeAcceptanceStore.js +66 -63
- package/dist/runtime/wakeFuse.d.ts +58 -3
- package/dist/runtime/wakeFuse.d.ts.map +1 -1
- package/dist/runtime/wakeFuse.js +106 -7
- package/dist/runtime/wakeMomentFs.d.ts +27 -0
- package/dist/runtime/wakeMomentFs.d.ts.map +1 -0
- package/dist/runtime/wakeMomentFs.js +223 -0
- package/dist/runtime/wakeMomentHistory.d.ts +26 -0
- package/dist/runtime/wakeMomentHistory.d.ts.map +1 -0
- package/dist/runtime/wakeMomentHistory.js +109 -0
- package/dist/runtime/wakeMomentIo.d.ts +22 -0
- package/dist/runtime/wakeMomentIo.d.ts.map +1 -0
- package/dist/runtime/wakeMomentIo.js +114 -0
- package/dist/runtime/wakeMomentRecorder.d.ts +33 -0
- package/dist/runtime/wakeMomentRecorder.d.ts.map +1 -0
- package/dist/runtime/wakeMomentRecorder.js +81 -0
- package/dist/runtime/wakeMomentRetention.d.ts +7 -0
- package/dist/runtime/wakeMomentRetention.d.ts.map +1 -0
- package/dist/runtime/wakeMomentRetention.js +143 -0
- package/dist/runtime/wakeMomentRows.d.ts +8 -0
- package/dist/runtime/wakeMomentRows.d.ts.map +1 -0
- package/dist/runtime/wakeMomentRows.js +66 -0
- package/dist/runtime/wakeMomentSnapshot.d.ts +56 -0
- package/dist/runtime/wakeMomentSnapshot.d.ts.map +1 -0
- package/dist/runtime/wakeMomentSnapshot.js +248 -0
- package/package.json +4 -4
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { WAKE_MOMENTS } from "../contracts/wakeMomentContract.js";
|
|
3
|
+
/** Receives the parser's already cloned JSON data; no I/O or caller hooks. */
|
|
4
|
+
export function parseRecording(value) {
|
|
5
|
+
const input = exact(value, ["directory", "keepMs", "snapshots"]);
|
|
6
|
+
const directory = absolute(input.directory);
|
|
7
|
+
if (typeof input.keepMs !== "number" || !Number.isSafeInteger(input.keepMs) || input.keepMs <= 0)
|
|
8
|
+
throw new TypeError("recording.keepMs must be a positive safe integer");
|
|
9
|
+
if (!Array.isArray(input.snapshots) || input.snapshots.length > WAKE_MOMENTS.maxSnapshotRoots)
|
|
10
|
+
throw new TypeError("recording.snapshots must have 0..16 roots");
|
|
11
|
+
const ids = new Set(), paths = new Set();
|
|
12
|
+
const snapshots = input.snapshots.map((value) => {
|
|
13
|
+
const root = exact(value, ["id", "path"]);
|
|
14
|
+
if (typeof root.id !== "string" || !/^[A-Za-z0-9._-]{1,128}$/.test(root.id))
|
|
15
|
+
throw new TypeError("recording snapshot id is invalid");
|
|
16
|
+
const source = absolute(root.path);
|
|
17
|
+
if (ids.has(root.id) || paths.has(source))
|
|
18
|
+
throw new TypeError("recording snapshots must have unique ids and paths");
|
|
19
|
+
if (pathsOverlap(source, directory))
|
|
20
|
+
throw new TypeError("recording snapshot and directory must not overlap");
|
|
21
|
+
ids.add(root.id);
|
|
22
|
+
paths.add(source);
|
|
23
|
+
return { id: root.id, path: source };
|
|
24
|
+
});
|
|
25
|
+
return { directory, keepMs: input.keepMs, snapshots };
|
|
26
|
+
}
|
|
27
|
+
export function isolateRecording(agents) {
|
|
28
|
+
for (const agent of agents) {
|
|
29
|
+
if (!agent.recording)
|
|
30
|
+
continue;
|
|
31
|
+
for (const peer of agents) {
|
|
32
|
+
for (const root of [peer.workspacePath, peer.runtimeHomePath, ...(peer.id === agent.id || !peer.recording ? [] : [peer.recording.directory])]) {
|
|
33
|
+
if (pathsOverlap(agent.recording.directory, root))
|
|
34
|
+
throw new TypeError("recording.directory must not overlap runtime roots");
|
|
35
|
+
}
|
|
36
|
+
for (const snapshot of peer.recording?.snapshots ?? []) {
|
|
37
|
+
if (pathsOverlap(agent.recording.directory, snapshot.path))
|
|
38
|
+
throw new TypeError("recording.directory must not overlap snapshot roots");
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
export function pathsOverlap(left, right) {
|
|
44
|
+
return left === right || left === "/" || right === "/" || left.startsWith(`${right}/`) || right.startsWith(`${left}/`);
|
|
45
|
+
}
|
|
46
|
+
function exact(value, keys) {
|
|
47
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
48
|
+
throw new TypeError("recording requires objects");
|
|
49
|
+
if (Object.keys(value).length !== keys.length || keys.some((key) => !Object.hasOwn(value, key)))
|
|
50
|
+
throw new TypeError("recording has invalid fields");
|
|
51
|
+
return value;
|
|
52
|
+
}
|
|
53
|
+
function absolute(value) {
|
|
54
|
+
if (typeof value !== "string" || !path.posix.isAbsolute(value) || value.includes("\0") || [...value].length > 4_096 || Buffer.byteLength(value) > 16_384)
|
|
55
|
+
throw new TypeError("recording paths must be bounded absolute POSIX paths");
|
|
56
|
+
// Match workspacePath/runtimeHomePath: canonicalize before testing equality/overlap.
|
|
57
|
+
return path.posix.normalize(value).replace(/\/+$/, "") || "/";
|
|
58
|
+
}
|
|
@@ -1,4 +1,12 @@
|
|
|
1
|
+
import { type Stats } from "node:fs";
|
|
2
|
+
import { lstat } from "node:fs/promises";
|
|
1
3
|
import type { OrganizationRuntimeAgentConfig } from "./organizationRuntime.js";
|
|
4
|
+
type Identity = Readonly<{
|
|
5
|
+
dev: number;
|
|
6
|
+
ino: number;
|
|
7
|
+
uid: number;
|
|
8
|
+
mode: number;
|
|
9
|
+
}>;
|
|
2
10
|
/**
|
|
3
11
|
* `private` is every engine's runtime home: 0700, nothing but the runtime user.
|
|
4
12
|
*
|
|
@@ -24,10 +32,12 @@ export type OrganizationRuntimePathAuthority = Readonly<{
|
|
|
24
32
|
workspacePath: string;
|
|
25
33
|
runtimeHomePath: string;
|
|
26
34
|
verify(): Promise<void>;
|
|
35
|
+
verifyRecording?(): Promise<void>;
|
|
27
36
|
}>;
|
|
28
37
|
close(): Promise<void>;
|
|
29
38
|
}>;
|
|
30
39
|
export declare function prepareOrganizationRuntimePaths(agents: readonly OrganizationRuntimeAgentConfig[]): Promise<OrganizationRuntimePathAuthority>;
|
|
40
|
+
export declare function assertNoSymlinkComponents(target: string, stat?: typeof lstat): Promise<void>;
|
|
31
41
|
/** Identity of the process Daimon runs as; a seam so every refusal is testable unprivileged. */
|
|
32
42
|
export type RuntimeIdentity = Readonly<{
|
|
33
43
|
uid: number;
|
|
@@ -43,5 +53,7 @@ type DirectoryEntry = Readonly<{
|
|
|
43
53
|
}>;
|
|
44
54
|
/** Pure shape check for a caller-prepared runtime root. */
|
|
45
55
|
export declare function assertRuntimeDirectory(entry: DirectoryEntry, label: string, shape: DirectoryShape, runtime: RuntimeIdentity): void;
|
|
56
|
+
export declare function identity(entry: Stats): Identity;
|
|
57
|
+
export declare function sameIdentity(left: Identity, right: Identity): boolean;
|
|
46
58
|
export {};
|
|
47
59
|
//# sourceMappingURL=physicalReadiness.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"physicalReadiness.d.ts","sourceRoot":"","sources":["../../src/runtime/physicalReadiness.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"physicalReadiness.d.ts","sourceRoot":"","sources":["../../src/runtime/physicalReadiness.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,KAAK,KAAK,EAAE,MAAM,SAAS,CAAC;AAChD,OAAO,EAAU,KAAK,EAAkB,MAAM,kBAAkB,CAAC;AAIjE,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,0BAA0B,CAAC;AAG/E,KAAK,QAAQ,GAAG,QAAQ,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAClF;;;;;;;;;;;;;;GAcG;AACH,KAAK,cAAc,GAAG,MAAM,GAAG,SAAS,GAAG,oBAAoB,CAAC;AAGhE;;;GAGG;AACH,MAAM,MAAM,gCAAgC,GAAG,QAAQ,CAAC;IACtD,QAAQ,CAAC,KAAK,EAAE,8BAA8B,GAAG,QAAQ,CAAC;QACxD,aAAa,EAAE,MAAM,CAAC;QACtB,eAAe,EAAE,MAAM,CAAC;QACxB,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;QACxB,eAAe,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;KACnC,CAAC,CAAC;IACH,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB,CAAC,CAAC;AAOH,wBAAsB,+BAA+B,CACnD,MAAM,EAAE,SAAS,8BAA8B,EAAE,GAChD,OAAO,CAAC,gCAAgC,CAAC,CA0D3C;AAiCD,wBAAsB,yBAAyB,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,GAAE,OAAO,KAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CASzG;AAgBD,gGAAgG;AAChG,MAAM,MAAM,eAAe,GAAG,QAAQ,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,cAAc,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAC9F,KAAK,cAAc,GAAG,QAAQ,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,WAAW,IAAI,OAAO,CAAC;IAAC,cAAc,IAAI,OAAO,CAAA;CAAE,CAAC,CAAC;AAE9H,2DAA2D;AAC3D,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,cAAc,EAAE,OAAO,EAAE,eAAe,GAAG,IAAI,CAalI;AAMD,wBAAgB,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,QAAQ,CAA0F;AAC1I,wBAAgB,YAAY,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,GAAG,OAAO,CAAmH"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { constants } from "node:fs";
|
|
2
|
-
import { lstat, open, realpath } from "node:fs/promises";
|
|
2
|
+
import { access, lstat, open, realpath } from "node:fs/promises";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { GROK_ENGINE_BROKER } from "../contracts/runtimeContractManifest.js";
|
|
5
|
+
import { pathsOverlap } from "./organizationRuntimeRecording.js";
|
|
5
6
|
/** Only a brokered Grok agent's home is worker-traversable; every other engine keeps 0700. */
|
|
6
7
|
function runtimeHomeShape(agent) {
|
|
7
8
|
return agent.engine.kind === "grok" ? "worker-traversable" : "private";
|
|
@@ -9,12 +10,15 @@ function runtimeHomeShape(agent) {
|
|
|
9
10
|
export async function prepareOrganizationRuntimePaths(agents) {
|
|
10
11
|
const workspaces = new Map();
|
|
11
12
|
const homes = new Map();
|
|
13
|
+
const recordings = new Map();
|
|
12
14
|
try {
|
|
13
15
|
for (const agent of agents) {
|
|
14
16
|
workspaces.set(agent.id, await verifyDirectory(agent.workspacePath, "workspacePath", "safe"));
|
|
15
17
|
homes.set(agent.id, await verifyDirectory(agent.runtimeHomePath, "runtimeHomePath", runtimeHomeShape(agent)));
|
|
18
|
+
if (agent.recording)
|
|
19
|
+
recordings.set(agent.id, await verifyDirectory(agent.recording.directory, "recording.directory", "private"));
|
|
16
20
|
}
|
|
17
|
-
const roots = [...workspaces.values(), ...homes.values()];
|
|
21
|
+
const roots = [...workspaces.values(), ...homes.values(), ...recordings.values()];
|
|
18
22
|
for (let left = 0; left < roots.length; left += 1)
|
|
19
23
|
for (let right = left + 1; right < roots.length; right += 1) {
|
|
20
24
|
const first = roots[left];
|
|
@@ -23,9 +27,15 @@ export async function prepareOrganizationRuntimePaths(agents) {
|
|
|
23
27
|
throw new Error(`physical runtime paths overlap: ${first.configured} and ${second.configured}`);
|
|
24
28
|
}
|
|
25
29
|
}
|
|
30
|
+
for (const agent of agents)
|
|
31
|
+
for (const source of agent.recording?.snapshots ?? []) {
|
|
32
|
+
const real = await readableSnapshotDirectory(source.path);
|
|
33
|
+
if (real !== undefined && [...recordings.values()].some((store) => pathsOverlap(store.real, real)))
|
|
34
|
+
throw new Error("physical recording and snapshot paths overlap");
|
|
35
|
+
}
|
|
26
36
|
}
|
|
27
37
|
catch (error) {
|
|
28
|
-
const closeError = await closeAll([...workspaces.values(), ...homes.values()]);
|
|
38
|
+
const closeError = await closeAll([...workspaces.values(), ...homes.values(), ...recordings.values()]);
|
|
29
39
|
if (closeError !== undefined)
|
|
30
40
|
throw new AggregateError([error, closeError], "runtime path validation cleanup failed");
|
|
31
41
|
throw error;
|
|
@@ -49,12 +59,20 @@ export async function prepareOrganizationRuntimePaths(agents) {
|
|
|
49
59
|
const home = homes.get(agent.id);
|
|
50
60
|
if (workspace === undefined || home === undefined)
|
|
51
61
|
throw new Error(`no runtime path authority for ${agent.id}`);
|
|
52
|
-
return { workspacePath: workspace.real, runtimeHomePath: home.real, verify: () => verify(agent)
|
|
62
|
+
return { workspacePath: workspace.real, runtimeHomePath: home.real, verify: () => verify(agent),
|
|
63
|
+
verifyRecording: async () => {
|
|
64
|
+
if (closed)
|
|
65
|
+
throw new Error("runtime path authority is closed");
|
|
66
|
+
const recording = recordings.get(agent.id);
|
|
67
|
+
if (recording)
|
|
68
|
+
await verifyIdentity(recording, "recording.directory", "private");
|
|
69
|
+
}
|
|
70
|
+
};
|
|
53
71
|
},
|
|
54
72
|
async close() {
|
|
55
73
|
if (closed)
|
|
56
74
|
return;
|
|
57
|
-
const failure = await closeAll([...workspaces.values(), ...homes.values()]);
|
|
75
|
+
const failure = await closeAll([...workspaces.values(), ...homes.values(), ...recordings.values()]);
|
|
58
76
|
if (failure !== undefined)
|
|
59
77
|
throw failure;
|
|
60
78
|
closed = true;
|
|
@@ -93,17 +111,33 @@ async function verifyIdentity(directory, label, shape) {
|
|
|
93
111
|
if (await realpath(directory.configured) !== directory.real)
|
|
94
112
|
throw new Error(`${label} changed after readiness validation`);
|
|
95
113
|
}
|
|
96
|
-
async function assertNoSymlinkComponents(target) {
|
|
114
|
+
export async function assertNoSymlinkComponents(target, stat = lstat) {
|
|
97
115
|
const parsed = path.parse(target);
|
|
98
116
|
let current = parsed.root;
|
|
99
117
|
for (const part of path.relative(parsed.root, target).split(path.sep).filter(Boolean)) {
|
|
100
118
|
current = path.join(current, part);
|
|
101
119
|
// macOS exposes /var as a system compatibility symlink to /private/var.
|
|
102
120
|
// It is an OS-root alias, not a caller-controlled component.
|
|
103
|
-
if ((await
|
|
121
|
+
if ((await stat(current)).isSymbolicLink() && current !== "/var")
|
|
104
122
|
throw new Error(`path contains symlink: ${current}`);
|
|
105
123
|
}
|
|
106
124
|
}
|
|
125
|
+
/** Shared sources have no owner/privacy requirement. Missing sources are empty captures. */
|
|
126
|
+
async function readableSnapshotDirectory(target) {
|
|
127
|
+
try {
|
|
128
|
+
await assertNoSymlinkComponents(target);
|
|
129
|
+
const entry = await lstat(target);
|
|
130
|
+
if (!entry.isDirectory() || entry.isSymbolicLink())
|
|
131
|
+
throw new Error("recording snapshot must be a readable real directory");
|
|
132
|
+
await access(target, constants.R_OK | constants.X_OK);
|
|
133
|
+
return await realpath(target);
|
|
134
|
+
}
|
|
135
|
+
catch (error) {
|
|
136
|
+
if (error.code === "ENOENT")
|
|
137
|
+
return undefined;
|
|
138
|
+
throw error;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
107
141
|
/** Pure shape check for a caller-prepared runtime root. */
|
|
108
142
|
export function assertRuntimeDirectory(entry, label, shape, runtime) {
|
|
109
143
|
if (!entry.isDirectory() || entry.isSymbolicLink())
|
|
@@ -127,8 +161,8 @@ export function assertRuntimeDirectory(entry, label, shape, runtime) {
|
|
|
127
161
|
function assertDirectory(entry, label, shape) {
|
|
128
162
|
assertRuntimeDirectory(entry, label, shape, { uid: process.getuid?.() ?? -1, gid: process.getgid?.() ?? -1 });
|
|
129
163
|
}
|
|
130
|
-
function identity(entry) { return { dev: entry.dev, ino: entry.ino, uid: entry.uid, mode: entry.mode & 0o7777 }; }
|
|
131
|
-
function sameIdentity(left, right) { return left.dev === right.dev && left.ino === right.ino && left.uid === right.uid && left.mode === right.mode; }
|
|
164
|
+
export function identity(entry) { return { dev: entry.dev, ino: entry.ino, uid: entry.uid, mode: entry.mode & 0o7777 }; }
|
|
165
|
+
export function sameIdentity(left, right) { return left.dev === right.dev && left.ino === right.ino && left.uid === right.uid && left.mode === right.mode; }
|
|
132
166
|
function overlaps(left, right) { return left === right || left.startsWith(`${right}${path.sep}`) || right.startsWith(`${left}${path.sep}`); }
|
|
133
167
|
function noFollow() { return constants.O_NOFOLLOW ?? 0; }
|
|
134
168
|
function directoryFlag() { return constants.O_DIRECTORY ?? 0; }
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"productionAgentTools.d.ts","sourceRoot":"","sources":["../../src/runtime/productionAgentTools.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AAMtE,OAAO,KAAK,EAAE,8BAA8B,EAAgC,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"productionAgentTools.d.ts","sourceRoot":"","sources":["../../src/runtime/productionAgentTools.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AAMtE,OAAO,KAAK,EAAE,8BAA8B,EAAgC,MAAM,0BAA0B,CAAC;AAO7G,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,6BAA6B,CAAC;AAe/E,wBAAsB,0BAA0B,CAAC,KAAK,EAAE,8BAA8B,EAAE,WAAW,GAAE,2BAAgC,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CAahK"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { spawn } from "
|
|
1
|
+
import { spawn, readyTaskClockEnvironment } from "./taskClockProcess.js";
|
|
2
2
|
import { createHash } from "node:crypto";
|
|
3
3
|
import { constants } from "node:fs";
|
|
4
4
|
import { lstat, open, readdir, rename, unlink } from "node:fs/promises";
|
|
@@ -12,6 +12,7 @@ import { McpToolCallError, MCP_TOOL_RESULT_MAX_BYTES, renderMcpToolResult, repla
|
|
|
12
12
|
import { ensureRuntimeHomeDirectory } from "./runtimeHomeLayout.js";
|
|
13
13
|
import { capToolResult, resolveExemptToolNames, resolveToolResultMaxBytes, TOOL_OUTPUT_DIRECTORY_NAME } from "./toolResultSpill.js";
|
|
14
14
|
import { cliChildEnvironment } from "../pi/cliEnvironment.js";
|
|
15
|
+
import { taskClockChildEnvironment, taskClockProcessEnvironment, taskClockTimestamp } from "./taskClock.js";
|
|
15
16
|
const MAX_RESULT = 65_536;
|
|
16
17
|
const TIMEOUT = 10_000;
|
|
17
18
|
/**
|
|
@@ -25,6 +26,10 @@ const TIMEOUT = 10_000;
|
|
|
25
26
|
*/
|
|
26
27
|
const DAIMON_ACTION_ID_PREFIX = "daimon-";
|
|
27
28
|
export async function createProductionAgentTools(agent, wakeContext = {}) {
|
|
29
|
+
taskClockChildEnvironment();
|
|
30
|
+
for (const server of agent.mcp ?? [])
|
|
31
|
+
taskClockChildEnvironment(server.env);
|
|
32
|
+
readyTaskClockEnvironment(cliChildEnvironment([], agent.runtimeHomePath));
|
|
28
33
|
await ensureRuntimeHomeDirectory(agent.runtimeHomePath, "tool-state");
|
|
29
34
|
// Resolved once, at agent start: a malformed bound is a configuration error
|
|
30
35
|
// that should refuse the agent, not a surprise thrown from the middle of a
|
|
@@ -202,7 +207,8 @@ function moltnetTool(agent, wakeContext) {
|
|
|
202
207
|
const prior = await priorReceipt(agent, deliveryId);
|
|
203
208
|
if (prior !== undefined) {
|
|
204
209
|
wakeContext.spokeFor = wakeContext.current;
|
|
205
|
-
|
|
210
|
+
const visible = typeof prior.at === "string" ? { ...prior, at: taskClockTimestamp(prior.at) } : prior;
|
|
211
|
+
return { content: [{ type: "text", text: JSON.stringify(visible) }], details: visible };
|
|
206
212
|
}
|
|
207
213
|
const response = await machine(agent.moltnet.cliPath, agent.moltnet.configPath, input.network, { version: "moltnet.machine.v1", correlation_id: deliveryId, operation: "send_nudge", send_nudge: { delivery_id: deliveryId, target: { kind, id: target }, body: input.text } });
|
|
208
214
|
const result = moltnetOperationResult(response, "send_nudge", "send");
|
|
@@ -219,10 +225,11 @@ function moltnetTool(agent, wakeContext) {
|
|
|
219
225
|
};
|
|
220
226
|
}
|
|
221
227
|
async function connect(agent, server) {
|
|
222
|
-
|
|
228
|
+
taskClockChildEnvironment(server.env);
|
|
229
|
+
const client = new Client({ name: "daimon-production", version: "0.2.1" });
|
|
223
230
|
const headers = server.authSecretEnv === undefined ? {} : { authorization: `Bearer ${requiredSecret(server.authSecretEnv)}` };
|
|
224
231
|
const transport = server.transport === "stdio"
|
|
225
|
-
? new StdioClientTransport({ command: server.command, args: [...server.args], env: stringEnvironment({ ...server.env, ...cliChildEnvironment([], agent.runtimeHomePath, { executablePath: server.command }) }) })
|
|
232
|
+
? new StdioClientTransport({ command: server.command, args: [...server.args], env: stringEnvironment(readyTaskClockEnvironment({ ...server.env, ...cliChildEnvironment([], agent.runtimeHomePath, { executablePath: server.command }) })) })
|
|
226
233
|
: server.transport === "sse" ? new SSEClientTransport(new URL(server.url), { requestInit: { headers } })
|
|
227
234
|
: new StreamableHTTPClientTransport(new URL(server.url), { requestInit: { headers } });
|
|
228
235
|
await client.connect(transport);
|
|
@@ -286,8 +293,9 @@ finally {
|
|
|
286
293
|
* no longer cancel it.
|
|
287
294
|
*/
|
|
288
295
|
async function machine(cli, config, network, request) {
|
|
296
|
+
const clockEnvironment = taskClockChildEnvironment();
|
|
289
297
|
return await new Promise((resolve, reject) => {
|
|
290
|
-
const child = spawn(cli, ["machine", "--config", config, "--network", network], { stdio: ["pipe", "pipe", "pipe"] });
|
|
298
|
+
const child = spawn(cli, ["machine", "--config", config, "--network", network], { stdio: ["pipe", "pipe", "pipe"], env: taskClockProcessEnvironment(process.env, clockEnvironment) });
|
|
291
299
|
let output = "", error = "", settled = false;
|
|
292
300
|
const settle = (action) => { if (settled)
|
|
293
301
|
return; settled = true; clearTimeout(timer); action(); };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type OrganizationRuntimeConfig } from "./organizationRuntime.js";
|
|
2
|
+
export type RuntimeConfigLocation = Readonly<{
|
|
3
|
+
workspace: string;
|
|
4
|
+
home: string;
|
|
5
|
+
memory: string;
|
|
6
|
+
/** Both paths are explicit: runtime config declares no control-token file. */
|
|
7
|
+
controlToken: Readonly<{
|
|
8
|
+
from: string;
|
|
9
|
+
to: string;
|
|
10
|
+
}>;
|
|
11
|
+
}>;
|
|
12
|
+
/** Rebase one memory-backed agent's path prefixes, preserving instructions verbatim. */
|
|
13
|
+
export declare function relocateRuntimeConfig(config: OrganizationRuntimeConfig, location: RuntimeConfigLocation): OrganizationRuntimeConfig;
|
|
14
|
+
//# sourceMappingURL=relocateRuntimeConfig.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"relocateRuntimeConfig.d.ts","sourceRoot":"","sources":["../../src/runtime/relocateRuntimeConfig.ts"],"names":[],"mappings":"AACA,OAAO,EAAkC,KAAK,yBAAyB,EAAE,MAAM,0BAA0B,CAAC;AAE1G,MAAM,MAAM,qBAAqB,GAAG,QAAQ,CAAC;IAC3C,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,8EAA8E;IAC9E,YAAY,EAAE,QAAQ,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACtD,CAAC,CAAC;AAEH,wFAAwF;AACxF,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,yBAAyB,EAAE,QAAQ,EAAE,qBAAqB,GAAG,yBAAyB,CA8BnI"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { posix } from "node:path";
|
|
2
|
+
import { parseOrganizationRuntimeConfig } from "./organizationRuntime.js";
|
|
3
|
+
/** Rebase one memory-backed agent's path prefixes, preserving instructions verbatim. */
|
|
4
|
+
export function relocateRuntimeConfig(config, location) {
|
|
5
|
+
const parsed = parseOrganizationRuntimeConfig(config);
|
|
6
|
+
const agent = parsed.agents[0];
|
|
7
|
+
if (parsed.agents.length !== 1 || !agent?.memory)
|
|
8
|
+
throw new TypeError("Relocation requires one memory-backed agent");
|
|
9
|
+
const mappings = [
|
|
10
|
+
[agent.workspacePath, location.workspace],
|
|
11
|
+
[agent.runtimeHomePath, location.home],
|
|
12
|
+
[agent.memory.runtimeHomePath, location.memory],
|
|
13
|
+
[location.controlToken.from, location.controlToken.to]
|
|
14
|
+
];
|
|
15
|
+
for (const pair of mappings)
|
|
16
|
+
for (const value of pair) {
|
|
17
|
+
if (typeof value !== "string" || !posix.isAbsolute(value) || posix.normalize(value) !== value || value === "/" || value.endsWith("/") || value.includes("\\") || value.includes("\0")) {
|
|
18
|
+
throw new TypeError("Relocation paths must be canonical absolute POSIX paths other than root");
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
// Memory may live below home; the most specific source must own that subtree.
|
|
22
|
+
const ordered = [...mappings].sort(([a], [b]) => b.length - a.length);
|
|
23
|
+
if (new Set(ordered.map(([source]) => source)).size !== ordered.length)
|
|
24
|
+
throw new TypeError("Relocation source paths must be distinct");
|
|
25
|
+
const relocate = (value) => {
|
|
26
|
+
if (typeof value === "string") {
|
|
27
|
+
const mapping = ordered.find(([source]) => value === source || value.startsWith(`${source}/`));
|
|
28
|
+
return mapping ? mapping[1] + value.slice(mapping[0].length) : value;
|
|
29
|
+
}
|
|
30
|
+
if (Array.isArray(value))
|
|
31
|
+
return value.map(relocate);
|
|
32
|
+
if (value !== null && typeof value === "object") {
|
|
33
|
+
return Object.fromEntries(Object.entries(value).map(([key, item]) => [key, key === "instructions" ? item : relocate(item)]));
|
|
34
|
+
}
|
|
35
|
+
return value;
|
|
36
|
+
};
|
|
37
|
+
return parseOrganizationRuntimeConfig(relocate(parsed));
|
|
38
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schedule.d.ts","sourceRoot":"","sources":["../../src/runtime/schedule.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"schedule.d.ts","sourceRoot":"","sources":["../../src/runtime/schedule.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,8BAA8B,EAAE,2BAA2B,EAAE,MAAM,0BAA0B,CAAC;AAK5G,eAAO,MAAM,kBAAkB,aAAgB,CAAC;AAKhD,MAAM,MAAM,mBAAmB,GAAG,QAAQ,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AACxH,KAAK,cAAc,GAAG,OAAO,CAAC,2BAA2B,EAAE;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,CAAC,CAAC;AAGjF,KAAK,KAAK,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC;AAE3C,MAAM,MAAM,kBAAkB,GAAG,QAAQ,CAAC;IAAE,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAAC,KAAK,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAAC,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CAAE,CAAC,CAAC;AACrI,MAAM,MAAM,yBAAyB,GAAG,QAAQ,CAAC;IAC/C,mBAAmB,EAAE,MAAM,CAAC;IAC5B,MAAM,EAAE,SAAS,8BAA8B,EAAE,CAAC;IAClD,8EAA8E;IAC9E,MAAM,CAAC,UAAU,EAAE,mBAAmB,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;IACjE,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,iJAAiJ;IACjJ,MAAM,CAAC,EAAE,MAAM,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,IAAI,EAAE,OAAO,EAAE,MAAM,KAAK,KAAK,CAAC;IAC5D,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACpC,4EAA4E;IAC5E,qBAAqB,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,GAAG,WAAW,GAAG,QAAQ,GAAG,gBAAgB,KAAK,IAAI,CAAC;CAC9F,CAAC,CAAC;AAEH,wFAAwF;AACxF,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,yBAAyB,GAAG,kBAAkB,CA8F/F;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,cAAc,EAAE,EAAE,EAAE,MAAM,GAAG,mBAAmB,CAIxG;AAED,wBAAgB,6BAA6B,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAKpE;AAED,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,GAAG,SAAS,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAY1H;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAA8E;AAEnI,iHAAiH;AACjH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,cAAc,GAAG,SAAS,EAAE,MAAM,EAAE,MAAM,MAAM,GAAG,MAAM,CAKjG"}
|
package/dist/runtime/schedule.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { assertTaskInstant, validTaskInstant } from "./taskClock.js";
|
|
1
2
|
import { createHash, randomUUID } from "node:crypto";
|
|
2
3
|
import { constants } from "node:fs";
|
|
3
4
|
import { lstat, open, readFile, rename, unlink } from "node:fs/promises";
|
|
@@ -11,7 +12,7 @@ const MAX_SEARCH_CHECKS = 1_000_000;
|
|
|
11
12
|
const CRON_FIELD_BOUNDS = [[0, 59], [0, 23], [1, 31], [1, 12], [0, 7]];
|
|
12
13
|
/** Schedules create durable pending occurrences; engine execution remains elsewhere. */
|
|
13
14
|
export function createScheduleController(options) {
|
|
14
|
-
const now = options.now ?? Date.now;
|
|
15
|
+
const now = () => assertTaskInstant((options.now ?? Date.now)());
|
|
15
16
|
const random = options.random ?? Math.random;
|
|
16
17
|
const setTimer = options.setTimer ?? ((callback, delay) => setTimeout(callback, delay));
|
|
17
18
|
const clearTimer = options.clearTimer ?? clearTimeout;
|
|
@@ -131,6 +132,7 @@ export function createScheduleController(options) {
|
|
|
131
132
|
};
|
|
132
133
|
}
|
|
133
134
|
export function occurrenceFor(agentId, schedule, at) {
|
|
135
|
+
assertTaskInstant(at);
|
|
134
136
|
const local = schedule.kind === "cron" ? occurrenceForOffset(at, schedule.timezone) : new Date(at).toISOString();
|
|
135
137
|
return { agentId, occurredAt: new Date(at).toISOString(), prompt: schedule.prompt, deliveryId: `schedule:${identity(agentId, schedule)}:${local}` };
|
|
136
138
|
}
|
|
@@ -142,16 +144,19 @@ export function isCanonicalScheduleDeliveryId(value) {
|
|
|
142
144
|
|| /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}@(?:GMT(?:[+-]\d{2}:\d{2})?|UTC)$/u.test(occurrence);
|
|
143
145
|
}
|
|
144
146
|
export function nextOccurrence(agentId, schedule, anchor, from) {
|
|
147
|
+
assertTaskInstant(from);
|
|
148
|
+
if (anchor !== undefined)
|
|
149
|
+
assertTaskInstant(anchor);
|
|
145
150
|
if (schedule.kind === "every") {
|
|
146
151
|
const base = anchor ?? from;
|
|
147
|
-
return base > from ? base : base + (Math.floor((from - base) / schedule.interval_ms) + 1) * schedule.interval_ms;
|
|
152
|
+
return assertTaskInstant(base > from ? base : base + (Math.floor((from - base) / schedule.interval_ms) + 1) * schedule.interval_ms);
|
|
148
153
|
}
|
|
149
154
|
const fields = parseCron(schedule.cron);
|
|
150
155
|
if (!calendarPossible(fields))
|
|
151
156
|
throw new Error(`schedule ${agentId} is impossible`);
|
|
152
157
|
const found = searchCron(fields, schedule.timezone, from, from + SEARCH_HORIZON_MS, 1);
|
|
153
158
|
if (found !== undefined)
|
|
154
|
-
return found;
|
|
159
|
+
return assertTaskInstant(found);
|
|
155
160
|
throw new Error(`schedule ${agentId} has no occurrence within the deterministic search bound`);
|
|
156
161
|
}
|
|
157
162
|
export function cronIsPossible(cron) { try {
|
|
@@ -170,7 +175,7 @@ export function jitterOffsetMs(schedule, random) {
|
|
|
170
175
|
}
|
|
171
176
|
function withFireTarget(entry, schedule, random) {
|
|
172
177
|
const offset = jitterOffsetMs(schedule, random);
|
|
173
|
-
return offset === 0 ? entry : { ...entry, fire_at_ms: entry.next_due_ms + offset };
|
|
178
|
+
return offset === 0 ? entry : { ...entry, fire_at_ms: assertTaskInstant(entry.next_due_ms + offset) };
|
|
174
179
|
}
|
|
175
180
|
function withoutPending(entry) {
|
|
176
181
|
return { next_due_ms: entry.next_due_ms, ...(entry.fire_at_ms === undefined ? {} : { fire_at_ms: entry.fire_at_ms }) };
|
|
@@ -306,13 +311,13 @@ async function restore(file, allowed) {
|
|
|
306
311
|
const keys = Object.keys(entry).sort().join();
|
|
307
312
|
if (!["fire_at_ms,next_due_ms", "fire_at_ms,latest_pending,next_due_ms", "latest_pending,next_due_ms", "next_due_ms"].includes(keys))
|
|
308
313
|
throw new Error("schedule state is invalid");
|
|
309
|
-
if (!
|
|
314
|
+
if (!validTaskInstant(entry.next_due_ms))
|
|
310
315
|
throw new Error("schedule state is invalid");
|
|
311
316
|
const nextDue = entry.next_due_ms;
|
|
312
317
|
const fireAt = entry.fire_at_ms;
|
|
313
318
|
if (fireAt !== undefined) {
|
|
314
319
|
const maximumFireAt = nextDue + jitterOffsetMs(allowed.get(key).schedule, () => 0.999_999_999);
|
|
315
|
-
if (!
|
|
320
|
+
if (!validTaskInstant(fireAt) || fireAt < nextDue || fireAt > maximumFireAt)
|
|
316
321
|
throw new Error("schedule state is invalid");
|
|
317
322
|
}
|
|
318
323
|
const pending = entry.latest_pending === undefined ? undefined : parseOccurrence(entry.latest_pending);
|
|
@@ -338,7 +343,7 @@ function parseOccurrence(value) {
|
|
|
338
343
|
if (Object.keys(item).sort().join() !== "agentId,deliveryId,occurredAt,prompt" || Object.values(item).some((entry) => typeof entry !== "string" || Buffer.byteLength(entry, "utf8") > 16_384))
|
|
339
344
|
throw new Error("schedule state is invalid");
|
|
340
345
|
const occurredAt = item.occurredAt;
|
|
341
|
-
if (
|
|
346
|
+
if (!validTaskInstant(Date.parse(occurredAt)) || new Date(occurredAt).toISOString() !== occurredAt || !/^schedule:[a-f0-9]{64}:/u.test(item.deliveryId))
|
|
342
347
|
throw new Error("schedule state is invalid");
|
|
343
348
|
return item;
|
|
344
349
|
}
|
|
@@ -15,6 +15,16 @@ export type StoreHostRegistrationIdentity = StoreHostRegistration & Readonly<{
|
|
|
15
15
|
}>;
|
|
16
16
|
export declare function acquireHostRegistration(root: string, directory: Awaited<ReturnType<typeof open>>, identity: StoreProcessIdentity): Promise<StoreHostRegistration>;
|
|
17
17
|
export declare function releaseHostRegistration(root: string, directory: Awaited<ReturnType<typeof open>>, registration: StoreHostRegistration): Promise<void>;
|
|
18
|
+
/**
|
|
19
|
+
* Remove `.host-online-*` markers left by hosts that are provably dead in this
|
|
20
|
+
* PID namespace. A host only ever removes its own marker on a clean close, so
|
|
21
|
+
* every crash, kill or container recreate left one behind (148 by 2026-10-05),
|
|
22
|
+
* and the markers count against the store's directory bound. The opening host,
|
|
23
|
+
* live owners, other namespaces and anything unreadable are left untouched.
|
|
24
|
+
*/
|
|
25
|
+
export declare function pruneDeadHostRegistrations(root: string, directory: Awaited<ReturnType<typeof open>>, self: StoreHostRegistration, liveness: (owner: StoreHostRegistration & Readonly<{
|
|
26
|
+
generation: string;
|
|
27
|
+
}>) => Promise<boolean>): Promise<number>;
|
|
18
28
|
/** Admin callers hold their durable offline lease before calling this. */
|
|
19
29
|
export declare function listHostRegistrations(root: string): Promise<readonly StoreHostRegistrationIdentity[]>;
|
|
20
30
|
/** Returns undefined when any registration is live, unknown, or changed. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storeCoordination.d.ts","sourceRoot":"","sources":["../../src/runtime/storeCoordination.ts"],"names":[],"mappings":"AAEA,OAAO,EAAS,IAAI,EAA6B,MAAM,kBAAkB,CAAC;AAG1E,MAAM,MAAM,oBAAoB,GAAG,QAAQ,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,iBAAiB,EAAE,MAAM,CAAC;IAAC,iBAAiB,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAC3J,MAAM,MAAM,qBAAqB,GAAG,oBAAoB,GAAG,QAAQ,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAC1F,MAAM,MAAM,6BAA6B,GAAG,qBAAqB,GAAG,QAAQ,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAE3G,wBAAsB,uBAAuB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,CAAC,UAAU,CAAC,OAAO,IAAI,CAAC,CAAC,EAAE,QAAQ,EAAE,oBAAoB,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAWvK;AAED,wBAAsB,uBAAuB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,CAAC,UAAU,CAAC,OAAO,IAAI,CAAC,CAAC,EAAE,YAAY,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CAM3J;AAED,0EAA0E;AAC1E,wBAAsB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,6BAA6B,EAAE,CAAC,CAA0O;AACtV,4EAA4E;AAC5E,wBAAsB,0BAA0B,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,CAAC,UAAU,CAAC,OAAO,IAAI,CAAC,CAAC,EAAE,QAAQ,EAAE,oBAAoB,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,qBAAqB,KAAK,OAAO,CAAC,OAAO,CAAC,EAAE,wBAAwB,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,SAAS,MAAM,EAAE,GAAG,SAAS,CAAC,CAgB/R;AAkBD,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,6BAA6B,GAAG,MAAM,CAA6E"}
|
|
1
|
+
{"version":3,"file":"storeCoordination.d.ts","sourceRoot":"","sources":["../../src/runtime/storeCoordination.ts"],"names":[],"mappings":"AAEA,OAAO,EAAS,IAAI,EAA6B,MAAM,kBAAkB,CAAC;AAG1E,MAAM,MAAM,oBAAoB,GAAG,QAAQ,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,iBAAiB,EAAE,MAAM,CAAC;IAAC,iBAAiB,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAC3J,MAAM,MAAM,qBAAqB,GAAG,oBAAoB,GAAG,QAAQ,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAC1F,MAAM,MAAM,6BAA6B,GAAG,qBAAqB,GAAG,QAAQ,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAE3G,wBAAsB,uBAAuB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,CAAC,UAAU,CAAC,OAAO,IAAI,CAAC,CAAC,EAAE,QAAQ,EAAE,oBAAoB,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAWvK;AAED,wBAAsB,uBAAuB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,CAAC,UAAU,CAAC,OAAO,IAAI,CAAC,CAAC,EAAE,YAAY,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CAM3J;AAED;;;;;;GAMG;AACH,wBAAsB,0BAA0B,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,CAAC,UAAU,CAAC,OAAO,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,qBAAqB,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,qBAAqB,GAAG,QAAQ,CAAC;IAAE,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC,KAAK,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAWzP;AAED,0EAA0E;AAC1E,wBAAsB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,6BAA6B,EAAE,CAAC,CAA0O;AACtV,4EAA4E;AAC5E,wBAAsB,0BAA0B,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,CAAC,UAAU,CAAC,OAAO,IAAI,CAAC,CAAC,EAAE,QAAQ,EAAE,oBAAoB,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,qBAAqB,KAAK,OAAO,CAAC,OAAO,CAAC,EAAE,wBAAwB,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,SAAS,MAAM,EAAE,GAAG,SAAS,CAAC,CAgB/R;AAkBD,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,6BAA6B,GAAG,MAAM,CAA6E"}
|
|
@@ -22,6 +22,29 @@ export async function releaseHostRegistration(root, directory, registration) {
|
|
|
22
22
|
await unlink(target);
|
|
23
23
|
await directory.sync();
|
|
24
24
|
}
|
|
25
|
+
/**
|
|
26
|
+
* Remove `.host-online-*` markers left by hosts that are provably dead in this
|
|
27
|
+
* PID namespace. A host only ever removes its own marker on a clean close, so
|
|
28
|
+
* every crash, kill or container recreate left one behind (148 by 2026-10-05),
|
|
29
|
+
* and the markers count against the store's directory bound. The opening host,
|
|
30
|
+
* live owners, other namespaces and anything unreadable are left untouched.
|
|
31
|
+
*/
|
|
32
|
+
export async function pruneDeadHostRegistrations(root, directory, self, liveness) {
|
|
33
|
+
let pruned = 0;
|
|
34
|
+
for (const entry of await readdir(root)) {
|
|
35
|
+
if (!/^\.host-online-[0-9a-f-]{36}\.json$/iu.test(entry) || entry === `.host-online-${self.owner_id}.json`)
|
|
36
|
+
continue;
|
|
37
|
+
const owner = await readRegistration(path.join(root, entry)).catch(() => undefined);
|
|
38
|
+
// This very process is alive by definition, whichever store in it registered the marker.
|
|
39
|
+
if (owner === undefined || !sameNamespace(owner, self) || (owner.pid === self.pid && owner.process_start === self.process_start && owner.boot_id === self.boot_id) || await liveness({ ...owner, generation: owner.owner_id }).catch(() => true))
|
|
40
|
+
continue;
|
|
41
|
+
await unlink(path.join(root, entry)).catch(() => undefined);
|
|
42
|
+
pruned += 1;
|
|
43
|
+
}
|
|
44
|
+
if (pruned > 0)
|
|
45
|
+
await directory.sync();
|
|
46
|
+
return pruned;
|
|
47
|
+
}
|
|
25
48
|
/** Admin callers hold their durable offline lease before calling this. */
|
|
26
49
|
export async function listHostRegistrations(root) { const result = []; for (const entry of await readdir(root)) {
|
|
27
50
|
if (/^\.host-online-[0-9a-f-]{36}\.json$/iu.test(entry))
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export declare const TASK_CLOCK_ENV = "NOOPOLIS_TASK_CLOCK";
|
|
2
|
+
export declare const TASK_CLOCK_VERSION = "noopolis.task-clock.v1";
|
|
3
|
+
export declare const TASK_CLOCK_MIN_MS = 0;
|
|
4
|
+
export declare const TASK_CLOCK_MAX_MS = 253402300799999;
|
|
5
|
+
export declare function validTaskInstant(value: unknown): value is number;
|
|
6
|
+
export declare function assertTaskInstant(value: number): number;
|
|
7
|
+
export type TaskClock = Readonly<{
|
|
8
|
+
raw: string;
|
|
9
|
+
origin: string;
|
|
10
|
+
anchorEpochMs: number;
|
|
11
|
+
/** Convert a real epoch timestamp without resetting the shared anchor. */
|
|
12
|
+
at(realEpochMs: number): number;
|
|
13
|
+
now(): number;
|
|
14
|
+
}>;
|
|
15
|
+
/** Environment-only contract: no clock callbacks or compiler config in the public API. */
|
|
16
|
+
export declare function readTaskClock(environment?: NodeJS.ProcessEnv): TaskClock | undefined;
|
|
17
|
+
export declare function parseTaskClock(raw: string | undefined): TaskClock | undefined;
|
|
18
|
+
/** The caller installs libfaketime; Daimon derives one process-independent offset. */
|
|
19
|
+
export declare function taskClockChildEnvironment(declared?: NodeJS.ProcessEnv, clock?: Readonly<{
|
|
20
|
+
raw: string;
|
|
21
|
+
origin: string;
|
|
22
|
+
anchorEpochMs: number;
|
|
23
|
+
/** Convert a real epoch timestamp without resetting the shared anchor. */
|
|
24
|
+
at(realEpochMs: number): number;
|
|
25
|
+
now(): number;
|
|
26
|
+
}> | undefined, environment?: NodeJS.ProcessEnv): Record<string, string>;
|
|
27
|
+
/** Inherited environments must not reintroduce another offset owner or loader controls. */
|
|
28
|
+
export declare function taskClockProcessEnvironment(inherited: NodeJS.ProcessEnv, derived?: Record<string, string>): NodeJS.ProcessEnv;
|
|
29
|
+
/** Provider/auth/control processes must never inherit the agent's process clock. */
|
|
30
|
+
export declare function realTimeProcessEnvironment(inherited: NodeJS.ProcessEnv): NodeJS.ProcessEnv;
|
|
31
|
+
/** Reject mixed loader lists: unrelated libraries must never ride this exception. */
|
|
32
|
+
export declare function taskClockPreload(value: string | undefined): string | undefined;
|
|
33
|
+
/** Project real delivery/receipt timestamps, never historical dates inside tool payloads. */
|
|
34
|
+
export declare function taskClockTimestamp(realTimestamp: string, clock?: Readonly<{
|
|
35
|
+
raw: string;
|
|
36
|
+
origin: string;
|
|
37
|
+
anchorEpochMs: number;
|
|
38
|
+
/** Convert a real epoch timestamp without resetting the shared anchor. */
|
|
39
|
+
at(realEpochMs: number): number;
|
|
40
|
+
now(): number;
|
|
41
|
+
}> | undefined): string;
|
|
42
|
+
//# sourceMappingURL=taskClock.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"taskClock.d.ts","sourceRoot":"","sources":["../../src/runtime/taskClock.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,cAAc,wBAAwB,CAAC;AACpD,eAAO,MAAM,kBAAkB,2BAA2B,CAAC;AAC3D,eAAO,MAAM,iBAAiB,IAAI,CAAC;AACnC,eAAO,MAAM,iBAAiB,kBAAsB,CAAC;AAErD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAEhE;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAGvD;AAED,MAAM,MAAM,SAAS,GAAG,QAAQ,CAAC;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;IACtB,0EAA0E;IAC1E,EAAE,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAAC;IAChC,GAAG,IAAI,MAAM,CAAC;CACf,CAAC,CAAC;AAEH,0FAA0F;AAC1F,wBAAgB,aAAa,CAAC,WAAW,GAAE,MAAM,CAAC,UAAwB,GAAG,SAAS,GAAG,SAAS,CAEjG;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,CAc7E;AAED,sFAAsF;AACtF,wBAAgB,yBAAyB,CACvC,QAAQ,GAAE,MAAM,CAAC,UAAe,EAAE,KAAK;SA/BlC,MAAM;YACH,MAAM;mBACC,MAAM;IACrB,0EAA0E;oBAC1D,MAAM,GAAG,MAAM;WACxB,MAAM;cA0B4C,EAAE,WAAW,GAAE,MAAM,CAAC,UAAwB,GACtG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAqBxB;AAED,2FAA2F;AAC3F,wBAAgB,2BAA2B,CACzC,SAAS,EAAE,MAAM,CAAC,UAAU,EAAE,OAAO,yBAA8B,GAClE,MAAM,CAAC,UAAU,CAGnB;AAMD,oFAAoF;AACpF,wBAAgB,0BAA0B,CAAC,SAAS,EAAE,MAAM,CAAC,UAAU,GAAG,MAAM,CAAC,UAAU,CAG1F;AAED,qFAAqF;AACrF,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAG9E;AAED,6FAA6F;AAC7F,wBAAgB,kBAAkB,CAAC,aAAa,EAAE,MAAM,EAAE,KAAK;SAhFxD,MAAM;YACH,MAAM;mBACC,MAAM;IACrB,0EAA0E;oBAC1D,MAAM,GAAG,MAAM;WACxB,MAAM;cA2EkE,GAAG,MAAM,CAEzF"}
|