@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 @@
|
|
|
1
|
+
{"version":3,"file":"portableCredentialAuth.d.ts","sourceRoot":"","sources":["../../src/runtime/portableCredentialAuth.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,sBAAsB,GAAG,OAAO,GAAG,MAAM,CAAC;AAEtD,2EAA2E;AAC3E,wBAAgB,gCAAgC,CAC9C,MAAM,EAAE,sBAAsB,EAC9B,KAAK,EAAE,UAAU,GAChB,OAAO,CAYT;AAED,qFAAqF;AACrF,wBAAgB,8BAA8B,CAC5C,MAAM,EAAE,sBAAsB,EAC9B,KAAK,EAAE,UAAU,GAChB,SAAS,MAAM,EAAE,CASnB"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/** Validates only the bounded provider-native shape needed for refresh. */
|
|
2
|
+
export function hasRefreshablePortableCredential(engine, bytes) {
|
|
3
|
+
let value;
|
|
4
|
+
try {
|
|
5
|
+
value = JSON.parse(Buffer.from(bytes.buffer, bytes.byteOffset, bytes.byteLength).toString("utf8"));
|
|
6
|
+
}
|
|
7
|
+
catch {
|
|
8
|
+
return false;
|
|
9
|
+
}
|
|
10
|
+
const pair = engine === "grok" ? grokTokenPair(value) : tokenPair(value);
|
|
11
|
+
if (pair.access === undefined || pair.refresh === undefined)
|
|
12
|
+
return false;
|
|
13
|
+
if (engine !== "grok")
|
|
14
|
+
return true;
|
|
15
|
+
const candidate = firstString(grokTokenEntry(value), ["expires_at"]);
|
|
16
|
+
return candidate !== undefined && Number.isFinite(Date.parse(candidate));
|
|
17
|
+
}
|
|
18
|
+
/** Returns only the provider-native bearer values for exact in-process redaction. */
|
|
19
|
+
export function portableCredentialSecretValues(engine, bytes) {
|
|
20
|
+
let value;
|
|
21
|
+
try {
|
|
22
|
+
value = JSON.parse(Buffer.from(bytes.buffer, bytes.byteOffset, bytes.byteLength).toString("utf8"));
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
return [];
|
|
26
|
+
}
|
|
27
|
+
const pair = engine === "grok" ? grokTokenPair(value) : tokenPair(value);
|
|
28
|
+
return [...new Set([pair.access, pair.refresh].filter((entry) => entry !== undefined))];
|
|
29
|
+
}
|
|
30
|
+
function tokenPair(value) {
|
|
31
|
+
const source = object(value);
|
|
32
|
+
const nested = object(source?.tokens) ?? source;
|
|
33
|
+
return {
|
|
34
|
+
access: firstNonBlankString(nested, ["access_token", "accessToken", "token"]),
|
|
35
|
+
refresh: firstNonBlankString(nested, ["refresh_token", "refreshToken"])
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
function grokTokenEntry(value) {
|
|
39
|
+
const source = object(value);
|
|
40
|
+
if (source === undefined)
|
|
41
|
+
return undefined;
|
|
42
|
+
for (const [key, entry] of Object.entries(source)) {
|
|
43
|
+
if (/^https:\/\/auth\.x\.ai::/u.test(key))
|
|
44
|
+
return object(entry);
|
|
45
|
+
}
|
|
46
|
+
return undefined;
|
|
47
|
+
}
|
|
48
|
+
function grokTokenPair(value) {
|
|
49
|
+
const entry = grokTokenEntry(value);
|
|
50
|
+
return {
|
|
51
|
+
access: firstNonBlankString(entry, ["key"]),
|
|
52
|
+
refresh: firstNonBlankString(entry, ["refresh_token"])
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
function object(value) {
|
|
56
|
+
return value !== null && typeof value === "object" && !Array.isArray(value)
|
|
57
|
+
? value
|
|
58
|
+
: undefined;
|
|
59
|
+
}
|
|
60
|
+
function firstString(value, names) {
|
|
61
|
+
for (const name of names) {
|
|
62
|
+
if (typeof value?.[name] === "string" && value[name].length > 0)
|
|
63
|
+
return value[name];
|
|
64
|
+
}
|
|
65
|
+
return undefined;
|
|
66
|
+
}
|
|
67
|
+
function firstNonBlankString(value, names) {
|
|
68
|
+
const candidate = firstString(value, names);
|
|
69
|
+
return candidate !== undefined && candidate.trim().length > 0 ? candidate : undefined;
|
|
70
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { OrganizationRuntimeAgentConfig } from "./organizationRuntime.js";
|
|
2
|
+
/**
|
|
3
|
+
* Seeds a runtime-writable CLI credential from Daimon's read-only ingress.
|
|
4
|
+
* A newer runtime copy wins so a CLI refresh survives process/container
|
|
5
|
+
* restarts; a later operator refresh of the ingress is imported on restart.
|
|
6
|
+
*/
|
|
7
|
+
export declare function materializePortableCredential(configuredAgent: OrganizationRuntimeAgentConfig, runtimeHomePath: string): Promise<"created" | "preserved" | "refreshed">;
|
|
8
|
+
//# sourceMappingURL=portableCredentialMaterial.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"portableCredentialMaterial.d.ts","sourceRoot":"","sources":["../../src/runtime/portableCredentialMaterial.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,0BAA0B,CAAC;AAc/E;;;;GAIG;AACH,wBAAsB,6BAA6B,CACjD,eAAe,EAAE,8BAA8B,EAC/C,eAAe,EAAE,MAAM,GACtB,OAAO,CAAC,SAAS,GAAG,WAAW,GAAG,WAAW,CAAC,CAsChD"}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { constants } from "node:fs";
|
|
2
|
+
import { chmod, lstat, mkdir, open, rename, unlink } from "node:fs/promises";
|
|
3
|
+
import { randomUUID } from "node:crypto";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { ENGINE_CREDENTIAL_MATERIAL } from "./contractManifest.js";
|
|
6
|
+
const MAX_CREDENTIAL_BYTES = 64 * 1024;
|
|
7
|
+
/**
|
|
8
|
+
* Seeds a runtime-writable CLI credential from Daimon's read-only ingress.
|
|
9
|
+
* A newer runtime copy wins so a CLI refresh survives process/container
|
|
10
|
+
* restarts; a later operator refresh of the ingress is imported on restart.
|
|
11
|
+
*/
|
|
12
|
+
export async function materializePortableCredential(configuredAgent, runtimeHomePath) {
|
|
13
|
+
if (configuredAgent.engine.kind !== "codex") {
|
|
14
|
+
throw new Error(`agent ${configuredAgent.id} ${configuredAgent.engine.kind} has no portable credential material`);
|
|
15
|
+
}
|
|
16
|
+
const agent = configuredAgent;
|
|
17
|
+
const rule = ENGINE_CREDENTIAL_MATERIAL[agent.engine.kind];
|
|
18
|
+
const sourcePath = contained(runtimeHomePath, rule.sourceRelativePath);
|
|
19
|
+
const destinationPath = contained(runtimeHomePath, rule.destinationRelativePath);
|
|
20
|
+
const destinationDirectory = path.dirname(destinationPath);
|
|
21
|
+
await assertPrivateDirectory(path.dirname(sourcePath), rule.directoryMode, agent, false);
|
|
22
|
+
const source = await readCredential(sourcePath, rule.fileMode, agent);
|
|
23
|
+
await prepareDestinationDirectory(destinationDirectory, rule.directoryMode, agent);
|
|
24
|
+
const existing = await existingCredential(destinationPath, rule.fileMode, agent);
|
|
25
|
+
if (existing !== undefined && existing.mtimeMs >= source.identity.mtimeMs)
|
|
26
|
+
return "preserved";
|
|
27
|
+
const temporaryPath = path.join(destinationDirectory, `.${path.basename(destinationPath)}.${randomUUID()}.tmp`);
|
|
28
|
+
let temporary;
|
|
29
|
+
try {
|
|
30
|
+
temporary = await open(temporaryPath, constants.O_CREAT | constants.O_EXCL | constants.O_WRONLY | noFollow(), rule.fileMode);
|
|
31
|
+
await temporary.writeFile(source.bytes);
|
|
32
|
+
await temporary.chmod(rule.fileMode);
|
|
33
|
+
await temporary.sync();
|
|
34
|
+
await temporary.close();
|
|
35
|
+
temporary = undefined;
|
|
36
|
+
await rename(temporaryPath, destinationPath);
|
|
37
|
+
await assertCredential(destinationPath, rule.fileMode, agent);
|
|
38
|
+
return existing === undefined ? "created" : "refreshed";
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
throw unavailable(agent, error);
|
|
42
|
+
}
|
|
43
|
+
finally {
|
|
44
|
+
await temporary?.close().catch(() => undefined);
|
|
45
|
+
await unlink(temporaryPath).catch(() => undefined);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
async function readCredential(filePath, mode, agent) {
|
|
49
|
+
let handle;
|
|
50
|
+
try {
|
|
51
|
+
// Opening a read-only bind can refresh its metadata. Validate the actual
|
|
52
|
+
// descriptor before consulting the refreshed path or reading any bytes.
|
|
53
|
+
// Nonblocking open lets us reject a FIFO by type instead of hanging here.
|
|
54
|
+
handle = await open(filePath, constants.O_RDONLY | noFollow() | constants.O_NONBLOCK);
|
|
55
|
+
const before = assertCredentialEntry(await handle.stat(), mode, agent);
|
|
56
|
+
if (!sameIdentity(before, await assertCredential(filePath, mode, agent)))
|
|
57
|
+
throw new Error("credential changed during import");
|
|
58
|
+
// One extra byte detects growth without allowing a changing file to drive
|
|
59
|
+
// an unbounded read/allocation. Partial reads advance within this buffer.
|
|
60
|
+
const buffer = Buffer.alloc(before.size + 1);
|
|
61
|
+
let length = 0;
|
|
62
|
+
while (length < buffer.length) {
|
|
63
|
+
const result = await handle.read(buffer, length, buffer.length - length, length);
|
|
64
|
+
if (result.bytesRead === 0)
|
|
65
|
+
break;
|
|
66
|
+
length += result.bytesRead;
|
|
67
|
+
}
|
|
68
|
+
const bytes = buffer.subarray(0, length);
|
|
69
|
+
const after = assertCredentialEntry(await handle.stat(), mode, agent);
|
|
70
|
+
const afterPath = await assertCredential(filePath, mode, agent);
|
|
71
|
+
if (!sameIdentity(before, after) || !sameIdentity(before, afterPath) || bytes.length !== before.size) {
|
|
72
|
+
throw new Error("credential changed during import");
|
|
73
|
+
}
|
|
74
|
+
return { bytes, identity: before };
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
throw unavailable(agent, error);
|
|
78
|
+
}
|
|
79
|
+
finally {
|
|
80
|
+
await handle?.close().catch(() => undefined);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
async function prepareDestinationDirectory(directoryPath, mode, agent) {
|
|
84
|
+
try {
|
|
85
|
+
await mkdir(directoryPath, { mode });
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
if (error.code !== "EEXIST")
|
|
89
|
+
throw unavailable(agent, error);
|
|
90
|
+
}
|
|
91
|
+
await assertPrivateDirectory(directoryPath, mode, agent, true);
|
|
92
|
+
}
|
|
93
|
+
async function assertPrivateDirectory(directoryPath, mode, agent, repairMode) {
|
|
94
|
+
try {
|
|
95
|
+
const entry = await lstat(directoryPath);
|
|
96
|
+
if (!entry.isDirectory() || entry.isSymbolicLink() || entry.uid !== process.getuid?.()) {
|
|
97
|
+
throw new Error("unsafe credential directory");
|
|
98
|
+
}
|
|
99
|
+
if (repairMode && (entry.mode & 0o777) !== mode)
|
|
100
|
+
await chmod(directoryPath, mode);
|
|
101
|
+
const secured = await lstat(directoryPath);
|
|
102
|
+
if (!secured.isDirectory() || secured.isSymbolicLink() || secured.uid !== process.getuid?.()
|
|
103
|
+
|| (secured.mode & 0o777) !== mode)
|
|
104
|
+
throw new Error("unsafe credential directory");
|
|
105
|
+
}
|
|
106
|
+
catch (error) {
|
|
107
|
+
throw unavailable(agent, error);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
async function existingCredential(filePath, mode, agent) {
|
|
111
|
+
try {
|
|
112
|
+
return await assertCredential(filePath, mode, agent);
|
|
113
|
+
}
|
|
114
|
+
catch (error) {
|
|
115
|
+
if (error.code === "ENOENT")
|
|
116
|
+
return undefined;
|
|
117
|
+
throw error;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
async function assertCredential(filePath, mode, agent) {
|
|
121
|
+
let entry;
|
|
122
|
+
try {
|
|
123
|
+
entry = await lstat(filePath);
|
|
124
|
+
}
|
|
125
|
+
catch (error) {
|
|
126
|
+
if (error.code === "ENOENT")
|
|
127
|
+
throw error;
|
|
128
|
+
throw unavailable(agent, error);
|
|
129
|
+
}
|
|
130
|
+
return assertCredentialEntry(entry, mode, agent);
|
|
131
|
+
}
|
|
132
|
+
function assertCredentialEntry(entry, mode, agent) {
|
|
133
|
+
if (!entry.isFile() || entry.isSymbolicLink() || entry.uid !== process.getuid?.()
|
|
134
|
+
|| entry.nlink !== 1 || (entry.mode & 0o777) !== mode
|
|
135
|
+
|| entry.size === 0 || entry.size > MAX_CREDENTIAL_BYTES) {
|
|
136
|
+
throw unavailable(agent, new Error("unsafe credential artifact"));
|
|
137
|
+
}
|
|
138
|
+
return identity(entry);
|
|
139
|
+
}
|
|
140
|
+
function contained(root, relative) {
|
|
141
|
+
const candidate = path.resolve(root, relative);
|
|
142
|
+
const relation = path.relative(path.resolve(root), candidate);
|
|
143
|
+
if (!relation || relation === ".." || relation.startsWith(`..${path.sep}`) || path.isAbsolute(relation)) {
|
|
144
|
+
throw new Error("Daimon credential contract escapes the runtime home");
|
|
145
|
+
}
|
|
146
|
+
return candidate;
|
|
147
|
+
}
|
|
148
|
+
function identity(value) {
|
|
149
|
+
const numeric = value;
|
|
150
|
+
return {
|
|
151
|
+
dev: numeric.dev,
|
|
152
|
+
ino: numeric.ino,
|
|
153
|
+
mode: numeric.mode & 0o7777,
|
|
154
|
+
mtimeMs: numeric.mtimeMs,
|
|
155
|
+
size: numeric.size,
|
|
156
|
+
uid: numeric.uid,
|
|
157
|
+
nlink: numeric.nlink
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
function sameIdentity(left, right) {
|
|
161
|
+
return left.dev === right.dev && left.ino === right.ino && left.mode === right.mode
|
|
162
|
+
&& left.mtimeMs === right.mtimeMs && left.size === right.size && left.uid === right.uid && left.nlink === right.nlink;
|
|
163
|
+
}
|
|
164
|
+
function noFollow() {
|
|
165
|
+
return constants.O_NOFOLLOW ?? 0;
|
|
166
|
+
}
|
|
167
|
+
function unavailable(agent, _cause) {
|
|
168
|
+
return new Error(`agent ${agent.id} ${agent.engine.kind} credential materialization failed`);
|
|
169
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { ToolDefinition } from "@earendil-works/pi-coding-agent";
|
|
2
|
+
import type { OrganizationRuntimeAgentConfig } from "./organizationRuntime.js";
|
|
3
|
+
import type { PiWakeEnvironmentContextRef } from "../pi/piAgentWakeSupport.js";
|
|
4
|
+
export declare function createProductionAgentTools(agent: OrganizationRuntimeAgentConfig, wakeContext?: PiWakeEnvironmentContextRef): Promise<ToolDefinition[]>;
|
|
5
|
+
//# sourceMappingURL=productionAgentTools.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"productionAgentTools.d.ts","sourceRoot":"","sources":["../../src/runtime/productionAgentTools.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AAMtE,OAAO,KAAK,EAAE,8BAA8B,EAAgC,MAAM,0BAA0B,CAAC;AAM7G,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,6BAA6B,CAAC;AAe/E,wBAAsB,0BAA0B,CAAC,KAAK,EAAE,8BAA8B,EAAE,WAAW,GAAE,2BAAgC,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CAUhK"}
|
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { createHash } from "node:crypto";
|
|
3
|
+
import { constants } from "node:fs";
|
|
4
|
+
import { lstat, open, readdir, rename, unlink } from "node:fs/promises";
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
7
|
+
import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js";
|
|
8
|
+
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
|
|
9
|
+
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
|
|
10
|
+
import { moltnetOperationResult, readMoltnetPages } from "./moltnetMachineRead.js";
|
|
11
|
+
import { McpToolCallError, MCP_TOOL_RESULT_MAX_BYTES, renderMcpToolResult, replayMcpReceipt } from "./mcpToolResult.js";
|
|
12
|
+
import { ensureRuntimeHomeDirectory } from "./runtimeHomeLayout.js";
|
|
13
|
+
import { capToolResult, resolveExemptToolNames, resolveToolResultMaxBytes, TOOL_OUTPUT_DIRECTORY_NAME } from "./toolResultSpill.js";
|
|
14
|
+
import { cliChildEnvironment } from "../pi/cliEnvironment.js";
|
|
15
|
+
const MAX_RESULT = 65_536;
|
|
16
|
+
const TIMEOUT = 10_000;
|
|
17
|
+
/**
|
|
18
|
+
* Action and delivery identifiers are prefixed with a hyphen, never a colon.
|
|
19
|
+
*
|
|
20
|
+
* Moltnet's machine protocol rejects any identifier that parses as a scoped
|
|
21
|
+
* agent id, and `ParseScopedAgentID` treats *every* `left:right` string as one
|
|
22
|
+
* (`moltnet/pkg/protocol/identity.go`). A `daimon:<digest>` delivery id
|
|
23
|
+
* therefore failed `delivery_id must be a local id`, and the CLI answered
|
|
24
|
+
* `error: invalid request` for every send an agent ever attempted.
|
|
25
|
+
*/
|
|
26
|
+
const DAIMON_ACTION_ID_PREFIX = "daimon-";
|
|
27
|
+
export async function createProductionAgentTools(agent, wakeContext = {}) {
|
|
28
|
+
await ensureRuntimeHomeDirectory(agent.runtimeHomePath, "tool-state");
|
|
29
|
+
// Resolved once, at agent start: a malformed bound is a configuration error
|
|
30
|
+
// that should refuse the agent, not a surprise thrown from the middle of a
|
|
31
|
+
// tool call the model is waiting on.
|
|
32
|
+
const cap = { maxBytes: resolveToolResultMaxBytes(), exempt: resolveExemptToolNames() };
|
|
33
|
+
const tools = [...await Promise.all((agent.mcp ?? []).map((server) => mcpTools(agent, server, wakeContext, cap)))].flat();
|
|
34
|
+
if (agent.moltnet !== undefined)
|
|
35
|
+
tools.push(moltnetTool(agent, wakeContext), moltnetReadTool(agent));
|
|
36
|
+
if (new Set(tools.map((tool) => tool.name)).size !== tools.length)
|
|
37
|
+
throw new Error("compiled cognition tool names collide");
|
|
38
|
+
return tools;
|
|
39
|
+
}
|
|
40
|
+
async function mcpTools(agent, server, wakeContext, cap) {
|
|
41
|
+
const { client, close } = await connect(agent, server);
|
|
42
|
+
const listed = await client.listTools(undefined, { timeout: TIMEOUT });
|
|
43
|
+
if (Buffer.byteLength(JSON.stringify(listed)) > MAX_RESULT) {
|
|
44
|
+
await close();
|
|
45
|
+
throw new Error(`MCP server ${server.name} tool list exceeds bound`);
|
|
46
|
+
}
|
|
47
|
+
const available = new Map(listed.tools.map((tool) => [tool.name, tool]));
|
|
48
|
+
const undeclared = [...available.keys()].filter((name) => !server.tools.includes(name));
|
|
49
|
+
if (undeclared.length > 0) {
|
|
50
|
+
await close();
|
|
51
|
+
throw new Error(`MCP server ${server.name} exposed undeclared tools`);
|
|
52
|
+
}
|
|
53
|
+
const missing = server.tools.filter((name) => !available.has(name));
|
|
54
|
+
if (missing.length > 0) {
|
|
55
|
+
await close();
|
|
56
|
+
throw new Error(`MCP server ${server.name} omitted declared tools`);
|
|
57
|
+
}
|
|
58
|
+
await close();
|
|
59
|
+
return server.tools.map((name) => {
|
|
60
|
+
const declared = available.get(name);
|
|
61
|
+
return {
|
|
62
|
+
name: mcpToolName(server.name, name),
|
|
63
|
+
label: `${server.name}: ${name}`,
|
|
64
|
+
description: declared.description ?? `Call declared MCP tool ${server.name}/${name}`,
|
|
65
|
+
parameters: declared.inputSchema,
|
|
66
|
+
async execute(_id, params) {
|
|
67
|
+
if (!wakeContext.current)
|
|
68
|
+
throw new Error("MCP call requires an active wake");
|
|
69
|
+
const actionId = `${DAIMON_ACTION_ID_PREFIX}${createHash("sha256").update(JSON.stringify([wakeContext.current, agent.id, server.name, name, params])).digest("hex")}`;
|
|
70
|
+
const prior = await priorReceipt(agent, actionId);
|
|
71
|
+
if (prior !== undefined) {
|
|
72
|
+
const replayed = replayMcpReceipt(server.name, name, prior);
|
|
73
|
+
return { content: replayed.content, details: replayed.details };
|
|
74
|
+
}
|
|
75
|
+
const active = await connect(agent, server);
|
|
76
|
+
try {
|
|
77
|
+
const result = await active.client.callTool({ name, arguments: params }, undefined, { timeout: TIMEOUT });
|
|
78
|
+
const bytes = JSON.stringify(result);
|
|
79
|
+
const envelope = { kind: "mcp", agent_id: agent.id, engine: agent.engine.kind, delivery_id: actionId, server: server.name, tool: name, digest: digest(bytes) };
|
|
80
|
+
let rendered;
|
|
81
|
+
try {
|
|
82
|
+
// The SDK types this as a union with the pre-schema compatibility shape;
|
|
83
|
+
// only the three fields `McpUpstreamResult` names are ever read.
|
|
84
|
+
rendered = renderMcpToolResult({ server: server.name, tool: name, result: result, maxBytes: MCP_TOOL_RESULT_MAX_BYTES });
|
|
85
|
+
// Every tool result stays in the transcript for every *subsequent*
|
|
86
|
+
// model request of the wake, so one oversized answer is re-billed
|
|
87
|
+
// once per remaining request. Above the bound the full payload goes
|
|
88
|
+
// to disk and the model gets head+tail plus the path
|
|
89
|
+
// (`toolResultSpill.ts`); at or below it, this returns `rendered`
|
|
90
|
+
// itself and the passthrough contract is untouched.
|
|
91
|
+
rendered = await capToolResult({
|
|
92
|
+
toolName: mcpToolName(server.name, name),
|
|
93
|
+
rendered,
|
|
94
|
+
result: result,
|
|
95
|
+
maxBytes: cap.maxBytes,
|
|
96
|
+
exempt: cap.exempt,
|
|
97
|
+
spillDirectory: path.join(agent.runtimeHomePath, TOOL_OUTPUT_DIRECTORY_NAME),
|
|
98
|
+
spillId: actionId
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
catch (error) {
|
|
102
|
+
// The server's own reason is the receipt's payload as much as the
|
|
103
|
+
// model's: a replayed failure has to fail for the same stated cause.
|
|
104
|
+
if (error instanceof McpToolCallError)
|
|
105
|
+
await receipt(agent, { ...envelope, is_error: true, error: error.reason });
|
|
106
|
+
throw error;
|
|
107
|
+
}
|
|
108
|
+
await receipt(agent, { ...envelope, is_error: false, result: { content: rendered.content, details: rendered.details }, ...(rendered.truncated ? { truncated: true } : {}) });
|
|
109
|
+
return { content: rendered.content, details: rendered.details };
|
|
110
|
+
}
|
|
111
|
+
finally {
|
|
112
|
+
await active.close();
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Reading a declared room is a native Moltnet machine operation. Without it an agent can
|
|
120
|
+
* only learn what a wake pushed at it, so any role that weighs several peers' messages
|
|
121
|
+
* has to be woken once per message instead of reading the room once.
|
|
122
|
+
*
|
|
123
|
+
* The whole payload goes in `details` as well as `content`, matching every other
|
|
124
|
+
* Daimon tool (`memoryTools.ts`, `worldTools.ts`). This tool was written by
|
|
125
|
+
* copying `moltnet_send`, whose useful payload genuinely *is* its details
|
|
126
|
+
* (`{"accepted":true}`) — but the MCP mount lowers `details` to
|
|
127
|
+
* `structuredContent` (`src/mcp/toolServer.ts`) and the engines render that in
|
|
128
|
+
* preference to `content`, so a read that put its messages only in `content`
|
|
129
|
+
* handed the model a bare `{"messages":5}` and dropped every message and the
|
|
130
|
+
* page cursor. It looked like a confused agent for a night; it was an empty tool.
|
|
131
|
+
*/
|
|
132
|
+
function moltnetReadTool(agent) {
|
|
133
|
+
return {
|
|
134
|
+
name: "moltnet_read", label: "Read a scoped Moltnet room or DM", description: "Read recent messages from one room or DM declared for this agent.",
|
|
135
|
+
parameters: { type: "object", additionalProperties: false, required: ["network", "target"], properties: { network: { type: "string" }, target: { type: "string" }, limit: { type: "integer", minimum: 1, maximum: 100 }, before: { type: "string" }, after: { type: "string" } } },
|
|
136
|
+
async execute(_id, params) {
|
|
137
|
+
const input = params;
|
|
138
|
+
const network = agent.moltnet.networks.find((entry) => entry.id === input.network);
|
|
139
|
+
if (network === undefined)
|
|
140
|
+
throw new Error("Moltnet action exceeds declared scope");
|
|
141
|
+
const [kind, target] = input.target.split(":", 2);
|
|
142
|
+
if ((kind === "room" && !network.rooms.includes(target ?? "")) || (kind === "dm" && !network.dms) || !target || !["room", "dm"].includes(kind ?? ""))
|
|
143
|
+
throw new Error("Moltnet target is not declared");
|
|
144
|
+
const read = await readMoltnetPages({
|
|
145
|
+
requested: input.limit ?? 20, maxBytes: MAX_RESULT,
|
|
146
|
+
...(input.before === undefined ? {} : { before: input.before }),
|
|
147
|
+
...(input.after === undefined ? {} : { after: input.after }),
|
|
148
|
+
fetch: (request) => moltnetReadPage(agent, input.network, kind, target, request)
|
|
149
|
+
});
|
|
150
|
+
const payload = {
|
|
151
|
+
target: read.target ?? { kind, id: target },
|
|
152
|
+
messages: read.messages,
|
|
153
|
+
message_count: read.messages.length,
|
|
154
|
+
page: {
|
|
155
|
+
has_more: read.hasMore,
|
|
156
|
+
...(read.nextBefore === undefined ? {} : { next_before: read.nextBefore }),
|
|
157
|
+
...(read.nextAfter === undefined ? {} : { next_after: read.nextAfter })
|
|
158
|
+
},
|
|
159
|
+
...(read.truncated === undefined ? {} : { truncated: read.truncated })
|
|
160
|
+
};
|
|
161
|
+
const bytes = JSON.stringify(payload);
|
|
162
|
+
if (Buffer.byteLength(bytes) > MAX_RESULT)
|
|
163
|
+
throw new Error("Moltnet read result exceeds bound");
|
|
164
|
+
return { content: [{ type: "text", text: bytes }], details: payload };
|
|
165
|
+
}
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
/** One `machine` read request, unwrapped onto the shape the pager consumes. */
|
|
169
|
+
async function moltnetReadPage(agent, networkId, kind, target, request) {
|
|
170
|
+
const correlationId = `${DAIMON_ACTION_ID_PREFIX}${createHash("sha256").update(JSON.stringify([agent.id, networkId, kind, target, request.limit, request.before ?? "", request.after ?? ""])).digest("hex")}`;
|
|
171
|
+
const response = await machine(agent.moltnet.cliPath, agent.moltnet.configPath, networkId, {
|
|
172
|
+
version: "moltnet.machine.v1", correlation_id: correlationId, operation: "read",
|
|
173
|
+
read: { target: { kind, id: target }, limit: request.limit, ...(request.before === undefined ? {} : { before: request.before }), ...(request.after === undefined ? {} : { after: request.after }) }
|
|
174
|
+
});
|
|
175
|
+
const result = moltnetOperationResult(response, "read", "read");
|
|
176
|
+
if (result?.page?.messages === undefined)
|
|
177
|
+
throw new Error("Moltnet read was not accepted");
|
|
178
|
+
const info = result.page.page ?? {};
|
|
179
|
+
return {
|
|
180
|
+
...(result.target === undefined ? {} : { target: result.target }),
|
|
181
|
+
messages: result.page.messages,
|
|
182
|
+
hasMore: info.has_more === true,
|
|
183
|
+
...(typeof info.next_before === "string" ? { nextBefore: info.next_before } : {}),
|
|
184
|
+
...(typeof info.next_after === "string" ? { nextAfter: info.next_after } : {})
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
function moltnetTool(agent, wakeContext) {
|
|
188
|
+
return {
|
|
189
|
+
name: "moltnet_send", label: "Send a scoped Moltnet message", description: "Send to one room or DM declared for this agent.",
|
|
190
|
+
parameters: { type: "object", additionalProperties: false, required: ["network", "target", "text"], properties: { network: { type: "string" }, target: { type: "string" }, text: { type: "string", minLength: 1, maxLength: 2048 } } },
|
|
191
|
+
async execute(_id, params) {
|
|
192
|
+
const input = params;
|
|
193
|
+
const network = agent.moltnet.networks.find((entry) => entry.id === input.network);
|
|
194
|
+
if (network === undefined || Buffer.byteLength(input.text) > 2_048)
|
|
195
|
+
throw new Error("Moltnet action exceeds declared scope");
|
|
196
|
+
const [kind, target] = input.target.split(":", 2);
|
|
197
|
+
if ((kind === "room" && !network.rooms.includes(target ?? "")) || (kind === "dm" && !network.dms) || !target || !["room", "dm"].includes(kind ?? ""))
|
|
198
|
+
throw new Error("Moltnet target is not declared");
|
|
199
|
+
if (!wakeContext.current)
|
|
200
|
+
throw new Error("Moltnet send requires an active wake");
|
|
201
|
+
const deliveryId = `${DAIMON_ACTION_ID_PREFIX}${createHash("sha256").update(JSON.stringify([wakeContext.current, agent.id, input.network, input.target, input.text])).digest("hex")}`;
|
|
202
|
+
const prior = await priorReceipt(agent, deliveryId);
|
|
203
|
+
if (prior !== undefined) {
|
|
204
|
+
wakeContext.spokeFor = wakeContext.current;
|
|
205
|
+
return { content: [{ type: "text", text: JSON.stringify(prior) }], details: prior };
|
|
206
|
+
}
|
|
207
|
+
const response = await machine(agent.moltnet.cliPath, agent.moltnet.configPath, input.network, { version: "moltnet.machine.v1", correlation_id: deliveryId, operation: "send_nudge", send_nudge: { delivery_id: deliveryId, target: { kind, id: target }, body: input.text } });
|
|
208
|
+
const result = moltnetOperationResult(response, "send_nudge", "send");
|
|
209
|
+
if (result?.accepted !== true || typeof result.message_id !== "string")
|
|
210
|
+
throw new Error("Moltnet send was not accepted");
|
|
211
|
+
await receipt(agent, { kind: "moltnet", agent_id: agent.id, engine: agent.engine.kind, delivery_id: deliveryId, network: input.network, target: input.target, message_id: result.message_id });
|
|
212
|
+
// An explicit send and the bridge's terminal-text fallback share one
|
|
213
|
+
// publication slot (moltnet AGENTS.md); recording that this wake spoke
|
|
214
|
+
// lets the wake-completion path blank the terminal text so it is not
|
|
215
|
+
// echoed as a second message.
|
|
216
|
+
wakeContext.spokeFor = wakeContext.current;
|
|
217
|
+
return { content: [{ type: "text", text: JSON.stringify({ accepted: true, message_id: result.message_id }) }], details: { accepted: true } };
|
|
218
|
+
}
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
async function connect(agent, server) {
|
|
222
|
+
const client = new Client({ name: "daimon-production", version: "0.2.0" });
|
|
223
|
+
const headers = server.authSecretEnv === undefined ? {} : { authorization: `Bearer ${requiredSecret(server.authSecretEnv)}` };
|
|
224
|
+
const transport = server.transport === "stdio"
|
|
225
|
+
? new StdioClientTransport({ command: server.command, args: [...server.args], env: stringEnvironment({ ...server.env, ...cliChildEnvironment([], agent.runtimeHomePath, { executablePath: server.command }) }) })
|
|
226
|
+
: server.transport === "sse" ? new SSEClientTransport(new URL(server.url), { requestInit: { headers } })
|
|
227
|
+
: new StreamableHTTPClientTransport(new URL(server.url), { requestInit: { headers } });
|
|
228
|
+
await client.connect(transport);
|
|
229
|
+
return { client, close: () => client.close() };
|
|
230
|
+
}
|
|
231
|
+
function requiredSecret(name) { const value = process.env[name]; if (!value)
|
|
232
|
+
throw new Error(`required MCP secret ${name} is missing`); return value; }
|
|
233
|
+
function receiptPath(agent, deliveryId) { return path.join(agent.runtimeHomePath, "tool-state", `${digest(deliveryId).slice(7)}.json`); }
|
|
234
|
+
async function receipt(agent, value) { const deliveryId = String(value.delivery_id); const file = receiptPath(agent, deliveryId); const temporary = `${file}.${process.pid}.${Date.now()}.tmp`; const bytes = `${JSON.stringify({ ...value, at: new Date().toISOString() })}\n`; if (Buffer.byteLength(bytes) > MAX_RESULT)
|
|
235
|
+
throw new Error("tool receipt exceeds bound"); const handle = await open(temporary, constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL | constants.O_NOFOLLOW, 0o600); try {
|
|
236
|
+
await handle.writeFile(bytes);
|
|
237
|
+
await handle.sync();
|
|
238
|
+
}
|
|
239
|
+
finally {
|
|
240
|
+
await handle.close();
|
|
241
|
+
} try {
|
|
242
|
+
await rename(temporary, file);
|
|
243
|
+
await pruneReceipts(path.dirname(file));
|
|
244
|
+
const directory = await open(path.dirname(file), constants.O_RDONLY);
|
|
245
|
+
try {
|
|
246
|
+
await directory.sync();
|
|
247
|
+
}
|
|
248
|
+
finally {
|
|
249
|
+
await directory.close();
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
catch (error) {
|
|
253
|
+
await unlink(temporary).catch(() => undefined);
|
|
254
|
+
throw error;
|
|
255
|
+
} }
|
|
256
|
+
async function pruneReceipts(directory) { const candidates = await Promise.all((await readdir(directory)).filter((name) => /^[a-f0-9]{64}\.json$/u.test(name)).map(async (name) => ({ name, info: await lstat(path.join(directory, name)) }))); if (candidates.some(({ info }) => !info.isFile() || info.nlink !== 1))
|
|
257
|
+
throw new Error("tool receipt directory contains an unsafe entry"); for (const candidate of candidates.sort((left, right) => right.info.mtimeMs - left.info.mtimeMs || right.name.localeCompare(left.name)).slice(2048))
|
|
258
|
+
await unlink(path.join(directory, candidate.name)); }
|
|
259
|
+
async function priorReceipt(agent, deliveryId) { const file = receiptPath(agent, deliveryId); let handle; try {
|
|
260
|
+
handle = await open(file, constants.O_RDONLY | constants.O_NOFOLLOW);
|
|
261
|
+
}
|
|
262
|
+
catch (error) {
|
|
263
|
+
if (error.code === "ENOENT")
|
|
264
|
+
return undefined;
|
|
265
|
+
throw error;
|
|
266
|
+
} try {
|
|
267
|
+
const entry = await handle.stat();
|
|
268
|
+
if (!entry.isFile() || entry.size > MAX_RESULT)
|
|
269
|
+
throw new Error("tool receipt is unsafe or exceeds bound");
|
|
270
|
+
const value = JSON.parse(await handle.readFile("utf8"));
|
|
271
|
+
if (value.delivery_id !== deliveryId || value.agent_id !== agent.id || value.engine !== agent.engine.kind)
|
|
272
|
+
throw new Error("tool receipt identity mismatch");
|
|
273
|
+
return value;
|
|
274
|
+
}
|
|
275
|
+
finally {
|
|
276
|
+
await handle.close();
|
|
277
|
+
} }
|
|
278
|
+
/**
|
|
279
|
+
* One request/response exchange with `moltnet machine`.
|
|
280
|
+
*
|
|
281
|
+
* Stdin is held open until the response line arrives. `moltnet machine` treats
|
|
282
|
+
* end-of-input as cancellation of everything still in flight, so ending stdin
|
|
283
|
+
* with the request — as this did — raced the send and lost: the CLI answered
|
|
284
|
+
* `{"error":{"code":"canceled"}}` and no message was ever delivered. The
|
|
285
|
+
* operation is complete once its line is on stdout, so closing stdin there can
|
|
286
|
+
* no longer cancel it.
|
|
287
|
+
*/
|
|
288
|
+
async function machine(cli, config, network, request) {
|
|
289
|
+
return await new Promise((resolve, reject) => {
|
|
290
|
+
const child = spawn(cli, ["machine", "--config", config, "--network", network], { stdio: ["pipe", "pipe", "pipe"] });
|
|
291
|
+
let output = "", error = "", settled = false;
|
|
292
|
+
const settle = (action) => { if (settled)
|
|
293
|
+
return; settled = true; clearTimeout(timer); action(); };
|
|
294
|
+
const timer = setTimeout(() => { child.kill("SIGKILL"); settle(() => reject(new Error("Moltnet machine timed out"))); }, TIMEOUT);
|
|
295
|
+
child.stdin.on("error", () => undefined);
|
|
296
|
+
child.stdout.on("data", (chunk) => {
|
|
297
|
+
output += chunk;
|
|
298
|
+
if (Buffer.byteLength(output) > MAX_RESULT) {
|
|
299
|
+
child.kill("SIGKILL");
|
|
300
|
+
settle(() => reject(new Error("Moltnet machine response exceeds bound")));
|
|
301
|
+
return;
|
|
302
|
+
}
|
|
303
|
+
const newline = output.indexOf("\n");
|
|
304
|
+
if (newline < 0)
|
|
305
|
+
return;
|
|
306
|
+
const line = output.slice(0, newline).trim();
|
|
307
|
+
if (line.length === 0)
|
|
308
|
+
return;
|
|
309
|
+
child.stdin.end();
|
|
310
|
+
settle(() => { try {
|
|
311
|
+
resolve(JSON.parse(line));
|
|
312
|
+
}
|
|
313
|
+
catch (cause) {
|
|
314
|
+
reject(cause);
|
|
315
|
+
} });
|
|
316
|
+
child.kill("SIGTERM");
|
|
317
|
+
});
|
|
318
|
+
child.stderr.on("data", (chunk) => { error += chunk; });
|
|
319
|
+
child.once("error", (cause) => settle(() => reject(cause)));
|
|
320
|
+
child.once("exit", () => settle(() => reject(new Error(`Moltnet machine failed: ${(error.slice(0, 1024) || "no response").trim()}`))));
|
|
321
|
+
child.stdin.write(`${JSON.stringify(request)}\n`);
|
|
322
|
+
});
|
|
323
|
+
}
|
|
324
|
+
function digest(value) { return `sha256:${createHash("sha256").update(value).digest("hex")}`; }
|
|
325
|
+
/** The mounted name of one declared MCP tool: the one place it is spelled. */
|
|
326
|
+
function mcpToolName(server, tool) { return `mcp_${safe(server)}_${safe(tool)}`; }
|
|
327
|
+
function safe(value) { return value.replace(/[^A-Za-z0-9_]/gu, "_").slice(0, 48); }
|
|
328
|
+
function stringEnvironment(value) { return Object.fromEntries(Object.entries(value).filter((entry) => entry[1] !== undefined)); }
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mode for every directory Daimon creates inside an agent's runtime home.
|
|
3
|
+
*
|
|
4
|
+
* A brokered Grok agent's runtime home is `0710`
|
|
5
|
+
* (`GROK_ENGINE_BROKER.worker.home.organizationRuntimeHome`) so its sandboxed
|
|
6
|
+
* worker can traverse into the setgid `tool-output/` spill directory. Traverse
|
|
7
|
+
* is all it may have: anything Daimon creates in that home — telemetry traces
|
|
8
|
+
* (prompts, replies, world trajectories), tool state, receipts, the engine's
|
|
9
|
+
* XDG directories and the private `.tmp` — stays `0700`, so a default
|
|
10
|
+
* `mkdir` (0755 under the usual umask) never turns a traversable home into a
|
|
11
|
+
* readable one.
|
|
12
|
+
*/
|
|
13
|
+
export declare const RUNTIME_HOME_SUBDIRECTORY_MODE = 448;
|
|
14
|
+
/**
|
|
15
|
+
* The home itself, created if it is absent and otherwise left exactly as it is.
|
|
16
|
+
*
|
|
17
|
+
* Create-only is the whole contract here. A brokered Grok agent's home is
|
|
18
|
+
* deliberately `0710` and an organization's may be `0700`; which of the two is
|
|
19
|
+
* correct is `physicalReadiness.ts`'s judgement, made against the agent's
|
|
20
|
+
* declared engine, and a layout helper that "corrected" a traversable home to
|
|
21
|
+
* `0700` would break the worker's only route to its own spills.
|
|
22
|
+
*/
|
|
23
|
+
export declare const ensureRuntimeHome: (runtimeHomePath: string) => Promise<string>;
|
|
24
|
+
/**
|
|
25
|
+
* One directory Daimon owns *below* a runtime home, private on every install.
|
|
26
|
+
*
|
|
27
|
+
* `mkdir(..., { mode })` decides nothing for a directory that already exists,
|
|
28
|
+
* and that is the common case rather than the exotic one: a `telemetry/` left
|
|
29
|
+
* at `0755` by a pre-branch Daimon, or pre-created by a deployment, stayed
|
|
30
|
+
* `0755` forever. Under a Grok agent's traversable `0710` home that is the
|
|
31
|
+
* worker reading its own agent's prompts, replies and causal history — the
|
|
32
|
+
* home is traverse-only precisely so that nothing but `tool-output/` is
|
|
33
|
+
* readable. `assertRuntimeDirectory` checks the home, and nothing checked what
|
|
34
|
+
* Daimon created inside it.
|
|
35
|
+
*
|
|
36
|
+
* So every level below the home is asserted and corrected on the way down,
|
|
37
|
+
* through a handle rather than a path: `O_DIRECTORY|O_NOFOLLOW` refuses a
|
|
38
|
+
* symlink planted where a directory belongs, and the `fchmod` that follows
|
|
39
|
+
* lands on the directory that was stat'd. A directory owned by anyone but the
|
|
40
|
+
* runtime user is **refused**, never widened and never silently accepted — the
|
|
41
|
+
* runtime cannot make someone else's directory private, and proceeding would
|
|
42
|
+
* write an agent's telemetry into it anyway.
|
|
43
|
+
*
|
|
44
|
+
* `owner` is a seam so both refusals are testable unprivileged, exactly as
|
|
45
|
+
* `physicalReadiness.ts`'s `RuntimeIdentity` is.
|
|
46
|
+
*/
|
|
47
|
+
export declare function ensureRuntimeHomeDirectory(runtimeHomePath: string, relative: string, owner?: number): Promise<string>;
|
|
48
|
+
//# sourceMappingURL=runtimeHomeLayout.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtimeHomeLayout.d.ts","sourceRoot":"","sources":["../../src/runtime/runtimeHomeLayout.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,8BAA8B,MAAQ,CAAC;AAEpD;;;;;;;;GAQG;AACH,eAAO,MAAM,iBAAiB,GAAU,iBAAiB,MAAM,KAAG,OAAO,CAAC,MAAM,CAG/E,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAsB,0BAA0B,CAAC,eAAe,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,GAAE,MAAiC,GAAG,OAAO,CAAC,MAAM,CAAC,CAcrJ"}
|