@noopolis/daimon 0.1.2 → 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 +275 -51
- package/dist/contracts/attentionContract.d.ts +142 -0
- package/dist/contracts/attentionContract.d.ts.map +1 -0
- package/dist/contracts/attentionContract.js +21 -0
- package/dist/contracts/canonicalJson.d.ts +3 -0
- package/dist/contracts/canonicalJson.d.ts.map +1 -0
- package/dist/contracts/canonicalJson.js +54 -0
- 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/grokWorkerContract.d.ts +74 -0
- package/dist/contracts/grokWorkerContract.d.ts.map +1 -0
- package/dist/contracts/grokWorkerContract.js +88 -0
- package/dist/contracts/organizationRuntimeContract.d.ts +841 -0
- package/dist/contracts/organizationRuntimeContract.d.ts.map +1 -0
- package/dist/contracts/organizationRuntimeContract.js +123 -0
- package/dist/contracts/runtimeContractManifest.d.ts +1822 -0
- package/dist/contracts/runtimeContractManifest.d.ts.map +1 -0
- package/dist/contracts/runtimeContractManifest.js +206 -0
- 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/credentialRedaction.d.ts +4 -0
- package/dist/core/credentialRedaction.d.ts.map +1 -0
- package/dist/core/credentialRedaction.js +28 -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/mcp/toolServer.d.ts +19 -2
- package/dist/mcp/toolServer.d.ts.map +1 -1
- package/dist/mcp/toolServer.js +57 -17
- package/dist/observability/causalEvents.d.ts +6 -6
- package/dist/observability/causalEvents.d.ts.map +1 -1
- package/dist/observability/causalEvents.js +107 -19
- package/dist/observability/orgObserver.d.ts.map +1 -1
- package/dist/observability/orgObserver.js +3 -3
- package/dist/pi/agyHeadlessResult.d.ts +60 -0
- package/dist/pi/agyHeadlessResult.d.ts.map +1 -0
- package/dist/pi/agyHeadlessResult.js +95 -0
- package/dist/pi/cliChildOutput.d.ts +67 -0
- package/dist/pi/cliChildOutput.d.ts.map +1 -0
- package/dist/pi/cliChildOutput.js +269 -0
- package/dist/pi/cliEngineRun.d.ts +16 -0
- package/dist/pi/cliEngineRun.d.ts.map +1 -0
- package/dist/pi/cliEngineRun.js +27 -0
- package/dist/pi/cliEngineSpawn.d.ts +55 -0
- package/dist/pi/cliEngineSpawn.d.ts.map +1 -0
- package/dist/pi/cliEngineSpawn.js +169 -0
- package/dist/pi/cliEnvironment.d.ts +12 -0
- package/dist/pi/cliEnvironment.d.ts.map +1 -0
- package/dist/pi/cliEnvironment.js +34 -0
- package/dist/pi/cliMcpRegistration.d.ts +61 -0
- package/dist/pi/cliMcpRegistration.d.ts.map +1 -0
- package/dist/pi/cliMcpRegistration.js +75 -0
- package/dist/pi/cliProcess.d.ts +7 -0
- package/dist/pi/cliProcess.d.ts.map +1 -0
- package/dist/pi/cliProcess.js +132 -0
- package/dist/pi/cliSession.d.ts +86 -24
- package/dist/pi/cliSession.d.ts.map +1 -1
- package/dist/pi/cliSession.js +251 -173
- 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/cliTurnMetering.d.ts +60 -0
- package/dist/pi/cliTurnMetering.d.ts.map +1 -0
- package/dist/pi/cliTurnMetering.js +60 -0
- package/dist/pi/codexFilesystemRules.d.ts +3 -0
- package/dist/pi/codexFilesystemRules.d.ts.map +1 -0
- package/dist/pi/codexFilesystemRules.js +28 -0
- package/dist/pi/codexHeadlessResult.d.ts +68 -0
- package/dist/pi/codexHeadlessResult.d.ts.map +1 -0
- package/dist/pi/codexHeadlessResult.js +122 -0
- package/dist/pi/codexRolloutUsage.d.ts +95 -0
- package/dist/pi/codexRolloutUsage.d.ts.map +1 -0
- package/dist/pi/codexRolloutUsage.js +221 -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/engineWakeLimits.d.ts +39 -0
- package/dist/pi/engineWakeLimits.d.ts.map +1 -0
- package/dist/pi/engineWakeLimits.js +55 -0
- package/dist/pi/grokHeadlessResult.d.ts +36 -0
- package/dist/pi/grokHeadlessResult.d.ts.map +1 -0
- package/dist/pi/grokHeadlessResult.js +118 -0
- package/dist/pi/grokHomeMcpRegistration.d.ts +21 -0
- package/dist/pi/grokHomeMcpRegistration.d.ts.map +1 -0
- package/dist/pi/grokHomeMcpRegistration.js +58 -0
- package/dist/pi/grokSandbox.d.ts +11 -0
- package/dist/pi/grokSandbox.d.ts.map +1 -0
- package/dist/pi/grokSandbox.js +216 -0
- package/dist/pi/grokStreamUsage.d.ts +31 -0
- package/dist/pi/grokStreamUsage.d.ts.map +1 -0
- package/dist/pi/grokStreamUsage.js +51 -0
- 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 +6 -3
- package/dist/pi/piAgentHandle.d.ts.map +1 -1
- package/dist/pi/piAgentHandle.js +42 -12
- package/dist/pi/piAgentWakeSupport.d.ts +35 -0
- package/dist/pi/piAgentWakeSupport.d.ts.map +1 -1
- package/dist/pi/piAgentWakeSupport.js +4 -0
- package/dist/pi/piHarness.d.ts +18 -3
- package/dist/pi/piHarness.d.ts.map +1 -1
- package/dist/pi/piHarness.js +83 -14
- package/dist/pi/prompts.d.ts +1 -0
- package/dist/pi/prompts.d.ts.map +1 -1
- package/dist/pi/prompts.js +24 -0
- 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/turnTrace.d.ts.map +1 -1
- package/dist/pi/turnTrace.js +5 -8
- 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/pi/worldTrajectory.d.ts +1 -1
- package/dist/pi/worldTrajectory.d.ts.map +1 -1
- package/dist/pi/worldTrajectory.js +3 -3
- package/dist/runtime/agySubscriptionBootstrap.d.ts +16 -0
- package/dist/runtime/agySubscriptionBootstrap.d.ts.map +1 -0
- package/dist/runtime/agySubscriptionBootstrap.js +80 -0
- package/dist/runtime/agySubscriptionRealm.d.ts +38 -0
- package/dist/runtime/agySubscriptionRealm.d.ts.map +1 -0
- package/dist/runtime/agySubscriptionRealm.js +242 -0
- package/dist/runtime/attention.d.ts +26 -0
- package/dist/runtime/attention.d.ts.map +1 -0
- package/dist/runtime/attention.js +49 -0
- package/dist/runtime/attentionDispatcher.d.ts +78 -0
- package/dist/runtime/attentionDispatcher.d.ts.map +1 -0
- package/dist/runtime/attentionDispatcher.js +365 -0
- package/dist/runtime/cli.d.ts +7 -0
- package/dist/runtime/cli.d.ts.map +1 -0
- package/dist/runtime/cli.js +256 -0
- package/dist/runtime/codexSandboxProjection.d.ts +17 -0
- package/dist/runtime/codexSandboxProjection.d.ts.map +1 -0
- package/dist/runtime/codexSandboxProjection.js +40 -0
- package/dist/runtime/contract-manifest.json +1 -0
- package/dist/runtime/contract-manifest.sha256 +1 -0
- package/dist/runtime/contractManifest.d.ts +8 -0
- package/dist/runtime/contractManifest.d.ts.map +1 -0
- package/dist/runtime/contractManifest.js +4 -0
- package/dist/runtime/engineBrokerCapabilities.d.ts +40 -0
- package/dist/runtime/engineBrokerCapabilities.d.ts.map +1 -0
- package/dist/runtime/engineBrokerCapabilities.js +69 -0
- package/dist/runtime/engineBrokerControlClient.d.ts +55 -0
- package/dist/runtime/engineBrokerControlClient.d.ts.map +1 -0
- package/dist/runtime/engineBrokerControlClient.js +228 -0
- package/dist/runtime/engineBrokerCredentialJournal.d.ts +12 -0
- package/dist/runtime/engineBrokerCredentialJournal.d.ts.map +1 -0
- package/dist/runtime/engineBrokerCredentialJournal.js +26 -0
- package/dist/runtime/engineBrokerInferenceProtocol.d.ts +53 -0
- package/dist/runtime/engineBrokerInferenceProtocol.d.ts.map +1 -0
- package/dist/runtime/engineBrokerInferenceProtocol.js +65 -0
- package/dist/runtime/engineBrokerMcpCallLog.d.ts +171 -0
- package/dist/runtime/engineBrokerMcpCallLog.d.ts.map +1 -0
- package/dist/runtime/engineBrokerMcpCallLog.js +231 -0
- package/dist/runtime/engineBrokerMcpFacade.d.ts +59 -0
- package/dist/runtime/engineBrokerMcpFacade.d.ts.map +1 -0
- package/dist/runtime/engineBrokerMcpFacade.js +346 -0
- package/dist/runtime/engineBrokerNativeClient.d.ts +52 -0
- package/dist/runtime/engineBrokerNativeClient.d.ts.map +1 -0
- package/dist/runtime/engineBrokerNativeClient.js +151 -0
- package/dist/runtime/engineBrokerProtocol.d.ts +167 -0
- package/dist/runtime/engineBrokerProtocol.d.ts.map +1 -0
- package/dist/runtime/engineBrokerProtocol.js +357 -0
- package/dist/runtime/engineBrokerSealLedger.d.ts +70 -0
- package/dist/runtime/engineBrokerSealLedger.d.ts.map +1 -0
- package/dist/runtime/engineBrokerSealLedger.js +132 -0
- package/dist/runtime/engineBrokerService.d.ts +43 -0
- package/dist/runtime/engineBrokerService.d.ts.map +1 -0
- package/dist/runtime/engineBrokerService.js +196 -0
- package/dist/runtime/engineBrokerServiceCli.d.ts +5 -0
- package/dist/runtime/engineBrokerServiceCli.d.ts.map +1 -0
- package/dist/runtime/engineBrokerServiceCli.js +32 -0
- package/dist/runtime/engineBrokerServiceConfig.d.ts +55 -0
- package/dist/runtime/engineBrokerServiceConfig.d.ts.map +1 -0
- package/dist/runtime/engineBrokerServiceConfig.js +130 -0
- package/dist/runtime/engineBrokerSingleflight.d.ts +13 -0
- package/dist/runtime/engineBrokerSingleflight.d.ts.map +1 -0
- package/dist/runtime/engineBrokerSingleflight.js +24 -0
- package/dist/runtime/engineBrokerTurnAccounting.d.ts +76 -0
- package/dist/runtime/engineBrokerTurnAccounting.d.ts.map +1 -0
- package/dist/runtime/engineBrokerTurnAccounting.js +108 -0
- package/dist/runtime/engineBrokerTurnRegistry.d.ts +57 -0
- package/dist/runtime/engineBrokerTurnRegistry.d.ts.map +1 -0
- package/dist/runtime/engineBrokerTurnRegistry.js +159 -0
- package/dist/runtime/engineDispatcher.d.ts +38 -0
- package/dist/runtime/engineDispatcher.d.ts.map +1 -0
- package/dist/runtime/engineDispatcher.js +228 -0
- package/dist/runtime/engineReadiness.d.ts +23 -0
- package/dist/runtime/engineReadiness.d.ts.map +1 -0
- package/dist/runtime/engineReadiness.js +222 -0
- package/dist/runtime/grokAuthenticationError.d.ts +8 -0
- package/dist/runtime/grokAuthenticationError.d.ts.map +1 -0
- package/dist/runtime/grokAuthenticationError.js +20 -0
- package/dist/runtime/grokBrokerCredentialAuthority.d.ts +23 -0
- package/dist/runtime/grokBrokerCredentialAuthority.d.ts.map +1 -0
- package/dist/runtime/grokBrokerCredentialAuthority.js +150 -0
- package/dist/runtime/grokBrokerCredentialReader.d.ts +6 -0
- package/dist/runtime/grokBrokerCredentialReader.d.ts.map +1 -0
- package/dist/runtime/grokBrokerCredentialReader.js +38 -0
- package/dist/runtime/grokBrokerModelPolicy.d.ts +23 -0
- package/dist/runtime/grokBrokerModelPolicy.d.ts.map +1 -0
- package/dist/runtime/grokBrokerModelPolicy.js +28 -0
- package/dist/runtime/grokBrokerProjection.d.ts +114 -0
- package/dist/runtime/grokBrokerProjection.d.ts.map +1 -0
- package/dist/runtime/grokBrokerProjection.js +101 -0
- 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 +69 -0
- package/dist/runtime/grokBrokerProxy.d.ts.map +1 -0
- package/dist/runtime/grokBrokerProxy.js +326 -0
- 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 +30 -0
- package/dist/runtime/grokBrokerProxyRequest.d.ts.map +1 -0
- package/dist/runtime/grokBrokerProxyRequest.js +85 -0
- package/dist/runtime/grokBrokerRealmLease.d.ts +4 -0
- package/dist/runtime/grokBrokerRealmLease.d.ts.map +1 -0
- package/dist/runtime/grokBrokerRealmLease.js +33 -0
- package/dist/runtime/grokBrokerRefresh.d.ts +2 -0
- package/dist/runtime/grokBrokerRefresh.d.ts.map +1 -0
- package/dist/runtime/grokBrokerRefresh.js +15 -0
- 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 +180 -0
- package/dist/runtime/grokBrokerTurnMeter.d.ts.map +1 -0
- package/dist/runtime/grokBrokerTurnMeter.js +337 -0
- package/dist/runtime/grokBrokerWorkerConfig.d.ts +89 -0
- package/dist/runtime/grokBrokerWorkerConfig.d.ts.map +1 -0
- package/dist/runtime/grokBrokerWorkerConfig.js +154 -0
- package/dist/runtime/grokEngineBroker.d.ts +88 -0
- package/dist/runtime/grokEngineBroker.d.ts.map +1 -0
- package/dist/runtime/grokEngineBroker.js +202 -0
- package/dist/runtime/grokEngineBrokerLedger.d.ts +52 -0
- package/dist/runtime/grokEngineBrokerLedger.d.ts.map +1 -0
- package/dist/runtime/grokEngineBrokerLedger.js +114 -0
- package/dist/runtime/grokEngineBrokerMetering.d.ts +51 -0
- package/dist/runtime/grokEngineBrokerMetering.d.ts.map +1 -0
- package/dist/runtime/grokEngineBrokerMetering.js +34 -0
- package/dist/runtime/grokEngineBrokerTurn.d.ts +82 -0
- package/dist/runtime/grokEngineBrokerTurn.d.ts.map +1 -0
- package/dist/runtime/grokEngineBrokerTurn.js +348 -0
- 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/grokInferenceClientConfig.d.ts +41 -0
- package/dist/runtime/grokInferenceClientConfig.d.ts.map +1 -0
- package/dist/runtime/grokInferenceClientConfig.js +62 -0
- package/dist/runtime/grokInferenceGrants.d.ts +77 -0
- package/dist/runtime/grokInferenceGrants.d.ts.map +1 -0
- package/dist/runtime/grokInferenceGrants.js +116 -0
- package/dist/runtime/grokInferenceProxy.d.ts +29 -0
- package/dist/runtime/grokInferenceProxy.d.ts.map +1 -0
- package/dist/runtime/grokInferenceProxy.js +85 -0
- package/dist/runtime/grokInferenceProxyRequest.d.ts +23 -0
- package/dist/runtime/grokInferenceProxyRequest.d.ts.map +1 -0
- package/dist/runtime/grokInferenceProxyRequest.js +63 -0
- package/dist/runtime/grokSlotPreflightReceipt.d.ts +70 -0
- package/dist/runtime/grokSlotPreflightReceipt.d.ts.map +1 -0
- package/dist/runtime/grokSlotPreflightReceipt.js +101 -0
- package/dist/runtime/grokSubscriptionRealm.d.ts +4 -0
- package/dist/runtime/grokSubscriptionRealm.d.ts.map +1 -0
- package/dist/runtime/grokSubscriptionRealm.js +435 -0
- package/dist/runtime/grokSubscriptionRealmTypes.d.ts +26 -0
- package/dist/runtime/grokSubscriptionRealmTypes.d.ts.map +1 -0
- package/dist/runtime/grokSubscriptionRealmTypes.js +1 -0
- package/dist/runtime/grokWorkerAttestation.d.ts +175 -0
- package/dist/runtime/grokWorkerAttestation.d.ts.map +1 -0
- package/dist/runtime/grokWorkerAttestation.js +266 -0
- package/dist/runtime/grokWorkerDenyPlacement.d.ts +80 -0
- package/dist/runtime/grokWorkerDenyPlacement.d.ts.map +1 -0
- package/dist/runtime/grokWorkerDenyPlacement.js +128 -0
- package/dist/runtime/grokWorkerHomeAttestation.d.ts +32 -0
- package/dist/runtime/grokWorkerHomeAttestation.d.ts.map +1 -0
- package/dist/runtime/grokWorkerHomeAttestation.js +75 -0
- package/dist/runtime/grokWorkerSandboxProfile.d.ts +27 -0
- package/dist/runtime/grokWorkerSandboxProfile.d.ts.map +1 -0
- package/dist/runtime/grokWorkerSandboxProfile.js +44 -0
- package/dist/runtime/grokWorkerTmpAttestation.d.ts +55 -0
- package/dist/runtime/grokWorkerTmpAttestation.d.ts.map +1 -0
- package/dist/runtime/grokWorkerTmpAttestation.js +63 -0
- package/dist/runtime/index.d.ts +31 -0
- package/dist/runtime/index.d.ts.map +1 -0
- package/dist/runtime/index.js +27 -0
- package/dist/runtime/inferenceUsageLedger.d.ts +38 -0
- package/dist/runtime/inferenceUsageLedger.d.ts.map +1 -0
- package/dist/runtime/inferenceUsageLedger.js +53 -0
- package/dist/runtime/mcpToolResult.d.ts +127 -0
- package/dist/runtime/mcpToolResult.d.ts.map +1 -0
- package/dist/runtime/mcpToolResult.js +214 -0
- package/dist/runtime/moltnetMachineRead.d.ts +97 -0
- package/dist/runtime/moltnetMachineRead.d.ts.map +1 -0
- package/dist/runtime/moltnetMachineRead.js +183 -0
- package/dist/runtime/native/daimon-engine-broker +0 -0
- package/dist/runtime/organizationRuntime.d.ts +168 -0
- package/dist/runtime/organizationRuntime.d.ts.map +1 -0
- package/dist/runtime/organizationRuntime.js +3 -0
- 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 +51 -0
- package/dist/runtime/organizationRuntimeControl.d.ts.map +1 -0
- package/dist/runtime/organizationRuntimeControl.js +283 -0
- package/dist/runtime/organizationRuntimeHost.d.ts +19 -0
- package/dist/runtime/organizationRuntimeHost.d.ts.map +1 -0
- package/dist/runtime/organizationRuntimeHost.js +368 -0
- package/dist/runtime/organizationRuntimeParsing.d.ts +6 -0
- package/dist/runtime/organizationRuntimeParsing.d.ts.map +1 -0
- package/dist/runtime/organizationRuntimeParsing.js +373 -0
- package/dist/runtime/organizationRuntimeReadiness.d.ts +12 -0
- package/dist/runtime/organizationRuntimeReadiness.d.ts.map +1 -0
- package/dist/runtime/organizationRuntimeReadiness.js +67 -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 +59 -0
- package/dist/runtime/physicalReadiness.d.ts.map +1 -0
- package/dist/runtime/physicalReadiness.js +176 -0
- package/dist/runtime/portableCredentialAuth.d.ts +6 -0
- package/dist/runtime/portableCredentialAuth.d.ts.map +1 -0
- package/dist/runtime/portableCredentialAuth.js +70 -0
- package/dist/runtime/portableCredentialMaterial.d.ts +8 -0
- package/dist/runtime/portableCredentialMaterial.d.ts.map +1 -0
- package/dist/runtime/portableCredentialMaterial.js +169 -0
- package/dist/runtime/productionAgentTools.d.ts +5 -0
- package/dist/runtime/productionAgentTools.d.ts.map +1 -0
- package/dist/runtime/productionAgentTools.js +336 -0
- 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/runtimeHomeLayout.d.ts +48 -0
- package/dist/runtime/runtimeHomeLayout.d.ts.map +1 -0
- package/dist/runtime/runtimeHomeLayout.js +84 -0
- package/dist/runtime/schedule.d.ts +40 -0
- package/dist/runtime/schedule.d.ts.map +1 -0
- package/dist/runtime/schedule.js +376 -0
- package/dist/runtime/storeCoordination.d.ts +33 -0
- package/dist/runtime/storeCoordination.d.ts.map +1 -0
- package/dist/runtime/storeCoordination.js +117 -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/toolResultSpill.d.ts +152 -0
- package/dist/runtime/toolResultSpill.d.ts.map +1 -0
- package/dist/runtime/toolResultSpill.js +351 -0
- package/dist/runtime/turnRequestLedger.d.ts +155 -0
- package/dist/runtime/turnRequestLedger.d.ts.map +1 -0
- package/dist/runtime/turnRequestLedger.js +251 -0
- package/dist/runtime/turnUsageLedger.d.ts +143 -0
- package/dist/runtime/turnUsageLedger.d.ts.map +1 -0
- package/dist/runtime/turnUsageLedger.js +203 -0
- 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 +25 -0
- package/dist/runtime/wakeAcceptanceProcessIdentity.d.ts.map +1 -0
- package/dist/runtime/wakeAcceptanceProcessIdentity.js +54 -0
- package/dist/runtime/wakeAcceptanceReconciliation.d.ts +211 -0
- package/dist/runtime/wakeAcceptanceReconciliation.d.ts.map +1 -0
- package/dist/runtime/wakeAcceptanceReconciliation.js +289 -0
- package/dist/runtime/wakeAcceptanceRecord.d.ts +25 -0
- package/dist/runtime/wakeAcceptanceRecord.d.ts.map +1 -0
- package/dist/runtime/wakeAcceptanceRecord.js +58 -0
- package/dist/runtime/wakeAcceptanceRetention.d.ts +36 -0
- package/dist/runtime/wakeAcceptanceRetention.d.ts.map +1 -0
- package/dist/runtime/wakeAcceptanceRetention.js +38 -0
- package/dist/runtime/wakeAcceptanceStore.d.ts +113 -0
- package/dist/runtime/wakeAcceptanceStore.d.ts.map +1 -0
- package/dist/runtime/wakeAcceptanceStore.js +561 -0
- package/dist/runtime/wakeAcceptanceTypes.d.ts +179 -0
- package/dist/runtime/wakeAcceptanceTypes.d.ts.map +1 -0
- package/dist/runtime/wakeAcceptanceTypes.js +95 -0
- package/dist/runtime/wakeFuse.d.ts +124 -0
- package/dist/runtime/wakeFuse.d.ts.map +1 -0
- package/dist/runtime/wakeFuse.js +466 -0
- 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 +22 -11
|
@@ -0,0 +1,466 @@
|
|
|
1
|
+
import { constants } from "node:fs";
|
|
2
|
+
import { open, readFile, readdir, rename, stat, unlink } from "node:fs/promises";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
5
|
+
import { resolveTurnUsageLedgerPath, TURN_USAGE_LEDGER, TURN_USAGE_MAX_IDENTIFIER_CHARS, TURN_USAGE_ROTATE_BYTES } from "./turnUsageLedger.js";
|
|
6
|
+
export const WAKE_FUSE_VERSION = "noopolis.daimon.wake-fuse.v1";
|
|
7
|
+
export const WAKE_FUSE_DIRECTORY_ENV = "DAIMON_WAKE_FUSE_DIRECTORY";
|
|
8
|
+
export const WAKE_FUSE_EPOCH_ZONE_ENV = "DAIMON_WAKE_FUSE_EPOCH_ZONE";
|
|
9
|
+
export const DEFAULT_WAKE_FUSE_MAX_WAKES = 100;
|
|
10
|
+
export const DEFAULT_WAKE_FUSE_MAX_TOKENS = 5_000_000;
|
|
11
|
+
/**
|
|
12
|
+
* The counting window, when the operator has not named one.
|
|
13
|
+
*
|
|
14
|
+
* WHY THIS IS DERIVED AND NOT CONFIGURED
|
|
15
|
+
* --------------------------------------
|
|
16
|
+
* `DAIMON_WAKE_FUSE_EPOCH` is read from the container's env file, and an env
|
|
17
|
+
* file is applied at container CREATION only. So an operator who wants a daily
|
|
18
|
+
* budget has to rewrite that file and RECREATE THE CONTAINER every day, and
|
|
19
|
+
* the only thing that ever did that was a daily rebuild. The budget was
|
|
20
|
+
* therefore coupled to a deploy: stop deploying daily and the wake ceiling
|
|
21
|
+
* never resets, and the organization stops admitting wakes for good.
|
|
22
|
+
*
|
|
23
|
+
* A date-derived epoch removes the coupling instead of moving it. There is no
|
|
24
|
+
* file to rewrite, no deploy, no restart, and no clock for anybody to forget.
|
|
25
|
+
*
|
|
26
|
+
* An explicitly configured epoch still wins, unchanged: an operator pinning one
|
|
27
|
+
* window is doing it deliberately, and this must not roll it out from under
|
|
28
|
+
* them.
|
|
29
|
+
*/
|
|
30
|
+
export function derivedEpoch(organizationKey, at, zone) {
|
|
31
|
+
// `en-CA` renders ISO-8601 (YYYY-MM-DD), which is what makes this sortable
|
|
32
|
+
// and stable; the zone is what makes "a day" mean the operator's day.
|
|
33
|
+
const day = new Intl.DateTimeFormat("en-CA", { timeZone: zone, year: "numeric", month: "2-digit", day: "2-digit" }).format(at);
|
|
34
|
+
return `organization-${createHash("sha256").update(organizationKey).digest("hex")}-${day}`;
|
|
35
|
+
}
|
|
36
|
+
const TRIP_MARKER = "fuse.trip.json";
|
|
37
|
+
let warnedDisarmed = false;
|
|
38
|
+
/**
|
|
39
|
+
* Durable catastrophic-wake admission fuse for one organization/container.
|
|
40
|
+
*
|
|
41
|
+
* Operator trip: `docker exec <container> touch /var/lib/spawnfile/daimon/usage/fuse.stop`.
|
|
42
|
+
* Unlike `recordTurnUsage` ("advisory: never rejects"), every storage or
|
|
43
|
+
* evaluation failure here rejects admission: this safety boundary fails closed.
|
|
44
|
+
*/
|
|
45
|
+
export class WakeFuse {
|
|
46
|
+
armed;
|
|
47
|
+
directory;
|
|
48
|
+
epoch;
|
|
49
|
+
epochStartedAt;
|
|
50
|
+
maxWakes;
|
|
51
|
+
maxTokens;
|
|
52
|
+
admissions;
|
|
53
|
+
usageLedgerPath;
|
|
54
|
+
now;
|
|
55
|
+
nextEpoch;
|
|
56
|
+
serial = Promise.resolve();
|
|
57
|
+
reason;
|
|
58
|
+
tripMarkerMissing = false;
|
|
59
|
+
constructor(armed, directory, epoch, epochStartedAt, maxWakes, maxTokens, admissions, usageLedgerPath, now, nextEpoch) {
|
|
60
|
+
this.armed = armed;
|
|
61
|
+
this.directory = directory;
|
|
62
|
+
this.epoch = epoch;
|
|
63
|
+
this.epochStartedAt = epochStartedAt;
|
|
64
|
+
this.maxWakes = maxWakes;
|
|
65
|
+
this.maxTokens = maxTokens;
|
|
66
|
+
this.admissions = admissions;
|
|
67
|
+
this.usageLedgerPath = usageLedgerPath;
|
|
68
|
+
this.now = now;
|
|
69
|
+
this.nextEpoch = nextEpoch;
|
|
70
|
+
}
|
|
71
|
+
static async open(options) {
|
|
72
|
+
const environment = options.environment ?? process.env;
|
|
73
|
+
const setting = environment.DAIMON_WAKE_FUSE;
|
|
74
|
+
if (setting !== undefined && setting !== "off")
|
|
75
|
+
throw new Error("DAIMON_WAKE_FUSE must be exactly 'off' when set");
|
|
76
|
+
if (environment.DAIMON_WAKE_FUSE_EPOCH !== undefined && nonBlank(environment.DAIMON_WAKE_FUSE_EPOCH) === undefined)
|
|
77
|
+
throw new Error("DAIMON_WAKE_FUSE_EPOCH must be non-blank");
|
|
78
|
+
const pinned = nonBlank(environment.DAIMON_WAKE_FUSE_EPOCH);
|
|
79
|
+
const zone = nonBlank(environment[WAKE_FUSE_EPOCH_ZONE_ENV]) ?? "UTC";
|
|
80
|
+
// A pinned epoch never rolls; a derived one rolls with the operator's day.
|
|
81
|
+
// Agent ids are the stable organization identity available to Daimon.
|
|
82
|
+
const nextEpoch = (at) => pinned ?? derivedEpoch(options.organizationKey, at, zone);
|
|
83
|
+
const maxWakes = ceiling(environment.DAIMON_WAKE_FUSE_MAX_WAKES, DEFAULT_WAKE_FUSE_MAX_WAKES, "DAIMON_WAKE_FUSE_MAX_WAKES");
|
|
84
|
+
const maxTokens = ceiling(environment.DAIMON_WAKE_FUSE_MAX_TOKENS, DEFAULT_WAKE_FUSE_MAX_TOKENS, "DAIMON_WAKE_FUSE_MAX_TOKENS");
|
|
85
|
+
const directory = resolveWakeFuseDirectory(environment);
|
|
86
|
+
const now = options.now ?? (() => new Date());
|
|
87
|
+
const epoch = nextEpoch(now());
|
|
88
|
+
const usageLedgerPath = resolveTurnUsageLedgerPath(environment);
|
|
89
|
+
if (setting === "off") {
|
|
90
|
+
if (!warnedDisarmed) {
|
|
91
|
+
warnedDisarmed = true;
|
|
92
|
+
console.error("DAIMON WAKE FUSE IS OFF: wake admission is unbounded");
|
|
93
|
+
}
|
|
94
|
+
return new WakeFuse(false, directory, epoch, now().toISOString(), maxWakes, maxTokens, new Set(), usageLedgerPath, now, nextEpoch);
|
|
95
|
+
}
|
|
96
|
+
// Unbounded defaults would reproduce exactly the failure this module prevents.
|
|
97
|
+
await readdir(directory);
|
|
98
|
+
await ensureUsageLedgerUsable(usageLedgerPath);
|
|
99
|
+
const records = await readFuseRecords(directory);
|
|
100
|
+
const existingStart = records.filter((record) => record.kind === "epoch_start" && record.epoch === epoch).at(-1);
|
|
101
|
+
const epochStartedAt = existingStart?.at ?? now().toISOString();
|
|
102
|
+
if (existingStart === undefined)
|
|
103
|
+
await append(directory, { v: WAKE_FUSE_VERSION, kind: "epoch_start", epoch, at: epochStartedAt });
|
|
104
|
+
const admissions = new Set(records
|
|
105
|
+
.filter((record) => record.kind === "admission" && record.epoch === epoch)
|
|
106
|
+
.map((record) => key(record.agent, record.delivery)));
|
|
107
|
+
const fuse = new WakeFuse(true, directory, epoch, epochStartedAt, maxWakes, maxTokens, admissions, usageLedgerPath, now, nextEpoch);
|
|
108
|
+
if (await exists(path.join(directory, "fuse.stop")))
|
|
109
|
+
fuse.reason = "operator_stop";
|
|
110
|
+
else
|
|
111
|
+
fuse.reason = await readTripMarker(directory, epoch);
|
|
112
|
+
return fuse;
|
|
113
|
+
}
|
|
114
|
+
admit(agentId, deliveryId, limits = {}) {
|
|
115
|
+
if (!this.armed)
|
|
116
|
+
return Promise.resolve({ state: "admitted" });
|
|
117
|
+
// One organization is one container/control-host process. This promise
|
|
118
|
+
// chain is organization-wide in-process serialization, not cross-process locking.
|
|
119
|
+
const result = this.serial.catch(() => undefined).then(async () => await this.admitNow(agentId, deliveryId, limits));
|
|
120
|
+
this.serial = result.then(() => undefined, () => undefined);
|
|
121
|
+
return result;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* The budget as the caller should act on it NOW — which means after the day
|
|
125
|
+
* has been allowed to roll.
|
|
126
|
+
*
|
|
127
|
+
* This is the gate the scheduler actually consults: `AttentionDispatcher.drain()`
|
|
128
|
+
* returns at `snapshot().state !== "available"` before it ever reaches
|
|
129
|
+
* `admit()`. Rolling only inside `admitNow` therefore never fired for an
|
|
130
|
+
* organization that had hit its ceiling — it stayed paused across midnight
|
|
131
|
+
* and only a process restart could renew the budget. The roll is serialized
|
|
132
|
+
* with admissions so a snapshot and an admission never see two windows.
|
|
133
|
+
*/
|
|
134
|
+
async snapshot(agentId, limits = {}) {
|
|
135
|
+
const result = this.serial.catch(() => undefined).then(async () => {
|
|
136
|
+
if (this.armed)
|
|
137
|
+
await this.rollEpochIfDue();
|
|
138
|
+
return await this.snapshotNow(agentId, limits);
|
|
139
|
+
});
|
|
140
|
+
this.serial = result.then(() => undefined, () => undefined);
|
|
141
|
+
return await result;
|
|
142
|
+
}
|
|
143
|
+
async snapshotNow(agentId, limits = {}) {
|
|
144
|
+
const used = this.admissions.size;
|
|
145
|
+
const agentUsed = [...this.admissions].filter((entry) => entry.startsWith(`${bounded(agentId)}\u0000`)).length;
|
|
146
|
+
const tokens = this.armed ? await sumTokens(this.usageLedgerPath, this.epochStartedAt) : 0;
|
|
147
|
+
const agentTokens = this.armed ? await sumTokens(this.usageLedgerPath, this.epochStartedAt, agentId) : 0;
|
|
148
|
+
const reason = this.reason ?? (this.armed ? used >= this.maxWakes ? "wake_ceiling" : tokens >= this.maxTokens ? "token_ceiling" : limits.maxExecutions !== undefined && agentUsed >= limits.maxExecutions ? "agent_execution_ceiling" : limits.maxTokens !== undefined && agentTokens >= limits.maxTokens ? "agent_token_ceiling" : undefined : undefined);
|
|
149
|
+
return { armed: this.armed, epoch: this.epoch, state: reason === undefined ? "available" : reason === "operator_stop" || reason === "ledger_unavailable" ? "stopped" : "paused", ...(reason === undefined ? {} : { reason }), executions_used: used, executions_remaining: Math.max(0, this.maxWakes - used), tokens_used: tokens, tokens_remaining: Math.max(0, this.maxTokens - tokens), agent_executions_used: agentUsed, agent_tokens_used: agentTokens, ...(limits.maxExecutions === undefined ? {} : { agent_executions_remaining: Math.max(0, limits.maxExecutions - agentUsed) }), ...(limits.maxTokens === undefined ? {} : { agent_tokens_remaining: Math.max(0, limits.maxTokens - agentTokens) }) };
|
|
150
|
+
}
|
|
151
|
+
async pollOperatorStop() {
|
|
152
|
+
if (!this.armed || this.reason === "operator_stop" || this.reason === "ledger_unavailable")
|
|
153
|
+
return this.reason;
|
|
154
|
+
try {
|
|
155
|
+
if (await exists(path.join(this.directory, "fuse.stop")))
|
|
156
|
+
await this.trip("operator_stop");
|
|
157
|
+
}
|
|
158
|
+
catch {
|
|
159
|
+
await this.trip("ledger_unavailable");
|
|
160
|
+
}
|
|
161
|
+
return this.reason;
|
|
162
|
+
}
|
|
163
|
+
tripped() { return this.reason; }
|
|
164
|
+
async close() { await this.serial; }
|
|
165
|
+
/**
|
|
166
|
+
* Moves the counting window when the derived day has changed.
|
|
167
|
+
*
|
|
168
|
+
* Called at admission, which is the only moment the answer can matter: the
|
|
169
|
+
* organization runtime is a long-lived process, so an epoch computed once at
|
|
170
|
+
* open() would be the same epoch a week later.
|
|
171
|
+
*
|
|
172
|
+
* WHAT ROLLS AND WHAT DOES NOT
|
|
173
|
+
* ----------------------------
|
|
174
|
+
* A new window clears a CEILING trip, exactly as selecting a new epoch by
|
|
175
|
+
* hand always did: `readTripMarker` only honours a marker belonging to the
|
|
176
|
+
* current epoch. It does NOT clear an operator stop. `fuse.stop` is checked
|
|
177
|
+
* by existence and is deliberately not epoch-scoped, so a parked newsroom
|
|
178
|
+
* stays parked across midnight. That asymmetry is the whole point: a budget
|
|
179
|
+
* is a thing that renews, an operator stop is a decision that does not.
|
|
180
|
+
*
|
|
181
|
+
* Admissions are rebuilt from the ledger rather than emptied, so a clock that
|
|
182
|
+
* steps BACKWARD into a window that already spent wakes does not hand the
|
|
183
|
+
* organization a fresh budget.
|
|
184
|
+
*/
|
|
185
|
+
async rollEpochIfDue() {
|
|
186
|
+
const wanted = this.nextEpoch(this.now());
|
|
187
|
+
if (wanted === this.epoch)
|
|
188
|
+
return;
|
|
189
|
+
const records = await readFuseRecords(this.directory);
|
|
190
|
+
const existingStart = records.filter((record) => record.kind === "epoch_start" && record.epoch === wanted).at(-1);
|
|
191
|
+
const startedAt = existingStart?.at ?? this.now().toISOString();
|
|
192
|
+
if (existingStart === undefined)
|
|
193
|
+
await append(this.directory, { v: WAKE_FUSE_VERSION, kind: "epoch_start", epoch: wanted, at: startedAt });
|
|
194
|
+
this.epoch = wanted;
|
|
195
|
+
this.epochStartedAt = startedAt;
|
|
196
|
+
this.admissions = new Set(records
|
|
197
|
+
.filter((record) => record.kind === "admission" && record.epoch === wanted)
|
|
198
|
+
.map((record) => key(record.agent, record.delivery)));
|
|
199
|
+
// Re-evaluate the trip for the NEW window. Clearing a CEILING is the part
|
|
200
|
+
// that does work here, and it is what makes the budget renew.
|
|
201
|
+
//
|
|
202
|
+
// The operator-stop branch is deliberately BELT AND BRACES, not the guard:
|
|
203
|
+
// `admitNow` checks `fuse.stop` itself on every admission, unscoped by
|
|
204
|
+
// epoch, and `trip()` sets the reason — so a park is already enforced
|
|
205
|
+
// whatever this line does. I could not write a failing test for it, and
|
|
206
|
+
// said so rather than dressing it up as a guarantee. It stays because it
|
|
207
|
+
// keeps the object's own state coherent at the moment it rolls; the test
|
|
208
|
+
// above pins the BEHAVIOUR, which is what must not regress.
|
|
209
|
+
this.reason = await exists(path.join(this.directory, "fuse.stop")) ? "operator_stop" : await readTripMarker(this.directory, wanted);
|
|
210
|
+
}
|
|
211
|
+
async admitNow(agentId, deliveryId, limits) {
|
|
212
|
+
// Before the trip is consulted: a new day may have cleared a ceiling.
|
|
213
|
+
await this.rollEpochIfDue();
|
|
214
|
+
if (this.reason !== undefined)
|
|
215
|
+
return await this.trip(this.reason);
|
|
216
|
+
try {
|
|
217
|
+
if (await exists(path.join(this.directory, "fuse.stop")))
|
|
218
|
+
return await this.trip("operator_stop");
|
|
219
|
+
const admissionKey = key(bounded(agentId), bounded(deliveryId));
|
|
220
|
+
if (this.admissions.has(admissionKey))
|
|
221
|
+
return { state: "admitted" };
|
|
222
|
+
const budget = await this.snapshotNow(agentId, limits);
|
|
223
|
+
if (budget.agent_executions_remaining === 0)
|
|
224
|
+
return { state: "paused", reason: "agent_execution_ceiling" };
|
|
225
|
+
if (budget.agent_tokens_remaining === 0)
|
|
226
|
+
return { state: "paused", reason: "agent_token_ceiling" };
|
|
227
|
+
if (this.admissions.size >= this.maxWakes)
|
|
228
|
+
return await this.trip("wake_ceiling");
|
|
229
|
+
// Lagging indicator: usage is written after turn completion, so in-flight
|
|
230
|
+
// spend can overshoot by one concurrent round. The wake ceiling bounds it;
|
|
231
|
+
// design §5.2 owns the later pre-spawn reservation.
|
|
232
|
+
if (await sumTokens(this.usageLedgerPath, this.epochStartedAt) >= this.maxTokens)
|
|
233
|
+
return await this.trip("token_ceiling");
|
|
234
|
+
const record = { v: WAKE_FUSE_VERSION, kind: "admission", epoch: this.epoch, at: this.now().toISOString(), agent: bounded(agentId), delivery: bounded(deliveryId) };
|
|
235
|
+
await append(this.directory, record);
|
|
236
|
+
this.admissions.add(admissionKey);
|
|
237
|
+
return { state: "admitted" };
|
|
238
|
+
}
|
|
239
|
+
catch {
|
|
240
|
+
return await this.trip("ledger_unavailable");
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
async trip(reason) {
|
|
244
|
+
if (this.reason === undefined || (reason === "operator_stop" || reason === "ledger_unavailable") && this.reason !== "operator_stop" && this.reason !== "ledger_unavailable") {
|
|
245
|
+
this.reason = reason;
|
|
246
|
+
this.tripMarkerMissing = true;
|
|
247
|
+
}
|
|
248
|
+
if (this.tripMarkerMissing) {
|
|
249
|
+
try {
|
|
250
|
+
await writeTripMarker(this.directory, { v: WAKE_FUSE_VERSION, kind: "trip", epoch: this.epoch, at: this.now().toISOString(), reason: this.reason });
|
|
251
|
+
this.tripMarkerMissing = false;
|
|
252
|
+
}
|
|
253
|
+
catch {
|
|
254
|
+
// Keep the in-memory fuse closed and retry durability on every later
|
|
255
|
+
// admit/trip. Marker I/O must never turn a tripped verdict into an
|
|
256
|
+
// unhandled rejection at the HTTP boundary.
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
return { state: "tripped", reason: this.reason };
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
export function resolveWakeFuseDirectory(environment = process.env) {
|
|
263
|
+
const override = environment[WAKE_FUSE_DIRECTORY_ENV]?.trim();
|
|
264
|
+
return override !== undefined && override.startsWith("/") ? override : TURN_USAGE_LEDGER.directoryPath;
|
|
265
|
+
}
|
|
266
|
+
function ceiling(value, fallback, name) {
|
|
267
|
+
if (value === undefined)
|
|
268
|
+
return fallback;
|
|
269
|
+
const parsed = Number(value);
|
|
270
|
+
if (!Number.isSafeInteger(parsed) || parsed <= 0)
|
|
271
|
+
throw new Error(`${name} must be a positive integer`);
|
|
272
|
+
return parsed;
|
|
273
|
+
}
|
|
274
|
+
function nonBlank(value) { const trimmed = value?.trim(); return trimmed ? trimmed : undefined; }
|
|
275
|
+
function bounded(value) { return [...value].slice(0, TURN_USAGE_MAX_IDENTIFIER_CHARS).join(""); }
|
|
276
|
+
function key(agent, delivery) { return `${agent}\u0000${delivery}`; }
|
|
277
|
+
function admissionsPath(directory) { return path.join(directory, "admissions.jsonl"); }
|
|
278
|
+
async function append(directory, record) {
|
|
279
|
+
const file = admissionsPath(directory);
|
|
280
|
+
try {
|
|
281
|
+
if ((await stat(file)).size >= TURN_USAGE_ROTATE_BYTES)
|
|
282
|
+
await rename(file, `${file}.1`);
|
|
283
|
+
}
|
|
284
|
+
catch (error) {
|
|
285
|
+
if (error.code !== "ENOENT")
|
|
286
|
+
throw error;
|
|
287
|
+
}
|
|
288
|
+
const bytes = Buffer.from(`${JSON.stringify(record)}\n`, "utf8");
|
|
289
|
+
const handle = await open(file, constants.O_WRONLY | constants.O_APPEND | constants.O_CREAT | constants.O_NOFOLLOW, TURN_USAGE_LEDGER.fileMode);
|
|
290
|
+
try {
|
|
291
|
+
const result = await handle.write(bytes, 0, bytes.length);
|
|
292
|
+
if (result.bytesWritten !== bytes.length)
|
|
293
|
+
throw new Error("wake fuse admission append was torn");
|
|
294
|
+
await handle.sync();
|
|
295
|
+
}
|
|
296
|
+
finally {
|
|
297
|
+
await handle.close();
|
|
298
|
+
}
|
|
299
|
+
await syncDirectory(directory);
|
|
300
|
+
}
|
|
301
|
+
async function syncDirectory(directory) { const handle = await open(directory, constants.O_RDONLY); try {
|
|
302
|
+
await handle.sync();
|
|
303
|
+
}
|
|
304
|
+
finally {
|
|
305
|
+
await handle.close();
|
|
306
|
+
} }
|
|
307
|
+
async function readFuseRecords(directory) {
|
|
308
|
+
const records = [];
|
|
309
|
+
for (const file of [`${admissionsPath(directory)}.1`, admissionsPath(directory)]) {
|
|
310
|
+
for (const line of await lines(file)) {
|
|
311
|
+
try {
|
|
312
|
+
const value = JSON.parse(line);
|
|
313
|
+
if (value.v !== WAKE_FUSE_VERSION || typeof value.epoch !== "string" || typeof value.at !== "string" || Number.isNaN(Date.parse(value.at)))
|
|
314
|
+
continue;
|
|
315
|
+
if (value.kind === "epoch_start")
|
|
316
|
+
records.push(value);
|
|
317
|
+
else if (value.kind === "admission" && typeof value.agent === "string" && typeof value.delivery === "string")
|
|
318
|
+
records.push(value);
|
|
319
|
+
}
|
|
320
|
+
catch { /* malformed historical fuse lines do not count */ }
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
return records;
|
|
324
|
+
}
|
|
325
|
+
async function sumTokens(ledgerPath, since, agentId) {
|
|
326
|
+
let total = 0;
|
|
327
|
+
// Rows carrying a `turn` idempotency key count once per turn, whichever file holds them.
|
|
328
|
+
const turns = new Set();
|
|
329
|
+
for (const file of [`${ledgerPath}.1`, ledgerPath]) {
|
|
330
|
+
for (const line of await lines(file)) {
|
|
331
|
+
try {
|
|
332
|
+
const value = JSON.parse(line);
|
|
333
|
+
// Evaluator inference rows belong to their own ledger; one here (a misconfigured path) is never subject spend.
|
|
334
|
+
if (value.kind === "inference")
|
|
335
|
+
continue;
|
|
336
|
+
if (typeof value.turn === "string") {
|
|
337
|
+
if (turns.has(value.turn))
|
|
338
|
+
continue;
|
|
339
|
+
turns.add(value.turn);
|
|
340
|
+
}
|
|
341
|
+
if ((agentId === undefined || value.agent === agentId) && typeof value.at === "string" && !Number.isNaN(Date.parse(value.at)) && value.at >= since && typeof value.total === "number" && Number.isFinite(value.total) && value.total >= 0)
|
|
342
|
+
total += value.total;
|
|
343
|
+
}
|
|
344
|
+
catch { /* usage accounting is advisory input; malformed lines are skipped */ }
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
return total;
|
|
348
|
+
}
|
|
349
|
+
async function writeTripMarker(directory, marker) {
|
|
350
|
+
const target = path.join(directory, TRIP_MARKER);
|
|
351
|
+
const temporary = path.join(directory, `.${TRIP_MARKER}.${process.pid}.${randomUUID()}`);
|
|
352
|
+
const bytes = Buffer.from(`${JSON.stringify(marker)}\n`, "utf8");
|
|
353
|
+
try {
|
|
354
|
+
const handle = await open(temporary, constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL | constants.O_NOFOLLOW, TURN_USAGE_LEDGER.fileMode);
|
|
355
|
+
try {
|
|
356
|
+
const result = await handle.write(bytes, 0, bytes.length);
|
|
357
|
+
if (result.bytesWritten !== bytes.length)
|
|
358
|
+
throw new Error("wake fuse trip marker write was torn");
|
|
359
|
+
await handle.sync();
|
|
360
|
+
}
|
|
361
|
+
finally {
|
|
362
|
+
await handle.close();
|
|
363
|
+
}
|
|
364
|
+
await rename(temporary, target);
|
|
365
|
+
await syncDirectory(directory);
|
|
366
|
+
}
|
|
367
|
+
finally {
|
|
368
|
+
await unlink(temporary).catch(() => undefined);
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
async function readTripMarker(directory, epoch) {
|
|
372
|
+
try {
|
|
373
|
+
const value = JSON.parse(await readFile(path.join(directory, TRIP_MARKER), "utf8"));
|
|
374
|
+
if (value.v !== WAKE_FUSE_VERSION || value.kind !== "trip" || typeof value.epoch !== "string" || typeof value.at !== "string" || Number.isNaN(Date.parse(value.at)) || !isTripReason(value.reason))
|
|
375
|
+
return "ledger_unavailable";
|
|
376
|
+
// A valid marker belongs to one explicit counting window. Selecting a new
|
|
377
|
+
// epoch deliberately clears it; a corrupt marker cannot prove that and fails closed.
|
|
378
|
+
return value.epoch === epoch ? value.reason : undefined;
|
|
379
|
+
}
|
|
380
|
+
catch (error) {
|
|
381
|
+
if (error.code === "ENOENT")
|
|
382
|
+
return undefined;
|
|
383
|
+
return "ledger_unavailable";
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
function isTripReason(value) { return value === "wake_ceiling" || value === "token_ceiling" || value === "operator_stop" || value === "ledger_unavailable"; }
|
|
387
|
+
async function lines(file) { try {
|
|
388
|
+
return (await readFile(file, "utf8")).split("\n").filter(Boolean);
|
|
389
|
+
}
|
|
390
|
+
catch (error) {
|
|
391
|
+
if (error.code === "ENOENT")
|
|
392
|
+
return [];
|
|
393
|
+
throw error;
|
|
394
|
+
} }
|
|
395
|
+
/**
|
|
396
|
+
* An unenforceable usage ledger at arm time must never degrade to a silent
|
|
397
|
+
* zero. `sumTokens` (used on every later `admit`) deliberately treats a
|
|
398
|
+
* missing ledger as an empty one — if the ledger is deleted mid-epoch, the
|
|
399
|
+
* fuse still needs to keep functioning rather than wedge the organization —
|
|
400
|
+
* but that same tolerance is exactly how a 17.6M-token run passed a 5M
|
|
401
|
+
* ceiling untouched: the ledger was never created at all, so every sum read
|
|
402
|
+
* zero and the ceiling never had anything to compare against.
|
|
403
|
+
*
|
|
404
|
+
* Four states, distinguished by what actually makes the ceiling
|
|
405
|
+
* unenforceable versus merely unwritten yet:
|
|
406
|
+
* - The ledger directory is missing, or present but not writable by this
|
|
407
|
+
* uid: the ceiling is genuinely unenforceable. Fails loudly, the same
|
|
408
|
+
* treatment `readdir(directory)` above already gives a missing
|
|
409
|
+
* admissions directory.
|
|
410
|
+
* - The directory is present and writable but the ledger file itself is
|
|
411
|
+
* absent: Spawnfile's entrypoint provisions and chows the directory as a
|
|
412
|
+
* persistent volume before the first turn ever writes usage
|
|
413
|
+
* (`renderDaimonUsageLedgerProvisioning`), so a brand-new organization
|
|
414
|
+
* legitimately has zero recorded spend. That is a true zero, not an
|
|
415
|
+
* unknown one — but only once this durably creates the (empty) ledger
|
|
416
|
+
* itself and verifies the result is readable, rather than assuming a
|
|
417
|
+
* missing file means zero.
|
|
418
|
+
* - The ledger file exists and is readable: arm normally; `sumTokens` sums
|
|
419
|
+
* whatever is in it.
|
|
420
|
+
* - The ledger file exists but is unreadable (EACCES, EISDIR, ...): fails
|
|
421
|
+
* loudly, exactly as before.
|
|
422
|
+
*/
|
|
423
|
+
async function ensureUsageLedgerUsable(ledgerPath) {
|
|
424
|
+
try {
|
|
425
|
+
await readFile(ledgerPath, "utf8");
|
|
426
|
+
return;
|
|
427
|
+
}
|
|
428
|
+
catch (error) {
|
|
429
|
+
const code = error.code;
|
|
430
|
+
if (code !== "ENOENT") {
|
|
431
|
+
throw new Error(`DAIMON_WAKE_FUSE cannot start: usage ledger at ${ledgerPath} is missing or unreadable (${code ?? String(error)}); refusing to admit wakes against an unenforceable token ceiling`);
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
// Ledger file absent. Create it empty, matching the mode the broker itself
|
|
435
|
+
// writes usage records with, so a fresh organization can start.
|
|
436
|
+
try {
|
|
437
|
+
const handle = await open(ledgerPath, constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL | constants.O_NOFOLLOW, TURN_USAGE_LEDGER.fileMode);
|
|
438
|
+
await handle.close();
|
|
439
|
+
}
|
|
440
|
+
catch (error) {
|
|
441
|
+
const code = error.code;
|
|
442
|
+
// EEXIST means a concurrent writer created it first (e.g. a racing turn
|
|
443
|
+
// append); that is not a creation failure, so fall through to verify.
|
|
444
|
+
if (code !== "EEXIST") {
|
|
445
|
+
throw new Error(`DAIMON_WAKE_FUSE cannot start: usage ledger at ${ledgerPath} is missing and could not be created (${code ?? String(error)}); refusing to admit wakes against an unenforceable token ceiling`);
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
// Never assume the create succeeded: read the file back before treating
|
|
449
|
+
// the ceiling as enforceable.
|
|
450
|
+
try {
|
|
451
|
+
await readFile(ledgerPath, "utf8");
|
|
452
|
+
}
|
|
453
|
+
catch (error) {
|
|
454
|
+
const code = error.code ?? String(error);
|
|
455
|
+
throw new Error(`DAIMON_WAKE_FUSE cannot start: usage ledger at ${ledgerPath} is missing or unreadable (${code}); refusing to admit wakes against an unenforceable token ceiling`);
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
async function exists(file) { try {
|
|
459
|
+
await stat(file);
|
|
460
|
+
return true;
|
|
461
|
+
}
|
|
462
|
+
catch (error) {
|
|
463
|
+
if (error.code === "ENOENT")
|
|
464
|
+
return false;
|
|
465
|
+
throw error;
|
|
466
|
+
} }
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { type FileHandle } from "node:fs/promises";
|
|
2
|
+
import { WakeMomentIo } from "./wakeMomentIo.js";
|
|
3
|
+
export { WakeMomentFault } from "./wakeMomentIo.js";
|
|
4
|
+
/** Diagnostics never include source paths, file contents, or arbitrary exception text. */
|
|
5
|
+
export declare function wakeMomentFailure(error: unknown): string;
|
|
6
|
+
export type MomentStore = {
|
|
7
|
+
verify(io: WakeMomentIo, target?: string): Promise<void>;
|
|
8
|
+
close(): Promise<void>;
|
|
9
|
+
};
|
|
10
|
+
/** Pin the caller's root, then re-check the same dev/ino/uid/mode at every write boundary. */
|
|
11
|
+
export declare function pinMomentStore(directory: string, io: WakeMomentIo, verifyPrepared?: () => Promise<void>): Promise<MomentStore>;
|
|
12
|
+
export declare function openMomentDirectory(directory: string, io?: WakeMomentIo): Promise<FileHandle>;
|
|
13
|
+
export declare function ensureMomentDirectory(directory: string, io?: WakeMomentIo): Promise<void>;
|
|
14
|
+
export declare function syncMomentDirectory(directory: string, io?: WakeMomentIo): Promise<void>;
|
|
15
|
+
/** Refuses symlinks, special files and hard-linked metadata, including a FIFO before it can block. */
|
|
16
|
+
export declare function openMomentFile(file: string, flags?: number, io?: WakeMomentIo): Promise<FileHandle>;
|
|
17
|
+
export declare function manifestBytes(value: unknown, max?: number): string;
|
|
18
|
+
export declare function readMomentJson(file: string, io?: WakeMomentIo, max?: number): Promise<unknown>;
|
|
19
|
+
/** Unlike FileHandle.writeFile, each syscall is admitted through the cancellation fence. */
|
|
20
|
+
export declare function writeMomentBytes(fd: FileHandle, bytes: string | Buffer): Promise<void>;
|
|
21
|
+
export declare function writeMomentJson(file: string, bytes: string, io: WakeMomentIo, cleanup: Set<string>, verifyReplacement?: () => Promise<void>): Promise<void>;
|
|
22
|
+
export declare function momentPathExists(target: string, io?: WakeMomentIo): Promise<boolean>;
|
|
23
|
+
/** Never recurse until root identity AND the target's parent components have just been verified. */
|
|
24
|
+
export declare function cleanMomentPaths(paths: Set<string>, store: MomentStore, io: WakeMomentIo): Promise<void>;
|
|
25
|
+
/** Explicit traversal keeps recursive cleanup cancellable between individual filesystem calls. */
|
|
26
|
+
export declare function removeMomentPath(target: string, store: MomentStore, io: WakeMomentIo): Promise<void>;
|
|
27
|
+
//# sourceMappingURL=wakeMomentFs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wakeMomentFs.d.ts","sourceRoot":"","sources":["../../src/runtime/wakeMomentFs.ts"],"names":[],"mappings":"AACA,OAAO,EAAQ,KAAK,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAKzD,OAAO,EAAmB,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAClE,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEpD,0FAA0F;AAC1F,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAIxD;AAED,MAAM,MAAM,WAAW,GAAG;IAAE,MAAM,CAAC,EAAE,EAAE,YAAY,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAAC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CAAE,CAAC;AAE/G,8FAA8F;AAC9F,wBAAsB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE,EAAE,YAAY,EAAE,cAAc,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,WAAW,CAAC,CA0BpI;AAMD,wBAAsB,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE,eAAqB,GAAG,OAAO,CAAC,UAAU,CAAC,CAKzG;AAED,wBAAsB,qBAAqB,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE,eAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CAOrG;AAED,wBAAsB,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE,eAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CAGnG;AAED,sGAAsG;AACtG,wBAAsB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,SAAqB,EAAE,EAAE,eAAqB,GAAG,OAAO,CAAC,UAAU,CAAC,CAO3H;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,GAAoC,MAAM,GAAG,MAAM,CAInG;AAED,wBAAsB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,eAAqB,EAAE,GAAG,GAAoC,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAiB3I;AAED,4FAA4F;AAC5F,wBAAsB,gBAAgB,CAAC,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAO5F;AAED,wBAAsB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,YAAY,EAAE,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,EAAE,iBAAiB,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAoBjK;AAED,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,eAAqB,GAAG,OAAO,CAAC,OAAO,CAAC,CAGhG;AAED,oGAAoG;AACpG,wBAAsB,gBAAgB,CAAC,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,EAAE,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAK9G;AAED,kGAAkG;AAClG,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,EAAE,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAc1G"}
|