@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,114 @@
|
|
|
1
|
+
import * as fs from "node:fs/promises";
|
|
2
|
+
import { performance } from "node:perf_hooks";
|
|
3
|
+
export class WakeMomentFault extends Error {
|
|
4
|
+
reason;
|
|
5
|
+
constructor(reason) {
|
|
6
|
+
super(reason);
|
|
7
|
+
this.reason = reason;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
/** Every filesystem call checks cancellation before issuing I/O and after it settles. */
|
|
11
|
+
export class WakeMomentIo {
|
|
12
|
+
probe;
|
|
13
|
+
fs;
|
|
14
|
+
verifyWrite;
|
|
15
|
+
aborted = false;
|
|
16
|
+
expires = Infinity;
|
|
17
|
+
constructor(probe) {
|
|
18
|
+
this.probe = probe;
|
|
19
|
+
this.fs = new Proxy(fs, {
|
|
20
|
+
get: (target, key) => {
|
|
21
|
+
const method = Reflect.get(target, key);
|
|
22
|
+
if (typeof method !== "function")
|
|
23
|
+
return method;
|
|
24
|
+
return (...args) => this.call(String(key), async () => {
|
|
25
|
+
const result = await Reflect.apply(method, target, args);
|
|
26
|
+
if (key === "open")
|
|
27
|
+
return this.handle(result, String(args[0]));
|
|
28
|
+
if (key === "opendir")
|
|
29
|
+
return this.directory(result, String(args[0]));
|
|
30
|
+
if (key === "readdir")
|
|
31
|
+
await this.probe?.("directoryEntries", String(args[0]), result.length);
|
|
32
|
+
return result;
|
|
33
|
+
}, typeof args[key === "symlink" || key === "link" ? 1 : 0] === "string" ? String(args[key === "symlink" || key === "link" ? 1 : 0]) : undefined);
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
check() {
|
|
38
|
+
if (this.aborted || performance.now() >= this.expires) {
|
|
39
|
+
this.aborted = true;
|
|
40
|
+
throw new WakeMomentFault("capture_deadline_exceeded");
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
async call(operation, action, target) {
|
|
44
|
+
this.check();
|
|
45
|
+
await this.probe?.(operation, target);
|
|
46
|
+
this.check();
|
|
47
|
+
if (["open", "mkdir", "rename", "rm", "unlink", "rmdir", "link", "symlink", "write", "writeFile", "chmod"].includes(operation)) {
|
|
48
|
+
await this.verifyWrite?.(target);
|
|
49
|
+
this.check();
|
|
50
|
+
}
|
|
51
|
+
const result = await action();
|
|
52
|
+
try {
|
|
53
|
+
this.check();
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
// An open already in flight can finish after abandonment; release its handle.
|
|
57
|
+
if (result && typeof result.close === "function") {
|
|
58
|
+
void result.close().catch(() => undefined);
|
|
59
|
+
}
|
|
60
|
+
throw error;
|
|
61
|
+
}
|
|
62
|
+
return result;
|
|
63
|
+
}
|
|
64
|
+
async bounded(milliseconds, action) {
|
|
65
|
+
this.expires = performance.now() + milliseconds;
|
|
66
|
+
let timer;
|
|
67
|
+
const deadline = new Promise((_resolve, reject) => {
|
|
68
|
+
timer = setTimeout(() => {
|
|
69
|
+
this.aborted = true;
|
|
70
|
+
reject(new WakeMomentFault("capture_deadline_exceeded"));
|
|
71
|
+
}, milliseconds);
|
|
72
|
+
});
|
|
73
|
+
try {
|
|
74
|
+
return await Promise.race([action(), deadline]);
|
|
75
|
+
}
|
|
76
|
+
finally {
|
|
77
|
+
clearTimeout(timer);
|
|
78
|
+
this.aborted = true;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
handle(handle, target) {
|
|
82
|
+
return new Proxy(handle, { get: (fd, key) => {
|
|
83
|
+
const method = Reflect.get(fd, key, fd);
|
|
84
|
+
if (typeof method !== "function")
|
|
85
|
+
return method;
|
|
86
|
+
if (key === "close")
|
|
87
|
+
return method.bind(fd); // Closing never publishes data.
|
|
88
|
+
return (...args) => this.call(String(key), async () => Reflect.apply(method, fd, args), target);
|
|
89
|
+
} });
|
|
90
|
+
}
|
|
91
|
+
directory(directory, target) {
|
|
92
|
+
const io = this;
|
|
93
|
+
return new Proxy(directory, { get: (dir, key) => {
|
|
94
|
+
if (key === Symbol.asyncIterator)
|
|
95
|
+
return async function* () {
|
|
96
|
+
try {
|
|
97
|
+
for (;;) {
|
|
98
|
+
const entry = await io.call("readdir", () => dir.read(), target);
|
|
99
|
+
if (!entry)
|
|
100
|
+
break;
|
|
101
|
+
await io.probe?.("directoryEntries", target, 1);
|
|
102
|
+
io.check();
|
|
103
|
+
yield entry;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
finally {
|
|
107
|
+
await dir.close();
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
const method = Reflect.get(dir, key, dir);
|
|
111
|
+
return typeof method === "function" ? method.bind(dir) : method;
|
|
112
|
+
} });
|
|
113
|
+
}
|
|
114
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { WAKE_MOMENTS } from "../contracts/wakeMomentContract.js";
|
|
2
|
+
import type { OrganizationRuntimeAgentConfig } from "./organizationRuntime.js";
|
|
3
|
+
import type { StoredWakeAcceptanceRecord } from "./wakeAcceptanceRecord.js";
|
|
4
|
+
import { type WakeMomentIoProbe } from "./wakeMomentIo.js";
|
|
5
|
+
import { type WakeSnapshot } from "./wakeMomentSnapshot.js";
|
|
6
|
+
export { appendWakeMomentRow } from "./wakeMomentRows.js";
|
|
7
|
+
export { pruneWakeMoments } from "./wakeMomentRetention.js";
|
|
8
|
+
export type WakeMomentRow = {
|
|
9
|
+
version: typeof WAKE_MOMENTS.version;
|
|
10
|
+
agent_id: string;
|
|
11
|
+
execution_id: string;
|
|
12
|
+
started_at: string;
|
|
13
|
+
deliveries: {
|
|
14
|
+
acceptance_id: string;
|
|
15
|
+
delivery_id: string;
|
|
16
|
+
kind: string;
|
|
17
|
+
occurred_at: string;
|
|
18
|
+
}[];
|
|
19
|
+
snapshots: WakeSnapshot[];
|
|
20
|
+
error?: string;
|
|
21
|
+
};
|
|
22
|
+
/** Internal seams, intentionally absent from the public runtime barrel/config schema. */
|
|
23
|
+
export type WakeMomentOptions = {
|
|
24
|
+
now?: () => number;
|
|
25
|
+
captureDeadlineMs?: number;
|
|
26
|
+
finalizationDeadlineMs?: number;
|
|
27
|
+
maxManifestBytes?: number;
|
|
28
|
+
probe?: WakeMomentIoProbe;
|
|
29
|
+
verifyStore?: () => Promise<void>;
|
|
30
|
+
};
|
|
31
|
+
/** Advisory, per attempt, and completely inert for an agent without recording. */
|
|
32
|
+
export declare function recordWakeMoment(agent: OrganizationRuntimeAgentConfig, executionId: string, records: readonly StoredWakeAcceptanceRecord[], options?: WakeMomentOptions): Promise<void>;
|
|
33
|
+
//# sourceMappingURL=wakeMomentRecorder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wakeMomentRecorder.d.ts","sourceRoot":"","sources":["../../src/runtime/wakeMomentRecorder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAC;AAClE,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,0BAA0B,CAAC;AAC/E,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,2BAA2B,CAAC;AAE5E,OAAO,EAAgB,KAAK,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACzE,OAAO,EAAuB,KAAK,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAGjF,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAE5D,MAAM,MAAM,aAAa,GAAG;IAC1B,OAAO,EAAE,OAAO,YAAY,CAAC,OAAO,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IACjG,UAAU,EAAE;QAAE,aAAa,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAChG,SAAS,EAAE,YAAY,EAAE,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CAC3C,CAAC;AAEF,yFAAyF;AACzF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAAC,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChF,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,iBAAiB,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CACzF,CAAC;AAEF,kFAAkF;AAClF,wBAAsB,gBAAgB,CAAC,KAAK,EAAE,8BAA8B,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,0BAA0B,EAAE,EAAE,OAAO,GAAE,iBAAsB,GAAG,OAAO,CAAC,IAAI,CAAC,CAgDjM"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { WAKE_MOMENTS } from "../contracts/wakeMomentContract.js";
|
|
2
|
+
import { cleanMomentPaths, pinMomentStore, wakeMomentFailure } from "./wakeMomentFs.js";
|
|
3
|
+
import { WakeMomentIo } from "./wakeMomentIo.js";
|
|
4
|
+
import { captureWakeSnapshot } from "./wakeMomentSnapshot.js";
|
|
5
|
+
import { appendWakeMomentRow } from "./wakeMomentRows.js";
|
|
6
|
+
import { pruneWakeMoments } from "./wakeMomentRetention.js";
|
|
7
|
+
export { appendWakeMomentRow } from "./wakeMomentRows.js";
|
|
8
|
+
export { pruneWakeMoments } from "./wakeMomentRetention.js";
|
|
9
|
+
/** Advisory, per attempt, and completely inert for an agent without recording. */
|
|
10
|
+
export async function recordWakeMoment(agent, executionId, records, options = {}) {
|
|
11
|
+
const recording = agent.recording;
|
|
12
|
+
if (!recording)
|
|
13
|
+
return;
|
|
14
|
+
const now = options.now ?? Date.now, io = new WakeMomentIo(options.probe), cleanup = new Set();
|
|
15
|
+
const errors = [];
|
|
16
|
+
let store, row;
|
|
17
|
+
try {
|
|
18
|
+
await io.bounded(options.captureDeadlineMs ?? WAKE_MOMENTS.captureDeadlineMs, async () => {
|
|
19
|
+
store = await pinMomentStore(recording.directory, io, options.verifyStore);
|
|
20
|
+
io.verifyWrite = (target) => store.verify(io, target);
|
|
21
|
+
await store.verify(io); // Immediately before capture, against the pinned root.
|
|
22
|
+
row = {
|
|
23
|
+
version: WAKE_MOMENTS.version, agent_id: agent.id, execution_id: executionId, started_at: new Date(now()).toISOString(),
|
|
24
|
+
deliveries: records.map(({ acceptance_id, delivery_id, event }) => ({ acceptance_id, delivery_id, kind: event.kind, occurred_at: event.occurred_at })), snapshots: []
|
|
25
|
+
};
|
|
26
|
+
for (const root of recording.snapshots) {
|
|
27
|
+
try {
|
|
28
|
+
const captured = await captureWakeSnapshot({ directory: recording.directory, root, startedAt: row.started_at, executionId, io, cleanup, maxManifestBytes: options.maxManifestBytes });
|
|
29
|
+
io.check();
|
|
30
|
+
row.snapshots.push(captured.snapshot);
|
|
31
|
+
if (captured.note)
|
|
32
|
+
errors.push(`${root.id}: ${captured.note}`);
|
|
33
|
+
}
|
|
34
|
+
catch (error) {
|
|
35
|
+
io.check(); // Deadline abandons the remaining roots, not just this one.
|
|
36
|
+
if (wakeMomentFailure(error) === "recording_store_changed")
|
|
37
|
+
throw error;
|
|
38
|
+
errors.push(`${root.id}: ${wakeMomentFailure(error)}`);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
catch (error) {
|
|
44
|
+
errors.push(wakeMomentFailure(error));
|
|
45
|
+
}
|
|
46
|
+
// Capture is fenced before the row or cognition: late I/O completions cannot issue another write.
|
|
47
|
+
const finalizer = new WakeMomentIo(options.probe);
|
|
48
|
+
try {
|
|
49
|
+
await finalizer.bounded(options.finalizationDeadlineMs ?? WAKE_MOMENTS.finalizationDeadlineMs, async () => {
|
|
50
|
+
if (!store || !row) {
|
|
51
|
+
logFailure(errors.join("; "));
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
finalizer.verifyWrite = (target) => store.verify(finalizer, target);
|
|
55
|
+
if (errors.length)
|
|
56
|
+
row.error = errors.join("; ").slice(0, 2048);
|
|
57
|
+
// A stuck best-effort cleanup must not prevent the error row from being attempted.
|
|
58
|
+
const [cleaned] = await Promise.all([
|
|
59
|
+
cleanMomentPaths(cleanup, store, finalizer).then(() => true, (error) => { logFailure(wakeMomentFailure(error)); return false; }),
|
|
60
|
+
appendWakeMomentRow(recording.directory, row, finalizer)
|
|
61
|
+
]);
|
|
62
|
+
if (cleaned) {
|
|
63
|
+
finalizer.check();
|
|
64
|
+
await pruneWakeMoments(recording, agent.id, now(), row, finalizer, store);
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
logFailure(wakeMomentFailure(error));
|
|
70
|
+
}
|
|
71
|
+
finally {
|
|
72
|
+
if (store)
|
|
73
|
+
void store.close().catch(() => undefined);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
function logFailure(reason) {
|
|
77
|
+
try {
|
|
78
|
+
console.error(`daimon: wake recording failed: ${reason}`);
|
|
79
|
+
}
|
|
80
|
+
catch { /* Logging is advisory too. */ }
|
|
81
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { type WakeMomentRecording } from "../contracts/wakeMomentContract.js";
|
|
2
|
+
import { type MomentStore } from "./wakeMomentFs.js";
|
|
3
|
+
import { WakeMomentIo } from "./wakeMomentIo.js";
|
|
4
|
+
import type { WakeMomentRow } from "./wakeMomentRecorder.js";
|
|
5
|
+
/** First-line age check; a full sweep every 64 calls also handles foreign prefixes/clock rollback. */
|
|
6
|
+
export declare function pruneWakeMoments(recording: WakeMomentRecording, agentId: string, now?: number, current?: WakeMomentRow, scope?: WakeMomentIo, authority?: MomentStore): Promise<void>;
|
|
7
|
+
//# sourceMappingURL=wakeMomentRetention.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wakeMomentRetention.d.ts","sourceRoot":"","sources":["../../src/runtime/wakeMomentRetention.ts"],"names":[],"mappings":"AAIA,OAAO,EAAgB,KAAK,mBAAmB,EAAE,MAAM,oCAAoC,CAAC;AAC5F,OAAO,EAAkI,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrL,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAkB7D,sGAAsG;AACtG,wBAAsB,gBAAgB,CAAC,SAAS,EAAE,mBAAmB,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,SAAa,EAAE,OAAO,CAAC,EAAE,aAAa,EAAE,KAAK,CAAC,EAAE,YAAY,EAAE,SAAS,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAU/L"}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { constants } from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { WAKE_MOMENTS } from "../contracts/wakeMomentContract.js";
|
|
5
|
+
import { cleanMomentPaths, openMomentDirectory, openMomentFile, pinMomentStore, removeMomentPath, syncMomentDirectory, writeMomentBytes } from "./wakeMomentFs.js";
|
|
6
|
+
import { WakeMomentIo } from "./wakeMomentIo.js";
|
|
7
|
+
import { momentLines } from "./wakeMomentRows.js";
|
|
8
|
+
import { completeSnapshotNames, eligibleSnapshot, indexFromNames, latestSnapshotIndex, snapshotRootName, snapshotTime, writeSnapshotIndex } from "./wakeMomentHistory.js";
|
|
9
|
+
const sweeps = new Map();
|
|
10
|
+
const key = (snapshot) => `${snapshot.id}/${snapshot.snapshot}`;
|
|
11
|
+
function expiredRow(line, agentId, cutoff, current) {
|
|
12
|
+
try {
|
|
13
|
+
const row = JSON.parse(line.toString("utf8"));
|
|
14
|
+
if (current && row.execution_id === current.execution_id && row.started_at === current.started_at)
|
|
15
|
+
return undefined;
|
|
16
|
+
if (row?.version === WAKE_MOMENTS.version && row.agent_id === agentId && typeof row.execution_id === "string"
|
|
17
|
+
&& Array.isArray(row.deliveries) && Array.isArray(row.snapshots) && typeof row.started_at === "string"
|
|
18
|
+
&& new Date(row.started_at).toISOString() === row.started_at && Date.parse(row.started_at) < cutoff)
|
|
19
|
+
return row;
|
|
20
|
+
}
|
|
21
|
+
catch { /* Unknown/partial lines are not ours to delete. */ }
|
|
22
|
+
return undefined;
|
|
23
|
+
}
|
|
24
|
+
/** First-line age check; a full sweep every 64 calls also handles foreign prefixes/clock rollback. */
|
|
25
|
+
export async function pruneWakeMoments(recording, agentId, now = Date.now(), current, scope, authority) {
|
|
26
|
+
const io = scope ?? new WakeMomentIo();
|
|
27
|
+
const store = authority ?? await pinMomentStore(recording.directory, io);
|
|
28
|
+
io.verifyWrite = (target) => store.verify(io, target);
|
|
29
|
+
try {
|
|
30
|
+
const cutoff = now - recording.keepMs;
|
|
31
|
+
await pruneSnapshots(recording.directory, new Set(current?.snapshots.map(key) ?? []), cutoff, io, store);
|
|
32
|
+
await pruneRows(recording, agentId, cutoff, current, io, store);
|
|
33
|
+
}
|
|
34
|
+
finally {
|
|
35
|
+
if (!authority)
|
|
36
|
+
await store.close();
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
async function pruneRows(recording, agentId, cutoff, current, io, store) {
|
|
40
|
+
const target = path.join(recording.directory, WAKE_MOMENTS.rowsFile);
|
|
41
|
+
let source;
|
|
42
|
+
try {
|
|
43
|
+
source = await openMomentFile(target, constants.O_RDONLY, io);
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
if (error.code === "ENOENT")
|
|
47
|
+
return;
|
|
48
|
+
throw error;
|
|
49
|
+
}
|
|
50
|
+
const temporary = `${target}.${randomUUID()}.tmp`;
|
|
51
|
+
let output, changed = false, created = false;
|
|
52
|
+
try {
|
|
53
|
+
const count = (sweeps.get(target) ?? 0) + 1;
|
|
54
|
+
sweeps.set(target, count % 64);
|
|
55
|
+
let firstExpired = false;
|
|
56
|
+
for await (const line of momentLines(source)) {
|
|
57
|
+
firstExpired = expiredRow(line, agentId, cutoff, current) !== undefined;
|
|
58
|
+
break;
|
|
59
|
+
}
|
|
60
|
+
if (!firstExpired && count % 64 !== 0)
|
|
61
|
+
return;
|
|
62
|
+
output = await openMomentFile(temporary, constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL, io);
|
|
63
|
+
created = true;
|
|
64
|
+
const reread = await openMomentFile(target, constants.O_RDONLY, io);
|
|
65
|
+
try {
|
|
66
|
+
for await (const line of momentLines(reread)) {
|
|
67
|
+
const expired = expiredRow(line, agentId, cutoff, current);
|
|
68
|
+
if (!expired) {
|
|
69
|
+
await writeMomentBytes(output, line);
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
changed = true;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
finally {
|
|
76
|
+
await reread.close();
|
|
77
|
+
}
|
|
78
|
+
if (!changed)
|
|
79
|
+
return;
|
|
80
|
+
await output.sync();
|
|
81
|
+
await output.close();
|
|
82
|
+
output = undefined;
|
|
83
|
+
await io.fs.rename(temporary, target);
|
|
84
|
+
created = false;
|
|
85
|
+
await syncMomentDirectory(recording.directory, io);
|
|
86
|
+
}
|
|
87
|
+
finally {
|
|
88
|
+
await source.close();
|
|
89
|
+
await output?.close();
|
|
90
|
+
if (created)
|
|
91
|
+
await removeMomentPath(temporary, store, io);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
/** Age comes from names; ownership comes from the writer's zero-byte completion marker. */
|
|
95
|
+
async function pruneSnapshots(directory, protectedSnapshots, cutoff, io, store) {
|
|
96
|
+
const namespace = path.join(directory, WAKE_MOMENTS.snapshotsDirectory);
|
|
97
|
+
try {
|
|
98
|
+
const ns = await openMomentDirectory(namespace, io);
|
|
99
|
+
await ns.close();
|
|
100
|
+
for await (const root of await io.fs.opendir(namespace)) {
|
|
101
|
+
if (!root.isDirectory() || !/^(?:[A-Za-z0-9._-]{1,128}|%2E|%2E%2E)$/.test(root.name))
|
|
102
|
+
continue;
|
|
103
|
+
const id = root.name === "%2E" ? "." : root.name === "%2E%2E" ? ".." : root.name;
|
|
104
|
+
if (snapshotRootName(id) !== root.name)
|
|
105
|
+
continue;
|
|
106
|
+
const base = path.join(namespace, root.name);
|
|
107
|
+
const fd = await openMomentDirectory(base, io);
|
|
108
|
+
await fd.close();
|
|
109
|
+
const state = await latestSnapshotIndex(base, io);
|
|
110
|
+
if (!state.names && (state.index.oldest === null || snapshotTime(state.index.oldest) >= cutoff))
|
|
111
|
+
continue;
|
|
112
|
+
const names = state.names ?? await completeSnapshotNames(base, io), removed = new Set();
|
|
113
|
+
for (const name of names.slice(1)) {
|
|
114
|
+
if (protectedSnapshots.has(`${id}/${name}`) || snapshotTime(name) >= cutoff)
|
|
115
|
+
continue;
|
|
116
|
+
const target = path.join(base, name), manifest = `${target}.manifest.json`, marker = `${target}${WAKE_MOMENTS.completionSuffix}`;
|
|
117
|
+
await store.verify(io, target);
|
|
118
|
+
if (!await eligibleSnapshot(base, name, io))
|
|
119
|
+
continue;
|
|
120
|
+
await store.verify(io, target);
|
|
121
|
+
await removeMomentPath(target, store, io);
|
|
122
|
+
await removeMomentPath(manifest, store, io);
|
|
123
|
+
await removeMomentPath(marker, store, io);
|
|
124
|
+
await syncMomentDirectory(base, io);
|
|
125
|
+
removed.add(name);
|
|
126
|
+
}
|
|
127
|
+
const index = indexFromNames(names.filter((name) => !removed.has(name)));
|
|
128
|
+
if (index) {
|
|
129
|
+
const cleanup = new Set();
|
|
130
|
+
try {
|
|
131
|
+
await writeSnapshotIndex(base, index, io, cleanup);
|
|
132
|
+
}
|
|
133
|
+
finally {
|
|
134
|
+
await cleanMomentPaths(cleanup, store, io);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
catch (error) {
|
|
140
|
+
if (error.code !== "ENOENT")
|
|
141
|
+
throw error;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { FileHandle } from "node:fs/promises";
|
|
2
|
+
import { WakeMomentIo } from "./wakeMomentIo.js";
|
|
3
|
+
import type { WakeMomentRow } from "./wakeMomentRecorder.js";
|
|
4
|
+
/** One append write and fsync. A torn prior append is delimited, never mistaken for this attempt. */
|
|
5
|
+
export declare function appendWakeMomentRow(directory: string, row: WakeMomentRow, io?: WakeMomentIo): Promise<void>;
|
|
6
|
+
/** Bound memory even when a damaged/foreign rows file has no newlines. */
|
|
7
|
+
export declare function momentLines(fd: FileHandle): AsyncGenerator<Buffer>;
|
|
8
|
+
//# sourceMappingURL=wakeMomentRows.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wakeMomentRows.d.ts","sourceRoot":"","sources":["../../src/runtime/wakeMomentRows.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAInD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAE7D,qGAAqG;AACrG,wBAAsB,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,aAAa,EAAE,EAAE,eAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CAoBvH;AAED,0EAA0E;AAC1E,wBAAuB,WAAW,CAAC,EAAE,EAAE,UAAU,GAAG,cAAc,CAAC,MAAM,CAAC,CAmBzE"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { constants } from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { WAKE_MOMENTS } from "../contracts/wakeMomentContract.js";
|
|
4
|
+
import { openMomentFile, syncMomentDirectory, WakeMomentFault } from "./wakeMomentFs.js";
|
|
5
|
+
import { WakeMomentIo } from "./wakeMomentIo.js";
|
|
6
|
+
/** One append write and fsync. A torn prior append is delimited, never mistaken for this attempt. */
|
|
7
|
+
export async function appendWakeMomentRow(directory, row, io = new WakeMomentIo()) {
|
|
8
|
+
const line = Buffer.from(`${JSON.stringify(row)}\n`);
|
|
9
|
+
if (line.length > WAKE_MOMENTS.maxRowBytes)
|
|
10
|
+
throw new WakeMomentFault("row_size_limit");
|
|
11
|
+
const target = path.join(directory, WAKE_MOMENTS.rowsFile);
|
|
12
|
+
let created = false, fd;
|
|
13
|
+
try {
|
|
14
|
+
fd = await openMomentFile(target, constants.O_RDWR | constants.O_CREAT | constants.O_EXCL | constants.O_APPEND, io);
|
|
15
|
+
created = true;
|
|
16
|
+
}
|
|
17
|
+
catch (error) {
|
|
18
|
+
if (error.code !== "EEXIST")
|
|
19
|
+
throw error;
|
|
20
|
+
fd = await openMomentFile(target, constants.O_RDWR | constants.O_APPEND, io);
|
|
21
|
+
}
|
|
22
|
+
try {
|
|
23
|
+
const size = (await fd.stat()).size;
|
|
24
|
+
const tail = Buffer.alloc(1);
|
|
25
|
+
if (size)
|
|
26
|
+
await fd.read(tail, 0, 1, size - 1);
|
|
27
|
+
const bytes = size && tail[0] !== 10 ? Buffer.concat([Buffer.from("\n"), line]) : line;
|
|
28
|
+
const { bytesWritten } = await fd.write(bytes);
|
|
29
|
+
if (bytesWritten !== bytes.length)
|
|
30
|
+
throw new WakeMomentFault("short_row_write");
|
|
31
|
+
await fd.sync();
|
|
32
|
+
if (created)
|
|
33
|
+
await syncMomentDirectory(directory, io);
|
|
34
|
+
}
|
|
35
|
+
finally {
|
|
36
|
+
await fd.close();
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/** Bound memory even when a damaged/foreign rows file has no newlines. */
|
|
40
|
+
export async function* momentLines(fd) {
|
|
41
|
+
const chunk = Buffer.alloc(64 * 1024);
|
|
42
|
+
let pending = [], length = 0;
|
|
43
|
+
for (;;) {
|
|
44
|
+
const { bytesRead } = await fd.read(chunk, 0, chunk.length, null);
|
|
45
|
+
if (!bytesRead)
|
|
46
|
+
break;
|
|
47
|
+
let start = 0;
|
|
48
|
+
while (start < bytesRead) {
|
|
49
|
+
const newline = chunk.indexOf(10, start);
|
|
50
|
+
const end = newline >= start && newline < bytesRead ? newline + 1 : bytesRead;
|
|
51
|
+
const part = Buffer.from(chunk.subarray(start, end));
|
|
52
|
+
length += part.length;
|
|
53
|
+
if (length > WAKE_MOMENTS.maxRowBytes)
|
|
54
|
+
throw new WakeMomentFault("row_size_limit");
|
|
55
|
+
pending.push(part);
|
|
56
|
+
if (part[part.length - 1] === 10) {
|
|
57
|
+
yield Buffer.concat(pending, length);
|
|
58
|
+
pending = [];
|
|
59
|
+
length = 0;
|
|
60
|
+
}
|
|
61
|
+
start = end;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
if (length)
|
|
65
|
+
yield Buffer.concat(pending, length);
|
|
66
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { WAKE_MOMENTS } from "../contracts/wakeMomentContract.js";
|
|
2
|
+
import { WakeMomentIo } from "./wakeMomentIo.js";
|
|
3
|
+
export { completeSnapshotNames, snapshotName, snapshotRootName, snapshotTime } from "./wakeMomentHistory.js";
|
|
4
|
+
type Identity = {
|
|
5
|
+
dev: string;
|
|
6
|
+
ino: string;
|
|
7
|
+
size: string;
|
|
8
|
+
mtimeNs: string;
|
|
9
|
+
ctimeNs: string;
|
|
10
|
+
mode: number;
|
|
11
|
+
};
|
|
12
|
+
export type SnapshotEntry = {
|
|
13
|
+
type: "file" | "directory" | "symlink";
|
|
14
|
+
mode: number;
|
|
15
|
+
size: string;
|
|
16
|
+
source: Identity;
|
|
17
|
+
target?: string;
|
|
18
|
+
};
|
|
19
|
+
export type WakeSnapshotManifest = {
|
|
20
|
+
version: typeof WAKE_MOMENTS.version;
|
|
21
|
+
id: string;
|
|
22
|
+
snapshot: string;
|
|
23
|
+
started_at: string;
|
|
24
|
+
sourcePath: string;
|
|
25
|
+
entries: Record<string, SnapshotEntry>;
|
|
26
|
+
};
|
|
27
|
+
export type WakeSnapshot = {
|
|
28
|
+
id: string;
|
|
29
|
+
snapshot: string;
|
|
30
|
+
files: number;
|
|
31
|
+
copied: number;
|
|
32
|
+
linked: number;
|
|
33
|
+
skipped: number;
|
|
34
|
+
};
|
|
35
|
+
export declare function readSnapshotManifest(directory: string, name: string, id: string, io?: WakeMomentIo, maxManifestBytes?: number): Promise<WakeSnapshotManifest | undefined>;
|
|
36
|
+
/** SOURCE identity, never the copied inode's metadata: ordinary writers cannot restore ctime. */
|
|
37
|
+
export declare function sameSnapshotSource(left: Identity, right: Identity): boolean;
|
|
38
|
+
type CaptureInput = {
|
|
39
|
+
directory: string;
|
|
40
|
+
root: {
|
|
41
|
+
id: string;
|
|
42
|
+
path: string;
|
|
43
|
+
};
|
|
44
|
+
startedAt: string;
|
|
45
|
+
executionId: string;
|
|
46
|
+
/** Internal test bounds; not caller configuration. */
|
|
47
|
+
maxEntries?: number;
|
|
48
|
+
maxManifestBytes?: number;
|
|
49
|
+
io?: WakeMomentIo;
|
|
50
|
+
cleanup?: Set<string>;
|
|
51
|
+
};
|
|
52
|
+
export declare function captureWakeSnapshot(input: CaptureInput): Promise<{
|
|
53
|
+
snapshot: WakeSnapshot;
|
|
54
|
+
note?: string;
|
|
55
|
+
}>;
|
|
56
|
+
//# sourceMappingURL=wakeMomentSnapshot.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wakeMomentSnapshot.d.ts","sourceRoot":"","sources":["../../src/runtime/wakeMomentSnapshot.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAC;AAIlE,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,OAAO,EAAE,qBAAqB,EAAE,YAAY,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAE7G,KAAK,QAAQ,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAC3G,MAAM,MAAM,aAAa,GAAG;IAAE,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,QAAQ,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AACtI,MAAM,MAAM,oBAAoB,GAAG;IACjC,OAAO,EAAE,OAAO,YAAY,CAAC,OAAO,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAC3G,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;CACxC,CAAC;AACF,MAAM,MAAM,YAAY,GAAG;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAC5H,wBAAsB,oBAAoB,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,eAAqB,EAAE,gBAAgB,GAAoC,MAAM,GAAG,OAAO,CAAC,oBAAoB,GAAG,SAAS,CAAC,CAQtN;AAED,iGAAiG;AACjG,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,GAAG,OAAO,CAG3E;AAKD,KAAK,YAAY,GAAG;IAClB,SAAS,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAC9F,sDAAsD;IACtD,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC/C,EAAE,CAAC,EAAE,YAAY,CAAC;IAAC,OAAO,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CAC1C,CAAC;AAEF,wBAAsB,mBAAmB,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC;IAAE,QAAQ,EAAE,YAAY,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAkBjH"}
|