@xenosystem/agent-interface-host 0.1.3 → 0.1.5

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 (121) hide show
  1. package/dist/acp/AcpAgentRegistryService.d.ts +43 -1
  2. package/dist/acp/AcpAgentRegistryService.d.ts.map +1 -1
  3. package/dist/acp/AcpAgentRegistryService.js +200 -1
  4. package/dist/acp/AcpAgentRegistryService.js.map +1 -1
  5. package/dist/acp/AcpAgentTurnExecutionAdapter.d.ts +66 -0
  6. package/dist/acp/AcpAgentTurnExecutionAdapter.d.ts.map +1 -1
  7. package/dist/acp/AcpAgentTurnExecutionAdapter.js +182 -1
  8. package/dist/acp/AcpAgentTurnExecutionAdapter.js.map +1 -1
  9. package/dist/acp/AcpPermissionBridge.d.ts.map +1 -1
  10. package/dist/acp/AcpPermissionBridge.js +3 -3
  11. package/dist/acp/AcpPermissionBridge.js.map +1 -1
  12. package/dist/acp/AcpProcessSupervisor.d.ts +81 -0
  13. package/dist/acp/AcpProcessSupervisor.d.ts.map +1 -1
  14. package/dist/acp/AcpProcessSupervisor.js +176 -2
  15. package/dist/acp/AcpProcessSupervisor.js.map +1 -1
  16. package/dist/acp/AcpRuntimeEventMapper.d.ts.map +1 -1
  17. package/dist/acp/AcpRuntimeEventMapper.js +9 -0
  18. package/dist/acp/AcpRuntimeEventMapper.js.map +1 -1
  19. package/dist/acp/AcpSessionService.d.ts +36 -0
  20. package/dist/acp/AcpSessionService.d.ts.map +1 -1
  21. package/dist/acp/AcpSessionService.js +57 -1
  22. package/dist/acp/AcpSessionService.js.map +1 -1
  23. package/dist/acp/DurableAcpPermissionPolicyStore.d.ts.map +1 -1
  24. package/dist/acp/DurableAcpPermissionPolicyStore.js +5 -3
  25. package/dist/acp/DurableAcpPermissionPolicyStore.js.map +1 -1
  26. package/dist/acp/acpRedaction.d.ts.map +1 -1
  27. package/dist/acp/acpRedaction.js +2 -0
  28. package/dist/acp/acpRedaction.js.map +1 -1
  29. package/dist/acp/acpTypes.d.ts +111 -1
  30. package/dist/acp/acpTypes.d.ts.map +1 -1
  31. package/dist/acp/acpTypes.js +21 -1
  32. package/dist/acp/acpTypes.js.map +1 -1
  33. package/dist/index.d.ts +108 -2
  34. package/dist/index.d.ts.map +1 -1
  35. package/dist/index.js +236 -11
  36. package/dist/index.js.map +1 -1
  37. package/dist/isolation/CommandExecution.d.ts +7 -12
  38. package/dist/isolation/CommandExecution.d.ts.map +1 -1
  39. package/dist/isolation/CommandExecution.js +7 -12
  40. package/dist/isolation/CommandExecution.js.map +1 -1
  41. package/dist/isolation/CommandStream.d.ts +100 -0
  42. package/dist/isolation/CommandStream.d.ts.map +1 -0
  43. package/dist/isolation/CommandStream.js +47 -0
  44. package/dist/isolation/CommandStream.js.map +1 -0
  45. package/dist/isolation/RunExecutionEnvironment.d.ts +15 -0
  46. package/dist/isolation/RunExecutionEnvironment.d.ts.map +1 -1
  47. package/dist/isolation/RunExecutionEnvironment.js +45 -9
  48. package/dist/isolation/RunExecutionEnvironment.js.map +1 -1
  49. package/dist/isolation/RunIsolationService.d.ts +10 -5
  50. package/dist/isolation/RunIsolationService.d.ts.map +1 -1
  51. package/dist/isolation/RunIsolationService.js +7 -3
  52. package/dist/isolation/RunIsolationService.js.map +1 -1
  53. package/dist/isolation/SandboxCapabilities.d.ts +28 -0
  54. package/dist/isolation/SandboxCapabilities.d.ts.map +1 -0
  55. package/dist/isolation/SandboxCapabilities.js +33 -0
  56. package/dist/isolation/SandboxCapabilities.js.map +1 -0
  57. package/dist/isolation/SandboxCommandExecutor.d.ts +4 -7
  58. package/dist/isolation/SandboxCommandExecutor.d.ts.map +1 -1
  59. package/dist/isolation/SandboxCommandExecutor.js +6 -7
  60. package/dist/isolation/SandboxCommandExecutor.js.map +1 -1
  61. package/dist/isolation/SandboxCommandStream.d.ts +38 -0
  62. package/dist/isolation/SandboxCommandStream.d.ts.map +1 -0
  63. package/dist/isolation/SandboxCommandStream.js +232 -0
  64. package/dist/isolation/SandboxCommandStream.js.map +1 -0
  65. package/dist/isolation/shellArgv.d.ts +15 -0
  66. package/dist/isolation/shellArgv.d.ts.map +1 -0
  67. package/dist/isolation/shellArgv.js +31 -0
  68. package/dist/isolation/shellArgv.js.map +1 -0
  69. package/dist/isolation/useIdempotency.d.ts +19 -0
  70. package/dist/isolation/useIdempotency.d.ts.map +1 -0
  71. package/dist/isolation/useIdempotency.js +57 -0
  72. package/dist/isolation/useIdempotency.js.map +1 -0
  73. package/dist/localRpcTransport.d.ts +18 -0
  74. package/dist/localRpcTransport.d.ts.map +1 -1
  75. package/dist/localRpcTransport.js +38 -4
  76. package/dist/localRpcTransport.js.map +1 -1
  77. package/dist/node.d.ts +19 -0
  78. package/dist/node.d.ts.map +1 -1
  79. package/dist/node.js +19 -0
  80. package/dist/node.js.map +1 -1
  81. package/dist/observation/XenoUseRunObserver.d.ts +20 -0
  82. package/dist/observation/XenoUseRunObserver.d.ts.map +1 -1
  83. package/dist/observation/XenoUseRunObserver.js +27 -13
  84. package/dist/observation/XenoUseRunObserver.js.map +1 -1
  85. package/dist/runtime/RuntimeTimelineProjection.d.ts +2 -2
  86. package/dist/runtime/RuntimeTimelineProjection.d.ts.map +1 -1
  87. package/dist/runtime/RuntimeTimelineProjection.js +194 -1
  88. package/dist/runtime/RuntimeTimelineProjection.js.map +1 -1
  89. package/dist/sdk/DurablePendingInjectionStore.d.ts +24 -0
  90. package/dist/sdk/DurablePendingInjectionStore.d.ts.map +1 -0
  91. package/dist/sdk/DurablePendingInjectionStore.js +103 -0
  92. package/dist/sdk/DurablePendingInjectionStore.js.map +1 -0
  93. package/dist/sdk/SdkNativeAgentTurnExecutionAdapter.d.ts +81 -1
  94. package/dist/sdk/SdkNativeAgentTurnExecutionAdapter.d.ts.map +1 -1
  95. package/dist/sdk/SdkNativeAgentTurnExecutionAdapter.js +122 -3
  96. package/dist/sdk/SdkNativeAgentTurnExecutionAdapter.js.map +1 -1
  97. package/dist/sdk/pendingInjections.d.ts +83 -0
  98. package/dist/sdk/pendingInjections.d.ts.map +1 -0
  99. package/dist/sdk/pendingInjections.js +79 -0
  100. package/dist/sdk/pendingInjections.js.map +1 -0
  101. package/dist/session/AgentSessionService.d.ts +34 -0
  102. package/dist/session/AgentSessionService.d.ts.map +1 -1
  103. package/dist/session/AgentSessionService.js +85 -1
  104. package/dist/session/AgentSessionService.js.map +1 -1
  105. package/dist/session/nativeTuiSessionPty.d.ts +40 -0
  106. package/dist/session/nativeTuiSessionPty.d.ts.map +1 -0
  107. package/dist/session/nativeTuiSessionPty.js +142 -0
  108. package/dist/session/nativeTuiSessionPty.js.map +1 -0
  109. package/dist/session/nodePtyLoader.d.ts +23 -0
  110. package/dist/session/nodePtyLoader.d.ts.map +1 -0
  111. package/dist/session/nodePtyLoader.js +41 -0
  112. package/dist/session/nodePtyLoader.js.map +1 -0
  113. package/dist/session/renderSupport.d.ts +34 -0
  114. package/dist/session/renderSupport.d.ts.map +1 -1
  115. package/dist/session/renderSupport.js +39 -1
  116. package/dist/session/renderSupport.js.map +1 -1
  117. package/dist/workspace/WorkspaceHostService.d.ts +27 -2
  118. package/dist/workspace/WorkspaceHostService.d.ts.map +1 -1
  119. package/dist/workspace/WorkspaceHostService.js +221 -25
  120. package/dist/workspace/WorkspaceHostService.js.map +1 -1
  121. package/package.json +6 -6
