@noopolis/daimon 0.1.1 → 0.2.0
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 +307 -45
- package/dist/contracts/attentionContract.d.ts +117 -0
- package/dist/contracts/attentionContract.d.ts.map +1 -0
- package/dist/contracts/attentionContract.js +14 -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/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 +765 -0
- package/dist/contracts/organizationRuntimeContract.d.ts.map +1 -0
- package/dist/contracts/organizationRuntimeContract.js +121 -0
- package/dist/contracts/runtimeContractManifest.d.ts +1615 -0
- package/dist/contracts/runtimeContractManifest.d.ts.map +1 -0
- package/dist/contracts/runtimeContractManifest.js +181 -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/siblingBuildFreshness.d.ts +21 -0
- package/dist/core/siblingBuildFreshness.d.ts.map +1 -0
- package/dist/core/siblingBuildFreshness.js +25 -0
- package/dist/core/types.d.ts +10 -1
- package/dist/core/types.d.ts.map +1 -1
- package/dist/examples/exampleCausalId.d.ts +3 -0
- package/dist/examples/exampleCausalId.d.ts.map +1 -0
- package/dist/examples/exampleCausalId.js +8 -0
- package/dist/examples/jungian-play-org.js +3 -2
- package/dist/examples/jungian-triad-org.js +3 -2
- package/dist/examples/jungianPlayAgent.d.ts +1 -1
- package/dist/examples/jungianPlayAgent.d.ts.map +1 -1
- package/dist/examples/jungianPlayAgent.js +1 -1
- package/dist/examples/jungianProfiles.d.ts +1 -1
- package/dist/examples/jungianProfiles.d.ts.map +1 -1
- package/dist/examples/jungianTriadProfiles.d.ts +1 -1
- package/dist/examples/jungianTriadProfiles.d.ts.map +1 -1
- package/dist/examples/pi-agent.js +3 -2
- package/dist/examples/pi-memory-org.js +6 -5
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/mcp/toolServer.d.ts +31 -0
- package/dist/mcp/toolServer.d.ts.map +1 -0
- package/dist/mcp/toolServer.js +145 -0
- package/dist/observability/causalEvents.d.ts +118 -0
- package/dist/observability/causalEvents.d.ts.map +1 -0
- package/dist/observability/causalEvents.js +223 -0
- package/dist/observability/controlCausal.d.ts +117 -0
- package/dist/observability/controlCausal.d.ts.map +1 -0
- package/dist/observability/controlCausal.js +107 -0
- package/dist/observability/emitCausalFixture.d.ts +25 -0
- package/dist/observability/emitCausalFixture.d.ts.map +1 -0
- package/dist/observability/emitCausalFixture.js +98 -0
- package/dist/observability/index.d.ts +2 -0
- package/dist/observability/index.d.ts.map +1 -1
- package/dist/observability/index.js +2 -0
- 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 +164 -0
- package/dist/pi/cliEnvironment.d.ts +12 -0
- package/dist/pi/cliEnvironment.d.ts.map +1 -0
- package/dist/pi/cliEnvironment.js +32 -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 +106 -0
- package/dist/pi/cliSession.d.ts.map +1 -0
- package/dist/pi/cliSession.js +379 -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/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 +57 -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/index.d.ts +5 -0
- package/dist/pi/index.d.ts.map +1 -1
- package/dist/pi/index.js +5 -0
- package/dist/pi/memoryTools.d.ts +55 -1
- package/dist/pi/memoryTools.d.ts.map +1 -1
- package/dist/pi/memoryTools.js +144 -24
- package/dist/pi/modelRegistry.d.ts +13 -0
- package/dist/pi/modelRegistry.d.ts.map +1 -0
- package/dist/pi/modelRegistry.js +19 -0
- package/dist/pi/piAgentHandle.d.ts +46 -0
- package/dist/pi/piAgentHandle.d.ts.map +1 -0
- package/dist/pi/piAgentHandle.js +351 -0
- package/dist/pi/piAgentWakeSupport.d.ts +103 -0
- package/dist/pi/piAgentWakeSupport.d.ts.map +1 -0
- package/dist/pi/piAgentWakeSupport.js +151 -0
- package/dist/pi/piHarness.d.ts +40 -5
- package/dist/pi/piHarness.d.ts.map +1 -1
- package/dist/pi/piHarness.js +151 -256
- package/dist/pi/prompts.d.ts +10 -0
- package/dist/pi/prompts.d.ts.map +1 -0
- package/dist/pi/prompts.js +63 -0
- package/dist/pi/rawTrainingCapture.d.ts +59 -0
- package/dist/pi/rawTrainingCapture.d.ts.map +1 -0
- package/dist/pi/rawTrainingCapture.js +175 -0
- package/dist/pi/turnCausal.d.ts +73 -0
- package/dist/pi/turnCausal.d.ts.map +1 -0
- package/dist/pi/turnCausal.js +75 -0
- package/dist/pi/turnTrace.d.ts +128 -0
- package/dist/pi/turnTrace.d.ts.map +1 -0
- package/dist/pi/turnTrace.js +138 -0
- package/dist/pi/wakeAcceptance.d.ts +49 -0
- package/dist/pi/wakeAcceptance.d.ts.map +1 -0
- package/dist/pi/wakeAcceptance.js +281 -0
- package/dist/pi/wakeAcceptanceFs.d.ts +44 -0
- package/dist/pi/wakeAcceptanceFs.d.ts.map +1 -0
- package/dist/pi/wakeAcceptanceFs.js +318 -0
- package/dist/pi/wakeAcceptanceSchema.d.ts +75 -0
- package/dist/pi/wakeAcceptanceSchema.d.ts.map +1 -0
- package/dist/pi/wakeAcceptanceSchema.js +265 -0
- package/dist/pi/wakeModes.d.ts +9 -0
- package/dist/pi/wakeModes.d.ts.map +1 -0
- package/dist/pi/wakeModes.js +19 -0
- package/dist/pi/worldNudge.d.ts +22 -0
- package/dist/pi/worldNudge.d.ts.map +1 -0
- package/dist/pi/worldNudge.js +62 -0
- package/dist/pi/worldToolProtocol.d.ts +13 -0
- package/dist/pi/worldToolProtocol.d.ts.map +1 -0
- package/dist/pi/worldToolProtocol.js +49 -0
- package/dist/pi/worldTools.d.ts +32 -0
- package/dist/pi/worldTools.d.ts.map +1 -0
- package/dist/pi/worldTools.js +373 -0
- package/dist/pi/worldTrajectory.d.ts +52 -0
- package/dist/pi/worldTrajectory.d.ts.map +1 -0
- package/dist/pi/worldTrajectory.js +131 -0
- 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 +21 -0
- package/dist/runtime/attention.d.ts.map +1 -0
- package/dist/runtime/attention.js +36 -0
- package/dist/runtime/attentionDispatcher.d.ts +66 -0
- package/dist/runtime/attentionDispatcher.d.ts.map +1 -0
- package/dist/runtime/attentionDispatcher.js +271 -0
- package/dist/runtime/cli.d.ts +7 -0
- package/dist/runtime/cli.d.ts.map +1 -0
- package/dist/runtime/cli.js +251 -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 +30 -0
- package/dist/runtime/engineBrokerCapabilities.d.ts.map +1 -0
- package/dist/runtime/engineBrokerCapabilities.js +59 -0
- package/dist/runtime/engineBrokerControlClient.d.ts +44 -0
- package/dist/runtime/engineBrokerControlClient.d.ts.map +1 -0
- package/dist/runtime/engineBrokerControlClient.js +132 -0
- package/dist/runtime/engineBrokerCredentialJournal.d.ts +10 -0
- package/dist/runtime/engineBrokerCredentialJournal.d.ts.map +1 -0
- package/dist/runtime/engineBrokerCredentialJournal.js +17 -0
- package/dist/runtime/engineBrokerInferenceProtocol.d.ts +52 -0
- package/dist/runtime/engineBrokerInferenceProtocol.d.ts.map +1 -0
- package/dist/runtime/engineBrokerInferenceProtocol.js +65 -0
- package/dist/runtime/engineBrokerMcpCallLog.d.ts +160 -0
- package/dist/runtime/engineBrokerMcpCallLog.d.ts.map +1 -0
- package/dist/runtime/engineBrokerMcpCallLog.js +219 -0
- package/dist/runtime/engineBrokerMcpFacade.d.ts +56 -0
- package/dist/runtime/engineBrokerMcpFacade.d.ts.map +1 -0
- package/dist/runtime/engineBrokerMcpFacade.js +343 -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 +135 -0
- package/dist/runtime/engineBrokerProtocol.d.ts.map +1 -0
- package/dist/runtime/engineBrokerProtocol.js +274 -0
- package/dist/runtime/engineBrokerSealLedger.d.ts +70 -0
- package/dist/runtime/engineBrokerSealLedger.d.ts.map +1 -0
- package/dist/runtime/engineBrokerSealLedger.js +123 -0
- package/dist/runtime/engineBrokerService.d.ts +37 -0
- package/dist/runtime/engineBrokerService.d.ts.map +1 -0
- package/dist/runtime/engineBrokerService.js +138 -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 +50 -0
- package/dist/runtime/engineBrokerServiceConfig.d.ts.map +1 -0
- package/dist/runtime/engineBrokerServiceConfig.js +92 -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 +158 -0
- package/dist/runtime/engineDispatcher.d.ts +36 -0
- package/dist/runtime/engineDispatcher.d.ts.map +1 -0
- package/dist/runtime/engineDispatcher.js +216 -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 +22 -0
- package/dist/runtime/grokBrokerCredentialAuthority.d.ts.map +1 -0
- package/dist/runtime/grokBrokerCredentialAuthority.js +124 -0
- package/dist/runtime/grokBrokerCredentialReader.d.ts +5 -0
- package/dist/runtime/grokBrokerCredentialReader.d.ts.map +1 -0
- package/dist/runtime/grokBrokerCredentialReader.js +37 -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 +106 -0
- package/dist/runtime/grokBrokerProjection.d.ts.map +1 -0
- package/dist/runtime/grokBrokerProjection.js +94 -0
- package/dist/runtime/grokBrokerProxy.d.ts +55 -0
- package/dist/runtime/grokBrokerProxy.d.ts.map +1 -0
- package/dist/runtime/grokBrokerProxy.js +262 -0
- package/dist/runtime/grokBrokerProxyRequest.d.ts +30 -0
- package/dist/runtime/grokBrokerProxyRequest.d.ts.map +1 -0
- package/dist/runtime/grokBrokerProxyRequest.js +74 -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/grokBrokerTurnMeter.d.ts +128 -0
- package/dist/runtime/grokBrokerTurnMeter.d.ts.map +1 -0
- package/dist/runtime/grokBrokerTurnMeter.js +251 -0
- package/dist/runtime/grokBrokerWorkerConfig.d.ts +86 -0
- package/dist/runtime/grokBrokerWorkerConfig.d.ts.map +1 -0
- package/dist/runtime/grokBrokerWorkerConfig.js +135 -0
- package/dist/runtime/grokEngineBroker.d.ts +48 -0
- package/dist/runtime/grokEngineBroker.d.ts.map +1 -0
- package/dist/runtime/grokEngineBroker.js +114 -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 +58 -0
- package/dist/runtime/grokEngineBrokerTurn.d.ts.map +1 -0
- package/dist/runtime/grokEngineBrokerTurn.js +165 -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 +82 -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 +170 -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 +30 -0
- package/dist/runtime/grokWorkerHomeAttestation.d.ts.map +1 -0
- package/dist/runtime/grokWorkerHomeAttestation.js +69 -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 +26 -0
- package/dist/runtime/index.d.ts.map +1 -0
- package/dist/runtime/index.js +23 -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 +165 -0
- package/dist/runtime/organizationRuntime.d.ts.map +1 -0
- package/dist/runtime/organizationRuntime.js +3 -0
- package/dist/runtime/organizationRuntimeControl.d.ts +42 -0
- package/dist/runtime/organizationRuntimeControl.d.ts.map +1 -0
- package/dist/runtime/organizationRuntimeControl.js +235 -0
- package/dist/runtime/organizationRuntimeHost.d.ts +19 -0
- package/dist/runtime/organizationRuntimeHost.d.ts.map +1 -0
- package/dist/runtime/organizationRuntimeHost.js +359 -0
- package/dist/runtime/organizationRuntimeParsing.d.ts +6 -0
- package/dist/runtime/organizationRuntimeParsing.d.ts.map +1 -0
- package/dist/runtime/organizationRuntimeParsing.js +370 -0
- package/dist/runtime/organizationRuntimeReadiness.d.ts +12 -0
- package/dist/runtime/organizationRuntimeReadiness.d.ts.map +1 -0
- package/dist/runtime/organizationRuntimeReadiness.js +59 -0
- package/dist/runtime/physicalReadiness.d.ts +47 -0
- package/dist/runtime/physicalReadiness.d.ts.map +1 -0
- package/dist/runtime/physicalReadiness.js +142 -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 +328 -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 +371 -0
- package/dist/runtime/storeCoordination.d.ts +23 -0
- package/dist/runtime/storeCoordination.d.ts.map +1 -0
- package/dist/runtime/storeCoordination.js +94 -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 +160 -0
- package/dist/runtime/turnRequestLedger.d.ts.map +1 -0
- package/dist/runtime/turnRequestLedger.js +249 -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/wakeAcceptanceProcessIdentity.d.ts +17 -0
- package/dist/runtime/wakeAcceptanceProcessIdentity.d.ts.map +1 -0
- package/dist/runtime/wakeAcceptanceProcessIdentity.js +50 -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 +23 -0
- package/dist/runtime/wakeAcceptanceRecord.d.ts.map +1 -0
- package/dist/runtime/wakeAcceptanceRecord.js +56 -0
- package/dist/runtime/wakeAcceptanceRetention.d.ts +12 -0
- package/dist/runtime/wakeAcceptanceRetention.d.ts.map +1 -0
- package/dist/runtime/wakeAcceptanceRetention.js +12 -0
- package/dist/runtime/wakeAcceptanceStore.d.ts +113 -0
- package/dist/runtime/wakeAcceptanceStore.d.ts.map +1 -0
- package/dist/runtime/wakeAcceptanceStore.js +558 -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 +69 -0
- package/dist/runtime/wakeFuse.d.ts.map +1 -0
- package/dist/runtime/wakeFuse.js +367 -0
- package/package.json +25 -17
- package/dist/examples/mixed-engine-org.d.ts +0 -2
- package/dist/examples/mixed-engine-org.d.ts.map +0 -1
- package/dist/examples/mixed-engine-org.js +0 -351
- package/dist/examples/mixedEngineCli.d.ts +0 -15
- package/dist/examples/mixedEngineCli.d.ts.map +0 -1
- package/dist/examples/mixedEngineCli.js +0 -174
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { type McpUpstreamResult, type RenderedMcpToolResult } from "./mcpToolResult.js";
|
|
2
|
+
/**
|
|
3
|
+
* Cap one declared MCP tool result, and spill the rest of it to disk.
|
|
4
|
+
*
|
|
5
|
+
* ## Why
|
|
6
|
+
*
|
|
7
|
+
* Production agents make 3–37 tool calls per wake, and every tool result stays
|
|
8
|
+
* in the transcript for every *subsequent* model request of that wake. Context
|
|
9
|
+
* per request is flat at 23–32k tokens, so one oversized result is not paid
|
|
10
|
+
* once — it is paid again on every request that follows it, at cache-read rates
|
|
11
|
+
* for the ones that hit and at fresh rates for the one that does not. A 40 KiB
|
|
12
|
+
* result returned on call three of thirty is re-billed twenty-seven times.
|
|
13
|
+
*
|
|
14
|
+
* Before this, Daimon applied no cap of its own to a declared MCP tool's answer.
|
|
15
|
+
* `mcpToolResult.ts` bounded it at 61,440 bytes — the receipt bound, not a
|
|
16
|
+
* context bound — and above that degraded it to a *head only*, with no way to
|
|
17
|
+
* recover the rest.
|
|
18
|
+
*
|
|
19
|
+
* ## The reference pattern
|
|
20
|
+
*
|
|
21
|
+
* `references/oh-my-pi` wraps **every** tool, MCP included, with the same
|
|
22
|
+
* centralized spill (`packages/coding-agent/src/tools/output-meta.ts:724-891`,
|
|
23
|
+
* mounted in `sdk.ts:2862-2869`):
|
|
24
|
+
*
|
|
25
|
+
* - a byte threshold (`tools.artifactSpillThreshold`, default 50 KiB);
|
|
26
|
+
* - **head + tail retention** with the middle elided, so the model keeps both
|
|
27
|
+
* ends of the output (`truncateMiddle`,
|
|
28
|
+
* `packages/coding-agent/src/session/streaming-output.ts`), defaults
|
|
29
|
+
* 20 KiB head + 20 KiB tail — an even split at 80% of the threshold;
|
|
30
|
+
* - the **full output written to disk** and addressed by an id
|
|
31
|
+
* (`session/artifacts.ts`);
|
|
32
|
+
* - a notice naming the ranges shown and the re-fetch address:
|
|
33
|
+
* `Showing lines X-Y of Z … Read artifact://ID for full output`
|
|
34
|
+
* (`formatTruncationMetaNotice`, `formatFullOutputReference`);
|
|
35
|
+
* - and the rule that a **failed save still truncates** — the recovery link is
|
|
36
|
+
* attached only when the write actually succeeded, because re-exposing the
|
|
37
|
+
* full output on a disk error is the one outcome worse than truncating.
|
|
38
|
+
*
|
|
39
|
+
* All five are reproduced here. What differs is only the address: oh-my-pi's
|
|
40
|
+
* `artifact://<id>` is resolved by its own `read` tool, and Daimon has no such
|
|
41
|
+
* protocol — so the notice names the **absolute path**, which every Daimon agent
|
|
42
|
+
* can already read with the mounted `bash` tool (`piHarness.ts`) or the engine's
|
|
43
|
+
* own shell. The file lives under the agent's own runtime home, which is exactly
|
|
44
|
+
* the tree that home is for and the one tree every sandbox profile leaves the
|
|
45
|
+
* agent (`grokSandboxProtectedPaths` denies *peers'* homes, never its own).
|
|
46
|
+
*/
|
|
47
|
+
/**
|
|
48
|
+
* The cap on one lowered MCP tool result, measured the way
|
|
49
|
+
* `mcpToolResult.ts` measures: the serialized `{content, structuredContent}`
|
|
50
|
+
* record, both channels included.
|
|
51
|
+
*
|
|
52
|
+
* **16 KiB, ≈4k tokens.** oh-my-pi's 50 KiB default is calibrated for an
|
|
53
|
+
* interactive coding agent with a 200k+ context; Daimon's whole per-request
|
|
54
|
+
* context is 23–32k tokens, so a 50 KiB result would be *half of it* and would
|
|
55
|
+
* be replayed on every remaining request of the wake. 16 KiB keeps any single
|
|
56
|
+
* result under roughly a sixth of a request while leaving a realistic answer
|
|
57
|
+
* — a page of messages, a document, a query result — entirely untouched: it is
|
|
58
|
+
* a ceiling on the pathological case, not a working budget.
|
|
59
|
+
*/
|
|
60
|
+
export declare const DEFAULT_TOOL_RESULT_MAX_BYTES: number;
|
|
61
|
+
export declare const TOOL_RESULT_MAX_BYTES_ENV: "DAIMON_TOOL_RESULT_MAX_BYTES";
|
|
62
|
+
/**
|
|
63
|
+
* Tools that must never be truncated, by mounted tool name
|
|
64
|
+
* (`mcp_<server>_<tool>`), comma-separated.
|
|
65
|
+
*
|
|
66
|
+
* Empty by default. It exists because Daimon cannot know what an organization
|
|
67
|
+
* declared: if a deployment has one MCP tool whose *whole* answer is load
|
|
68
|
+
* bearing — a signature, a checksummed document, a payload the agent must
|
|
69
|
+
* reproduce verbatim — head+tail is not a degradation there, it is a wrong
|
|
70
|
+
* answer, and no re-fetch instruction fixes a model that did not notice. That
|
|
71
|
+
* judgement belongs to whoever declared the tool, so it is configuration rather
|
|
72
|
+
* than a Daimon-side guess. An exempt tool keeps exactly today's behaviour,
|
|
73
|
+
* including `mcpToolResult.ts`'s 61,440-byte receipt bound.
|
|
74
|
+
*/
|
|
75
|
+
export declare const TOOL_RESULT_EXEMPT_ENV: "DAIMON_TOOL_RESULT_NO_TRUNCATE";
|
|
76
|
+
/**
|
|
77
|
+
* A result may never be capped below this. Below roughly a kilobyte the head and
|
|
78
|
+
* tail stop being usable at all and the notice dominates the payload, so a
|
|
79
|
+
* mistyped bound degrades into "every tool is blind" — worse than no cap.
|
|
80
|
+
*/
|
|
81
|
+
export declare const MIN_TOOL_RESULT_MAX_BYTES = 2048;
|
|
82
|
+
/** Spilled files live here, under the agent's own runtime home. */
|
|
83
|
+
export declare const TOOL_OUTPUT_DIRECTORY_NAME: "tool-output";
|
|
84
|
+
/** Newest-first retention for spilled files, mirroring `pruneReceipts`. */
|
|
85
|
+
export declare const TOOL_OUTPUT_RETAINED_FILES = 256;
|
|
86
|
+
export declare const resolveToolResultMaxBytes: (environment?: NodeJS.ProcessEnv) => number;
|
|
87
|
+
export declare const resolveExemptToolNames: (environment?: NodeJS.ProcessEnv) => ReadonlySet<string>;
|
|
88
|
+
/** Cut on a code-point boundary, from the front. */
|
|
89
|
+
/** Exported for the bounded diagnostic window (`cliChildOutput.ts`): one boundary-safe implementation, not two. */
|
|
90
|
+
export declare const headUtf8: (value: string, maxBytes: number) => string;
|
|
91
|
+
/** Cut on a code-point boundary, from the back. */
|
|
92
|
+
/** Exported for the bounded diagnostic window (`cliChildOutput.ts`): one boundary-safe implementation, not two. */
|
|
93
|
+
export declare const tailUtf8: (value: string, maxBytes: number) => string;
|
|
94
|
+
/**
|
|
95
|
+
* The complete payload, as the text that gets written to disk and sliced.
|
|
96
|
+
*
|
|
97
|
+
* A result that is nothing but text parts is spilled as that text, because a
|
|
98
|
+
* human-readable log is what the agent will `grep` and `sed`. Anything else — a
|
|
99
|
+
* structured result, an image part, a mixed result — is spilled as the
|
|
100
|
+
* serialized upstream record, which is lossless and is the same serialization
|
|
101
|
+
* `mcpToolResult.ts` already degrades to today.
|
|
102
|
+
*/
|
|
103
|
+
export declare const spillPayload: (result: McpUpstreamResult) => {
|
|
104
|
+
text: string;
|
|
105
|
+
format: "text" | "json";
|
|
106
|
+
};
|
|
107
|
+
/**
|
|
108
|
+
* Spilled files are group-readable and never other-readable.
|
|
109
|
+
*
|
|
110
|
+
* A brokered Grok worker runs as its own uid and reads a spill with
|
|
111
|
+
* `read_file`, so a 0600 file owned by the runtime (uid 2000) was unreadable to
|
|
112
|
+
* the very agent the notice sends there. The group grant reaches exactly that
|
|
113
|
+
* agent's worker only when the deployment provisions `tool-output` as
|
|
114
|
+
* `<runtime uid>:<worker gid> 2750` (setgid, so each file inherits the worker
|
|
115
|
+
* group; `GROK_ENGINE_BROKER.worker.home.spillDirectory`). A directory Daimon
|
|
116
|
+
* creates itself stays 0700, so for every other engine nothing new is exposed.
|
|
117
|
+
*/
|
|
118
|
+
export declare const SPILL_FILE_MODE = 416;
|
|
119
|
+
export declare const SPILL_DIRECTORY_MAX_MODE = 1512;
|
|
120
|
+
/** Pure so a foreign owner is testable without root. */
|
|
121
|
+
export declare const assertSpillDirectoryStat: (entry: Readonly<{
|
|
122
|
+
uid: number;
|
|
123
|
+
gid: number;
|
|
124
|
+
mode: number;
|
|
125
|
+
isDirectory(): boolean;
|
|
126
|
+
}>, runtime: Readonly<{
|
|
127
|
+
uid: number;
|
|
128
|
+
gid: number;
|
|
129
|
+
}>) => void;
|
|
130
|
+
export type CappedToolResult = RenderedMcpToolResult & {
|
|
131
|
+
/** Absolute path of the spilled full result, when one was written. */
|
|
132
|
+
readonly spillPath?: string;
|
|
133
|
+
};
|
|
134
|
+
/**
|
|
135
|
+
* Return `rendered` untouched when it fits, or a head+tail view of the full
|
|
136
|
+
* payload plus a notice naming the file that holds the rest.
|
|
137
|
+
*
|
|
138
|
+
* A result under the cap passes through **byte-identical**: the `mcp_*`
|
|
139
|
+
* passthrough contract — both channels carrying the payload, an upstream
|
|
140
|
+
* `structuredContent` forwarded verbatim — is unchanged for every result that
|
|
141
|
+
* does not blow the bound, which is the overwhelming majority of them.
|
|
142
|
+
*/
|
|
143
|
+
export declare const capToolResult: (input: Readonly<{
|
|
144
|
+
toolName: string;
|
|
145
|
+
rendered: RenderedMcpToolResult;
|
|
146
|
+
result: McpUpstreamResult;
|
|
147
|
+
maxBytes: number;
|
|
148
|
+
exempt: ReadonlySet<string>;
|
|
149
|
+
spillDirectory: string;
|
|
150
|
+
spillId: string;
|
|
151
|
+
}>) => Promise<CappedToolResult>;
|
|
152
|
+
//# sourceMappingURL=toolResultSpill.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toolResultSpill.d.ts","sourceRoot":"","sources":["../../src/runtime/toolResultSpill.ts"],"names":[],"mappings":"AAIA,OAAO,EAAkB,KAAK,iBAAiB,EAAE,KAAK,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAExG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AAEH;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,6BAA6B,QAAY,CAAC;AAEvD,eAAO,MAAM,yBAAyB,EAAG,8BAAuC,CAAC;AAEjF;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,sBAAsB,EAAG,gCAAyC,CAAC;AAEhF;;;;GAIG;AACH,eAAO,MAAM,yBAAyB,OAAQ,CAAC;AAE/C,mEAAmE;AACnE,eAAO,MAAM,0BAA0B,EAAG,aAAsB,CAAC;AAEjE,2EAA2E;AAC3E,eAAO,MAAM,0BAA0B,MAAM,CAAC;AAE9C,eAAO,MAAM,yBAAyB,GAAI,cAAa,MAAM,CAAC,UAAwB,KAAG,MAQxF,CAAC;AAEF,eAAO,MAAM,sBAAsB,GAAI,cAAa,MAAM,CAAC,UAAwB,KAAG,WAAW,CAAC,MAAM,CACsB,CAAC;AAS/H,oDAAoD;AACpD,mHAAmH;AACnH,eAAO,MAAM,QAAQ,GAAI,OAAO,MAAM,EAAE,UAAU,MAAM,KAAG,MAM1D,CAAC;AAEF,mDAAmD;AACnD,mHAAmH;AACnH,eAAO,MAAM,QAAQ,GAAI,OAAO,MAAM,EAAE,UAAU,MAAM,KAAG,MAM1D,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,YAAY,GAAI,QAAQ,iBAAiB,KAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAA;CAc/F,CAAC;AAyBF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,eAAe,MAAQ,CAAC;AACrC,eAAO,MAAM,wBAAwB,OAAS,CAAC;AA0D/C,wDAAwD;AACxD,eAAO,MAAM,wBAAwB,GAAI,OAAO,QAAQ,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,WAAW,IAAI,OAAO,CAAA;CAAE,CAAC,EAAE,SAAS,QAAQ,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC,KAAG,IAO/K,CAAC;AAoBF,MAAM,MAAM,gBAAgB,GAAG,qBAAqB,GAAG;IACrD,sEAAsE;IACtE,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,aAAa,GAAU,OAAO,QAAQ,CAAC;IAClD,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,qBAAqB,CAAC;IAChC,MAAM,EAAE,iBAAiB,CAAC;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC5B,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC,KAAG,OAAO,CAAC,gBAAgB,CA6D5B,CAAC"}
|
|
@@ -0,0 +1,351 @@
|
|
|
1
|
+
import { constants } from "node:fs";
|
|
2
|
+
import { lstat, mkdir, open, readdir, rename, unlink } from "node:fs/promises";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { mcpContentText } from "./mcpToolResult.js";
|
|
5
|
+
/**
|
|
6
|
+
* Cap one declared MCP tool result, and spill the rest of it to disk.
|
|
7
|
+
*
|
|
8
|
+
* ## Why
|
|
9
|
+
*
|
|
10
|
+
* Production agents make 3–37 tool calls per wake, and every tool result stays
|
|
11
|
+
* in the transcript for every *subsequent* model request of that wake. Context
|
|
12
|
+
* per request is flat at 23–32k tokens, so one oversized result is not paid
|
|
13
|
+
* once — it is paid again on every request that follows it, at cache-read rates
|
|
14
|
+
* for the ones that hit and at fresh rates for the one that does not. A 40 KiB
|
|
15
|
+
* result returned on call three of thirty is re-billed twenty-seven times.
|
|
16
|
+
*
|
|
17
|
+
* Before this, Daimon applied no cap of its own to a declared MCP tool's answer.
|
|
18
|
+
* `mcpToolResult.ts` bounded it at 61,440 bytes — the receipt bound, not a
|
|
19
|
+
* context bound — and above that degraded it to a *head only*, with no way to
|
|
20
|
+
* recover the rest.
|
|
21
|
+
*
|
|
22
|
+
* ## The reference pattern
|
|
23
|
+
*
|
|
24
|
+
* `references/oh-my-pi` wraps **every** tool, MCP included, with the same
|
|
25
|
+
* centralized spill (`packages/coding-agent/src/tools/output-meta.ts:724-891`,
|
|
26
|
+
* mounted in `sdk.ts:2862-2869`):
|
|
27
|
+
*
|
|
28
|
+
* - a byte threshold (`tools.artifactSpillThreshold`, default 50 KiB);
|
|
29
|
+
* - **head + tail retention** with the middle elided, so the model keeps both
|
|
30
|
+
* ends of the output (`truncateMiddle`,
|
|
31
|
+
* `packages/coding-agent/src/session/streaming-output.ts`), defaults
|
|
32
|
+
* 20 KiB head + 20 KiB tail — an even split at 80% of the threshold;
|
|
33
|
+
* - the **full output written to disk** and addressed by an id
|
|
34
|
+
* (`session/artifacts.ts`);
|
|
35
|
+
* - a notice naming the ranges shown and the re-fetch address:
|
|
36
|
+
* `Showing lines X-Y of Z … Read artifact://ID for full output`
|
|
37
|
+
* (`formatTruncationMetaNotice`, `formatFullOutputReference`);
|
|
38
|
+
* - and the rule that a **failed save still truncates** — the recovery link is
|
|
39
|
+
* attached only when the write actually succeeded, because re-exposing the
|
|
40
|
+
* full output on a disk error is the one outcome worse than truncating.
|
|
41
|
+
*
|
|
42
|
+
* All five are reproduced here. What differs is only the address: oh-my-pi's
|
|
43
|
+
* `artifact://<id>` is resolved by its own `read` tool, and Daimon has no such
|
|
44
|
+
* protocol — so the notice names the **absolute path**, which every Daimon agent
|
|
45
|
+
* can already read with the mounted `bash` tool (`piHarness.ts`) or the engine's
|
|
46
|
+
* own shell. The file lives under the agent's own runtime home, which is exactly
|
|
47
|
+
* the tree that home is for and the one tree every sandbox profile leaves the
|
|
48
|
+
* agent (`grokSandboxProtectedPaths` denies *peers'* homes, never its own).
|
|
49
|
+
*/
|
|
50
|
+
/**
|
|
51
|
+
* The cap on one lowered MCP tool result, measured the way
|
|
52
|
+
* `mcpToolResult.ts` measures: the serialized `{content, structuredContent}`
|
|
53
|
+
* record, both channels included.
|
|
54
|
+
*
|
|
55
|
+
* **16 KiB, ≈4k tokens.** oh-my-pi's 50 KiB default is calibrated for an
|
|
56
|
+
* interactive coding agent with a 200k+ context; Daimon's whole per-request
|
|
57
|
+
* context is 23–32k tokens, so a 50 KiB result would be *half of it* and would
|
|
58
|
+
* be replayed on every remaining request of the wake. 16 KiB keeps any single
|
|
59
|
+
* result under roughly a sixth of a request while leaving a realistic answer
|
|
60
|
+
* — a page of messages, a document, a query result — entirely untouched: it is
|
|
61
|
+
* a ceiling on the pathological case, not a working budget.
|
|
62
|
+
*/
|
|
63
|
+
export const DEFAULT_TOOL_RESULT_MAX_BYTES = 16 * 1024;
|
|
64
|
+
export const TOOL_RESULT_MAX_BYTES_ENV = "DAIMON_TOOL_RESULT_MAX_BYTES";
|
|
65
|
+
/**
|
|
66
|
+
* Tools that must never be truncated, by mounted tool name
|
|
67
|
+
* (`mcp_<server>_<tool>`), comma-separated.
|
|
68
|
+
*
|
|
69
|
+
* Empty by default. It exists because Daimon cannot know what an organization
|
|
70
|
+
* declared: if a deployment has one MCP tool whose *whole* answer is load
|
|
71
|
+
* bearing — a signature, a checksummed document, a payload the agent must
|
|
72
|
+
* reproduce verbatim — head+tail is not a degradation there, it is a wrong
|
|
73
|
+
* answer, and no re-fetch instruction fixes a model that did not notice. That
|
|
74
|
+
* judgement belongs to whoever declared the tool, so it is configuration rather
|
|
75
|
+
* than a Daimon-side guess. An exempt tool keeps exactly today's behaviour,
|
|
76
|
+
* including `mcpToolResult.ts`'s 61,440-byte receipt bound.
|
|
77
|
+
*/
|
|
78
|
+
export const TOOL_RESULT_EXEMPT_ENV = "DAIMON_TOOL_RESULT_NO_TRUNCATE";
|
|
79
|
+
/**
|
|
80
|
+
* A result may never be capped below this. Below roughly a kilobyte the head and
|
|
81
|
+
* tail stop being usable at all and the notice dominates the payload, so a
|
|
82
|
+
* mistyped bound degrades into "every tool is blind" — worse than no cap.
|
|
83
|
+
*/
|
|
84
|
+
export const MIN_TOOL_RESULT_MAX_BYTES = 2_048;
|
|
85
|
+
/** Spilled files live here, under the agent's own runtime home. */
|
|
86
|
+
export const TOOL_OUTPUT_DIRECTORY_NAME = "tool-output";
|
|
87
|
+
/** Newest-first retention for spilled files, mirroring `pruneReceipts`. */
|
|
88
|
+
export const TOOL_OUTPUT_RETAINED_FILES = 256;
|
|
89
|
+
export const resolveToolResultMaxBytes = (environment = process.env) => {
|
|
90
|
+
const raw = environment[TOOL_RESULT_MAX_BYTES_ENV]?.trim();
|
|
91
|
+
if (raw === undefined || raw.length === 0)
|
|
92
|
+
return DEFAULT_TOOL_RESULT_MAX_BYTES;
|
|
93
|
+
const parsed = Number(raw);
|
|
94
|
+
if (!Number.isSafeInteger(parsed) || parsed < MIN_TOOL_RESULT_MAX_BYTES) {
|
|
95
|
+
throw new Error(`${TOOL_RESULT_MAX_BYTES_ENV} must be an integer of at least ${MIN_TOOL_RESULT_MAX_BYTES}`);
|
|
96
|
+
}
|
|
97
|
+
return parsed;
|
|
98
|
+
};
|
|
99
|
+
export const resolveExemptToolNames = (environment = process.env) => new Set((environment[TOOL_RESULT_EXEMPT_ENV] ?? "").split(",").map((name) => name.trim()).filter((name) => name.length > 0));
|
|
100
|
+
const safeStringify = (value) => {
|
|
101
|
+
try {
|
|
102
|
+
return JSON.stringify(value) ?? "";
|
|
103
|
+
}
|
|
104
|
+
catch {
|
|
105
|
+
return "[daimon: the MCP server returned a value that is not JSON-serialisable]";
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
const measure = (content, details) => Buffer.byteLength(safeStringify({ content, structuredContent: details }), "utf8");
|
|
109
|
+
/** Cut on a code-point boundary, from the front. */
|
|
110
|
+
/** Exported for the bounded diagnostic window (`cliChildOutput.ts`): one boundary-safe implementation, not two. */
|
|
111
|
+
export const headUtf8 = (value, maxBytes) => {
|
|
112
|
+
const bytes = Buffer.from(value, "utf8");
|
|
113
|
+
if (bytes.byteLength <= maxBytes)
|
|
114
|
+
return value;
|
|
115
|
+
let end = Math.max(0, maxBytes);
|
|
116
|
+
while (end > 0 && (bytes[end] & 0xc0) === 0x80)
|
|
117
|
+
end -= 1;
|
|
118
|
+
return bytes.subarray(0, end).toString("utf8");
|
|
119
|
+
};
|
|
120
|
+
/** Cut on a code-point boundary, from the back. */
|
|
121
|
+
/** Exported for the bounded diagnostic window (`cliChildOutput.ts`): one boundary-safe implementation, not two. */
|
|
122
|
+
export const tailUtf8 = (value, maxBytes) => {
|
|
123
|
+
const bytes = Buffer.from(value, "utf8");
|
|
124
|
+
if (bytes.byteLength <= maxBytes)
|
|
125
|
+
return value;
|
|
126
|
+
let start = Math.max(0, bytes.byteLength - maxBytes);
|
|
127
|
+
while (start < bytes.byteLength && (bytes[start] & 0xc0) === 0x80)
|
|
128
|
+
start += 1;
|
|
129
|
+
return bytes.subarray(start).toString("utf8");
|
|
130
|
+
};
|
|
131
|
+
/**
|
|
132
|
+
* The complete payload, as the text that gets written to disk and sliced.
|
|
133
|
+
*
|
|
134
|
+
* A result that is nothing but text parts is spilled as that text, because a
|
|
135
|
+
* human-readable log is what the agent will `grep` and `sed`. Anything else — a
|
|
136
|
+
* structured result, an image part, a mixed result — is spilled as the
|
|
137
|
+
* serialized upstream record, which is lossless and is the same serialization
|
|
138
|
+
* `mcpToolResult.ts` already degrades to today.
|
|
139
|
+
*/
|
|
140
|
+
export const spillPayload = (result) => {
|
|
141
|
+
const content = Array.isArray(result.content) ? result.content : undefined;
|
|
142
|
+
const textOnly = content !== undefined
|
|
143
|
+
&& content.length > 0
|
|
144
|
+
&& content.every((part) => typeof part === "object" && part !== null && part.type === "text")
|
|
145
|
+
&& result.structuredContent === undefined;
|
|
146
|
+
if (textOnly)
|
|
147
|
+
return { text: mcpContentText(content), format: "text" };
|
|
148
|
+
return {
|
|
149
|
+
text: safeStringify({
|
|
150
|
+
...(result.content === undefined ? {} : { content: result.content }),
|
|
151
|
+
...(result.structuredContent === undefined ? {} : { structured_content: result.structuredContent })
|
|
152
|
+
}),
|
|
153
|
+
format: "json"
|
|
154
|
+
};
|
|
155
|
+
};
|
|
156
|
+
const notice = (input) => {
|
|
157
|
+
const elided = Math.max(0, input.totalBytes - input.headBytes - input.tailBytes);
|
|
158
|
+
const shape = input.format === "json" ? "the serialized result record" : "the result text";
|
|
159
|
+
const head = [
|
|
160
|
+
`\n\n[daimon: truncated — this tool result was ${input.totalBytes} bytes, above the ${input.boundBytes}-byte per-result bound.`,
|
|
161
|
+
`Showing the first ${input.headBytes} and last ${input.tailBytes} bytes of ${shape}; ${elided} bytes were elided from the middle.`
|
|
162
|
+
].join(" ");
|
|
163
|
+
if (input.spillPath === undefined) {
|
|
164
|
+
return `${head} The complete result could NOT be written to disk, so the elided bytes are unrecoverable.`
|
|
165
|
+
+ " Repeating this call will truncate again — narrow the call's arguments instead, or ask for the missing part specifically.]";
|
|
166
|
+
}
|
|
167
|
+
return `${head} The complete result is saved at ${input.spillPath}.`
|
|
168
|
+
+ ` Read the elided middle from that file with the shell — for example \`sed -n '1,200p' ${input.spillPath}\``
|
|
169
|
+
+ ` or \`grep -n "<pattern>" ${input.spillPath}\` — and do NOT repeat this tool call to see it: an identical call returns this same truncation.]`;
|
|
170
|
+
};
|
|
171
|
+
/**
|
|
172
|
+
* Spilled files are group-readable and never other-readable.
|
|
173
|
+
*
|
|
174
|
+
* A brokered Grok worker runs as its own uid and reads a spill with
|
|
175
|
+
* `read_file`, so a 0600 file owned by the runtime (uid 2000) was unreadable to
|
|
176
|
+
* the very agent the notice sends there. The group grant reaches exactly that
|
|
177
|
+
* agent's worker only when the deployment provisions `tool-output` as
|
|
178
|
+
* `<runtime uid>:<worker gid> 2750` (setgid, so each file inherits the worker
|
|
179
|
+
* group; `GROK_ENGINE_BROKER.worker.home.spillDirectory`). A directory Daimon
|
|
180
|
+
* creates itself stays 0700, so for every other engine nothing new is exposed.
|
|
181
|
+
*/
|
|
182
|
+
export const SPILL_FILE_MODE = 0o640;
|
|
183
|
+
export const SPILL_DIRECTORY_MAX_MODE = 0o2750;
|
|
184
|
+
/**
|
|
185
|
+
* Write the full payload where the agent can read it, atomically.
|
|
186
|
+
*
|
|
187
|
+
* Staged to a sibling and renamed, so a half-written file is never addressable:
|
|
188
|
+
* a truncation notice that points at a truncated file is worse than one that
|
|
189
|
+
* admits the save failed.
|
|
190
|
+
*/
|
|
191
|
+
const writeSpill = async (directory, name, text) => {
|
|
192
|
+
await mkdir(directory, { recursive: true, mode: 0o700 });
|
|
193
|
+
const pinned = await pinSpillDirectory(directory);
|
|
194
|
+
const file = path.join(directory, name);
|
|
195
|
+
const temporary = `${file}.${process.pid}.${Date.now()}.tmp`;
|
|
196
|
+
try {
|
|
197
|
+
const handle = await open(temporary, constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL | constants.O_NOFOLLOW, SPILL_FILE_MODE);
|
|
198
|
+
let written;
|
|
199
|
+
// Explicit, so a restrictive umask cannot strip the group read an agent's sandboxed worker needs.
|
|
200
|
+
try {
|
|
201
|
+
await handle.chmod(SPILL_FILE_MODE);
|
|
202
|
+
await handle.writeFile(text, "utf8");
|
|
203
|
+
await handle.sync();
|
|
204
|
+
written = await handle.stat();
|
|
205
|
+
}
|
|
206
|
+
finally {
|
|
207
|
+
await handle.close();
|
|
208
|
+
}
|
|
209
|
+
if (!written.isFile() || written.nlink !== 1 || written.uid !== process.getuid?.())
|
|
210
|
+
throw new Error("spill file is not a private regular file");
|
|
211
|
+
// Node has no openat: re-check that the directory entry still names the pinned inode before publishing into it.
|
|
212
|
+
await assertSameDirectory(directory, pinned);
|
|
213
|
+
// rename replaces a pre-existing destination entry (a symlink included) without following it.
|
|
214
|
+
await rename(temporary, file);
|
|
215
|
+
const published = await lstat(file);
|
|
216
|
+
if (!published.isFile() || published.dev !== written.dev || published.ino !== written.ino)
|
|
217
|
+
throw new Error("spill file was replaced");
|
|
218
|
+
return file;
|
|
219
|
+
}
|
|
220
|
+
catch (error) {
|
|
221
|
+
await unlink(temporary).catch(() => undefined);
|
|
222
|
+
throw error;
|
|
223
|
+
}
|
|
224
|
+
finally {
|
|
225
|
+
await pinned.handle.close();
|
|
226
|
+
}
|
|
227
|
+
};
|
|
228
|
+
/**
|
|
229
|
+
* The spill directory must be a real directory owned by this runtime and no
|
|
230
|
+
* wider than `2750`: either Daimon's own `0700`, or a deployment-provisioned
|
|
231
|
+
* setgid directory whose group is not the runtime's own (a worker group). A
|
|
232
|
+
* symlinked, foreign-owned, world-accessible, or group-open-without-setgid
|
|
233
|
+
* directory is refused and nothing is written. Daimon cannot know *which*
|
|
234
|
+
* worker gid belongs to this agent; that mapping is the deployment's
|
|
235
|
+
* provisioning contract (`GROK_ENGINE_BROKER.worker.home.spillDirectory`).
|
|
236
|
+
*/
|
|
237
|
+
const pinSpillDirectory = async (directory) => {
|
|
238
|
+
const before = await lstat(directory);
|
|
239
|
+
if (before.isSymbolicLink() || !before.isDirectory())
|
|
240
|
+
throw new Error("spill directory is not a real directory");
|
|
241
|
+
const handle = await open(directory, constants.O_RDONLY | constants.O_DIRECTORY | constants.O_NOFOLLOW);
|
|
242
|
+
try {
|
|
243
|
+
const opened = await handle.stat();
|
|
244
|
+
if (opened.dev !== before.dev || opened.ino !== before.ino)
|
|
245
|
+
throw new Error("spill directory was replaced");
|
|
246
|
+
assertSpillDirectoryStat(opened, { uid: process.getuid?.() ?? -1, gid: process.getgid?.() ?? -1 });
|
|
247
|
+
return { handle, dev: Number(opened.dev), ino: Number(opened.ino) };
|
|
248
|
+
}
|
|
249
|
+
catch (error) {
|
|
250
|
+
await handle.close();
|
|
251
|
+
throw error;
|
|
252
|
+
}
|
|
253
|
+
};
|
|
254
|
+
/** Pure so a foreign owner is testable without root. */
|
|
255
|
+
export const assertSpillDirectoryStat = (entry, runtime) => {
|
|
256
|
+
const mode = Number(entry.mode) & 0o7777;
|
|
257
|
+
const groupOpen = (mode & 0o070) !== 0;
|
|
258
|
+
if (!entry.isDirectory() || entry.uid !== runtime.uid || (mode & ~SPILL_DIRECTORY_MAX_MODE) !== 0
|
|
259
|
+
|| (groupOpen && ((mode & 0o2000) === 0 || entry.gid === runtime.gid))) {
|
|
260
|
+
throw new Error("spill directory is not a private or provisioned worker-group directory");
|
|
261
|
+
}
|
|
262
|
+
};
|
|
263
|
+
const assertSameDirectory = async (directory, pinned) => {
|
|
264
|
+
const [now, held] = await Promise.all([lstat(directory), pinned.handle.stat()]);
|
|
265
|
+
if (now.isSymbolicLink() || Number(now.dev) !== pinned.dev || Number(now.ino) !== pinned.ino || Number(held.ino) !== pinned.ino)
|
|
266
|
+
throw new Error("spill directory was replaced");
|
|
267
|
+
};
|
|
268
|
+
/** Newest-first retention, so a busy agent cannot fill its own runtime home. */
|
|
269
|
+
const pruneSpills = async (directory) => {
|
|
270
|
+
const names = (await readdir(directory)).filter((name) => /\.log$/u.test(name));
|
|
271
|
+
const entries = await Promise.all(names.map(async (name) => ({ name, info: await lstat(path.join(directory, name)) })));
|
|
272
|
+
const files = entries.filter(({ info }) => info.isFile() && info.nlink === 1);
|
|
273
|
+
for (const candidate of files.sort((left, right) => right.info.mtimeMs - left.info.mtimeMs || right.name.localeCompare(left.name)).slice(TOOL_OUTPUT_RETAINED_FILES)) {
|
|
274
|
+
await unlink(path.join(directory, candidate.name)).catch(() => undefined);
|
|
275
|
+
}
|
|
276
|
+
};
|
|
277
|
+
/** `mcp_<server>_<tool>` is already `[A-Za-z0-9_]`, but the filename never trusts that. */
|
|
278
|
+
const safeName = (value) => value.replace(/[^A-Za-z0-9_-]+/gu, "_").slice(0, 64) || "tool";
|
|
279
|
+
/**
|
|
280
|
+
* Return `rendered` untouched when it fits, or a head+tail view of the full
|
|
281
|
+
* payload plus a notice naming the file that holds the rest.
|
|
282
|
+
*
|
|
283
|
+
* A result under the cap passes through **byte-identical**: the `mcp_*`
|
|
284
|
+
* passthrough contract — both channels carrying the payload, an upstream
|
|
285
|
+
* `structuredContent` forwarded verbatim — is unchanged for every result that
|
|
286
|
+
* does not blow the bound, which is the overwhelming majority of them.
|
|
287
|
+
*/
|
|
288
|
+
export const capToolResult = async (input) => {
|
|
289
|
+
if (input.exempt.has(input.toolName))
|
|
290
|
+
return input.rendered;
|
|
291
|
+
if (measure(input.rendered.content, input.rendered.details) <= input.maxBytes)
|
|
292
|
+
return input.rendered;
|
|
293
|
+
const payload = spillPayload(input.result);
|
|
294
|
+
const totalBytes = Buffer.byteLength(payload.text, "utf8");
|
|
295
|
+
let spillPath;
|
|
296
|
+
try {
|
|
297
|
+
spillPath = await writeSpill(input.spillDirectory, `${safeName(input.spillId)}.${safeName(input.toolName)}.log`, payload.text);
|
|
298
|
+
}
|
|
299
|
+
catch {
|
|
300
|
+
// oh-my-pi's rule, and the reason it is a rule: a save failure must never
|
|
301
|
+
// convert a successful call into an error, and must never re-expose the
|
|
302
|
+
// full output. Truncate anyway; only the recovery link is withheld.
|
|
303
|
+
spillPath = undefined;
|
|
304
|
+
}
|
|
305
|
+
if (spillPath !== undefined)
|
|
306
|
+
await pruneSpills(input.spillDirectory).catch(() => undefined);
|
|
307
|
+
// The notice's own bytes are reserved first, priced with the widest numbers it
|
|
308
|
+
// could print. Both channels then mirror each other (`mcpToolResult.ts` rule
|
|
309
|
+
// 1) so the retained body is written twice and the budget is halved to pay for
|
|
310
|
+
// it — the same arithmetic, and the same reason, as that file's `degrade`. The
|
|
311
|
+
// fit is then *verified* rather than estimated, because JSON escaping of the
|
|
312
|
+
// payload's own bytes (a newline costs two) is not predictable from its length.
|
|
313
|
+
const reserve = Buffer.byteLength(notice({
|
|
314
|
+
totalBytes, headBytes: totalBytes, tailBytes: totalBytes, boundBytes: input.maxBytes, format: payload.format, ...(spillPath === undefined ? {} : { spillPath })
|
|
315
|
+
}), "utf8");
|
|
316
|
+
const build = (budget) => {
|
|
317
|
+
const head = headUtf8(payload.text, Math.floor(budget / 2));
|
|
318
|
+
const headBytes = Buffer.byteLength(head, "utf8");
|
|
319
|
+
const tail = tailUtf8(payload.text, Math.max(0, budget - headBytes));
|
|
320
|
+
const tailBytes = Buffer.byteLength(tail, "utf8");
|
|
321
|
+
const elided = Math.max(0, totalBytes - headBytes - tailBytes);
|
|
322
|
+
const shown = `${head}\n[… ${elided} bytes elided …]\n${tail}`;
|
|
323
|
+
const text = `${shown}${notice({ totalBytes, headBytes, tailBytes, boundBytes: input.maxBytes, format: payload.format, ...(spillPath === undefined ? {} : { spillPath }) })}`;
|
|
324
|
+
return {
|
|
325
|
+
content: [{ type: "text", text }],
|
|
326
|
+
details: {
|
|
327
|
+
daimon_truncated: true,
|
|
328
|
+
bound_bytes: input.maxBytes,
|
|
329
|
+
result_bytes: totalBytes,
|
|
330
|
+
shown_head_bytes: headBytes,
|
|
331
|
+
shown_tail_bytes: tailBytes,
|
|
332
|
+
elided_bytes: elided,
|
|
333
|
+
payload_format: payload.format,
|
|
334
|
+
...(spillPath === undefined ? { full_output_saved: false } : { full_output_path: spillPath }),
|
|
335
|
+
result_head_tail: shown
|
|
336
|
+
},
|
|
337
|
+
truncated: true,
|
|
338
|
+
...(spillPath === undefined ? {} : { spillPath })
|
|
339
|
+
};
|
|
340
|
+
};
|
|
341
|
+
let budget = Math.max(0, Math.floor((input.maxBytes - reserve) / 2));
|
|
342
|
+
let candidate = build(budget);
|
|
343
|
+
for (let attempt = 0; attempt < 8 && budget > 0; attempt += 1) {
|
|
344
|
+
const size = measure(candidate.content, candidate.details);
|
|
345
|
+
if (size <= input.maxBytes)
|
|
346
|
+
return candidate;
|
|
347
|
+
budget = Math.max(0, budget - Math.ceil((size - input.maxBytes) / 2) - 16);
|
|
348
|
+
candidate = build(budget);
|
|
349
|
+
}
|
|
350
|
+
return candidate;
|
|
351
|
+
};
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { type CodexRequestUsage } from "../pi/codexRolloutUsage.js";
|
|
2
|
+
import type { GrokBrokerModel } from "./grokBrokerModelPolicy.js";
|
|
3
|
+
/**
|
|
4
|
+
* Per-model-request token accounting, written *beside* the per-wake usage
|
|
5
|
+
* ledger and never inside it.
|
|
6
|
+
*
|
|
7
|
+
* `turnUsageLedger.ts` records one aggregate row per wake. Production measured
|
|
8
|
+
* 55 wakes at 14,890,263 input tokens against 159,726 output — output is 1.06%
|
|
9
|
+
* of the spend — with context per model request flat at 23–32k regardless of
|
|
10
|
+
* how many requests a wake made. That is the signature of a fixed prefix
|
|
11
|
+
* replayed once per request rather than of a conversation that grows, but the
|
|
12
|
+
* aggregate row cannot tell the two apart, and every optimisation worth doing
|
|
13
|
+
* next depends on which one it is. This file is what tells them apart.
|
|
14
|
+
*
|
|
15
|
+
* It is a separate stream, not a wider row, for one specific reason. Spawnfile's
|
|
16
|
+
* reader (`spawnfile/src/runtime/usageLedger.ts`) rejects any line whose `v` is
|
|
17
|
+
* not `noopolis.daimon.turn-usage.v1` and returns `null` for the whole line, so
|
|
18
|
+
* a version bump on the existing ledger would make an unreleased Spawnfile drop
|
|
19
|
+
* every row it can read today. Nothing here changes the shape, version, path, or
|
|
20
|
+
* field list of that ledger; a reader that knows nothing about this file keeps
|
|
21
|
+
* working byte for byte.
|
|
22
|
+
*/
|
|
23
|
+
export declare const TURN_REQUEST_LEDGER_VERSION: "noopolis.daimon.turn-requests.v1";
|
|
24
|
+
/**
|
|
25
|
+
* Default location: the directory Spawnfile already provisions for the usage
|
|
26
|
+
* ledger, under its own filename. No new mount, no new provisioning step.
|
|
27
|
+
*/
|
|
28
|
+
export declare const TURN_REQUEST_LEDGER: {
|
|
29
|
+
readonly version: "noopolis.daimon.turn-requests.v1";
|
|
30
|
+
readonly directoryPath: "/var/lib/spawnfile/daimon/usage";
|
|
31
|
+
readonly filePath: "/var/lib/spawnfile/daimon/usage/requests.jsonl";
|
|
32
|
+
readonly rotatedFilePath: "/var/lib/spawnfile/daimon/usage/requests.jsonl.1";
|
|
33
|
+
readonly fileMode: 416;
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* `DAIMON_TURN_REQUESTS_LEDGER_PATH` relocates the stream, exactly as
|
|
37
|
+
* `DAIMON_TURN_USAGE_LEDGER_PATH` relocates the ledger it sits beside. A
|
|
38
|
+
* relative or empty value is ignored rather than honoured: a ledger written to
|
|
39
|
+
* a process-relative path is a ledger nobody can find again.
|
|
40
|
+
*/
|
|
41
|
+
export declare const TURN_REQUEST_LEDGER_PATH_ENV: "DAIMON_TURN_REQUESTS_LEDGER_PATH";
|
|
42
|
+
export declare const resolveTurnRequestLedgerPath: (environment?: NodeJS.ProcessEnv) => string;
|
|
43
|
+
export type TurnRequestEntry = Readonly<{
|
|
44
|
+
agent: string;
|
|
45
|
+
wake: string;
|
|
46
|
+
/** The Codex thread whose rollout these rows were read from. */
|
|
47
|
+
thread: string;
|
|
48
|
+
requests: readonly CodexRequestUsage[];
|
|
49
|
+
at?: string;
|
|
50
|
+
}>;
|
|
51
|
+
/**
|
|
52
|
+
* One line per model request.
|
|
53
|
+
*
|
|
54
|
+
* `fresh_input` is `input − cached_input`, the split the whole exercise exists
|
|
55
|
+
* to see. It is derived from exactly the relationship Daimon already validates
|
|
56
|
+
* (`cached_input_tokens` is a subset of `input_tokens`, asserted by Codex's own
|
|
57
|
+
* reconciled totals and re-checked when the block is decoded). `cache_write` is
|
|
58
|
+
* emitted raw and never subtracted, because whether Codex counts a cache write
|
|
59
|
+
* inside `input_tokens` has not been verified — a reader that needs that answer
|
|
60
|
+
* has the raw number to work from instead of a guess baked into the row.
|
|
61
|
+
*/
|
|
62
|
+
export declare const renderTurnRequestLines: (entry: TurnRequestEntry) => string;
|
|
63
|
+
/** One Grok broker model request: usage from the worker stream, timing from the proxy. */
|
|
64
|
+
/**
|
|
65
|
+
* `usageSource`: `stream` (the worker's own per-request frame), `upstream`
|
|
66
|
+
* (the provider response the proxy saw), or `estimated` (no valid usage; the
|
|
67
|
+
* proxy's conservative charge, see `grokBrokerTurnMeter.ts`).
|
|
68
|
+
*/
|
|
69
|
+
/**
|
|
70
|
+
* `toolCalls` are the tool-call names that request's response carried, as the
|
|
71
|
+
* proxy read them (`grokBrokerTurnMeter.ts`): names only, bounded, `[]` for a
|
|
72
|
+
* response that called nothing, and absent when no response could be decoded.
|
|
73
|
+
*/
|
|
74
|
+
export type GrokTurnRequest = Readonly<{
|
|
75
|
+
index: number;
|
|
76
|
+
input: number;
|
|
77
|
+
cacheRead: number;
|
|
78
|
+
cacheWrite: number;
|
|
79
|
+
output: number;
|
|
80
|
+
total: number;
|
|
81
|
+
startedAt?: string;
|
|
82
|
+
endedAt?: string;
|
|
83
|
+
usageSource?: "stream" | "upstream" | "estimated";
|
|
84
|
+
toolCalls?: readonly string[];
|
|
85
|
+
}>;
|
|
86
|
+
/**
|
|
87
|
+
* `requestCount` is the turn's admitted request count when it exceeds the rows:
|
|
88
|
+
* a killed turn's in-flight request was sent upstream but never reported usage,
|
|
89
|
+
* so it has no row yet still counts in every row's `requests`.
|
|
90
|
+
*/
|
|
91
|
+
export type GrokTurnRequestEntry = Readonly<{
|
|
92
|
+
agent: string;
|
|
93
|
+
wake: string;
|
|
94
|
+
turn: string;
|
|
95
|
+
session?: string;
|
|
96
|
+
model: GrokBrokerModel;
|
|
97
|
+
requests: readonly GrokTurnRequest[];
|
|
98
|
+
requestCount?: number;
|
|
99
|
+
at?: string;
|
|
100
|
+
}>;
|
|
101
|
+
/**
|
|
102
|
+
* Grok rows share the Codex row's field meaning: `input` is the whole prompt
|
|
103
|
+
* side the request replayed (`input_tokens + cache_read`), `cached_input` the
|
|
104
|
+
* cache read, `fresh_input` the uncached remainder. Grok does not separate
|
|
105
|
+
* reasoning tokens, so `reasoning` is absent rather than zero. `turn` is the
|
|
106
|
+
* broker idempotency key and `thread` the Grok session id when the stream
|
|
107
|
+
* named one.
|
|
108
|
+
*
|
|
109
|
+
* `tool_calls` is what a turn's rows could not say before: whether the model
|
|
110
|
+
* ever *tried* to call anything. Two live turns ended with correctly mounted
|
|
111
|
+
* tools and no visible attempt, and the rows recorded timings and tokens only,
|
|
112
|
+
* so the question could not be answered after the fact. It is names only —
|
|
113
|
+
* never arguments, never message content, never a bearer — bounded, `[]` for a
|
|
114
|
+
* response that called nothing, and absent for a response that could not be
|
|
115
|
+
* decoded, because a fabricated empty list is byte-identical to a measured one.
|
|
116
|
+
*
|
|
117
|
+
* It is an additive field inside the unchanged
|
|
118
|
+
* `noopolis.daimon.turn-requests.v1` row, deliberately without a version bump:
|
|
119
|
+
* Spawnfile's usage reader (`spawnfile/src/runtime/usageLedger.ts`) drops every
|
|
120
|
+
* line whose `v` it does not recognise while ignoring fields it does not know,
|
|
121
|
+
* and Paideia only relocates this stream's path
|
|
122
|
+
* (`DAIMON_TURN_REQUESTS_LEDGER_PATH`). A bump is what would blind them; a new
|
|
123
|
+
* field is not.
|
|
124
|
+
*/
|
|
125
|
+
export declare const renderGrokTurnRequestLines: (entry: GrokTurnRequestEntry) => string;
|
|
126
|
+
/**
|
|
127
|
+
* Append already-rendered, newline-terminated ledger lines in one write, with the
|
|
128
|
+
* same rotation and file mode as both ledgers. Advisory: never rejects. The
|
|
129
|
+
* broker uses it to append the exact bytes it sealed into a turn record.
|
|
130
|
+
*/
|
|
131
|
+
export declare const recordLedgerLines: (file: string, lines: string) => Promise<boolean>;
|
|
132
|
+
/** Advisory and never rejects, like {@link recordTurnRequests}; an empty turn writes nothing. */
|
|
133
|
+
export declare const recordGrokTurnRequests: (file: string, entry: GrokTurnRequestEntry) => Promise<boolean>;
|
|
134
|
+
/**
|
|
135
|
+
* Advisory. Never rejects, and never writes an empty wake.
|
|
136
|
+
*
|
|
137
|
+
* A wake whose rollout was absent, unreadable, or undecodable contributes no
|
|
138
|
+
* rows at all rather than a zero row — the same invariant the usage ledger
|
|
139
|
+
* holds, for the same reason: a fabricated zero is byte-identical to a measured
|
|
140
|
+
* one, and this stream exists to be believed.
|
|
141
|
+
*/
|
|
142
|
+
export declare const recordTurnRequests: (file: string, entry: TurnRequestEntry) => Promise<boolean>;
|
|
143
|
+
/**
|
|
144
|
+
* The whole instrumentation path for one Codex wake: find that thread's
|
|
145
|
+
* rollout, decode its per-request usage, append it. Never throws.
|
|
146
|
+
*
|
|
147
|
+
* A wake that produced no rows says so on stderr exactly once. Silence would
|
|
148
|
+
* make a permanently blind instrument indistinguishable from a working one —
|
|
149
|
+
* `--ephemeral`, a relocated `CODEX_HOME`, or a Codex version that renamed the
|
|
150
|
+
* usage frame all end here, and each is worth one line rather than a
|
|
151
|
+
* quietly-empty file nobody questions.
|
|
152
|
+
*/
|
|
153
|
+
export declare const recordCodexTurnRequests: (input: Readonly<{
|
|
154
|
+
agent: string;
|
|
155
|
+
wake: string;
|
|
156
|
+
codexHome: string;
|
|
157
|
+
threadId: string;
|
|
158
|
+
file?: string;
|
|
159
|
+
}>) => Promise<boolean>;
|
|
160
|
+
//# sourceMappingURL=turnRequestLedger.d.ts.map
|