@xenosystem/agent-interface-host 0.1.4 → 0.1.6

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 (124) 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/AcpProviderCatalogService.d.ts.map +1 -1
  17. package/dist/acp/AcpProviderCatalogService.js +68 -2
  18. package/dist/acp/AcpProviderCatalogService.js.map +1 -1
  19. package/dist/acp/AcpRuntimeEventMapper.d.ts.map +1 -1
  20. package/dist/acp/AcpRuntimeEventMapper.js +9 -0
  21. package/dist/acp/AcpRuntimeEventMapper.js.map +1 -1
  22. package/dist/acp/AcpSessionService.d.ts +36 -0
  23. package/dist/acp/AcpSessionService.d.ts.map +1 -1
  24. package/dist/acp/AcpSessionService.js +57 -1
  25. package/dist/acp/AcpSessionService.js.map +1 -1
  26. package/dist/acp/DurableAcpPermissionPolicyStore.d.ts.map +1 -1
  27. package/dist/acp/DurableAcpPermissionPolicyStore.js +5 -3
  28. package/dist/acp/DurableAcpPermissionPolicyStore.js.map +1 -1
  29. package/dist/acp/acpRedaction.d.ts.map +1 -1
  30. package/dist/acp/acpRedaction.js +2 -0
  31. package/dist/acp/acpRedaction.js.map +1 -1
  32. package/dist/acp/acpTypes.d.ts +111 -1
  33. package/dist/acp/acpTypes.d.ts.map +1 -1
  34. package/dist/acp/acpTypes.js +21 -1
  35. package/dist/acp/acpTypes.js.map +1 -1
  36. package/dist/index.d.ts +108 -2
  37. package/dist/index.d.ts.map +1 -1
  38. package/dist/index.js +236 -11
  39. package/dist/index.js.map +1 -1
  40. package/dist/isolation/CommandExecution.d.ts +7 -12
  41. package/dist/isolation/CommandExecution.d.ts.map +1 -1
  42. package/dist/isolation/CommandExecution.js +7 -12
  43. package/dist/isolation/CommandExecution.js.map +1 -1
  44. package/dist/isolation/CommandStream.d.ts +100 -0
  45. package/dist/isolation/CommandStream.d.ts.map +1 -0
  46. package/dist/isolation/CommandStream.js +47 -0
  47. package/dist/isolation/CommandStream.js.map +1 -0
  48. package/dist/isolation/RunExecutionEnvironment.d.ts +15 -0
  49. package/dist/isolation/RunExecutionEnvironment.d.ts.map +1 -1
  50. package/dist/isolation/RunExecutionEnvironment.js +45 -9
  51. package/dist/isolation/RunExecutionEnvironment.js.map +1 -1
  52. package/dist/isolation/RunIsolationService.d.ts +10 -5
  53. package/dist/isolation/RunIsolationService.d.ts.map +1 -1
  54. package/dist/isolation/RunIsolationService.js +7 -3
  55. package/dist/isolation/RunIsolationService.js.map +1 -1
  56. package/dist/isolation/SandboxCapabilities.d.ts +28 -0
  57. package/dist/isolation/SandboxCapabilities.d.ts.map +1 -0
  58. package/dist/isolation/SandboxCapabilities.js +33 -0
  59. package/dist/isolation/SandboxCapabilities.js.map +1 -0
  60. package/dist/isolation/SandboxCommandExecutor.d.ts +4 -7
  61. package/dist/isolation/SandboxCommandExecutor.d.ts.map +1 -1
  62. package/dist/isolation/SandboxCommandExecutor.js +6 -7
  63. package/dist/isolation/SandboxCommandExecutor.js.map +1 -1
  64. package/dist/isolation/SandboxCommandStream.d.ts +38 -0
  65. package/dist/isolation/SandboxCommandStream.d.ts.map +1 -0
  66. package/dist/isolation/SandboxCommandStream.js +232 -0
  67. package/dist/isolation/SandboxCommandStream.js.map +1 -0
  68. package/dist/isolation/shellArgv.d.ts +15 -0
  69. package/dist/isolation/shellArgv.d.ts.map +1 -0
  70. package/dist/isolation/shellArgv.js +31 -0
  71. package/dist/isolation/shellArgv.js.map +1 -0
  72. package/dist/isolation/useIdempotency.d.ts +19 -0
  73. package/dist/isolation/useIdempotency.d.ts.map +1 -0
  74. package/dist/isolation/useIdempotency.js +57 -0
  75. package/dist/isolation/useIdempotency.js.map +1 -0
  76. package/dist/localRpcTransport.d.ts +18 -0
  77. package/dist/localRpcTransport.d.ts.map +1 -1
  78. package/dist/localRpcTransport.js +38 -4
  79. package/dist/localRpcTransport.js.map +1 -1
  80. package/dist/node.d.ts +19 -0
  81. package/dist/node.d.ts.map +1 -1
  82. package/dist/node.js +19 -0
  83. package/dist/node.js.map +1 -1
  84. package/dist/observation/XenoUseRunObserver.d.ts +20 -0
  85. package/dist/observation/XenoUseRunObserver.d.ts.map +1 -1
  86. package/dist/observation/XenoUseRunObserver.js +27 -13
  87. package/dist/observation/XenoUseRunObserver.js.map +1 -1
  88. package/dist/runtime/RuntimeTimelineProjection.d.ts +2 -2
  89. package/dist/runtime/RuntimeTimelineProjection.d.ts.map +1 -1
  90. package/dist/runtime/RuntimeTimelineProjection.js +196 -1
  91. package/dist/runtime/RuntimeTimelineProjection.js.map +1 -1
  92. package/dist/sdk/DurablePendingInjectionStore.d.ts +24 -0
  93. package/dist/sdk/DurablePendingInjectionStore.d.ts.map +1 -0
  94. package/dist/sdk/DurablePendingInjectionStore.js +103 -0
  95. package/dist/sdk/DurablePendingInjectionStore.js.map +1 -0
  96. package/dist/sdk/SdkNativeAgentTurnExecutionAdapter.d.ts +81 -1
  97. package/dist/sdk/SdkNativeAgentTurnExecutionAdapter.d.ts.map +1 -1
  98. package/dist/sdk/SdkNativeAgentTurnExecutionAdapter.js +122 -3
  99. package/dist/sdk/SdkNativeAgentTurnExecutionAdapter.js.map +1 -1
  100. package/dist/sdk/pendingInjections.d.ts +83 -0
  101. package/dist/sdk/pendingInjections.d.ts.map +1 -0
  102. package/dist/sdk/pendingInjections.js +79 -0
  103. package/dist/sdk/pendingInjections.js.map +1 -0
  104. package/dist/session/AgentSessionService.d.ts +34 -0
  105. package/dist/session/AgentSessionService.d.ts.map +1 -1
  106. package/dist/session/AgentSessionService.js +85 -1
  107. package/dist/session/AgentSessionService.js.map +1 -1
  108. package/dist/session/nativeTuiSessionPty.d.ts +40 -0
  109. package/dist/session/nativeTuiSessionPty.d.ts.map +1 -0
  110. package/dist/session/nativeTuiSessionPty.js +142 -0
  111. package/dist/session/nativeTuiSessionPty.js.map +1 -0
  112. package/dist/session/nodePtyLoader.d.ts +23 -0
  113. package/dist/session/nodePtyLoader.d.ts.map +1 -0
  114. package/dist/session/nodePtyLoader.js +41 -0
  115. package/dist/session/nodePtyLoader.js.map +1 -0
  116. package/dist/session/renderSupport.d.ts +34 -0
  117. package/dist/session/renderSupport.d.ts.map +1 -1
  118. package/dist/session/renderSupport.js +39 -1
  119. package/dist/session/renderSupport.js.map +1 -1
  120. package/dist/workspace/WorkspaceHostService.d.ts +27 -2
  121. package/dist/workspace/WorkspaceHostService.d.ts.map +1 -1
  122. package/dist/workspace/WorkspaceHostService.js +221 -25
  123. package/dist/workspace/WorkspaceHostService.js.map +1 -1
  124. package/package.json +8 -8