@@ -1 +1 @@
1
- {"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../src/node.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../src/node.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAA;AAC1B,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,eAAe,EACpB,KAAK,eAAe,EACpB,KAAK,kBAAkB,GACxB,MAAM,sCAAsC,CAAA;AAC7C,cAAc,+BAA+B,CAAA;AAC7C,cAAc,qBAAqB,CAAA;AACnC,cAAc,yBAAyB,CAAA;AACvC,cAAc,0BAA0B,CAAA;AACxC,cAAc,6BAA6B,CAAA;AAC3C,cAAc,wBAAwB,CAAA;AACtC,cAAc,qBAAqB,CAAA;AACnC,cAAc,qCAAqC,CAAA;AACnD,cAAc,uCAAuC,CAAA;AACrD,cAAc,uCAAuC,CAAA;AACrD,cAAc,iCAAiC,CAAA;AAC/C,cAAc,wCAAwC,CAAA;AACtD,cAAc,uCAAuC,CAAA;AACrD,cAAc,qCAAqC,CAAA;AACnD,cAAc,2CAA2C,CAAA;AACzD,cAAc,qCAAqC,CAAA;AACnD,cAAc,sCAAsC,CAAA;AACpD,cAAc,iCAAiC,CAAA;AAC/C,cAAc,gCAAgC,CAAA;AAC9C,cAAc,iDAAiD,CAAA;AAC/D,cAAc,wCAAwC,CAAA;AACtD,cAAc,gCAAgC,CAAA;AAC9C,cAAc,kCAAkC,CAAA;AAChD,cAAc,+BAA+B,CAAA;AAC7C,cAAc,mCAAmC,CAAA;AACjD,cAAc,mCAAmC,CAAA;AACjD,cAAc,qCAAqC,CAAA;AACnD,cAAc,8CAA8C,CAAA;AAC5D,cAAc,iCAAiC,CAAA;AAC/C,cAAc,mCAAmC,CAAA;AACjD,cAAc,yBAAyB,CAAA;AACvC,cAAc,yBAAyB,CAAA;AACvC,cAAc,2CAA2C,CAAA;AACzD,cAAc,4BAA4B,CAAA;AAC1C,cAAc,+BAA+B,CAAA;AAC7C,cAAc,2BAA2B,CAAA;AACzC,cAAc,4CAA4C,CAAA;AAC1D,cAAc,6BAA6B,CAAA;AAC3C,cAAc,2BAA2B,CAAA;AACzC,cAAc,8BAA8B,CAAA;AAC5C,cAAc,qCAAqC,CAAA;AACnD,cAAc,sCAAsC,CAAA;AACpD,cAAc,2CAA2C,CAAA;AACzD,cAAc,qCAAqC,CAAA;AACnD,cAAc,sCAAsC,CAAA;AACpD,cAAc,wCAAwC,CAAA;AACtD,cAAc,2CAA2C,CAAA;AACzD,OAAO,EACL,kBAAkB,EAClB,eAAe,EACf,cAAc,EACd,mBAAmB,EACnB,gBAAgB,EAChB,iBAAiB,EACjB,gBAAgB,EAChB,kBAAkB,EAClB,aAAa,IAAI,mBAAmB,EACpC,cAAc,IAAI,oBAAoB,GACvC,MAAM,8BAA8B,CAAA;AACrC,cAAc,oCAAoC,CAAA;AAClD,cAAc,yBAAyB,CAAA;AACvC,cAAc,yBAAyB,CAAA;AACvC,cAAc,wCAAwC,CAAA;AACtD,cAAc,+BAA+B,CAAA;AAC7C,cAAc,kCAAkC,CAAA;AAChD,cAAc,mCAAmC,CAAA;AACjD,cAAc,kCAAkC,CAAA;AAChD,cAAc,mCAAmC,CAAA;AACjD,cAAc,gCAAgC,CAAA;AAC9C,cAAc,iDAAiD,CAAA;AAC/D,cAAc,8BAA8B,CAAA;AAC5C,cAAc,gCAAgC,CAAA;AAC9C,cAAc,4CAA4C,CAAA;AAC1D,cAAc,4CAA4C,CAAA;AAC1D,cAAc,mBAAmB,CAAA;AACjC,cAAc,oBAAoB,CAAA;AAClC,cAAc,uBAAuB,CAAA;AACrC,cAAc,wBAAwB,CAAA;AACtC,cAAc,8BAA8B,CAAA;AAC5C,cAAc,8BAA8B,CAAA;AAC5C,cAAc,0CAA0C,CAAA;AACxD,cAAc,6BAA6B,CAAA;AAC3C,cAAc,wCAAwC,CAAA;AACtD,cAAc,yCAAyC,CAAA;AACvD,cAAc,2BAA2B,CAAA;AACzC,cAAc,gCAAgC,CAAA;AAC9C,cAAc,sCAAsC,CAAA;AACpD,cAAc,kCAAkC,CAAA;AAChD,cAAc,gCAAgC,CAAA;AAC9C,cAAc,kCAAkC,CAAA;AAChD,cAAc,0CAA0C,CAAA;AACxD,cAAc,+BAA+B,CAAA;AAC7C,cAAc,qCAAqC,CAAA;AACnD,cAAc,oCAAoC,CAAA;AAClD,cAAc,4BAA4B,CAAA;AAC1C,cAAc,uCAAuC,CAAA;AACrD,cAAc,6CAA6C,CAAA;AAC3D,cAAc,4BAA4B,CAAA;AAC1C,cAAc,uCAAuC,CAAA;AACrD,cAAc,+CAA+C,CAAA;AAC7D,YAAY,EAAE,oBAAoB,EAAE,MAAM,sCAAsC,CAAA;AAChF,cAAc,wCAAwC,CAAA;AACtD,cAAc,iCAAiC,CAAA;AAC/C;;;;;;;;;GASG;AACH,cAAc,iCAAiC,CAAA;AAC/C,cAAc,8BAA8B,CAAA;AAC5C,cAAc,qCAAqC,CAAA;AACnD,cAAc,qCAAqC,CAAA;AACnD,cAAc,oCAAoC,CAAA;AAClD,cAAc,0BAA0B,CAAA;AACxC,cAAc,wCAAwC,CAAA;AAEtD;;;;;;;;;GASG;AACH,cAAc,qCAAqC,CAAA"}
package/dist/node.js CHANGED
@@ -86,6 +86,8 @@ export * from './acp/AcpProviderCatalogService.js';
86
86
  export * from './acp/AcpSessionService.js';
