@noopolis/daimon 0.1.2 → 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 +269 -51
- 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/mcp/toolServer.d.ts +19 -2
- package/dist/mcp/toolServer.d.ts.map +1 -1
- package/dist/mcp/toolServer.js +57 -17
- package/dist/observability/causalEvents.d.ts +3 -3
- package/dist/observability/causalEvents.d.ts.map +1 -1
- package/dist/observability/causalEvents.js +103 -15
- 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 +84 -24
- package/dist/pi/cliSession.d.ts.map +1 -1
- package/dist/pi/cliSession.js +313 -158
- 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/piAgentHandle.d.ts +4 -3
- package/dist/pi/piAgentHandle.d.ts.map +1 -1
- package/dist/pi/piAgentHandle.js +37 -10
- package/dist/pi/piAgentWakeSupport.d.ts +35 -0
- package/dist/pi/piAgentWakeSupport.d.ts.map +1 -1
- package/dist/pi/piAgentWakeSupport.js +4 -0
- package/dist/pi/piHarness.d.ts +10 -1
- package/dist/pi/piHarness.d.ts.map +1 -1
- package/dist/pi/piHarness.js +61 -8
- package/dist/pi/prompts.d.ts +1 -0
- package/dist/pi/prompts.d.ts.map +1 -1
- package/dist/pi/prompts.js +24 -0
- package/dist/pi/turnTrace.d.ts.map +1 -1
- package/dist/pi/turnTrace.js +5 -8
- package/dist/pi/worldTrajectory.d.ts +1 -1
- package/dist/pi/worldTrajectory.d.ts.map +1 -1
- package/dist/pi/worldTrajectory.js +3 -3
- package/dist/runtime/agySubscriptionBootstrap.d.ts +16 -0
- package/dist/runtime/agySubscriptionBootstrap.d.ts.map +1 -0
- package/dist/runtime/agySubscriptionBootstrap.js +80 -0
- package/dist/runtime/agySubscriptionRealm.d.ts +38 -0
- package/dist/runtime/agySubscriptionRealm.d.ts.map +1 -0
- package/dist/runtime/agySubscriptionRealm.js +242 -0
- package/dist/runtime/attention.d.ts +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 +20 -9
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { trackCliChild } from "./cliProcess.js";
|
|
3
|
+
import { cliChildEnvironment } from "./cliEnvironment.js";
|
|
4
|
+
import { codexFilesystemRules } from "./codexFilesystemRules.js";
|
|
5
|
+
export const GROK_STRICT_SANDBOX_PROFILE = "strict";
|
|
6
|
+
export const renderGrokSandboxArgs = (commandArgs, profile) => [...assertSafeGrokCommandArgs(commandArgs), "--sandbox", profile];
|
|
7
|
+
/**
|
|
8
|
+
* Codex's `--json` stream is unconditional: it is the only output shape that
|
|
9
|
+
* carries `turn.completed.usage`, and an unmetered Codex turn is one whose
|
|
10
|
+
* subscription cost is invisible. The guarded arguments make this Daimon's
|
|
11
|
+
* security and metering boundary rather than a caller-controlled format.
|
|
12
|
+
*
|
|
13
|
+
* `model`/`reasoningEffort` come from parsed, bounded organization-runtime
|
|
14
|
+
* config, but are rendered defensively anyway: each is emitted as a single
|
|
15
|
+
* `--flag=value` argv token (never a bare flag followed by a separate value
|
|
16
|
+
* token), so a value that itself looks like a flag (e.g. `--sandbox`) can
|
|
17
|
+
* never be parsed as a second, independent argument — the same shape already
|
|
18
|
+
* used below for `mcp_servers.daimon.url=`. Omitting both fields leaves Codex's
|
|
19
|
+
* model defaults unchanged.
|
|
20
|
+
*
|
|
21
|
+
* The per-wake MCP server is always enabled and required. Otherwise Codex can
|
|
22
|
+
* continue a normal turn with only built-in tools after MCP startup fails.
|
|
23
|
+
* Subscription apps and installed plugins are not caller-declared tools.
|
|
24
|
+
* Disable their discovery per invocation, including with strict config: the
|
|
25
|
+
* CLI's defaults can otherwise add them even when user config is ignored.
|
|
26
|
+
*/
|
|
27
|
+
export const renderCodexArgs = (options, cwd, endpoint, sandbox = options.codexSandbox?.mode ?? process.env.DAIMON_CODEX_SANDBOX ?? "danger-full-access") => {
|
|
28
|
+
const strictPolicy = options.codexSandbox;
|
|
29
|
+
if (strictPolicy !== undefined && (strictPolicy.mode !== "workspace-write" || strictPolicy.networkAccess !== false || strictPolicy.webSearch !== "disabled" || Object.keys(strictPolicy).length !== 3)) {
|
|
30
|
+
throw new Error("Codex sandbox policy is Daimon-owned and must be workspace-write with network and web search disabled");
|
|
31
|
+
}
|
|
32
|
+
const effectiveSandbox = strictPolicy?.mode ?? sandbox;
|
|
33
|
+
const profileName = "daimon-strict";
|
|
34
|
+
const policyArgs = strictPolicy === undefined ? [] : [
|
|
35
|
+
"--ignore-user-config",
|
|
36
|
+
"--ignore-rules",
|
|
37
|
+
"--strict-config",
|
|
38
|
+
"-c", "web_search=\"disabled\"",
|
|
39
|
+
"-c", `default_permissions=${JSON.stringify(profileName)}`,
|
|
40
|
+
"-c", renderCodexPermissionProfile(profileName, options.codexSandboxProtectedPaths ?? [], options.codexSandboxReadablePaths ?? [], cwd),
|
|
41
|
+
"-c", "approval_policy=\"never\"",
|
|
42
|
+
"-c", `mcp_servers={daimon={url=\"${endpoint}\",enabled=true,default_tools_approval_mode=\"approve\"}}`
|
|
43
|
+
];
|
|
44
|
+
return [...assertSafeCodexCommandArgs(options.commandArgs, strictPolicy !== undefined), "exec", ...(strictPolicy === undefined ? ["--sandbox", effectiveSandbox] : []), ...policyArgs, "--skip-git-repo-check",
|
|
45
|
+
...(options.model === undefined ? [] : [`--model=${options.model}`]),
|
|
46
|
+
...(options.reasoningEffort === undefined ? [] : ["-c", `model_reasoning_effort=${options.reasoningEffort}`]),
|
|
47
|
+
"--color", "never", "--json", "-C", cwd,
|
|
48
|
+
"-c", `mcp_servers.daimon.url=${endpoint}`,
|
|
49
|
+
"-c", "features.apps=false", "-c", "features.plugins=false",
|
|
50
|
+
"-c", "mcp_servers.daimon.enabled=true",
|
|
51
|
+
"-c", "mcp_servers.daimon.required=true", "-"];
|
|
52
|
+
};
|
|
53
|
+
export const renderCodexPermissionProfile = (profileName, protectedPaths, readablePaths = [], workspacePath) => {
|
|
54
|
+
const filesystem = {
|
|
55
|
+
":workspace_roots": { ".": "write" },
|
|
56
|
+
...codexFilesystemRules(protectedPaths, readablePaths, workspacePath)
|
|
57
|
+
};
|
|
58
|
+
return `permissions=${tomlInline({ [profileName]: {
|
|
59
|
+
extends: ":workspace",
|
|
60
|
+
filesystem,
|
|
61
|
+
network: { enabled: false }
|
|
62
|
+
} })}`;
|
|
63
|
+
};
|
|
64
|
+
/**
|
|
65
|
+
* AGY's headless invocation.
|
|
66
|
+
*
|
|
67
|
+
* `--output-format stream-json` is unconditional: it is the only shape that
|
|
68
|
+
* carries `result.usage`, and an AGY turn that is not metered is an AGY turn
|
|
69
|
+
* whose subscription cost is invisible (see `agyHeadlessResult.ts`).
|
|
70
|
+
*
|
|
71
|
+
* `--dangerously-skip-permissions` is required for tools to work at all. AGY's
|
|
72
|
+
* default headless permission mode is `request-review`, and there is no
|
|
73
|
+
* reviewer inside a container, so a tool call can never be approved without it;
|
|
74
|
+
* the live probe that proved AGY's MCP tool calling ran with exactly this flag
|
|
75
|
+
* and reported `permission_mode: always-proceed`. Every Daimon CLI agent mounts
|
|
76
|
+
* at least the protected bash tool (`piHarness.ts`), so there is no AGY wake
|
|
77
|
+
* for which this is unnecessary and no conditional worth forking behavior over.
|
|
78
|
+
*
|
|
79
|
+
* SECURITY: the flag also auto-approves AGY's own ~50 built-in tools —
|
|
80
|
+
* `run_command`, `write_to_file`, the browser tools — none of which Daimon
|
|
81
|
+
* mediates. Inside the container that is the exposure Codex already has
|
|
82
|
+
* (`--sandbox danger-full-access`), but unlike Grok there is no kernel-enforced
|
|
83
|
+
* per-agent profile confining it to this agent's own workspace and runtime
|
|
84
|
+
* home. `DAIMON_AGY_SANDBOX=1` opts into AGY's own terminal-restricting
|
|
85
|
+
* sandbox; it is off by default only because its interaction with the MCP
|
|
86
|
+
* transport could not be verified without spending the operator's subscription
|
|
87
|
+
* quota, and shipping an unverified default that silently disables every tool
|
|
88
|
+
* would be worse than shipping the exposure with this note on it.
|
|
89
|
+
*/
|
|
90
|
+
export const renderAgyArgs = (options, prompt, sandbox = process.env.DAIMON_AGY_SANDBOX === "1") => [
|
|
91
|
+
...assertSafeAgyCommandArgs(options.commandArgs),
|
|
92
|
+
"--print", prompt,
|
|
93
|
+
"--output-format", "stream-json",
|
|
94
|
+
"--dangerously-skip-permissions",
|
|
95
|
+
...(sandbox ? ["--sandbox"] : []),
|
|
96
|
+
...(options.timeoutMs === undefined ? [] : ["--print-timeout", `${options.timeoutMs}ms`])
|
|
97
|
+
];
|
|
98
|
+
export const spawnEngine = (options, prompt, input, endpoint, wakeId) => {
|
|
99
|
+
const command = options.command ?? options.engine;
|
|
100
|
+
const env = cliChildEnvironment([
|
|
101
|
+
...(options.redactedEnvironmentNames ?? []),
|
|
102
|
+
...(input.daimonSecretEnvironmentNames ?? [])
|
|
103
|
+
], input.runtimeHomePath, {
|
|
104
|
+
dbusSessionBusAddress: options.engine === "agy" ? options.dbusSessionBusAddress : undefined,
|
|
105
|
+
engine: options.engine,
|
|
106
|
+
executablePath: options.command,
|
|
107
|
+
engineHomePath: options.engineHomePath,
|
|
108
|
+
wakeId
|
|
109
|
+
});
|
|
110
|
+
if (options.engine === "codex") {
|
|
111
|
+
const child = trackCliChild(spawn(command, renderCodexArgs(options, input.cwd, endpoint), { cwd: input.cwd, env, detached: process.platform !== "win32", stdio: ["pipe", "pipe", "pipe"] }));
|
|
112
|
+
child.stdin.on("error", () => undefined);
|
|
113
|
+
child.stdin.write(prompt);
|
|
114
|
+
child.stdin.end();
|
|
115
|
+
return child;
|
|
116
|
+
}
|
|
117
|
+
// Production supplies a Daimon-owned custom profile whose enforcement and
|
|
118
|
+
// explicit realm/peer denies are verified before every Grok process.
|
|
119
|
+
const args = options.engine === "grok"
|
|
120
|
+
? [...renderGrokSandboxArgs(options.commandArgs, options.grokSandboxProfile ?? GROK_STRICT_SANDBOX_PROFILE), "--always-approve", "--no-subagents", "--single", prompt, "--no-memory", "--disable-web-search", "--cwd", input.cwd,
|
|
121
|
+
"--output-format", "streaming-messages-json"]
|
|
122
|
+
: renderAgyArgs(options, prompt);
|
|
123
|
+
return trackCliChild(spawn(command, args, { cwd: input.cwd, env, detached: process.platform !== "win32", stdio: ["ignore", "pipe", "pipe"] }));
|
|
124
|
+
};
|
|
125
|
+
/**
|
|
126
|
+
* AGY's output format, permission mode, sandbox, and session continuity are
|
|
127
|
+
* Daimon-owned, exactly as Grok's sandbox and approval flags are. A caller
|
|
128
|
+
* cannot re-open the permission boundary, silence the metering stream, or turn
|
|
129
|
+
* a per-wake cold process into a resumed conversation through `commandArgs`.
|
|
130
|
+
*/
|
|
131
|
+
const assertSafeAgyCommandArgs = (args) => {
|
|
132
|
+
const values = args ?? [];
|
|
133
|
+
if (values.some((value) => /^(?:--dangerously-skip-permissions|--sandbox|--output-format|--print|--prompt|--prompt-interactive|--mode|--continue|--conversation|-p|-i|-c)(?:=|$)/u.test(value))) {
|
|
134
|
+
throw new Error("AGY security-boundary arguments are Daimon-owned");
|
|
135
|
+
}
|
|
136
|
+
return values;
|
|
137
|
+
};
|
|
138
|
+
/** Caller arguments cannot reopen Codex's sandbox, output, cwd, or config boundary. */
|
|
139
|
+
const assertSafeCodexCommandArgs = (args, strictPolicy = false) => {
|
|
140
|
+
const values = args ?? [];
|
|
141
|
+
const pattern = /^(?:--json|--sandbox|--dangerously-bypass-approvals-and-sandbox|--output-last-message|--config|--ignore-user-config|--ignore-rules|--skip-git-repo-check|--color|--cd|--enable|-c|-C)(?:=|$)/u;
|
|
142
|
+
const strictPattern = /^(?:--strict-config|--profile|-p|-P|--permissions-profile|--enable|--disable|--add-dir|--search)(?:=|$)|^(?:default_permissions|permissions)(?:=|\.)/u;
|
|
143
|
+
if (values.some((value) => pattern.test(value) || (strictPolicy && strictPattern.test(value)))) {
|
|
144
|
+
throw new Error("Codex security-boundary arguments are Daimon-owned");
|
|
145
|
+
}
|
|
146
|
+
return values;
|
|
147
|
+
};
|
|
148
|
+
const assertSafeGrokCommandArgs = (args) => {
|
|
149
|
+
const values = args ?? [];
|
|
150
|
+
if (values.some((value) => /^(?:--sandbox|--always-approve|--permission-mode|--leader-socket)(?:=|$)/u.test(value))) {
|
|
151
|
+
throw new Error("Grok security-boundary arguments are Daimon-owned");
|
|
152
|
+
}
|
|
153
|
+
return values;
|
|
154
|
+
};
|
|
155
|
+
function tomlInline(value) {
|
|
156
|
+
if (typeof value === "string")
|
|
157
|
+
return JSON.stringify(value);
|
|
158
|
+
if (typeof value === "boolean")
|
|
159
|
+
return value ? "true" : "false";
|
|
160
|
+
if (value !== null && typeof value === "object" && !Array.isArray(value)) {
|
|
161
|
+
return `{${Object.entries(value).map(([key, entry]) => `${JSON.stringify(key)}=${tomlInline(entry)}`).join(",")}}`;
|
|
162
|
+
}
|
|
163
|
+
throw new Error("unsupported Codex permission profile value");
|
|
164
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
type CliEnvironmentIntent = Readonly<{
|
|
2
|
+
dbusSessionBusAddress?: string;
|
|
3
|
+
engine?: "codex" | "grok" | "agy";
|
|
4
|
+
executablePath?: string;
|
|
5
|
+
engineHomePath?: string;
|
|
6
|
+
wakeId?: string;
|
|
7
|
+
}>;
|
|
8
|
+
export declare const DAIMON_WAKE_ID_ENV: "DAIMON_WAKE_ID";
|
|
9
|
+
/** Build a positive child environment; agent CLIs never inherit host secrets. */
|
|
10
|
+
export declare const cliChildEnvironment: (_redactedNames: readonly string[], runtimeHomePath?: string, intent?: CliEnvironmentIntent) => NodeJS.ProcessEnv;
|
|
11
|
+
export {};
|
|
12
|
+
//# sourceMappingURL=cliEnvironment.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cliEnvironment.d.ts","sourceRoot":"","sources":["../../src/pi/cliEnvironment.ts"],"names":[],"mappings":"AAEA,KAAK,oBAAoB,GAAG,QAAQ,CAAC;IACnC,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,MAAM,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,KAAK,CAAC;IAClC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC,CAAC;AAEH,eAAO,MAAM,kBAAkB,EAAG,gBAAyB,CAAC;AAE5D,iFAAiF;AACjF,eAAO,MAAM,mBAAmB,GAC9B,gBAAgB,SAAS,MAAM,EAAE,EAAE,kBAAkB,MAAM,EAAE,SAAQ,oBAAyB,KAC7F,MAAM,CAAC,UA2BT,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
export const DAIMON_WAKE_ID_ENV = "DAIMON_WAKE_ID";
|
|
3
|
+
/** Build a positive child environment; agent CLIs never inherit host secrets. */
|
|
4
|
+
export const cliChildEnvironment = (_redactedNames, runtimeHomePath, intent = {}) => {
|
|
5
|
+
if (runtimeHomePath === undefined) {
|
|
6
|
+
// This legacy branch is only used by the standalone Pi helpers, which do
|
|
7
|
+
// not claim production organization-runtime isolation.
|
|
8
|
+
return { PATH: process.env.PATH, LANG: process.env.LANG ?? "C", LC_ALL: process.env.LC_ALL ?? "C", TZ: process.env.TZ ?? "UTC" };
|
|
9
|
+
}
|
|
10
|
+
const engine = intent.engine;
|
|
11
|
+
const engineVariable = engine === "codex" ? "CODEX_HOME" : engine === "grok" ? "GROK_HOME" : engine === "agy" ? "ANTIGRAVITY_CLI_HOME" : undefined;
|
|
12
|
+
const engineHome = intent.engineHomePath;
|
|
13
|
+
const keyringBus = engine === "agy" ? localSecretServiceBus(intent.dbusSessionBusAddress) : undefined;
|
|
14
|
+
return {
|
|
15
|
+
// The executable is pinned absolutely. PATH remains only for a trusted
|
|
16
|
+
// interpreter in a local shebang (and never selects the engine itself).
|
|
17
|
+
PATH: intent.executablePath === undefined ? process.env.PATH : `${path.dirname(intent.executablePath)}${path.delimiter}${path.dirname(process.execPath)}`,
|
|
18
|
+
LANG: process.env.LANG ?? "C",
|
|
19
|
+
LC_ALL: process.env.LC_ALL ?? "C",
|
|
20
|
+
TZ: process.env.TZ ?? "UTC",
|
|
21
|
+
HOME: runtimeHomePath,
|
|
22
|
+
XDG_CONFIG_HOME: `${runtimeHomePath}/.config`,
|
|
23
|
+
XDG_DATA_HOME: `${runtimeHomePath}/.local/share`,
|
|
24
|
+
XDG_STATE_HOME: `${runtimeHomePath}/.local/state`,
|
|
25
|
+
XDG_CACHE_HOME: `${runtimeHomePath}/.cache`,
|
|
26
|
+
TMPDIR: `${runtimeHomePath}/.tmp`,
|
|
27
|
+
...(engineVariable === undefined || engineHome === undefined ? {} : { [engineVariable]: engineHome }),
|
|
28
|
+
...(keyringBus === undefined ? {} : { DBUS_SESSION_BUS_ADDRESS: keyringBus }),
|
|
29
|
+
...(intent.wakeId === undefined ? {} : { [DAIMON_WAKE_ID_ENV]: intent.wakeId })
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
const localSecretServiceBus = (value) => value !== undefined && /^unix:(?:path|abstract)=[^;,\r\n]+$/u.test(value) ? value : undefined;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { type ChildProcess } from "node:child_process";
|
|
2
|
+
/**
|
|
3
|
+
* Per-wake MCP endpoint registration for the CLI engines that cannot take the
|
|
4
|
+
* endpoint on their own command line.
|
|
5
|
+
*
|
|
6
|
+
* Codex takes `-c mcp_servers.daimon.url=<endpoint>` per invocation and needs
|
|
7
|
+
* nothing here. AGY is config-file driven, so Daimon registers the ephemeral
|
|
8
|
+
* endpoint before the turn and removes it afterwards through its own `mcp
|
|
9
|
+
* add`/`mcp remove` subcommands. Grok no longer uses this path: its project
|
|
10
|
+
* scope is ignored in untrusted workspaces on 1.0.34, so its endpoint is written
|
|
11
|
+
* into the agent's Daimon-owned GROK_HOME (`grokHomeMcpRegistration.ts`).
|
|
12
|
+
*
|
|
13
|
+
* The registration is deliberately performed by the engine CLI rather than by
|
|
14
|
+
* writing its config file directly: the file format belongs to the engine, and
|
|
15
|
+
* a format change absorbed by `mcp add` would silently disable every tool if
|
|
16
|
+
* Daimon hand-wrote it instead.
|
|
17
|
+
*/
|
|
18
|
+
export type CliMcpRegistration = Readonly<{
|
|
19
|
+
close: () => Promise<void>;
|
|
20
|
+
}>;
|
|
21
|
+
export type CliMcpRegistrationInput = Readonly<{
|
|
22
|
+
addArgs: readonly string[];
|
|
23
|
+
command: string;
|
|
24
|
+
cwd: string;
|
|
25
|
+
env: NodeJS.ProcessEnv;
|
|
26
|
+
failureClassifier?: (diagnostic: string) => Error | undefined;
|
|
27
|
+
onChild: (child: ChildProcess) => void;
|
|
28
|
+
onChildSettled: (child: ChildProcess) => void;
|
|
29
|
+
removeArgs: readonly string[];
|
|
30
|
+
secretValues: readonly string[];
|
|
31
|
+
verify?: () => Promise<void>;
|
|
32
|
+
}>;
|
|
33
|
+
/**
|
|
34
|
+
* Registers the endpoint, returning a single-shot remover.
|
|
35
|
+
*
|
|
36
|
+
* `verify` is the caller's production authority (the Grok sandbox profile
|
|
37
|
+
* check); it runs before both the add and the remove so a registration can
|
|
38
|
+
* never be issued against an unverified engine.
|
|
39
|
+
*/
|
|
40
|
+
export declare const registerCliMcpServer: (input: CliMcpRegistrationInput) => Promise<CliMcpRegistration>;
|
|
41
|
+
/** The MCP server name every CLI engine registers Daimon's per-wake endpoint under. */
|
|
42
|
+
export declare const DAIMON_MCP_SERVER_NAME: "daimon";
|
|
43
|
+
/**
|
|
44
|
+
* `agy mcp add --type http <name> <url>`.
|
|
45
|
+
*
|
|
46
|
+
* AGY has no per-invocation MCP flag, so this writes into the config file AGY
|
|
47
|
+
* reads at `$HOME/.gemini/config/mcp_config.json`. That is safe to do per wake
|
|
48
|
+
* because Daimon already gives every AGY agent its own `HOME`
|
|
49
|
+
* (`runtimeHomePath`, see `cliChildEnvironment`): two agents in one
|
|
50
|
+
* organization cannot collide, and a developer's real `~/.gemini` is never on
|
|
51
|
+
* the path a runtime child sees. `add` is an upsert, so a stale entry left by a
|
|
52
|
+
* crashed wake is replaced rather than duplicated.
|
|
53
|
+
*
|
|
54
|
+
* No `--header` is passed: Daimon's tool endpoint is an unauthenticated
|
|
55
|
+
* loopback listener on an ephemeral port, exactly as Codex and Grok receive it.
|
|
56
|
+
* Adding a bearer header here would put a secret in `argv` and in a file on the
|
|
57
|
+
* agent's durable runtime home for no gain.
|
|
58
|
+
*/
|
|
59
|
+
export declare const renderAgyMcpAddArgs: (commandArgs: readonly string[] | undefined, endpoint: string) => string[];
|
|
60
|
+
export declare const renderAgyMcpRemoveArgs: (commandArgs: readonly string[] | undefined) => string[];
|
|
61
|
+
//# sourceMappingURL=cliMcpRegistration.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cliMcpRegistration.d.ts","sourceRoot":"","sources":["../../src/pi/cliMcpRegistration.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAK9D;;;;;;;;;;;;;;;GAeG;AACH,MAAM,MAAM,kBAAkB,GAAG,QAAQ,CAAC;IAAE,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAAE,CAAC,CAAC;AAE1E,MAAM,MAAM,uBAAuB,GAAG,QAAQ,CAAC;IAC7C,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IACvB,iBAAiB,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,KAAK,GAAG,SAAS,CAAC;IAC9D,OAAO,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC;IACvC,cAAc,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC;IAC9C,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;IAC9B,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;IAChC,MAAM,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9B,CAAC,CAAC;AAsCH;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,GAC/B,OAAO,uBAAuB,KAC7B,OAAO,CAAC,kBAAkB,CAU5B,CAAC;AAEF,uFAAuF;AACvF,eAAO,MAAM,sBAAsB,EAAG,QAAiB,CAAC;AAExD;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,mBAAmB,GAAI,aAAa,SAAS,MAAM,EAAE,GAAG,SAAS,EAAE,UAAU,MAAM,KAAG,MAAM,EACb,CAAC;AAE7F,eAAO,MAAM,sBAAsB,GAAI,aAAa,SAAS,MAAM,EAAE,GAAG,SAAS,KAAG,MAAM,EACvB,CAAC"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { readChild } from "./cliChildOutput.js";
|
|
3
|
+
import { terminateChild, trackCliChild } from "./cliProcess.js";
|
|
4
|
+
/**
|
|
5
|
+
* `swept` decides whether the session's dispose path may kill this child.
|
|
6
|
+
*
|
|
7
|
+
* The *add* is swept: a dispose that arrives while the endpoint is still being
|
|
8
|
+
* registered should tear that child down with everything else. The *remove* is
|
|
9
|
+
* deliberately not, because dispose is precisely the caller that is waiting on
|
|
10
|
+
* it to finish — sweeping it makes the session terminate the cleanup it is
|
|
11
|
+
* awaiting, and the resulting `CLI engine exited SIGTERM` is then reported as a
|
|
12
|
+
* failed `stop()` for a wake that was cancelled on purpose. It stays bounded
|
|
13
|
+
* without the sweep: `readChild`'s 30s deadline aborts and terminates it, and
|
|
14
|
+
* `trackCliChild` still owns it for process exit.
|
|
15
|
+
*/
|
|
16
|
+
const runRegistrationCommand = async (input, args, swept) => {
|
|
17
|
+
const child = trackCliChild(spawn(input.command, args, {
|
|
18
|
+
cwd: input.cwd,
|
|
19
|
+
env: input.env,
|
|
20
|
+
detached: process.platform !== "win32",
|
|
21
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
22
|
+
}));
|
|
23
|
+
if (swept)
|
|
24
|
+
input.onChild(child);
|
|
25
|
+
try {
|
|
26
|
+
await readChild(child, 30_000, input.secretValues, {
|
|
27
|
+
...(input.failureClassifier === undefined ? {} : { failureClassifier: input.failureClassifier })
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
finally {
|
|
31
|
+
// An engine CLI may let an auxiliary process outlive its leader. Do not
|
|
32
|
+
// release the tracked setup child until its detached group is quiescent.
|
|
33
|
+
await terminateChild(child);
|
|
34
|
+
if (swept)
|
|
35
|
+
input.onChildSettled(child);
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* Registers the endpoint, returning a single-shot remover.
|
|
40
|
+
*
|
|
41
|
+
* `verify` is the caller's production authority (the Grok sandbox profile
|
|
42
|
+
* check); it runs before both the add and the remove so a registration can
|
|
43
|
+
* never be issued against an unverified engine.
|
|
44
|
+
*/
|
|
45
|
+
export const registerCliMcpServer = async (input) => {
|
|
46
|
+
await input.verify?.();
|
|
47
|
+
await runRegistrationCommand(input, input.addArgs, true);
|
|
48
|
+
let closePromise;
|
|
49
|
+
return {
|
|
50
|
+
close: () => closePromise ??= (async () => {
|
|
51
|
+
await input.verify?.();
|
|
52
|
+
await runRegistrationCommand(input, input.removeArgs, false);
|
|
53
|
+
})()
|
|
54
|
+
};
|
|
55
|
+
};
|
|
56
|
+
/** The MCP server name every CLI engine registers Daimon's per-wake endpoint under. */
|
|
57
|
+
export const DAIMON_MCP_SERVER_NAME = "daimon";
|
|
58
|
+
/**
|
|
59
|
+
* `agy mcp add --type http <name> <url>`.
|
|
60
|
+
*
|
|
61
|
+
* AGY has no per-invocation MCP flag, so this writes into the config file AGY
|
|
62
|
+
* reads at `$HOME/.gemini/config/mcp_config.json`. That is safe to do per wake
|
|
63
|
+
* because Daimon already gives every AGY agent its own `HOME`
|
|
64
|
+
* (`runtimeHomePath`, see `cliChildEnvironment`): two agents in one
|
|
65
|
+
* organization cannot collide, and a developer's real `~/.gemini` is never on
|
|
66
|
+
* the path a runtime child sees. `add` is an upsert, so a stale entry left by a
|
|
67
|
+
* crashed wake is replaced rather than duplicated.
|
|
68
|
+
*
|
|
69
|
+
* No `--header` is passed: Daimon's tool endpoint is an unauthenticated
|
|
70
|
+
* loopback listener on an ephemeral port, exactly as Codex and Grok receive it.
|
|
71
|
+
* Adding a bearer header here would put a secret in `argv` and in a file on the
|
|
72
|
+
* agent's durable runtime home for no gain.
|
|
73
|
+
*/
|
|
74
|
+
export const renderAgyMcpAddArgs = (commandArgs, endpoint) => [...(commandArgs ?? []), "mcp", "add", "--type", "http", DAIMON_MCP_SERVER_NAME, endpoint];
|
|
75
|
+
export const renderAgyMcpRemoveArgs = (commandArgs) => [...(commandArgs ?? []), "mcp", "remove", DAIMON_MCP_SERVER_NAME];
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ChildProcess } from "node:child_process";
|
|
2
|
+
export declare class CliProcessCleanupError extends Error {
|
|
3
|
+
constructor(operation: string, cause?: unknown);
|
|
4
|
+
}
|
|
5
|
+
export declare const trackCliChild: (child: ChildProcess) => ChildProcess;
|
|
6
|
+
export declare const terminateChild: (child: ChildProcess) => Promise<void>;
|
|
7
|
+
//# sourceMappingURL=cliProcess.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cliProcess.d.ts","sourceRoot":"","sources":["../../src/pi/cliProcess.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAQvD,qBAAa,sBAAuB,SAAQ,KAAK;gBAC5B,SAAS,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO;CAItD;AAED,eAAO,MAAM,aAAa,GAAI,OAAO,YAAY,KAAG,YAanD,CAAC;AA8FF,eAAO,MAAM,cAAc,GAAU,OAAO,YAAY,KAAG,OAAO,CAAC,IAAI,CAqBtE,CAAC"}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { readdir, readFile } from "node:fs/promises";
|
|
2
|
+
const childStates = new WeakMap();
|
|
3
|
+
const delay = (milliseconds) => new Promise((resolve) => setTimeout(resolve, milliseconds));
|
|
4
|
+
export class CliProcessCleanupError extends Error {
|
|
5
|
+
constructor(operation, cause) {
|
|
6
|
+
super(`CLI process cleanup failed while ${operation}`, { cause });
|
|
7
|
+
this.name = "CliProcessCleanupError";
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
export const trackCliChild = (child) => {
|
|
11
|
+
if (childStates.has(child))
|
|
12
|
+
return child;
|
|
13
|
+
let resolveClose;
|
|
14
|
+
// Keep the process group id at spawn time. `child.pid` is no longer a useful
|
|
15
|
+
// source of truth after the leader exits while one of its descendants lives.
|
|
16
|
+
const state = {
|
|
17
|
+
closed: false,
|
|
18
|
+
close: new Promise((resolve) => { resolveClose = resolve; }),
|
|
19
|
+
...(process.platform === "win32" || child.pid === undefined ? {} : { pgid: child.pid })
|
|
20
|
+
};
|
|
21
|
+
child.once("close", () => { state.closed = true; resolveClose(); });
|
|
22
|
+
childStates.set(child, state);
|
|
23
|
+
return child;
|
|
24
|
+
};
|
|
25
|
+
const groupExists = (pgid) => {
|
|
26
|
+
try {
|
|
27
|
+
process.kill(-pgid, 0);
|
|
28
|
+
return true;
|
|
29
|
+
}
|
|
30
|
+
catch (error) {
|
|
31
|
+
if (error.code === "ESRCH")
|
|
32
|
+
return false;
|
|
33
|
+
throw new CliProcessCleanupError(`inspecting process group ${pgid}`, error);
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
const parseLinuxProcessState = (stat) => {
|
|
37
|
+
const commandEnd = stat.lastIndexOf(")");
|
|
38
|
+
if (commandEnd < 0)
|
|
39
|
+
return undefined;
|
|
40
|
+
const fields = stat.slice(commandEnd + 1).trim().split(/\s+/u);
|
|
41
|
+
const group = Number(fields[2]);
|
|
42
|
+
return fields.length >= 3 && Number.isInteger(group) ? { state: fields[0], group } : undefined;
|
|
43
|
+
};
|
|
44
|
+
const linuxGroupScan = async (pgid, procRoot = "/proc") => {
|
|
45
|
+
let entries;
|
|
46
|
+
try {
|
|
47
|
+
entries = await readdir(procRoot);
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
return "unknown";
|
|
51
|
+
}
|
|
52
|
+
for (const entry of entries) {
|
|
53
|
+
if (!/^\d+$/u.test(entry))
|
|
54
|
+
continue;
|
|
55
|
+
try {
|
|
56
|
+
const processState = parseLinuxProcessState(await readFile(`${procRoot}/${entry}/stat`, "utf8"));
|
|
57
|
+
if (processState?.group !== pgid)
|
|
58
|
+
continue;
|
|
59
|
+
if (processState.state !== "Z" && processState.state !== "X")
|
|
60
|
+
return "live";
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
// ENOENT is the process exiting mid-scan, which is exactly what settling
|
|
64
|
+
// looks like; anything else means the snapshot cannot be trusted.
|
|
65
|
+
if (error.code !== "ENOENT")
|
|
66
|
+
return "unknown";
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return "settled";
|
|
70
|
+
};
|
|
71
|
+
const groupSettled = async (pgid) => {
|
|
72
|
+
if (!groupExists(pgid))
|
|
73
|
+
return true;
|
|
74
|
+
if (process.platform !== "linux")
|
|
75
|
+
return false;
|
|
76
|
+
return await linuxGroupScan(pgid) === "settled";
|
|
77
|
+
};
|
|
78
|
+
const signalGroup = (pgid, signal) => {
|
|
79
|
+
try {
|
|
80
|
+
process.kill(-pgid, signal);
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
83
|
+
catch (error) {
|
|
84
|
+
if (error.code === "ESRCH")
|
|
85
|
+
return false;
|
|
86
|
+
throw new CliProcessCleanupError(`signaling process group ${pgid}`, error);
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
const waitForGroupSettled = async (pgid, milliseconds) => {
|
|
90
|
+
const deadline = Date.now() + milliseconds;
|
|
91
|
+
while (true) {
|
|
92
|
+
try {
|
|
93
|
+
if (await groupSettled(pgid))
|
|
94
|
+
return true;
|
|
95
|
+
}
|
|
96
|
+
catch (error) {
|
|
97
|
+
// EPERM is not evidence that a group is settled. Keep waiting for
|
|
98
|
+
// ESRCH or, on Linux, a /proc snapshot containing only exited zombies.
|
|
99
|
+
if (!isPermissionError(error) || Date.now() >= deadline)
|
|
100
|
+
throw error;
|
|
101
|
+
}
|
|
102
|
+
if (Date.now() >= deadline)
|
|
103
|
+
return false;
|
|
104
|
+
await delay(10);
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
const isPermissionError = (error) => error instanceof CliProcessCleanupError
|
|
108
|
+
&& error.cause?.code === "EPERM";
|
|
109
|
+
export const terminateChild = async (child) => {
|
|
110
|
+
trackCliChild(child);
|
|
111
|
+
const state = childStates.get(child);
|
|
112
|
+
const pgid = state.pgid;
|
|
113
|
+
if (pgid !== undefined && !await groupSettled(pgid)) {
|
|
114
|
+
if (signalGroup(pgid, "SIGTERM") && !await waitForGroupSettled(pgid, 1_000)) {
|
|
115
|
+
signalGroup(pgid, "SIGKILL");
|
|
116
|
+
if (!await waitForGroupSettled(pgid, 1_000)) {
|
|
117
|
+
throw new CliProcessCleanupError(`waiting for process group ${pgid} to exit`);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
else if (child.exitCode === null && child.signalCode === null) {
|
|
122
|
+
child.kill("SIGTERM");
|
|
123
|
+
}
|
|
124
|
+
// A `close` event proves that Node released its pipes. ESRCH, or a Linux
|
|
125
|
+
// process-group snapshot containing only exited zombies, proves that no
|
|
126
|
+
// detached descendant can still execute. Both are required for success.
|
|
127
|
+
if (!state.closed)
|
|
128
|
+
await state.close;
|
|
129
|
+
if (pgid !== undefined && !await groupSettled(pgid)) {
|
|
130
|
+
throw new CliProcessCleanupError(`waiting for process group ${pgid} to exit`);
|
|
131
|
+
}
|
|
132
|
+
};
|
package/dist/pi/cliSession.d.ts
CHANGED
|
@@ -1,46 +1,106 @@
|
|
|
1
|
-
import type { ChildProcess } from "node:child_process";
|
|
2
1
|
import type { ToolDefinition } from "@earendil-works/pi-coding-agent";
|
|
2
|
+
import type { TurnUsageOutcome } from "../runtime/turnUsageLedger.js";
|
|
3
|
+
import { type AgyTurnUsage } from "./agyHeadlessResult.js";
|
|
4
|
+
import { type CodexTurnUsage } from "./codexHeadlessResult.js";
|
|
3
5
|
import type { PiSessionLike } from "./piAgentHandle.js";
|
|
4
6
|
import type { PiSessionFactoryInput } from "./piHarness.js";
|
|
5
7
|
export type CliEngineKind = "agy" | "codex" | "grok";
|
|
8
|
+
/**
|
|
9
|
+
* The per-wake tool-call bound for AGY, and the one place it is decided.
|
|
10
|
+
*
|
|
11
|
+
* Codex and Grok leave this `undefined` — their only bound is the wake
|
|
12
|
+
* deadline. AGY does not get that treatment, for a measured reason: its
|
|
13
|
+
* terminal usage frame is the *sum* over the turn's model steps, and each tool
|
|
14
|
+
* step resends the whole context. The live capture is 13,796 total tokens for a
|
|
15
|
+
* tool-free turn and 45,381 for a turn with a single call against an
|
|
16
|
+
* empty-schema tool — one call roughly triples the wake. An unbounded loop on
|
|
17
|
+
* the one engine whose subscription quota is currently the operator's only
|
|
18
|
+
* working credential is a cost hazard, not a capability.
|
|
19
|
+
*
|
|
20
|
+
* 16 is chosen so a realistic wake is never truncated (read a few declared MCP
|
|
21
|
+
* tools, then send one or two Moltnet messages) while the worst case is bounded
|
|
22
|
+
* at roughly a quarter-million tokens instead of "whatever fits in 180s". The
|
|
23
|
+
* bound degrades gracefully rather than failing the wake: exceeding it returns
|
|
24
|
+
* `McpToolTurnLimitError` to the model as a tool *error*, so the agent can still
|
|
25
|
+
* finish its turn and reply.
|
|
26
|
+
*/
|
|
27
|
+
export declare const AGY_MAX_TOOL_TURNS = 16;
|
|
28
|
+
export { DAIMON_CODEX_WAKE_TIMEOUT_MS_ENV, DAIMON_CODEX_WAKE_TOKEN_CEILING_ENV, DAIMON_ENGINE_WAKE_TIMEOUT_MS_ENV, DAIMON_ENGINE_WAKE_TOKEN_CEILING_ENV, DEFAULT_CODEX_WAKE_TIMEOUT_MS, DEFAULT_CODEX_WAKE_TOKEN_CEILING, resolveCodexWakeTimeoutMs, resolveCodexWakeTokenCeiling, resolveEngineWakeLimitOverrides } from "./engineWakeLimits.js";
|
|
6
29
|
export type CliEngineOptions = {
|
|
7
30
|
readonly commandArgs?: readonly string[];
|
|
8
31
|
readonly command?: string;
|
|
9
|
-
|
|
32
|
+
/** Internal production authority: rechecked immediately before each child. */
|
|
33
|
+
readonly verifyExecutable?: () => Promise<void>;
|
|
34
|
+
readonly verifyRuntimePaths?: () => Promise<void>;
|
|
35
|
+
readonly engineHomePath?: string;
|
|
36
|
+
readonly maxToolTurns?: number;
|
|
10
37
|
readonly onToolsMounted?: (tools: readonly ToolDefinition[]) => void;
|
|
11
|
-
readonly timeoutMs
|
|
38
|
+
readonly timeoutMs?: number;
|
|
39
|
+
/** Daimon-owned identity envelope prepended exactly once to every wake. */
|
|
40
|
+
readonly identityPrompt?: string;
|
|
12
41
|
readonly redactedEnvironmentNames?: readonly string[];
|
|
42
|
+
/** Internal secret-file authority used only for exact reply redaction. */
|
|
43
|
+
readonly credentialSecretValues?: () => Promise<readonly string[]>;
|
|
44
|
+
/** Internal production boundary; confirms the custom kernel profile before every Grok process. */
|
|
45
|
+
readonly verifyGrokSandbox?: () => Promise<void>;
|
|
46
|
+
readonly grokSandboxProfile?: string;
|
|
47
|
+
readonly grokBrokerTurn?: (prompt: string, mcpEndpoint: string, signal: AbortSignal) => Promise<string>;
|
|
48
|
+
/** Codex only: kills the child and fails the wake once a turn's own reported usage reaches this. */
|
|
49
|
+
readonly codexTokenCeiling?: number;
|
|
50
|
+
/** Codex only: pinned model name, rendered as `--model=<value>`. Omitted, Codex resolves its own default. */
|
|
51
|
+
readonly model?: string;
|
|
52
|
+
/** Codex only: pinned `model_reasoning_effort`, rendered as `-c model_reasoning_effort=<value>`. */
|
|
53
|
+
readonly reasoningEffort?: string;
|
|
54
|
+
readonly codexSandbox?: {
|
|
55
|
+
readonly mode: "workspace-write";
|
|
56
|
+
readonly networkAccess: false;
|
|
57
|
+
readonly webSearch: "disabled";
|
|
58
|
+
};
|
|
59
|
+
/** Internal production boundary: absolute host paths denied to Codex model-run local commands. */
|
|
60
|
+
readonly codexSandboxProtectedPaths?: readonly string[];
|
|
61
|
+
/** Internal production boundary: own non-secret runtime paths a strict Codex turn may read. */
|
|
62
|
+
readonly codexSandboxReadablePaths?: readonly string[];
|
|
63
|
+
/**
|
|
64
|
+
* Advisory per-turn metering sink for the engines whose headless stream
|
|
65
|
+
* reports token usage and that do not run behind the Grok engine broker
|
|
66
|
+
* (which meters its own turns). It never fails a turn that published.
|
|
67
|
+
*
|
|
68
|
+
* `outcome` says whether the wake this usage belongs to went on to succeed.
|
|
69
|
+
* A failed wake spends real money, so it is metered exactly like a
|
|
70
|
+
* successful one and the reader tells them apart by this field rather than
|
|
71
|
+
* by the row's absence.
|
|
72
|
+
*/
|
|
73
|
+
readonly onTurnUsage?: (usage: AgyTurnUsage | CodexTurnUsage, outcome: TurnUsageOutcome) => Promise<void>;
|
|
74
|
+
/**
|
|
75
|
+
* Codex only: advisory per-model-request instrumentation, called once per
|
|
76
|
+
* wake with the thread id Codex announced on `thread.started`.
|
|
77
|
+
*
|
|
78
|
+
* The usage ledger's row is one sum per wake and cannot distinguish a cold
|
|
79
|
+
* prefix replayed per request from a context that grows per request. The
|
|
80
|
+
* per-request detail exists in the rollout Codex already writes for this
|
|
81
|
+
* thread; the thread id is the only thing that identifies *which* rollout,
|
|
82
|
+
* which is why it is carried out of the stream rather than inferred from
|
|
83
|
+
* whichever file on disk is newest. Errors here never reach the wake.
|
|
84
|
+
*/
|
|
85
|
+
readonly onCodexTurnRequests?: (threadId: string) => Promise<void>;
|
|
13
86
|
} & ({
|
|
14
87
|
readonly engine: "codex" | "grok";
|
|
15
88
|
} | {
|
|
16
|
-
|
|
89
|
+
readonly dbusSessionBusAddress?: string;
|
|
17
90
|
readonly engine: "agy";
|
|
18
|
-
readonly toolAccess: "none";
|
|
19
91
|
});
|
|
20
|
-
type
|
|
92
|
+
export type CliSessionInput = {
|
|
21
93
|
readonly cwd: string;
|
|
22
94
|
readonly customTools?: ToolDefinition[];
|
|
23
95
|
readonly daimonSecretEnvironmentNames?: readonly string[];
|
|
96
|
+
readonly runtimeHomePath?: string;
|
|
24
97
|
};
|
|
25
|
-
export declare const
|
|
26
|
-
export
|
|
27
|
-
export
|
|
98
|
+
export declare const prepareCliRuntimeHome: (runtimeHomePath: string | undefined) => Promise<void>;
|
|
99
|
+
export { terminateChild } from "./cliProcess.js";
|
|
100
|
+
export { CLI_ENGINE_MAX_DIAGNOSTIC_BYTES, CLI_ENGINE_MAX_OUTPUT_BYTES, readChild } from "./cliChildOutput.js";
|
|
28
101
|
export declare const createCliSessionFactory: (options: CliEngineOptions) => (input: PiSessionFactoryInput) => Promise<{
|
|
29
102
|
session: PiSessionLike;
|
|
30
103
|
}>;
|
|
31
|
-
export
|
|
32
|
-
|
|
33
|
-
readonly outputChars: number;
|
|
34
|
-
readonly promptChars: number;
|
|
35
|
-
readonly text: string;
|
|
36
|
-
}
|
|
37
|
-
export declare const runEngineDetailed: (engine: CliEngineKind, prompt: string, paths: {
|
|
38
|
-
readonly workspacePath: string;
|
|
39
|
-
readonly runtimeHomePath?: string;
|
|
40
|
-
}) => Promise<EngineRunResult>;
|
|
41
|
-
export declare const runEngine: (engine: CliEngineKind, prompt: string, paths: {
|
|
42
|
-
readonly workspacePath: string;
|
|
43
|
-
readonly runtimeHomePath?: string;
|
|
44
|
-
}) => Promise<string>;
|
|
45
|
-
export {};
|
|
104
|
+
export { runEngine, runEngineDetailed, type EngineRunResult } from "./cliEngineRun.js";
|
|
105
|
+
export { renderAgyArgs, renderCodexArgs, spawnEngine } from "./cliEngineSpawn.js";
|
|
46
106
|
//# sourceMappingURL=cliSession.d.ts.map
|