@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
|
@@ -5,6 +5,7 @@ import { grokWorkerEventsPathFor } from "./grokWorkerSandboxProfile.js";
|
|
|
5
5
|
import { TURN_REQUEST_LEDGER } from "./turnRequestLedger.js";
|
|
6
6
|
import { TURN_USAGE_LEDGER } from "./turnUsageLedger.js";
|
|
7
7
|
export const ENGINE_BROKER_SERVICE_V1 = "noopolis.daimon.engine-broker-service.v1";
|
|
8
|
+
export const ENGINE_BROKER_SERVICE_V3 = "noopolis.daimon.engine-broker-service.v3";
|
|
8
9
|
export const ENGINE_BROKER_SERVICE_V2 = "noopolis.daimon.engine-broker-service.v2";
|
|
9
10
|
const V1_REGISTRATION = ["agentId", "slot", "workerUid", "workspace", "profilePath", "eventsPath", "profileSha256"];
|
|
10
11
|
const V2_REGISTRATION = [...V1_REGISTRATION, "usageLedgerPath", "limits", "model"];
|
|
@@ -29,6 +30,8 @@ export const engineBrokerSealLedgerPathFor = (usageLedgerPath) => path.posix.joi
|
|
|
29
30
|
/**
|
|
30
31
|
* Strict `service.json` parser.
|
|
31
32
|
*
|
|
33
|
+
* v3 retains seven-field registrations and binds slotPolicies by slot; agent IDs
|
|
34
|
+
* may repeat, while worker UIDs, slots and ledger streams must be distinct.
|
|
32
35
|
* v2 requires every registration to declare its usage ledger, limits and model
|
|
33
36
|
* (`model.id`/`model.reasoningEffort` from the closed lists); unknown keys at
|
|
34
37
|
* any level are refused. v1 is still accepted and receives today's defaults:
|
|
@@ -38,39 +41,74 @@ export const engineBrokerSealLedgerPathFor = (usageLedgerPath) => path.posix.joi
|
|
|
38
41
|
export function parseEngineBrokerServiceConfig(value) {
|
|
39
42
|
if (!plain(value))
|
|
40
43
|
throw invalid();
|
|
41
|
-
const
|
|
44
|
+
const v3 = value.version === ENGINE_BROKER_SERVICE_V3;
|
|
45
|
+
const v2 = v3 || value.version === ENGINE_BROKER_SERVICE_V2;
|
|
42
46
|
if (!v2 && value.version !== ENGINE_BROKER_SERVICE_V1)
|
|
43
47
|
throw invalid();
|
|
44
|
-
const top = ["version", "credentialHome", "turnStore", "registrations"];
|
|
48
|
+
const top = ["version", "credentialHome", "turnStore", "registrations", ...(v3 ? ["slotPolicies"] : [])];
|
|
49
|
+
if (v3 && Object.hasOwn(value, "maxRunRequests")) {
|
|
50
|
+
if (!Number.isSafeInteger(value.maxRunRequests) || value.maxRunRequests < 1)
|
|
51
|
+
throw invalid();
|
|
52
|
+
top.push("maxRunRequests");
|
|
53
|
+
}
|
|
54
|
+
if (v3 && Object.hasOwn(value, "runRequestStore")) {
|
|
55
|
+
if (!absolute(value.runRequestStore) || value.maxRunRequests === undefined)
|
|
56
|
+
throw invalid();
|
|
57
|
+
top.push("runRequestStore");
|
|
58
|
+
}
|
|
45
59
|
exact(value, v2 && Object.hasOwn(value, "inferenceLedgerPath") ? [...top, "inferenceLedgerPath"] : top);
|
|
46
60
|
if (!absolute(value.credentialHome) || !absolute(value.turnStore) || !Array.isArray(value.registrations) || value.registrations.length === 0)
|
|
47
61
|
throw invalid();
|
|
48
|
-
const
|
|
62
|
+
const policies = new Map();
|
|
63
|
+
if (v3) {
|
|
64
|
+
if (!Array.isArray(value.slotPolicies) || value.slotPolicies.length !== value.registrations.length)
|
|
65
|
+
throw invalid();
|
|
66
|
+
for (const policy of value.slotPolicies) {
|
|
67
|
+
if (!plain(policy))
|
|
68
|
+
throw invalid();
|
|
69
|
+
exact(policy, ["slot", "usageLedgerPath", "limits", "model"]);
|
|
70
|
+
if (!Number.isSafeInteger(policy.slot) || policy.slot < 0 || policies.has(policy.slot))
|
|
71
|
+
throw invalid();
|
|
72
|
+
policies.set(policy.slot, policy);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
const seen = new Set(), slots = new Set(), workers = new Set();
|
|
76
|
+
const ledgers = new Set();
|
|
49
77
|
const registrations = value.registrations.map((entry) => {
|
|
50
78
|
if (!plain(entry))
|
|
51
79
|
throw invalid();
|
|
52
|
-
exact(entry, v2 ? V2_REGISTRATION : V1_REGISTRATION);
|
|
80
|
+
exact(entry, v2 && !v3 ? V2_REGISTRATION : V1_REGISTRATION);
|
|
53
81
|
const { agentId, slot, workerUid, workspace, profilePath, eventsPath, profileSha256 } = entry;
|
|
54
|
-
if (typeof agentId !== "string" || !agentId.trim() || seen.has(agentId) || !Number.isSafeInteger(slot) || slot < 0 || slots.has(slot) || !Number.isSafeInteger(workerUid) || workerUid < 2200 || !absolute(workspace) || !absolute(profilePath) || !absolute(eventsPath) || typeof profileSha256 !== "string" || !/^[a-f0-9]{64}$/u.test(profileSha256) || eventsPath !== grokWorkerEventsPathFor(profilePath) || !profilePath.endsWith("/sandbox.toml"))
|
|
82
|
+
if (typeof agentId !== "string" || !agentId.trim() || (!v3 && seen.has(agentId)) || !Number.isSafeInteger(slot) || slot < 0 || slots.has(slot) || !Number.isSafeInteger(workerUid) || workerUid < 2200 || workers.has(workerUid) || !absolute(workspace) || !absolute(profilePath) || !absolute(eventsPath) || typeof profileSha256 !== "string" || !/^[a-f0-9]{64}$/u.test(profileSha256) || eventsPath !== grokWorkerEventsPathFor(profilePath) || !profilePath.endsWith("/sandbox.toml"))
|
|
55
83
|
throw invalid();
|
|
56
84
|
seen.add(agentId);
|
|
57
85
|
slots.add(slot);
|
|
86
|
+
workers.add(workerUid);
|
|
58
87
|
const base = { agentId, slot: slot, workerUid: workerUid, workspace, profilePath, eventsPath, profileSha256 };
|
|
59
88
|
if (!v2)
|
|
60
89
|
return { ...base, usageLedgerPath: TURN_USAGE_LEDGER.filePath, limits: DEFAULT_GROK_BROKER_TURN_LIMITS, model: DEFAULT_GROK_BROKER_MODEL_POLICY };
|
|
61
|
-
const
|
|
90
|
+
const policy = v3 ? policies.get(slot) : entry;
|
|
91
|
+
if (policy === undefined)
|
|
92
|
+
throw invalid();
|
|
93
|
+
const usageLedgerPath = policy.usageLedgerPath;
|
|
62
94
|
if (!ledgerPath(usageLedgerPath) || usageLedgerPath === engineBrokerRequestLedgerPathFor(usageLedgerPath) || usageLedgerPath === engineBrokerSealLedgerPathFor(usageLedgerPath))
|
|
63
95
|
throw invalid();
|
|
96
|
+
const streams = [usageLedgerPath, engineBrokerRequestLedgerPathFor(usageLedgerPath), engineBrokerSealLedgerPathFor(usageLedgerPath)];
|
|
97
|
+
if (v3 && streams.some((file) => ledgers.has(file)))
|
|
98
|
+
throw invalid();
|
|
99
|
+
streams.forEach((file) => ledgers.add(file));
|
|
64
100
|
let limits;
|
|
65
101
|
try {
|
|
66
|
-
limits = parseEngineBrokerTurnLimits(
|
|
102
|
+
limits = parseEngineBrokerTurnLimits(policy.limits);
|
|
67
103
|
}
|
|
68
104
|
catch {
|
|
69
105
|
throw invalid();
|
|
70
106
|
}
|
|
71
|
-
return { ...base, usageLedgerPath, limits, model: parseServiceModel(
|
|
107
|
+
return { ...base, usageLedgerPath, limits, model: parseServiceModel(policy.model) };
|
|
72
108
|
});
|
|
73
|
-
const base = { credentialHome: value.credentialHome, turnStore: value.turnStore, registrations
|
|
109
|
+
const base = { credentialHome: value.credentialHome, turnStore: value.turnStore, registrations,
|
|
110
|
+
...(value.runRequestStore === undefined ? {} : { runRequestStore: value.runRequestStore }),
|
|
111
|
+
...(value.maxRunRequests === undefined ? {} : { maxRunRequests: value.maxRunRequests }) };
|
|
74
112
|
if (!Object.hasOwn(value, "inferenceLedgerPath"))
|
|
75
113
|
return base;
|
|
76
114
|
const inferenceLedgerPath = value.inferenceLedgerPath;
|
|
@@ -48,7 +48,7 @@ export declare class EngineBrokerTurnRegistry {
|
|
|
48
48
|
}
|
|
49
49
|
/**
|
|
50
50
|
* Strict record parser. v2 accepts exactly `{version,digest,state,bootId}`
|
|
51
|
-
* plus `response` and its sealed `ledger` bytes when terminal, and the response
|
|
51
|
+
* plus `response` and its sealed `ledger` bytes when terminal, and the response may be a v2, v3 or v4 terminal frame (older frames upgrade on read).
|
|
52
52
|
* v1 records keep their historical looser shape and are upgraded on read: no
|
|
53
53
|
* usage (`null`), zero requests, `limitReason: "none"`, the declared model.
|
|
54
54
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"engineBrokerTurnRegistry.d.ts","sourceRoot":"","sources":["../../src/runtime/engineBrokerTurnRegistry.ts"],"names":[],"mappings":"AAIA,OAAO,
|
|
1
|
+
{"version":3,"file":"engineBrokerTurnRegistry.d.ts","sourceRoot":"","sources":["../../src/runtime/engineBrokerTurnRegistry.ts"],"names":[],"mappings":"AAIA,OAAO,EAAmK,KAAK,mBAAmB,EAAE,KAAK,4BAA4B,EAAE,MAAM,2BAA2B,CAAC;AACzQ,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAClE,OAAO,EAAwD,KAAK,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AAE/H,KAAK,KAAK,GAAG,OAAO,CAAC,mBAAmB,EAAE;IAAE,IAAI,EAAE,YAAY,CAAA;CAAE,CAAC,CAAC;AAClE,KAAK,QAAQ,GAAG,4BAA4B,CAAC;AAC7C,eAAO,MAAM,4BAA4B,EAAG,uCAAgD,CAAC;AAC7F,eAAO,MAAM,4BAA4B,EAAG,uCAAgD,CAAC;AAM7F,KAAK,QAAQ,GAAG,QAAQ,CAAC;IAAE,OAAO,EAAE,OAAO,4BAA4B,GAAG,OAAO,4BAA4B,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,QAAQ,GAAG,UAAU,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC;IAAC,MAAM,CAAC,EAAE,qBAAqB,CAAA;CAAE,CAAC,CAAC;AAEpO;;;;;GAKG;AACH,qBAAa,wBAAwB;IAEvB,OAAO,CAAC,QAAQ,CAAC,IAAI;IAAS,OAAO,CAAC,QAAQ,CAAC,MAAM;IAAqB,OAAO,CAAC,QAAQ,CAAC,eAAe;IADtH,yGAAyG;gBAC5E,IAAI,EAAE,MAAM,EAAkB,MAAM,GAAC,MAAmB,EAAkB,eAAe,GAAC,CAAC,SAAS,EAAC,MAAM,KAAG,OAAO,CAAC,IAAI,CAAe;IACtK,gGAAgG;IAC1F,KAAK,CAAC,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,OAAO,GAAG;QAAE,MAAM,EAAE,QAAQ,CAAC;QAAC,MAAM,EAAE,qBAAqB,CAAA;KAAE,CAAC;IAW3H;;;;;;;;;OASG;IACG,MAAM,CAAC,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,GAAE,qBAAgD,GAAG,OAAO,CAAC,QAAQ,CAAC;QAAE,eAAe,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;CAO5J;AAED;;;;;GAKG;AACH,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,eAAe,GAAG,QAAQ,CAyB1F"}
|
|
@@ -2,13 +2,14 @@ import { createHash, randomUUID } from "node:crypto";
|
|
|
2
2
|
import { constants } from "node:fs";
|
|
3
3
|
import { mkdir, open, readFile, rename, unlink } from "node:fs/promises";
|
|
4
4
|
import path from "node:path";
|
|
5
|
-
import { parseEngineBrokerResponse, parseEngineBrokerV1TerminalResponse } from "./engineBrokerProtocol.js";
|
|
5
|
+
import { ENGINE_BROKER_VERSION, parseEngineBrokerResponse, parseEngineBrokerV1TerminalResponse, parseEngineBrokerV2TerminalResponse, parseEngineBrokerV3TerminalResponse } from "./engineBrokerProtocol.js";
|
|
6
6
|
import { EMPTY_BROKER_TURN_LEDGER, parseBrokerTurnLedgerLines } from "./grokEngineBrokerLedger.js";
|
|
7
7
|
export const ENGINE_BROKER_TURN_RECORD_V1 = "noopolis.daimon.engine-broker-turn.v1";
|
|
8
8
|
export const ENGINE_BROKER_TURN_RECORD_V2 = "noopolis.daimon.engine-broker-turn.v2";
|
|
9
9
|
// The digest deliberately excludes `limits` and the protocol version, so a v1
|
|
10
|
-
// record written before the upgrade still identifies the same turn.
|
|
11
|
-
|
|
10
|
+
// record written before the upgrade still identifies the same unclocked turn.
|
|
11
|
+
// A supplied process clock changes execution and must conflict with any other value.
|
|
12
|
+
const digest = (request) => createHash("sha256").update(JSON.stringify([request.turnId, request.agentId, request.wakeId, request.prompt, request.mcpEndpoint, ...(request.processClock === undefined ? [] : [request.processClock])])).digest("hex");
|
|
12
13
|
const safe = (turnId) => `${createHash("sha256").update(turnId).digest("hex")}.json`;
|
|
13
14
|
/**
|
|
14
15
|
* Durable per-turn state. Record v2 stores the terminal response *with* its
|
|
@@ -97,7 +98,7 @@ export class EngineBrokerTurnRegistry {
|
|
|
97
98
|
}
|
|
98
99
|
/**
|
|
99
100
|
* Strict record parser. v2 accepts exactly `{version,digest,state,bootId}`
|
|
100
|
-
* plus `response` and its sealed `ledger` bytes when terminal, and the response
|
|
101
|
+
* plus `response` and its sealed `ledger` bytes when terminal, and the response may be a v2, v3 or v4 terminal frame (older frames upgrade on read).
|
|
101
102
|
* v1 records keep their historical looser shape and are upgraded on read: no
|
|
102
103
|
* usage (`null`), zero requests, `limitReason: "none"`, the declared model.
|
|
103
104
|
*/
|
|
@@ -126,7 +127,7 @@ export function parseEngineBrokerTurnRecord(text, model) {
|
|
|
126
127
|
throw new Error("broker turn registry unavailable");
|
|
127
128
|
}
|
|
128
129
|
const accounting = { outcome: legacy.kind, usage: null, model, requests: 0, limitReason: "none" };
|
|
129
|
-
const response = { ...legacy, ...accounting, version:
|
|
130
|
+
const response = { ...legacy, ...accounting, version: ENGINE_BROKER_VERSION };
|
|
130
131
|
return { version: ENGINE_BROKER_TURN_RECORD_V1, ...base, response };
|
|
131
132
|
}
|
|
132
133
|
if (input.version !== ENGINE_BROKER_TURN_RECORD_V2)
|
|
@@ -138,7 +139,7 @@ export function parseEngineBrokerTurnRecord(text, model) {
|
|
|
138
139
|
return { version: ENGINE_BROKER_TURN_RECORD_V2, ...base };
|
|
139
140
|
let response;
|
|
140
141
|
try {
|
|
141
|
-
response = parseEngineBrokerResponse(input.response);
|
|
142
|
+
response = input.response?.version === "noopolis.daimon.engine-broker.v2" ? parseEngineBrokerV2TerminalResponse(input.response) : input.response?.version === "noopolis.daimon.engine-broker.v3" ? parseEngineBrokerV3TerminalResponse(input.response) : parseEngineBrokerResponse(input.response);
|
|
142
143
|
}
|
|
143
144
|
catch {
|
|
144
145
|
throw new Error("broker turn registry unavailable");
|
|
@@ -11,6 +11,8 @@ export declare function startOrganizationRuntimeEngine(agent: OrganizationRuntim
|
|
|
11
11
|
export declare function grokSandboxProtectedPaths(currentAgentId: string, organizationAgents: readonly OrganizationRuntimeAgentConfig[], sharedProtectedPaths?: readonly string[]): readonly string[];
|
|
12
12
|
export declare function codexSandboxProtectedPaths(currentAgentId: string, currentAgent: OrganizationRuntimeAgentConfig, currentEngineHomePath: string, organizationAgents: readonly OrganizationRuntimeAgentConfig[], sharedProtectedPaths?: readonly string[]): readonly string[];
|
|
13
13
|
export declare function codexSandboxReadablePaths(currentAgent: OrganizationRuntimeAgentConfig): readonly string[];
|
|
14
|
+
/** @internal The same callback used by the production session; no native process clock enters the engine environment. */
|
|
15
|
+
export declare function grokBrokerTurnFor(agent: OrganizationRuntimeAgentConfig, grokBroker: EngineBrokerTurnClient, wakeEnvironmentContext: import("../pi/piAgentWakeSupport.js").PiWakeEnvironmentContextRef): (prompt: string, endpoint: string, signal: AbortSignal) => Promise<string>;
|
|
14
16
|
/**
|
|
15
17
|
* CLI engines do not consume Pi's resource loader. Frame the same immutable
|
|
16
18
|
* identity in JSON so arbitrary names/instructions cannot change its shape.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"engineDispatcher.d.ts","sourceRoot":"","sources":["../../src/runtime/engineDispatcher.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"engineDispatcher.d.ts","sourceRoot":"","sources":["../../src/runtime/engineDispatcher.ts"],"names":[],"mappings":"AAEA,OAAO,EAAkB,KAAK,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAMxE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAQpD,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,0BAA0B,CAAC;AAC/E,OAAO,KAAK,EAAE,gCAAgC,EAAE,MAAM,wBAAwB,CAAC;AAE/E,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAC;AAM7E;;;GAGG;AACH,wBAAsB,8BAA8B,CAClD,KAAK,EAAE,8BAA8B,EACrC,eAAe,EAAE,MAAM,EACvB,KAAK,CAAC,EAAE,UAAU,CAAC,gCAAgC,CAAC,UAAU,CAAC,CAAC,EAChE,aAAa,CAAC,EAAE,MAAM,EACtB,UAAU,CAAC,EAAE,sBAAsB,EACnC,kBAAkB,CAAC,EAAE,SAAS,8BAA8B,EAAE,EAC9D,oBAAoB,GAAE,SAAS,MAAM,EAAO,EAC5C,SAAS,CAAC,EAAE,iBAAiB,GAC5B,OAAO,CAAC,WAAW,CAAC,CAiDtB;AAED,wBAAgB,yBAAyB,CACvC,cAAc,EAAE,MAAM,EACtB,kBAAkB,EAAE,SAAS,8BAA8B,EAAE,EAC7D,oBAAoB,GAAE,SAAS,MAAM,EAAO,GAC3C,SAAS,MAAM,EAAE,CAYnB;AAED,wBAAgB,0BAA0B,CACxC,cAAc,EAAE,MAAM,EACtB,YAAY,EAAE,8BAA8B,EAC5C,qBAAqB,EAAE,MAAM,EAC7B,kBAAkB,EAAE,SAAS,8BAA8B,EAAE,EAC7D,oBAAoB,GAAE,SAAS,MAAM,EAAO,GAC3C,SAAS,MAAM,EAAE,CAQnB;AAED,wBAAgB,yBAAyB,CACvC,YAAY,EAAE,8BAA8B,GAC3C,SAAS,MAAM,EAAE,CAEnB;AAkDD,yHAAyH;AACzH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,8BAA8B,EAAE,UAAU,EAAE,sBAAsB,EAAE,sBAAsB,EAAE,OAAO,6BAA6B,EAAE,2BAA2B,IAG5L,QAAQ,MAAM,EAAE,UAAU,MAAM,EAAE,QAAQ,WAAW,qBAI9D;AAED;;;GAGG;AACH;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,8BAA8B,EAAE,gBAAgB,GAAE,SAAS,MAAM,EAAO,GAAG,MAAM,CAkBxH"}
|
|
@@ -1,4 +1,8 @@
|
|
|
1
|
+
import { brokerProcessClock } from "./grokBrokerTaskClock.js";
|
|
2
|
+
import { reportEngineTaskClockGap } from "../pi/engineTaskClock.js";
|
|
1
3
|
import { attentionTools } from "./attention.js";
|
|
4
|
+
import { readTaskClock } from "./taskClock.js";
|
|
5
|
+
import { memoryClockOptions } from "../pi/memoryClock.js";
|
|
2
6
|
import { grokDaimonToolName, grokMountedToolNamingRule } from "../contracts/grokWorkerContract.js";
|
|
3
7
|
import path from "node:path";
|
|
4
8
|
import { AGY_MAX_TOOL_TURNS, createCliSessionFactory, resolveCodexWakeTimeoutMs, resolveCodexWakeTokenCeiling, resolveEngineWakeLimitOverrides } from "../pi/cliSession.js";
|
|
@@ -14,6 +18,10 @@ import { recordCodexTurnRequests } from "./turnRequestLedger.js";
|
|
|
14
18
|
* existing one-agent harness. Configuration never carries a command or env.
|
|
15
19
|
*/
|
|
16
20
|
export async function startOrganizationRuntimeEngine(agent, controlTokenEnv, paths, agyBusAddress, grokBroker, organizationAgents, sharedProtectedPaths = [], attention) {
|
|
21
|
+
const clock = readTaskClock();
|
|
22
|
+
reportEngineTaskClockGap(agent.engine.kind);
|
|
23
|
+
if (agent.memory !== undefined)
|
|
24
|
+
memoryClockOptions(clock);
|
|
17
25
|
// A declared Grok model is enforced by the broker proxy and worker config;
|
|
18
26
|
// the direct path has neither, so it refuses rather than silently ignoring it.
|
|
19
27
|
if (agent.engine.kind === "grok" && agent.engine.model !== undefined && grokBroker === undefined)
|
|
@@ -137,10 +145,14 @@ function adapterFor(agent, controlTokenEnv, verifyExecutable, executablePath, en
|
|
|
137
145
|
} : {}) });
|
|
138
146
|
return cliHarness(agent, sessionFactory, [controlTokenEnv], productionTools, wakeEnvironmentContext);
|
|
139
147
|
}
|
|
140
|
-
|
|
148
|
+
/** @internal The same callback used by the production session; no native process clock enters the engine environment. */
|
|
149
|
+
export function grokBrokerTurnFor(agent, grokBroker, wakeEnvironmentContext) {
|
|
141
150
|
const limits = resolveEngineWakeLimitOverrides();
|
|
142
151
|
const options = { ...(limits === undefined ? {} : { limits }), ...(agent.engine.model === undefined ? {} : { model: agent.engine.model }) };
|
|
143
|
-
return (prompt, endpoint, signal) =>
|
|
152
|
+
return (prompt, endpoint, signal) => {
|
|
153
|
+
const processClock = brokerProcessClock();
|
|
154
|
+
return grokBroker.turn(agent.id, wakeEnvironmentContext.current ?? "wake", prompt, endpoint, signal, { ...options, ...(processClock === undefined ? {} : { processClock }) });
|
|
155
|
+
};
|
|
144
156
|
}
|
|
145
157
|
/**
|
|
146
158
|
* CLI engines do not consume Pi's resource loader. Frame the same immutable
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { constants } from "node:fs";
|
|
2
2
|
import { lstat, open, realpath, stat } from "node:fs/promises";
|
|
3
3
|
import path from "node:path";
|
|
4
|
-
import { spawn } from "
|
|
4
|
+
import { spawnRealTime as spawn } from "./taskClockProcess.js";
|
|
5
5
|
import { createHash } from "node:crypto";
|
|
6
6
|
import { cliChildEnvironment } from "../pi/cliEnvironment.js";
|
|
7
7
|
import { hasRefreshablePortableCredential, portableCredentialSecretValues } from "./portableCredentialAuth.js";
|
|
@@ -9,6 +9,7 @@ export declare class DurableGrokBrokerCredentialAuthority {
|
|
|
9
9
|
private staleWrite;
|
|
10
10
|
private lastDigest;
|
|
11
11
|
private generation;
|
|
12
|
+
private ancestorDigests;
|
|
12
13
|
constructor(command: string, home: string, authFile?: string);
|
|
13
14
|
initialize(): Promise<void>;
|
|
14
15
|
accessToken(forceRefresh: boolean): Promise<string>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"grokBrokerCredentialAuthority.d.ts","sourceRoot":"","sources":["../../src/runtime/grokBrokerCredentialAuthority.ts"],"names":[],"mappings":"AAUA,qBAAa,oCAAoC;
|
|
1
|
+
{"version":3,"file":"grokBrokerCredentialAuthority.d.ts","sourceRoot":"","sources":["../../src/runtime/grokBrokerCredentialAuthority.ts"],"names":[],"mappings":"AAUA,qBAAa,oCAAoC;IAGnC,OAAO,CAAC,QAAQ,CAAC,OAAO;IAAU,OAAO,CAAC,QAAQ,CAAC,IAAI;IAAU,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAFtG,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA0C;IAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAqC;IAAC,OAAO,CAAC,KAAK,CAAS;IAAA,OAAO,CAAC,WAAW,CAAO;IAAA,OAAO,CAAC,UAAU,CAAyB;IAAA,OAAO,CAAC,UAAU,CAAkB;IAAA,OAAO,CAAC,UAAU,CAAG;IAClR,OAAO,CAAC,eAAe,CAAyB;gBACnB,OAAO,EAAE,MAAM,EAAmB,IAAI,EAAE,MAAM,EAAmB,QAAQ,SAA+B;IAC/H,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAiC3B,WAAW,CAAC,YAAY,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC;IAInD,qBAAqB,CAAC,mBAAmB,EAAC,MAAM,GAAE,OAAO,CAAC,MAAM,CAAC;IACvE,OAAO,CAAC,OAAO;IAYT,YAAY,CAAC,mBAAmB,CAAC,EAAC,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAC9D,OAAO,IAAG,OAAO;IACjB,OAAO,CAAC,SAAS;YACH,KAAK;CAKpB"}
|
|
@@ -6,7 +6,7 @@ import path from "node:path";
|
|
|
6
6
|
import { readGrokBrokerCredential } from "./grokBrokerCredentialReader.js";
|
|
7
7
|
import { refreshGrokBrokerCredential } from "./grokBrokerRefresh.js";
|
|
8
8
|
import { EngineBrokerGenerationFence, EngineBrokerSingleflight } from "./engineBrokerSingleflight.js";
|
|
9
|
-
import { parseBrokerCredentialJournal, recoverBrokerCredentialJournal } from "./engineBrokerCredentialJournal.js";
|
|
9
|
+
import { BROKER_CREDENTIAL_MAX_ANCESTORS, parseBrokerCredentialJournal, recoverBrokerCredentialJournal } from "./engineBrokerCredentialJournal.js";
|
|
10
10
|
export class DurableGrokBrokerCredentialAuthority {
|
|
11
11
|
command;
|
|
12
12
|
home;
|
|
@@ -18,33 +18,52 @@ export class DurableGrokBrokerCredentialAuthority {
|
|
|
18
18
|
staleWrite;
|
|
19
19
|
lastDigest;
|
|
20
20
|
generation = 0;
|
|
21
|
+
ancestorDigests = [];
|
|
21
22
|
constructor(command, home, authFile = path.join(home, "auth.json")) {
|
|
22
23
|
this.command = command;
|
|
23
24
|
this.home = home;
|
|
24
25
|
this.authFile = authFile;
|
|
25
26
|
}
|
|
26
|
-
async initialize() {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
27
|
+
async initialize() {
|
|
28
|
+
if (this.initialized)
|
|
29
|
+
return;
|
|
30
|
+
const credential = await readGrokBrokerCredential(this.authFile);
|
|
31
|
+
this.lastDigest = credential.digest;
|
|
32
|
+
const file = path.join(this.home, ".daimon-broker", "credential-journal.json");
|
|
33
|
+
let handle;
|
|
34
|
+
try {
|
|
35
|
+
handle = await open(file, constants.O_RDONLY | constants.O_NOFOLLOW);
|
|
36
|
+
const stat = await handle.stat();
|
|
37
|
+
if (!stat.isFile() || stat.uid !== process.getuid?.() || (stat.mode & 0o777) !== 0o600 || stat.size > 65536)
|
|
38
|
+
throw unavailable();
|
|
39
|
+
const journal = parseBrokerCredentialJournal(JSON.parse(await handle.readFile("utf8")));
|
|
34
40
|
this.generation = journal.generation;
|
|
35
|
-
|
|
36
|
-
|
|
41
|
+
if (recoverBrokerCredentialJournal(journal, credential.digest) === "stale") {
|
|
42
|
+
await this.markStale();
|
|
43
|
+
throw unavailable();
|
|
44
|
+
}
|
|
45
|
+
this.ancestorDigests = [...new Set([...(journal.ancestorDigests ?? []), journal.sourceDigest])]
|
|
46
|
+
.filter((digest) => digest !== credential.digest);
|
|
47
|
+
if (journal.state === "refreshing") {
|
|
48
|
+
// The durable credential still matches the pre-exchange source. Settle
|
|
49
|
+
// before serving it so writeback and drain need no subsequent refresh.
|
|
50
|
+
// No exchange completed: preserve the generation and existing lineage.
|
|
51
|
+
await this.write({ state: "promoted", generation: journal.generation,
|
|
52
|
+
sourceDigest: credential.digest, promotedDigest: credential.digest });
|
|
53
|
+
}
|
|
54
|
+
this.fence.restore(journal.generation);
|
|
37
55
|
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
56
|
+
catch (error) {
|
|
57
|
+
// Only a missing journal on open is an unjournaled bootstrap. A failed
|
|
58
|
+
// recovery write (including ENOENT) must never publish readiness.
|
|
59
|
+
if (handle !== undefined || error.code !== "ENOENT")
|
|
60
|
+
throw unavailable();
|
|
61
|
+
}
|
|
62
|
+
finally {
|
|
63
|
+
await handle?.close().catch(() => undefined);
|
|
64
|
+
}
|
|
65
|
+
this.initialized = true;
|
|
44
66
|
}
|
|
45
|
-
finally {
|
|
46
|
-
await handle?.close().catch(() => undefined);
|
|
47
|
-
} this.initialized = true; }
|
|
48
67
|
async accessToken(forceRefresh) {
|
|
49
68
|
if (!this.initialized)
|
|
50
69
|
await this.initialize();
|
|
@@ -64,6 +83,11 @@ export class DurableGrokBrokerCredentialAuthority {
|
|
|
64
83
|
const before = await readGrokBrokerCredential(this.authFile);
|
|
65
84
|
if (rejectedTokenDigest !== undefined && createHash("sha256").update(before.accessToken).digest("hex") !== rejectedTokenDigest)
|
|
66
85
|
return before.accessToken;
|
|
86
|
+
// Never spend a refresh whose lineage cannot be persisted. Advancing expiry
|
|
87
|
+
// normally clears the history, so this bound applies to one expiry epoch.
|
|
88
|
+
const ancestors = [...new Set([...this.ancestorDigests, before.digest])];
|
|
89
|
+
if (ancestors.length > BROKER_CREDENTIAL_MAX_ANCESTORS)
|
|
90
|
+
throw unavailable();
|
|
67
91
|
try {
|
|
68
92
|
await this.write({ state: "refreshing", generation, sourceDigest: before.digest });
|
|
69
93
|
await refreshGrokBrokerCredential(this.command, this.home);
|
|
@@ -72,7 +96,9 @@ export class DurableGrokBrokerCredentialAuthority {
|
|
|
72
96
|
throw unavailable();
|
|
73
97
|
const next = this.fence.promote(generation);
|
|
74
98
|
this.generation = next;
|
|
75
|
-
|
|
99
|
+
const ancestorDigests = before.expiresAt !== undefined && after.expiresAt !== undefined && after.expiresAt > before.expiresAt ? [] : ancestors;
|
|
100
|
+
await this.write({ state: "promoted", generation: next, sourceDigest: before.digest, promotedDigest: after.digest, ancestorDigests });
|
|
101
|
+
this.ancestorDigests = ancestorDigests;
|
|
76
102
|
this.lastDigest = after.digest;
|
|
77
103
|
return after.accessToken;
|
|
78
104
|
}
|
|
@@ -100,7 +126,7 @@ export class DurableGrokBrokerCredentialAuthority {
|
|
|
100
126
|
const temporary = `${file}.${process.pid}.${randomUUID()}.tmp`;
|
|
101
127
|
const handle = await open(temporary, constants.O_CREAT | constants.O_EXCL | constants.O_WRONLY, 0o600);
|
|
102
128
|
try {
|
|
103
|
-
await handle.writeFile(`${JSON.stringify({ version: "noopolis.daimon.broker-credential-journal.v1", ...value })}\n`);
|
|
129
|
+
await handle.writeFile(`${JSON.stringify({ version: "noopolis.daimon.broker-credential-journal.v1", ancestorDigests: this.ancestorDigests, ...value })}\n`);
|
|
104
130
|
await handle.sync();
|
|
105
131
|
}
|
|
106
132
|
finally {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"grokBrokerCredentialReader.d.ts","sourceRoot":"","sources":["../../src/runtime/grokBrokerCredentialReader.ts"],"names":[],"mappings":"AAIA,wBAAsB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC,
|
|
1
|
+
{"version":3,"file":"grokBrokerCredentialReader.d.ts","sourceRoot":"","sources":["../../src/runtime/grokBrokerCredentialReader.ts"],"names":[],"mappings":"AAIA,wBAAsB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC,CAW3I"}
|
|
@@ -22,7 +22,8 @@ export async function readGrokBrokerCredential(file) {
|
|
|
22
22
|
const rows = Object.values(root).filter((value) => value !== null && typeof value === "object" && !Array.isArray(value));
|
|
23
23
|
if (rows.length !== 1 || typeof rows[0].key !== "string" || rows[0].key.length < 32 || typeof rows[0].refresh_token !== "string" || rows[0].refresh_token.length < 16)
|
|
24
24
|
throw new Error();
|
|
25
|
-
|
|
25
|
+
const expiresAt = typeof rows[0].expires_at === "string" ? Date.parse(rows[0].expires_at) : NaN;
|
|
26
|
+
return { accessToken: rows[0].key, digest: createHash("sha256").update(bytes).digest("hex"), ...(Number.isFinite(expiresAt) ? { expiresAt } : {}) };
|
|
26
27
|
}
|
|
27
28
|
catch {
|
|
28
29
|
throw new Error("Grok broker credential authority unavailable");
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import { GROK_BROKER_TASK_CLOCK, type GrokWorkerConfigVariant } from "../contracts/grokBrokerTaskClock.js";
|
|
1
2
|
import { type EngineBrokerServiceRegistration } from "./engineBrokerServiceConfig.js";
|
|
2
3
|
import { type EngineBrokerTurnLimits } from "./engineBrokerTurnAccounting.js";
|
|
3
4
|
import type { GrokBrokerModel, GrokBrokerReasoningEffort } from "./grokBrokerModelPolicy.js";
|
|
4
5
|
import { GROK_WORKER_SANDBOX_PROFILE } from "./grokWorkerSandboxProfile.js";
|
|
5
|
-
export declare const GROK_BROKER_PROJECTION_VERSION: "noopolis.daimon.grok-broker-projection.
|
|
6
|
+
export declare const GROK_BROKER_PROJECTION_VERSION: "noopolis.daimon.grok-broker-projection.v3";
|
|
6
7
|
/**
|
|
7
8
|
* Everything a consumer (Spawnfile provisioning, Paideia's native adapter, the
|
|
8
9
|
* root slot supervisor) needs to know about one brokered Grok agent's slot,
|
|
@@ -20,6 +21,11 @@ export type OrganizationGrokBrokerProjection = Readonly<{
|
|
|
20
21
|
profileSha256: string;
|
|
21
22
|
denyPaths: readonly string[];
|
|
22
23
|
workerConfigSha256: string;
|
|
24
|
+
workerConfigVariant: GrokWorkerConfigVariant;
|
|
25
|
+
taskClock?: Omit<typeof GROK_BROKER_TASK_CLOCK, "directoryPath" | "timestampFilePath"> & Readonly<{
|
|
26
|
+
directoryPath: string;
|
|
27
|
+
timestampFilePath: string;
|
|
28
|
+
}>;
|
|
23
29
|
systemPromptSha256: string;
|
|
24
30
|
grokCliVersion: string;
|
|
25
31
|
grokExecutableSha256: string;
|
|
@@ -40,6 +46,8 @@ export type OrganizationGrokBrokerProjection = Readonly<{
|
|
|
40
46
|
}>;
|
|
41
47
|
}>;
|
|
42
48
|
export type OrganizationGrokBrokerProjectionOptions = Readonly<{
|
|
49
|
+
/** Clocked configs require an isolated clock directory per slot. Defaults to the unchanged production bytes. */
|
|
50
|
+
workerConfigVariant?: GrokWorkerConfigVariant;
|
|
43
51
|
/** Deployment-assigned slot identity. */
|
|
44
52
|
slot: number;
|
|
45
53
|
workerUid: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"grokBrokerProjection.d.ts","sourceRoot":"","sources":["../../src/runtime/grokBrokerProjection.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"grokBrokerProjection.d.ts","sourceRoot":"","sources":["../../src/runtime/grokBrokerProjection.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { brokerTaskClockFileFor } from "./grokBrokerSlot.js";
|
|
2
|
+
import { GROK_BROKER_TASK_CLOCK } from "../contracts/grokBrokerTaskClock.js";
|
|
1
3
|
import { createHash } from "node:crypto";
|
|
2
4
|
import path from "node:path";
|
|
3
5
|
import { canonicalJson } from "../contracts/canonicalJson.js";
|
|
@@ -6,7 +8,7 @@ import { GROK_ENGINE_BROKER } from "../contracts/runtimeContractManifest.js";
|
|
|
6
8
|
import { grokSandboxProtectedPaths } from "./engineDispatcher.js";
|
|
7
9
|
import { parseEngineBrokerServiceConfig } from "./engineBrokerServiceConfig.js";
|
|
8
10
|
import { parseEngineBrokerTurnLimits } from "./engineBrokerTurnAccounting.js";
|
|
9
|
-
import { grokBrokerWorkerConfigSha256 } from "./grokBrokerWorkerConfig.js";
|
|
11
|
+
import { grokBrokerWorkerConfigPins, grokBrokerWorkerConfigSha256 } from "./grokBrokerWorkerConfig.js";
|
|
10
12
|
import { GROK_WORKER_SANDBOX_PROFILE, grokWorkerEventsPathFor, renderGrokWorkerSandboxProfile, grokWorkerSandboxProfileSha256 } from "./grokWorkerSandboxProfile.js";
|
|
11
13
|
import { parseOrganizationRuntimeConfig } from "./organizationRuntime.js";
|
|
12
14
|
export const GROK_BROKER_PROJECTION_VERSION = GROK_ENGINE_BROKER.projectionVersion;
|
|
@@ -50,8 +52,12 @@ export function resolveOrganizationGrokBrokerProjection(config, agentId, options
|
|
|
50
52
|
const profileSha256 = grokWorkerSandboxProfileSha256(denyPaths);
|
|
51
53
|
if (options.profileSha256 !== undefined && options.profileSha256 !== profileSha256)
|
|
52
54
|
throw new Error("Grok broker projection profile digest mismatch");
|
|
53
|
-
const
|
|
54
|
-
|
|
55
|
+
const workerConfigVariant = options.workerConfigVariant ?? "unclocked";
|
|
56
|
+
const workerConfigSha256 = grokBrokerWorkerConfigSha256({ model, reasoningEffort }, workerConfigVariant, options.slot);
|
|
57
|
+
const pin = grokBrokerWorkerConfigPins({ model, reasoningEffort }, options.slot)[workerConfigVariant];
|
|
58
|
+
if (workerConfigVariant === "clocked" && denyPaths.some((denied) => [brokerTaskClockFileFor(options.slot), GROK_BROKER_TASK_CLOCK.preloadPath].some((file) => file === denied || file.startsWith(`${denied}/`))))
|
|
59
|
+
throw new Error("Grok broker task clock path is denied");
|
|
60
|
+
if (workerConfigSha256 !== pin)
|
|
55
61
|
throw new Error("Grok broker projection worker config drifted from the manifest");
|
|
56
62
|
if (createHash("sha256").update(DAIMON_GROK_SYSTEM_PROMPT).digest("hex") !== GROK_ENGINE_BROKER.worker.systemPromptSha256)
|
|
57
63
|
throw new Error("Grok broker projection system prompt drifted from the manifest");
|
|
@@ -61,7 +67,8 @@ export function resolveOrganizationGrokBrokerProjection(config, agentId, options
|
|
|
61
67
|
const profilePath = path.posix.join(options.workerHomePath, ".grok", "sandbox.toml");
|
|
62
68
|
const projection = {
|
|
63
69
|
version: GROK_BROKER_PROJECTION_VERSION, agentId, workspacePath: agent.workspacePath, runtimeHomePath: agent.runtimeHomePath,
|
|
64
|
-
workerUid: options.workerUid, slot: options.slot, profilePath, profileSha256, denyPaths, workerConfigSha256,
|
|
70
|
+
workerUid: options.workerUid, slot: options.slot, profilePath, profileSha256, denyPaths, workerConfigSha256, workerConfigVariant,
|
|
71
|
+
...(workerConfigVariant === "clocked" ? { taskClock: { ...GROK_BROKER_TASK_CLOCK, directoryPath: path.posix.dirname(brokerTaskClockFileFor(options.slot)), timestampFilePath: brokerTaskClockFileFor(options.slot) } } : {}),
|
|
65
72
|
systemPromptSha256: GROK_ENGINE_BROKER.worker.systemPromptSha256, grokCliVersion: GROK_ENGINE_BROKER.grokCliVersion, grokExecutableSha256: artifact.sha256,
|
|
66
73
|
nativeAbiVersion: GROK_ENGINE_BROKER.nativeAbiVersion, model, reasoningEffort, limits: parseEngineBrokerTurnLimits(options.limits), usageLedgerPath: options.usageLedgerPath, seccompProfileSha256: options.seccompProfileSha256,
|
|
67
74
|
attestation: { platform: "linux/landlock", enforced: true, restrictNetwork: true, profileName: GROK_WORKER_SANDBOX_PROFILE, sandboxRuntime: "bubblewrap", eventsPath: grokWorkerEventsPathFor(profilePath) }
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export type GrokBrokerProviderClockObservation = Readonly<{
|
|
2
|
+
requests: number;
|
|
3
|
+
linesRewritten: number;
|
|
4
|
+
requestsWithoutDateLine: number;
|
|
5
|
+
/** Date-like message lines outside the injected block; absent on older seals. */
|
|
6
|
+
linesIgnored?: number;
|
|
7
|
+
/** The last rewritten line's dates; null until a line is rewritten. */
|
|
8
|
+
injectedDate: string | null;
|
|
9
|
+
taskDate: string | null;
|
|
10
|
+
}>;
|
|
11
|
+
export declare class GrokBrokerProviderClockRefusal extends Error {
|
|
12
|
+
readonly reason: "task_clock_date_format" | "task_clock_date_range" | "request_body_rejected";
|
|
13
|
+
constructor(reason: "task_clock_date_format" | "task_clock_date_range" | "request_body_rejected");
|
|
14
|
+
}
|
|
15
|
+
/** One processClock, owned by one turn; never reads the broker's ambient TZ. */
|
|
16
|
+
export declare class GrokBrokerProviderClock {
|
|
17
|
+
private readonly now;
|
|
18
|
+
private readonly offsetMs;
|
|
19
|
+
private observation;
|
|
20
|
+
constructor(processClock: string, now?: () => number);
|
|
21
|
+
rewrite(body: Uint8Array): Uint8Array;
|
|
22
|
+
snapshot(): GrokBrokerProviderClockObservation;
|
|
23
|
+
}
|
|
24
|
+
/** Closed, dates-only observation on the v3 terminal frame and durable seal. */
|
|
25
|
+
export declare function parseGrokBrokerProviderClockObservation(value: unknown): GrokBrokerProviderClockObservation;
|
|
26
|
+
//# sourceMappingURL=grokBrokerProviderClock.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"grokBrokerProviderClock.d.ts","sourceRoot":"","sources":["../../src/runtime/grokBrokerProviderClock.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,kCAAkC,GAAG,QAAQ,CAAC;IACxD,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;IACvB,uBAAuB,EAAE,MAAM,CAAC;IAChC,iFAAiF;IACjF,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,uEAAuE;IACvE,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB,CAAC,CAAC;AAEH,qBAAa,8BAA+B,SAAQ,KAAK;IAC3C,QAAQ,CAAC,MAAM,EAAE,wBAAwB,GAAG,uBAAuB,GAAG,uBAAuB;gBAApF,MAAM,EAAE,wBAAwB,GAAG,uBAAuB,GAAG,uBAAuB;CAG1G;AAOD,gFAAgF;AAChF,qBAAa,uBAAuB;IAOA,OAAO,CAAC,QAAQ,CAAC,GAAG;IANtD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,WAAW,CAGjB;gBAEU,YAAY,EAAE,MAAM,EAAmB,GAAG,GAAE,MAAM,MAAyB;IAIvF,OAAO,CAAC,IAAI,EAAE,UAAU,GAAG,UAAU;IAuErC,QAAQ,IAAI,kCAAkC;CAG/C;AAKD,gFAAgF;AAChF,wBAAgB,uCAAuC,CAAC,KAAK,EAAE,OAAO,GAAG,kCAAkC,CAuB1G"}
|