87
87
  export * from './acp/AcpAgentTurnExecutionAdapter.js';
88
88
  export * from './sdk/SdkNativeAgentTurnExecutionAdapter.js';
89
+ export * from './sdk/pendingInjections.js';
90
+ export * from './sdk/DurablePendingInjectionStore.js';
89
91
  export * from './cloud/XenoCloudAgentTurnExecutionAdapter.js';
90
92
  export * from './support/SupportDiagnosticsService.js';
91
93
  export * from './cli/CliControlPlaneService.js';
@@ -99,5 +101,22 @@ export * from './cli/CliControlPlaneService.js';
99
101
  * real processes. (`SandboxCommandExecutor` is `fetch`-only and stays in the
100
102
  * browser barrel.)
101
103
  */
104
+ export * from './isolation/CommandExecution.js';
105
+ export * from './isolation/CommandStream.js';
106
+ export * from './isolation/LocalCommandExecutor.js';
107
+ export * from './isolation/SandboxCommandStream.js';
108
+ export * from './isolation/SandboxCapabilities.js';
109
+ export * from './isolation/shellArgv.js';
102
110
  export * from './isolation/RunExecutionEnvironment.js';
111
+ /**
112
+ * NODE-only for the same reason as the block above: it calls
113
+ * `lstat` on the workspace before binding a sandbox. It reached the browser
114
+ * barrel by inheritance, not by decision, and broke `embed-preview`'s build
115
+ * with `"createHash"/"lstat" is not exported by __vite-browser-external`.
116
+ *
117
+ * Its one consumer is `apps/desktop/src/main/composeHost.ts`, which already
118
+ * imports from THIS entry — so the move costs no consumer a line.
119
+ * `XenoUseObservationSource` stays in the browser barrel: it is fetch-only.
120
+ */
121
+ export * from './observation/XenoUseRunObserver.js';
103
122
  //# sourceMappingURL=node.js.map
package/dist/node.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"node.js","sourceRoot":"","sources":["../src/node.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"node.js","sourceRoot":"","sources":["../src/node.ts"],"names":[],"mappings":"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"}
@@ -73,6 +73,18 @@ export interface XenoUseRunObserverOptions {
73
73
  containerDirectory: string;
74
74
  }) => RunContentReader;
75
75
  fetch?: typeof globalThis.fetch;
76
+ /**
77
+ * What the host directory IS on disk, before it is handed to Docker.
78
+ *
79
+ * 🔴 A Windows junction (and a Unix symlink) is followed by the bind mount.
80
+ * Granting `D:\\work\\repo` that is a junction to `C:\\` would put the
81
+ * whole volume inside the sandbox while the UI still names the grant.
82
+ * `lstat` is the probe: `stat`/`realpath` would follow the escape and
83
+ * report the target as if it were the path the operator chose.
84
+ */
85
+ probeHostDirectory?: (path: string) => Promise<{
86
+ isReparsePoint: boolean;
87
+ }>;
76
88
  /** Per-request timeout for the lifecycle calls. Distinct from the drain's own:
77
89
  * spawning a container is slower than reading a batch off one. */
78
90
  timeoutMs?: number;
@@ -83,6 +95,14 @@ export interface XenoUseRunObserverOptions {
83
95
  reason: string;
84
96
  }) => void;
85
97
  }