@@ -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":"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"}
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;AA0zBD,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,KAAK,CAAC,oBAAoB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,yBAAyB,CA6F/H"}
@@ -34,6 +34,24 @@ 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 === 'model' || value === 'fallback'
43
+ ? value
44
+ : undefined;
45
+ }
46
+ function readAccountingSource(record, key) {
47
+ const value = record[key];
48
+ // Same rule as the budget source above, and it fails in the same direction: an unrecognised
49
+ // provenance reads as ABSENT rather than being trusted. Promoting an unknown value to `exact`
50
+ // would let a surface show a decimal percentage for a number nobody measured.
51
+ return value === 'exact' || value === 'provider-reported' || value === 'estimated'
52
+ ? value
53
+ : undefined;
54
+ }
37
55
  function readTokenUsage(value) {
38
56
  if (!isRecord(value))
39
57
  return undefined;
@@ -241,12 +259,16 @@ function handleTurnEvent(state, event) {
241
259
  request.status = 'running';
242
260
  request.startedAt = event.timestamp || request.startedAt;
243
261
  request.model = readString(event.payload, 'model') || request.model;
262
+ request.contextBudgetTokens = readNumber(event.payload, 'contextBudgetTokens') ?? request.contextBudgetTokens;
263
+ request.contextBudgetSource = readContextBudgetSource(event.payload, 'contextBudgetSource') ?? request.contextBudgetSource;
244
264
  }
245
265
  else if (event.type === 'turn.completed') {
246
266
  request.status = 'completed';
247
267
  request.completedAt = event.timestamp || request.completedAt;
248
268
  request.tokenUsage = readTokenUsage(event.payload.tokenUsage) || request.tokenUsage;
249
269
  state.tokenUsage = request.tokenUsage || state.tokenUsage;
270
+ // Deliberately NOT folded into tokenUsage: that is what was billed, this is what is resident.
271
+ request.contextTokens = readNumber(event.payload, 'contextTokens') ?? request.contextTokens;
250
272
  }
251
273
  else if (event.type === 'turn.failed') {
252
274
  request.status = 'failed';
@@ -328,6 +350,47 @@ function handleAcpSessionEvent(state, event) {
328
350
  const total = readNumber(event.payload, 'totalTokens') ?? input + output;
329
351
  request.tokenUsage = { input, output, total };
330
352
  state.tokenUsage = request.tokenUsage;
353
+ // The ACP lane's pressure reading, landing in the SAME request fields as the SDK lane so a
354
+ // surface divides once and never asks which kind of agent produced the numbers.
355
+ //
356
+ // 🔴 Deliberately NOT derived from the counters just above. Those are cumulative session
357
+ // totals that only rise; the resident count is what FALLS when an agent compacts, and it is
358
+ // the only one that can answer how close the agent is to compacting.
359
+ const residentTokens = readNumber(event.payload, 'contextTokens');
360
+ const agentWindowTokens = readNumber(event.payload, 'contextWindowTokens');
361
+ const observedTokens = readNumber(event.payload, 'observedCompactionTokens');
362
+ if (residentTokens !== undefined && residentTokens >= 0)
363
+ request.contextTokens = residentTokens;
364
+ if (agentWindowTokens !== undefined && agentWindowTokens > 0) {
365
+ request.contextBudgetTokens = agentWindowTokens;
366
+ // An agent's own window - neither our config nor a provider profile.
367
+ request.contextBudgetSource = 'agent';
368
+ }
369
+ /**
370
+ * 🔴 AN OBSERVED COMPACTION POINT BEATS A DECLARED WINDOW, and the order here is the claim.
371
+ *
372
+ * §2.1 asks how full a context is "against what it compacts at". An agent may compact well
373
+ * before filling its window, so the window is a LARGER denominator than the real one — it
374
+ * understates pressure and hides the approach to the event this signal exists to anticipate.
375
+ * Where we have watched the agent compact, that is the threshold.
376
+ *
377
+ * ⚠️ Applied AFTER the window on purpose, so it overrides rather than defers. Both are
378
+ * approximate; only one is about compaction.
379
+ */
380
+ if (observedTokens !== undefined && observedTokens > 0) {
381
+ request.contextBudgetTokens = observedTokens;
382
+ request.contextBudgetSource = 'observed';
383
+ }
384
+ /**
385
+ * 🔴 ONE EVENT, TWO COLLECTIONS — and that is why the boundary rides the usage update rather
386
+ * than arriving separately. The fall in `contextTokens` and the reason for it are the same
387
+ * fact; splitting them would hand every consumer a timestamp-correlation problem to learn why
388
+ * a number dropped, which is exactly the ambiguity §2.1 exists to remove.
389
+ *
390
+ * ⚠️ Folding one event into two collections is not a special case here — the request fields
391
+ * above are already a second write from this same event.
392
+ */
393
+ recordAcpCompaction(state, event);
331
394
  return;
332
395
  }
333
396
  if (event.type === 'acp.session.completed') {
@@ -458,6 +521,20 @@ function handleCheckpointEvent(state, event) {
458
521
  * something true; dropping the record because one number is absent would lose the boundary itself,
459
522
  * which is the part no consumer can reconstruct.
460
523
  */
524
+ function handleInjectionEvent(state, event) {
525
+ const injection = {
526
+ id: event.id,
527
+ requestId: event.requestId,
528
+ messageId: readString(event.payload, 'messageId'),
529
+ sourceNodeId: readString(event.payload, 'sourceNodeId'),
530
+ label: readString(event.payload, 'label'),
531
+ deferred: readBoolean(event.payload, 'deferred'),
532
+ iteration: readNumber(event.payload, 'iteration'),
533
+ injectedAt: event.timestamp,
534
+ eventId: event.id,
535
+ };
536
+ state.injections.set(injection.id, injection);
537
+ }
461
538
  function handleCompactionEvent(state, event) {
462
539
  const compaction = {
463
540
  id: `${event.requestId}:compaction:${event.id}`,
@@ -477,6 +554,95 @@ function handleCompactionEvent(state, event) {
477
554
  };
478
555
  state.compactions.set(compaction.id, compaction);
479
556
  }
557
+ /**
558
+ * `context.history.compacted` — the SDK loop summarised history out of its request.
559
+ *
560
+ * 🔴 Deliberately a SEPARATE collection from `state.compactions`, which projects the HOST's
561
+ * `context.compacted`. The separation still stands and the reason has been corrected: BOTH
562
+ * are request-scoped and neither destroys anything. Measured 2026-08-21 on a real compacting
563
+ * turn — the durable message list GREW, the summary is not in it, and all 49 "removed" ids
564
+ * are still there. They differ in WHO compacts and WHAT is reported, and their payloads share
565
+ * NO field names, so one handler reading the other's event yields a row of `undefined`.
566
+ *
567
+ * What the row conveys is what the agent can no longer SEE while it stays over budget — not
568
+ * that anything was destroyed.
569
+ *
570
+ * ⚠️ `afterTokens` is NOT written into `request.contextTokens`. That field carries
571
+ * provider-REPORTED readings; this is usually `estimated`, and the request has no field to record
572
+ * that its numerator changed provenance. A consumer wanting the post-compaction figure reads it
573
+ * here, where `accounting` says what it is.
574
+ */
575
+ /**
576
+ * The ACP lane's compaction boundary, carried in `_meta["xeno.dev"]` on a usage update.
577
+ *
578
+ * 🔴 IT REPORTS THE OPPOSITE HALF. A third-party agent tells us what it PRESERVED; our SDK tells us
579
+ * what it REMOVED. So `removedMessageIds` is left ABSENT rather than `[]` — an empty array would
580
+ * assert that nothing was removed from a compaction that dropped a million tokens — and `reports`
581
+ * says which half this is, as a field a consumer cannot skip the way it can skip a comment.
582
+ */
583
+ function recordAcpCompaction(state, event) {
584
+ const raw = event.payload['compaction'];
585
+ if (!raw || typeof raw !== 'object' || Array.isArray(raw))
586
+ return;
587
+ const payload = raw;
588
+ const num = (key) => {
589
+ const value = payload[key];
590
+ return typeof value === 'number' && Number.isFinite(value) && value >= 0 ? value : undefined;
591
+ };
592
+ const compaction = {
593
+ id: `${event.requestId}:history-compaction:${event.id}`,
594
+ requestId: event.requestId,
595
+ reports: 'preserved',
596
+ ...(typeof payload.trigger === 'string' ? { trigger: payload.trigger } : {}),
597
+ ...(num('preservedMessageCount') === undefined ? {} : { preservedMessageCount: num('preservedMessageCount') }),
598
+ ...(num('cumulativeDroppedTokens') === undefined ? {} : { cumulativeDroppedTokens: num('cumulativeDroppedTokens') }),
599
+ ...(num('durationMs') === undefined ? {} : { durationMs: num('durationMs') }),
600
+ ...(num('preTokens') === undefined ? {} : { beforeTokens: num('preTokens') }),
601
+ ...(num('postTokens') === undefined ? {} : { afterTokens: num('postTokens') }),
602
+ // The agent's own numbers, not ours — the same provenance the SDK lane records when the
603
+ // planner supplies them rather than estimating.
604
+ accounting: 'provider-reported',
605
+ compactedAt: event.timestamp,
606
+ eventId: event.id,
607
+ };
608
+ state.historyCompactions.set(compaction.id, compaction);
609
+ }
610
+ function handleHistoryCompactionEvent(state, event) {
611
+ /**
612
+ * 🔴 TWO LANES REPORT OPPOSITE HALVES OF THE SAME BOUNDARY, so the discriminator is DERIVED from
613
+ * what actually arrived rather than from which lane sent it. A lane label would be a second place
614
+ * to keep in step; the data is the evidence.
615
+ *
616
+ * ⚠️ `removedMessageIds` is left ABSENT, not `[]`, when nothing named them. An empty array on a
617
+ * `preserved` boundary asserts that nothing was removed — from a compaction that dropped a
618
+ * million tokens. This workspace's rule is that absent and zero are different claims, and this is
619
+ * the case that makes it concrete.
620
+ */
621
+ const rawRemoved = event.payload['removedMessageIds'];
622
+ const removedMessageIds = rawRemoved === undefined ? undefined : readStringArray(rawRemoved);
623
+ const preservedMessageCount = readNumber(event.payload, 'preservedMessageCount');
624
+ const compaction = {
625
+ id: `${event.requestId}:history-compaction:${event.id}`,
626
+ requestId: event.requestId,
627
+ reports: removedMessageIds !== undefined ? 'removed' : 'preserved',
628
+ ...(removedMessageIds === undefined ? {} : { removedMessageIds }),
629
+ ...(preservedMessageCount === undefined ? {} : { preservedMessageCount }),
630
+ trigger: readString(event.payload, 'trigger'),
631
+ cumulativeDroppedTokens: readNumber(event.payload, 'cumulativeDroppedTokens'),
632
+ durationMs: readNumber(event.payload, 'durationMs'),
633
+ summaryMessageId: readString(event.payload, 'summaryMessageId'),
634
+ firstMessageId: readString(event.payload, 'firstMessageId'),
635
+ lastMessageId: readString(event.payload, 'lastMessageId'),
636
+ messagesRemoved: readNumber(event.payload, 'messagesRemoved'),
637
+ tokensSaved: readNumber(event.payload, 'tokensSaved'),
638
+ beforeTokens: readNumber(event.payload, 'beforeTokens'),
639
+ afterTokens: readNumber(event.payload, 'afterTokens'),
640
+ accounting: readAccountingSource(event.payload, 'accounting'),
641
+ compactedAt: event.timestamp,
642
+ eventId: event.id,
643
+ };
644
+ state.historyCompactions.set(compaction.id, compaction);
645
+ }
480
646
  function handleModelWaitEvent(state, event) {
481
647
  const waitMs = readNumber(event.payload, 'waitMs');
482
648
  const wait = {
@@ -586,10 +752,32 @@ function applyEvent(state, event) {
586
752
  handleCheckpointEvent(state, event);
587
753
  return;
588
754
  }
755
+ if (event.type === 'context.pressure') {
756
+ // A LIVE reading: the same numbers turn.completed carries, but arriving after every model
757
+ // response. Compaction fires mid-turn, so a surface that only learns the occupancy at the
758
+ // terminal event finds out after the summary already replaced what a human would have pinned.
759
+ const pressureRequest = ensureRequest(state, event);
760
+ pressureRequest.contextTokens = readNumber(event.payload, 'contextTokens') ?? pressureRequest.contextTokens;
761
+ pressureRequest.contextBudgetTokens = readNumber(event.payload, 'budgetTokens') ?? pressureRequest.contextBudgetTokens;
762
+ pressureRequest.contextBudgetSource = readContextBudgetSource(event.payload, 'budgetSource') ?? pressureRequest.contextBudgetSource;
763
+ return;
764
+ }
765
+ if (event.type === 'context.injected') {
766
+ handleInjectionEvent(state, event);
767
+ return;
768
+ }
589
769
  if (event.type === 'context.compacted') {
590
770
  handleCompactionEvent(state, event);
591
771
  return;
592
772
  }
773
+ if (event.type === 'context.history.compacted') {
774
+ // ⚠️ EXACT match, and it must stay exact. This event and `context.compacted` above differ by
775
+ // one path segment and carry DISJOINT payloads, so a `startsWith('context.')` here would
776
+ // route each into a handler that reads none of its fields — a row of `undefined` rather
777
+ // than an error.
778
+ handleHistoryCompactionEvent(state, event);
779
+ return;
780
+ }
593
781
  if (event.type.startsWith('hub.model.')) {
594
782
  handleModelWaitEvent(state, event);
595
783
  return;
@@ -621,6 +809,8 @@ export function projectRuntimeTimeline(inputs) {
621
809
  permissionProfiles: new Map(),
622
810
  checkpoints: new Map(),
623
811
  compactions: new Map(),
812
+ injections: new Map(),
813
+ historyCompactions: new Map(),
624
814
  modelWaits: new Map(),
625
815
  askUserRequests: new Map(),
626
816
  duplicateEventCount,
@@ -640,7 +830,10 @@ export function projectRuntimeTimeline(inputs) {
640
830
  .sort((a, b) => firstProfileSequence(a, orderedEvents) - firstProfileSequence(b, orderedEvents));
641
831
  const checkpoints = Array.from(state.checkpoints.values())
642
832
  .sort((a, b) => firstCheckpointSequence(a, orderedEvents) - firstCheckpointSequence(b, orderedEvents));
643
- const compactions = Array.from(state.compactions.values())
833
+ const compactions = Array.from(state.compactions.values());
834
+ const injections = Array.from(state.injections.values())
835
+ .sort((a, b) => firstCheckpointSequence(a, orderedEvents) - firstCheckpointSequence(b, orderedEvents));
836
+ const historyCompactions = Array.from(state.historyCompactions.values())
644
837
  .sort((a, b) => firstCheckpointSequence(a, orderedEvents) - firstCheckpointSequence(b, orderedEvents));
645
838
  const modelWaits = Array.from(state.modelWaits.values());
646
839
  const maxModelWaitMs = modelWaits.reduce((max, wait) => Math.max(max, wait.waitMs || 0), 0);
@@ -660,6 +853,8 @@ export function projectRuntimeTimeline(inputs) {
660
853
  permissionProfiles,
661
854
  checkpoints,
662
855
  compactions,
856
+ injections,
857
+ historyCompactions,
663
858
  modelWaits,
664
859
  askUserRequests,
665
860
  lastEventType: last?.type,