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