98
+ /**
99
+ * `lstat`, not `stat`. `stat` follows a junction and reports the target as if
100
+ * it were the path the operator chose — which is the escape this exists to
101
+ * refuse.
102
+ */
103
+ export declare function probeHostDirectory(path: string): Promise<{
104
+ isReparsePoint: boolean;
105
+ }>;
86
106
  /**
87
107
  * The sandbox a run is bound to, in both sides' terms.
88
108
  *
@@ -1 +1 @@
1
- {"version":3,"file":"XenoUseRunObserver.d.ts","sourceRoot":"","sources":["../../src/observation/XenoUseRunObserver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,OAAO,KAAK,EACV,gBAAgB,EAChB,qBAAqB,EACtB,MAAM,4BAA4B,CAAA;AAGnC,oEAAoE;AACpE,MAAM,WAAW,eAAe;IAC9B,kEAAkE;IAClE,aAAa,EAAE,MAAM,CAAA;IACrB,4EAA4E;IAC5E,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,kBAAkB;IACjC,IAAI,CAAC,OAAO,EAAE;QACZ,aAAa,EAAE,MAAM,CAAA;QACrB,kBAAkB,EAAE,MAAM,CAAA;KAC3B,GAAG,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,EAAE,CAAC;QAAC,QAAQ,EAAE,OAAO,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CACtE;AAED,MAAM,WAAW,yBAAyB;IACxC,wEAAwE;IACxE,OAAO,EAAE,MAAM,CAAA;IACf,iEAAiE;IACjE,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,qBAAqB,CAAA;IAC9B,sFAAsF;IACtF,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,eAAe,CAAC,EAAE,kBAAkB,CAAA;IACpC;kFAC8E;IAC9E,mBAAmB,CAAC,EAAE,CAAC,KAAK,EAAE;QAC5B,aAAa,EAAE,MAAM,CAAA;QACrB,kBAAkB,EAAE,MAAM,CAAA;KAC3B,KAAK,gBAAgB,CAAA;IACtB,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAA;IAC/B;uEACmE;IACnE,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;0EACsE;IACtE,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAA;CACjE;AAWD;;;;;;;;;GASG;AACH,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,MAAM,CAAA;IACjB,aAAa,EAAE,MAAM,CAAA;IACrB,kBAAkB,EAAE,MAAM,CAAA;CAC3B;AAED,qBAAa,kBAAkB;;gBAejB,OAAO,EAAE,yBAAyB;IAY9C;;;;;;OAMG;IACH,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,oBAAoB,GAAG,SAAS;IAU3D,wDAAwD;IACxD,YAAY,IAAI,MAAM,EAAE;IAIxB;;;;;;;;;;OAUG;IACG,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,OAAO,CAAC;IAmEpE;;;;;;;;OAQG;IACG,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOxC;iFAC6E;IACvE,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;CAgF/B"}
1
+ {"version":3,"file":"XenoUseRunObserver.d.ts","sourceRoot":"","sources":["../../src/observation/XenoUseRunObserver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAKH,OAAO,KAAK,EACV,gBAAgB,EAChB,qBAAqB,EACtB,MAAM,4BAA4B,CAAA;AAGnC,oEAAoE;AACpE,MAAM,WAAW,eAAe;IAC9B,kEAAkE;IAClE,aAAa,EAAE,MAAM,CAAA;IACrB,4EAA4E;IAC5E,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,kBAAkB;IACjC,IAAI,CAAC,OAAO,EAAE;QACZ,aAAa,EAAE,MAAM,CAAA;QACrB,kBAAkB,EAAE,MAAM,CAAA;KAC3B,GAAG,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,EAAE,CAAC;QAAC,QAAQ,EAAE,OAAO,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CACtE;AAED,MAAM,WAAW,yBAAyB;IACxC,wEAAwE;IACxE,OAAO,EAAE,MAAM,CAAA;IACf,iEAAiE;IACjE,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,qBAAqB,CAAA;IAC9B,sFAAsF;IACtF,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,eAAe,CAAC,EAAE,kBAAkB,CAAA;IACpC;kFAC8E;IAC9E,mBAAmB,CAAC,EAAE,CAAC,KAAK,EAAE;QAC5B,aAAa,EAAE,MAAM,CAAA;QACrB,kBAAkB,EAAE,MAAM,CAAA;KAC3B,KAAK,gBAAgB,CAAA;IACtB,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAA;IAC/B;;;;;;;;OAQG;IACH,kBAAkB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;QAAE,cAAc,EAAE,OAAO,CAAA;KAAE,CAAC,CAAA;IAC3E;uEACmE;IACnE,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;0EACsE;IACtE,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAA;CACjE;AAKD;;;;GAIG;AACH,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,cAAc,EAAE,OAAO,CAAA;CAAE,CAAC,CAG3F;AAQD;;;;;;;;;GASG;AACH,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,MAAM,CAAA;IACjB,aAAa,EAAE,MAAM,CAAA;IACrB,kBAAkB,EAAE,MAAM,CAAA;CAC3B;AAED,qBAAa,kBAAkB;;gBAgBjB,OAAO,EAAE,yBAAyB;IAa9C;;;;;;OAMG;IACH,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,oBAAoB,GAAG,SAAS;IAU3D,wDAAwD;IACxD,YAAY,IAAI,MAAM,EAAE;IAIxB;;;;;;;;;;OAUG;IACG,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,OAAO,CAAC;IA8EpE;;;;;;;;OAQG;IACG,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOxC;iFAC6E;IACvE,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;CA+F/B"}
@@ -30,9 +30,20 @@
30
30
  * to start is right when it never began. They are different facts and this
31
31
  * distinction is what keeps them apart.
32
32
  */
33
+ import { lstat } from 'node:fs/promises';
34
+ import { stableUseIdempotencyKey } from '../isolation/useIdempotency.js';
33
35
  import { XenoUseObservationSource } from './XenoUseObservationSource.js';
34
36
  const DEFAULT_CONTAINER_DIRECTORY = '/mnt/xeno/work';
35
37
  const DEFAULT_TIMEOUT_MS = 60_000;
38
+ /**
39
+ * `lstat`, not `stat`. `stat` follows a junction and reports the target as if
40
+ * it were the path the operator chose — which is the escape this exists to
41
+ * refuse.
42
+ */
43
+ export async function probeHostDirectory(path) {
44
+ const stat = await lstat(path);
45
+ return { isReparsePoint: stat.isSymbolicLink() };
46
+ }
36
47
  export class XenoUseRunObserver {
37
48
  #baseUrl;
38
49
  #token;
@@ -41,6 +52,7 @@ export class XenoUseRunObserver {
41
52
  #baselineScanner;
42
53
  #createContentReader;
43
54
  #fetch;
55
+ #probeHostDirectory;
44
56
  #timeoutMs;
45
57
  #onProblem;
46
58
  #active = new Map();
@@ -55,6 +67,7 @@ export class XenoUseRunObserver {
55
67
  this.#baselineScanner = options.baselineScanner;
56
68
  this.#createContentReader = options.createContentReader;
57
69
  this.#fetch = options.fetch ?? globalThis.fetch;
70
+ this.#probeHostDirectory = options.probeHostDirectory ?? probeHostDirectory;
58
71
  this.#timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
59
72
  this.#onProblem = options.onProblem ?? (() => { });
60
73
  }
@@ -106,7 +119,11 @@ export class XenoUseRunObserver {
106
119
  const containerDirectory = normaliseContainerDirectory(mount.containerDirectory ?? DEFAULT_CONTAINER_DIRECTORY);
107
120
  let sandboxId;
108
121
  try {
109
- sandboxId = await this.#createSandbox(mount, containerDirectory);
122
+ const probe = await this.#probeHostDirectory(mount.hostDirectory);
123
+ if (probe.isReparsePoint) {
124
+ throw new Error(`${mount.hostDirectory} is a junction or symlink; Docker would follow it past the grant`);
125
+ }
126
+ sandboxId = await this.#createSandbox(runId, mount, containerDirectory);
110
127
  }
111
128
  catch (error) {
112
129
  // 🔴 The run is NOT registered. See the header: registering here would
@@ -115,7 +132,7 @@ export class XenoUseRunObserver {
115
132
  return false;
116
133
  }
117
134
  try {
118
- await this.#post(`/v1/use/sandbox/${encodeURIComponent(sandboxId)}/observation`);
135
+ await this.#request('POST', `/v1/use/sandbox/${encodeURIComponent(sandboxId)}/observation`, undefined, stableUseIdempotencyKey('observe', runId));
119
136
  }
120
137
  catch (error) {
121
138
  // The sandbox exists but nothing is watching it, so this is the same
@@ -172,8 +189,8 @@ export class XenoUseRunObserver {
172
189
  async stopAll() {
173
190
  await Promise.all([...this.#active.keys()].map((runId) => this.stop(runId)));
174
191
  }
175
- async #createSandbox(mount, containerDirectory) {
176
- const response = await this.#post('/v1/use/sandbox', {
192
+ async #createSandbox(runId, mount, containerDirectory) {
193
+ const response = await this.#request('POST', '/v1/use/sandbox', {
177
194
  ...(this.#image ? { image: this.#image } : {}),
178
195
  mounts: [
179
196
  {
@@ -182,7 +199,7 @@ export class XenoUseRunObserver {
182
199
  read_only: mount.readOnly === true,
183
200
  },
184
201
  ],
185
- });
202
+ }, stableUseIdempotencyKey('create', runId));
186
203
  const body = (await response.json());
187
204
  const id = body.data?.id;
188
205
  if (!id)
@@ -208,7 +225,7 @@ export class XenoUseRunObserver {
208
225
  }
209
226
  async #destroy(sandboxId) {
210
227
  try {
211
- await this.#request('DELETE', `/v1/use/sandbox/${encodeURIComponent(sandboxId)}`);
228
+ await this.#request('DELETE', `/v1/use/sandbox/${encodeURIComponent(sandboxId)}`, undefined, stableUseIdempotencyKey('destroy', sandboxId));
212
229
  }
213
230
  catch (error) {
214
231
  // Reported, never swallowed. A teardown that never worked once looked
@@ -216,10 +233,7 @@ export class XenoUseRunObserver {
216
233
  this.#onProblem({ runId: '', reason: `could not remove observation sandbox: ${reason(error)}` });
217
234
  }
218
235
  }
219
- async #post(path, body) {
220
- return this.#request('POST', path, body);
221
- }
222
- async #request(method, path, body) {
236
+ async #request(method, path, body, idempotencyKey) {
223
237
  const controller = new AbortController();
224
238
  const timer = setTimeout(() => controller.abort(), this.#timeoutMs);
225
239
  try {
@@ -228,9 +242,9 @@ export class XenoUseRunObserver {
228
242
  headers: {
229
243
  authorization: `Bearer ${this.#token}`,
230
244
  'content-type': 'application/json',
231
- // Every mutating `/v1/use` route requires one. Keyed by the request
232
- // itself so a retry is a replay rather than a second container.
233
- 'idempotency-key': `xeno-agent-${method}-${path}`,
245
+ // A path-only key made every run share one create, so the second
246
+ // workspace 409'd. Lifecycle keys include the run or sandbox id.
247
+ 'idempotency-key': idempotencyKey,
234
248
  },
235
249
  // `{}` rather than nothing: fastify refuses an empty payload when the
236
250
  // content-type says JSON, and the bodyless routes accept `{}` by schema.
@@ -1 +1 @@
1
- {"version":3,"file":"XenoUseRunObserver.js","sourceRoot":"","sources":["../../src/observation/XenoUseRunObserver.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"XenoUseRunObserver.js","sourceRoot":"","sources":["../../src/observation/XenoUseRunObserver.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import type { RuntimeEventEnvelope } from './runtimeEventTypes.js';
2
- import type { RuntimeTimelineAskUser, RuntimeTimelineAskUserStatus, RuntimeTimelineCheckpoint, RuntimeTimelineEvent, RuntimeTimelineModelWait, RuntimeTimelineModelWaitStatus, RuntimeTimelinePermission, RuntimeTimelinePermissionProfile, RuntimeTimelinePermissionStatus, RuntimeTimelineProjection, RuntimeTimelineRequest, RuntimeTimelineTool, RuntimeTimelineToolStatus, RuntimeTimelineTurnStatus } from '@xenosystem/agent-interface-contract';
3
- export type { RuntimeTimelineAskUser, RuntimeTimelineAskUserStatus, RuntimeTimelineCheckpoint, RuntimeTimelineEvent, RuntimeTimelineModelWait, RuntimeTimelineModelWaitStatus, RuntimeTimelinePermission, RuntimeTimelinePermissionProfile, RuntimeTimelinePermissionStatus, RuntimeTimelineProjection, RuntimeTimelineRequest, RuntimeTimelineTool, RuntimeTimelineToolStatus, RuntimeTimelineTurnStatus, };
2
+ import type { RuntimeTimelineAskUser, RuntimeTimelineAskUserStatus, RuntimeTimelineCheckpoint, RuntimeTimelineContextBudgetSource, RuntimeTimelineEvent, RuntimeTimelineHistoryCompaction, RuntimeTimelineInjection, RuntimeTimelineModelWait, RuntimeTimelineModelWaitStatus, RuntimeTimelinePermission, RuntimeTimelinePermissionProfile, RuntimeTimelinePermissionStatus, RuntimeTimelineProjection, RuntimeTimelineRequest, RuntimeTimelineTool, RuntimeTimelineToolStatus, RuntimeTimelineTurnStatus } from '@xenosystem/agent-interface-contract';
3
+ export type { RuntimeTimelineAskUser, RuntimeTimelineAskUserStatus, RuntimeTimelineCheckpoint, RuntimeTimelineContextBudgetSource, RuntimeTimelineEvent, RuntimeTimelineHistoryCompaction, RuntimeTimelineInjection, RuntimeTimelineModelWait, RuntimeTimelineModelWaitStatus, RuntimeTimelinePermission, RuntimeTimelinePermissionProfile, RuntimeTimelinePermissionStatus, RuntimeTimelineProjection, RuntimeTimelineRequest, RuntimeTimelineTool, RuntimeTimelineToolStatus, RuntimeTimelineTurnStatus, };
4
4
  export declare function projectRuntimeTimeline(inputs: Array<RuntimeEventEnvelope | Record<string, unknown>>): RuntimeTimelineProjection;
5
5
  //# sourceMappingURL=RuntimeTimelineProjection.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"RuntimeTimelineProjection.d.ts","sourceRoot":"","sources":["../../src/runtime/RuntimeTimelineProjection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAA;AAElE,OAAO,KAAK,EACV,sBAAsB,EACtB,4BAA4B,EAC5B,yBAAyB,EAEzB,oBAAoB,EACpB,wBAAwB,EACxB,8BAA8B,EAC9B,yBAAyB,EACzB,gCAAgC,EAChC,+BAA+B,EAC/B,yBAAyB,EACzB,sBAAsB,EACtB,mBAAmB,EACnB,yBAAyB,EACzB,yBAAyB,EAC1B,MAAM,sCAAsC,CAAA;AAK7C,YAAY,EACV,sBAAsB,EACtB,4BAA4B,EAC5B,yBAAyB,EACzB,oBAAoB,EACpB,wBAAwB,EACxB,8BAA8B,EAC9B,yBAAyB,EACzB,gCAAgC,EAChC,+BAA+B,EAC/B,yBAAyB,EACzB,sBAAsB,EACtB,mBAAmB,EACnB,yBAAyB,EACzB,yBAAyB,GAC1B,CAAA;AAgnBD,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,KAAK,CAAC,oBAAoB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,yBAAyB,CAmF/H"}
1
+ {"version":3,"file":"RuntimeTimelineProjection.d.ts","sourceRoot":"","sources":["../../src/runtime/RuntimeTimelineProjection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAA;AAElE,OAAO,KAAK,EACV,sBAAsB,EACtB,4BAA4B,EAC5B,yBAAyB,EAEzB,kCAAkC,EAClC,oBAAoB,EACpB,gCAAgC,EAChC,wBAAwB,EACxB,wBAAwB,EACxB,8BAA8B,EAC9B,yBAAyB,EACzB,gCAAgC,EAChC,+BAA+B,EAC/B,yBAAyB,EACzB,sBAAsB,EACtB,mBAAmB,EACnB,yBAAyB,EACzB,yBAAyB,EAC1B,MAAM,sCAAsC,CAAA;AAK7C,YAAY,EACV,sBAAsB,EACtB,4BAA4B,EAC5B,yBAAyB,EACzB,kCAAkC,EAClC,oBAAoB,EACpB,gCAAgC,EAChC,wBAAwB,EACxB,wBAAwB,EACxB,8BAA8B,EAC9B,yBAAyB,EACzB,gCAAgC,EAChC,+BAA+B,EAC/B,yBAAyB,EACzB,sBAAsB,EACtB,mBAAmB,EACnB,yBAAyB,EACzB,yBAAyB,GAC1B,CAAA;AAwzBD,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,KAAK,CAAC,oBAAoB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,yBAAyB,CA6F/H"}
@@ -34,6 +34,22 @@ function readStringArray(value) {
34
34
  }
35
35
  return out;
36
36
  }
37
+ function readContextBudgetSource(record, key) {
38
+ const value = record[key];
39
+ // Validated against the union rather than cast: an unrecognised provenance must read as ABSENT,
40
+ // not as an exact `config`. Trusting the string would let a future SDK value silently promote an
41
+ // approximate budget to an exact one, which is the one direction this field must not fail in.
42
+ return value === 'config' || value === 'provider' || value === 'fallback' ? value : undefined;
43
+ }
44
+ function readAccountingSource(record, key) {
45
+ const value = record[key];
46
+ // Same rule as the budget source above, and it fails in the same direction: an unrecognised
47
+ // provenance reads as ABSENT rather than being trusted. Promoting an unknown value to `exact`
48
+ // would let a surface show a decimal percentage for a number nobody measured.
49
+ return value === 'exact' || value === 'provider-reported' || value === 'estimated'
50
+ ? value
51
+ : undefined;
52
+ }
37
53
  function readTokenUsage(value) {
38
54
  if (!isRecord(value))
39
55
  return undefined;
@@ -241,12 +257,16 @@ function handleTurnEvent(state, event) {
241
257
  request.status = 'running';
242
258
  request.startedAt = event.timestamp || request.startedAt;
243
259
  request.model = readString(event.payload, 'model') || request.model;
260
+ request.contextBudgetTokens = readNumber(event.payload, 'contextBudgetTokens') ?? request.contextBudgetTokens;
261
+ request.contextBudgetSource = readContextBudgetSource(event.payload, 'contextBudgetSource') ?? request.contextBudgetSource;
244
262
  }
245
263
  else if (event.type === 'turn.completed') {
246
264
  request.status = 'completed';
247
265
  request.completedAt = event.timestamp || request.completedAt;
248
266
  request.tokenUsage = readTokenUsage(event.payload.tokenUsage) || request.tokenUsage;
249
267
  state.tokenUsage = request.tokenUsage || state.tokenUsage;
268
+ // Deliberately NOT folded into tokenUsage: that is what was billed, this is what is resident.
269
+ request.contextTokens = readNumber(event.payload, 'contextTokens') ?? request.contextTokens;
250
270
  }
251
271
  else if (event.type === 'turn.failed') {
252
272
  request.status = 'failed';
@@ -328,6 +348,47 @@ function handleAcpSessionEvent(state, event) {
328
348
  const total = readNumber(event.payload, 'totalTokens') ?? input + output;
329
349
  request.tokenUsage = { input, output, total };
330
350
  state.tokenUsage = request.tokenUsage;
351
+ // The ACP lane's pressure reading, landing in the SAME request fields as the SDK lane so a
352
+ // surface divides once and never asks which kind of agent produced the numbers.
353
+ //
354
+ // 🔴 Deliberately NOT derived from the counters just above. Those are cumulative session
355
+ // totals that only rise; the resident count is what FALLS when an agent compacts, and it is
356
+ // the only one that can answer how close the agent is to compacting.
357
+ const residentTokens = readNumber(event.payload, 'contextTokens');
358
+ const agentWindowTokens = readNumber(event.payload, 'contextWindowTokens');
359
+ const observedTokens = readNumber(event.payload, 'observedCompactionTokens');
360
+ if (residentTokens !== undefined && residentTokens >= 0)
361
+ request.contextTokens = residentTokens;
362
+ if (agentWindowTokens !== undefined && agentWindowTokens > 0) {
363
+ request.contextBudgetTokens = agentWindowTokens;
364
+ // An agent's own window - neither our config nor a provider profile.
365
+ request.contextBudgetSource = 'agent';
366
+ }
367
+ /**
368
+ * 🔴 AN OBSERVED COMPACTION POINT BEATS A DECLARED WINDOW, and the order here is the claim.
369
+ *
370
+ * §2.1 asks how full a context is "against what it compacts at". An agent may compact well
371
+ * before filling its window, so the window is a LARGER denominator than the real one — it
372
+ * understates pressure and hides the approach to the event this signal exists to anticipate.
373
+ * Where we have watched the agent compact, that is the threshold.
374
+ *
375
+ * ⚠️ Applied AFTER the window on purpose, so it overrides rather than defers. Both are
376
+ * approximate; only one is about compaction.
377
+ */
378
+ if (observedTokens !== undefined && observedTokens > 0) {
379
+ request.contextBudgetTokens = observedTokens;
380
+ request.contextBudgetSource = 'observed';
381
+ }
382
+ /**
383
+ * 🔴 ONE EVENT, TWO COLLECTIONS — and that is why the boundary rides the usage update rather
384
+ * than arriving separately. The fall in `contextTokens` and the reason for it are the same
385
+ * fact; splitting them would hand every consumer a timestamp-correlation problem to learn why
386
+ * a number dropped, which is exactly the ambiguity §2.1 exists to remove.
387
+ *
388
+ * ⚠️ Folding one event into two collections is not a special case here — the request fields
389
+ * above are already a second write from this same event.
390
+ */
391
+ recordAcpCompaction(state, event);
331
392
  return;
332
393
  }
333
394
  if (event.type === 'acp.session.completed') {
@@ -458,6 +519,20 @@ function handleCheckpointEvent(state, event) {
458
519
  * something true; dropping the record because one number is absent would lose the boundary itself,
459
520
  * which is the part no consumer can reconstruct.
460
521
  */
522
+ function handleInjectionEvent(state, event) {
523
+ const injection = {
524
+ id: event.id,
525
+ requestId: event.requestId,
526
+ messageId: readString(event.payload, 'messageId'),
527
+ sourceNodeId: readString(event.payload, 'sourceNodeId'),
528
+ label: readString(event.payload, 'label'),
529
+ deferred: readBoolean(event.payload, 'deferred'),
530
+ iteration: readNumber(event.payload, 'iteration'),
531
+ injectedAt: event.timestamp,
532
+ eventId: event.id,
533
+ };
534
+ state.injections.set(injection.id, injection);
535
+ }
461
536
  function handleCompactionEvent(state, event) {
462
537
  const compaction = {
463
538
  id: `${event.requestId}:compaction:${event.id}`,
@@ -477,6 +552,95 @@ function handleCompactionEvent(state, event) {
477
552
  };
478
553
  state.compactions.set(compaction.id, compaction);
479
554
  }
555
+ /**
556
+ * `context.history.compacted` — the SDK loop summarised history out of its request.
557
+ *
558
+ * 🔴 Deliberately a SEPARATE collection from `state.compactions`, which projects the HOST's
559
+ * `context.compacted`. The separation still stands and the reason has been corrected: BOTH
560
+ * are request-scoped and neither destroys anything. Measured 2026-08-21 on a real compacting
561
+ * turn — the durable message list GREW, the summary is not in it, and all 49 "removed" ids
562
+ * are still there. They differ in WHO compacts and WHAT is reported, and their payloads share
563
+ * NO field names, so one handler reading the other's event yields a row of `undefined`.
564
+ *
565
+ * What the row conveys is what the agent can no longer SEE while it stays over budget — not
566
+ * that anything was destroyed.
567
+ *
568
+ * ⚠️ `afterTokens` is NOT written into `request.contextTokens`. That field carries
569
+ * provider-REPORTED readings; this is usually `estimated`, and the request has no field to record
570
+ * that its numerator changed provenance. A consumer wanting the post-compaction figure reads it
571
+ * here, where `accounting` says what it is.
572
+ */
573
+ /**
574
+ * The ACP lane's compaction boundary, carried in `_meta["xeno.dev"]` on a usage update.
575
+ *
576
+ * 🔴 IT REPORTS THE OPPOSITE HALF. A third-party agent tells us what it PRESERVED; our SDK tells us
577
+ * what it REMOVED. So `removedMessageIds` is left ABSENT rather than `[]` — an empty array would
578
+ * assert that nothing was removed from a compaction that dropped a million tokens — and `reports`
579
+ * says which half this is, as a field a consumer cannot skip the way it can skip a comment.
580
+ */
581
+ function recordAcpCompaction(state, event) {
582
+ const raw = event.payload['compaction'];
583
+ if (!raw || typeof raw !== 'object' || Array.isArray(raw))
584
+ return;
585
+ const payload = raw;
586
+ const num = (key) => {
587
+ const value = payload[key];
588
+ return typeof value === 'number' && Number.isFinite(value) && value >= 0 ? value : undefined;
589
+ };
590
+ const compaction = {
591
+ id: `${event.requestId}:history-compaction:${event.id}`,
592
+ requestId: event.requestId,
593
+ reports: 'preserved',
594
+ ...(typeof payload.trigger === 'string' ? { trigger: payload.trigger } : {}),
595
+ ...(num('preservedMessageCount') === undefined ? {} : { preservedMessageCount: num('preservedMessageCount') }),
596
+ ...(num('cumulativeDroppedTokens') === undefined ? {} : { cumulativeDroppedTokens: num('cumulativeDroppedTokens') }),
597
+ ...(num('durationMs') === undefined ? {} : { durationMs: num('durationMs') }),
598
+ ...(num('preTokens') === undefined ? {} : { beforeTokens: num('preTokens') }),
599
+ ...(num('postTokens') === undefined ? {} : { afterTokens: num('postTokens') }),
600
+ // The agent's own numbers, not ours — the same provenance the SDK lane records when the
601
+ // planner supplies them rather than estimating.
602
+ accounting: 'provider-reported',
603
+ compactedAt: event.timestamp,
604
+ eventId: event.id,
605
+ };
606
+ state.historyCompactions.set(compaction.id, compaction);
607
+ }
608
+ function handleHistoryCompactionEvent(state, event) {
609
+ /**
610
+ * 🔴 TWO LANES REPORT OPPOSITE HALVES OF THE SAME BOUNDARY, so the discriminator is DERIVED from
611
+ * what actually arrived rather than from which lane sent it. A lane label would be a second place
612
+ * to keep in step; the data is the evidence.
613
+ *
614
+ * ⚠️ `removedMessageIds` is left ABSENT, not `[]`, when nothing named them. An empty array on a
615
+ * `preserved` boundary asserts that nothing was removed — from a compaction that dropped a
616
+ * million tokens. This workspace's rule is that absent and zero are different claims, and this is
617
+ * the case that makes it concrete.
618
+ */
619
+ const rawRemoved = event.payload['removedMessageIds'];
620
+ const removedMessageIds = rawRemoved === undefined ? undefined : readStringArray(rawRemoved);
621
+ const preservedMessageCount = readNumber(event.payload, 'preservedMessageCount');
622
+ const compaction = {
623
+ id: `${event.requestId}:history-compaction:${event.id}`,
624
+ requestId: event.requestId,
625
+ reports: removedMessageIds !== undefined ? 'removed' : 'preserved',
626
+ ...(removedMessageIds === undefined ? {} : { removedMessageIds }),
627
+ ...(preservedMessageCount === undefined ? {} : { preservedMessageCount }),
628
+ trigger: readString(event.payload, 'trigger'),
629
+ cumulativeDroppedTokens: readNumber(event.payload, 'cumulativeDroppedTokens'),
630
+ durationMs: readNumber(event.payload, 'durationMs'),
631
+ summaryMessageId: readString(event.payload, 'summaryMessageId'),
632
+ firstMessageId: readString(event.payload, 'firstMessageId'),
633
+ lastMessageId: readString(event.payload, 'lastMessageId'),
634
+ messagesRemoved: readNumber(event.payload, 'messagesRemoved'),
635
+ tokensSaved: readNumber(event.payload, 'tokensSaved'),
636
+ beforeTokens: readNumber(event.payload, 'beforeTokens'),
637
+ afterTokens: readNumber(event.payload, 'afterTokens'),
638
+ accounting: readAccountingSource(event.payload, 'accounting'),
639
+ compactedAt: event.timestamp,
640
+ eventId: event.id,
641
+ };
642
+ state.historyCompactions.set(compaction.id, compaction);
643
+ }
480
644
  function handleModelWaitEvent(state, event) {
481
645
  const waitMs = readNumber(event.payload, 'waitMs');
482
646
  const wait = {
@@ -586,10 +750,32 @@ function applyEvent(state, event) {
586
750
  handleCheckpointEvent(state, event);
587
751
  return;
588
752
  }
753
+ if (event.type === 'context.pressure') {
754
+ // A LIVE reading: the same numbers turn.completed carries, but arriving after every model
755
+ // response. Compaction fires mid-turn, so a surface that only learns the occupancy at the
756
+ // terminal event finds out after the summary already replaced what a human would have pinned.
757
+ const pressureRequest = ensureRequest(state, event);
758
+ pressureRequest.contextTokens = readNumber(event.payload, 'contextTokens') ?? pressureRequest.contextTokens;
759
+ pressureRequest.contextBudgetTokens = readNumber(event.payload, 'budgetTokens') ?? pressureRequest.contextBudgetTokens;
760
+ pressureRequest.contextBudgetSource = readContextBudgetSource(event.payload, 'budgetSource') ?? pressureRequest.contextBudgetSource;
761
+ return;
762
+ }
763
+ if (event.type === 'context.injected') {
764
+ handleInjectionEvent(state, event);
765
+ return;
766
+ }
589
767
  if (event.type === 'context.compacted') {
590
768
  handleCompactionEvent(state, event);
591
769
  return;
592
770
  }
771
+ if (event.type === 'context.history.compacted') {
772
+ // ⚠️ EXACT match, and it must stay exact. This event and `context.compacted` above differ by
773
+ // one path segment and carry DISJOINT payloads, so a `startsWith('context.')` here would
774
+ // route each into a handler that reads none of its fields — a row of `undefined` rather
775
+ // than an error.
776
+ handleHistoryCompactionEvent(state, event);
777
+ return;
778
+ }
593
779
  if (event.type.startsWith('hub.model.')) {
594
780
  handleModelWaitEvent(state, event);
595
781
  return;
@@ -621,6 +807,8 @@ export function projectRuntimeTimeline(inputs) {
621
807
  permissionProfiles: new Map(),
622
808
  checkpoints: new Map(),
623
809
  compactions: new Map(),
810
+ injections: new Map(),
811
+ historyCompactions: new Map(),
624
812
  modelWaits: new Map(),
625
813
  askUserRequests: new Map(),
626
814
  duplicateEventCount,
@@ -640,7 +828,10 @@ export function projectRuntimeTimeline(inputs) {
640
828
  .sort((a, b) => firstProfileSequence(a, orderedEvents) - firstProfileSequence(b, orderedEvents));
641
829
  const checkpoints = Array.from(state.checkpoints.values())
642
830
  .sort((a, b) => firstCheckpointSequence(a, orderedEvents) - firstCheckpointSequence(b, orderedEvents));
643
- const compactions = Array.from(state.compactions.values())
831
+ const compactions = Array.from(state.compactions.values());
832
+ const injections = Array.from(state.injections.values())
833
+ .sort((a, b) => firstCheckpointSequence(a, orderedEvents) - firstCheckpointSequence(b, orderedEvents));
834
+ const historyCompactions = Array.from(state.historyCompactions.values())
644
835
  .sort((a, b) => firstCheckpointSequence(a, orderedEvents) - firstCheckpointSequence(b, orderedEvents));
645
836
  const modelWaits = Array.from(state.modelWaits.values());
646
837
  const maxModelWaitMs = modelWaits.reduce((max, wait) => Math.max(max, wait.waitMs || 0), 0);
@@ -660,6 +851,8 @@ export function projectRuntimeTimeline(inputs) {
660
851
  permissionProfiles,
661
852
  checkpoints,
662
853
  compactions,
854
+ injections,
855
+ historyCompactions,
663
856
  modelWaits,
664
857
  askUserRequests,
665
858
  lastEventType: last?.type,