@paperclipai/adapter-utils 2026.1012.0 → 2026.1012.1-canary.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 (134) hide show
  1. package/dist/acpx-engine/accounting-model.d.ts +5 -0
  2. package/dist/acpx-engine/accounting-model.d.ts.map +1 -0
  3. package/dist/acpx-engine/accounting-model.js +10 -0
  4. package/dist/acpx-engine/accounting-model.js.map +1 -0
  5. package/dist/acpx-engine/accounting-model.test.d.ts +2 -0
  6. package/dist/acpx-engine/accounting-model.test.d.ts.map +1 -0
  7. package/dist/acpx-engine/accounting-model.test.js +18 -0
  8. package/dist/acpx-engine/accounting-model.test.js.map +1 -0
  9. package/dist/acpx-engine/constants.d.ts +1 -0
  10. package/dist/acpx-engine/constants.d.ts.map +1 -1
  11. package/dist/acpx-engine/constants.js +6 -0
  12. package/dist/acpx-engine/constants.js.map +1 -1
  13. package/dist/acpx-engine/execute.d.ts +13 -0
  14. package/dist/acpx-engine/execute.d.ts.map +1 -1
  15. package/dist/acpx-engine/execute.js +139 -12
  16. package/dist/acpx-engine/execute.js.map +1 -1
  17. package/dist/acpx-engine/execute.test.js +582 -30
  18. package/dist/acpx-engine/execute.test.js.map +1 -1
  19. package/dist/acpx-engine/filesystem-protocol.test.d.ts +2 -0
  20. package/dist/acpx-engine/filesystem-protocol.test.d.ts.map +1 -0
  21. package/dist/acpx-engine/filesystem-protocol.test.js +99 -0
  22. package/dist/acpx-engine/filesystem-protocol.test.js.map +1 -0
  23. package/dist/acpx-engine/run-contracts.d.ts +1 -0
  24. package/dist/acpx-engine/run-contracts.d.ts.map +1 -1
  25. package/dist/acpx-engine/run-fault-matrix.test.js +76 -28
  26. package/dist/acpx-engine/run-fault-matrix.test.js.map +1 -1
  27. package/dist/api-billing-type.d.ts +5 -0
  28. package/dist/api-billing-type.d.ts.map +1 -0
  29. package/dist/api-billing-type.js +16 -0
  30. package/dist/api-billing-type.js.map +1 -0
  31. package/dist/api-billing-type.test.d.ts +2 -0
  32. package/dist/api-billing-type.test.d.ts.map +1 -0
  33. package/dist/api-billing-type.test.js +20 -0
  34. package/dist/api-billing-type.test.js.map +1 -0
  35. package/dist/billing.d.ts +7 -0
  36. package/dist/billing.d.ts.map +1 -1
  37. package/dist/billing.js +25 -2
  38. package/dist/billing.js.map +1 -1
  39. package/dist/billing.test.js +17 -1
  40. package/dist/billing.test.js.map +1 -1
  41. package/dist/chat-file-delivery.d.ts +1 -1
  42. package/dist/chat-file-delivery.d.ts.map +1 -1
  43. package/dist/chat-file-delivery.js +4 -3
  44. package/dist/chat-file-delivery.js.map +1 -1
  45. package/dist/chat-file-delivery.test.js +2 -2
  46. package/dist/chat-file-delivery.test.js.map +1 -1
  47. package/dist/command-managed-runtime.d.ts +6 -0
  48. package/dist/command-managed-runtime.d.ts.map +1 -1
  49. package/dist/command-managed-runtime.js +5 -1
  50. package/dist/command-managed-runtime.js.map +1 -1
  51. package/dist/connection-failure.d.ts +33 -0
  52. package/dist/connection-failure.d.ts.map +1 -0
  53. package/dist/connection-failure.js +43 -0
  54. package/dist/connection-failure.js.map +1 -0
  55. package/dist/connection-failure.test.d.ts +2 -0
  56. package/dist/connection-failure.test.d.ts.map +1 -0
  57. package/dist/connection-failure.test.js +94 -0
  58. package/dist/connection-failure.test.js.map +1 -0
  59. package/dist/directory-merge-lock.test.js +4 -2
  60. package/dist/directory-merge-lock.test.js.map +1 -1
  61. package/dist/execution-target-sandbox.test.js +468 -1154
  62. package/dist/execution-target-sandbox.test.js.map +1 -1
  63. package/dist/execution-target.d.ts +12 -0
  64. package/dist/execution-target.d.ts.map +1 -1
  65. package/dist/execution-target.js +49 -13
  66. package/dist/execution-target.js.map +1 -1
  67. package/dist/execution-target.test.js +59 -106
  68. package/dist/execution-target.test.js.map +1 -1
  69. package/dist/github-launcher-environment.test.js +37 -0
  70. package/dist/github-launcher-environment.test.js.map +1 -1
  71. package/dist/index.d.ts +3 -3
  72. package/dist/index.d.ts.map +1 -1
  73. package/dist/index.js +2 -2
  74. package/dist/index.js.map +1 -1
  75. package/dist/paperclip-runner-permissions.d.ts +15 -4
  76. package/dist/paperclip-runner-permissions.d.ts.map +1 -1
  77. package/dist/paperclip-runner-permissions.js +29 -3
  78. package/dist/paperclip-runner-permissions.js.map +1 -1
  79. package/dist/paperclip-runner-permissions.test.js +34 -1
  80. package/dist/paperclip-runner-permissions.test.js.map +1 -1
  81. package/dist/sandbox-callback-bridge.d.ts.map +1 -1
  82. package/dist/sandbox-callback-bridge.js +1 -0
  83. package/dist/sandbox-callback-bridge.js.map +1 -1
  84. package/dist/sandbox-callback-bridge.test.js +113 -16
  85. package/dist/sandbox-callback-bridge.test.js.map +1 -1
  86. package/dist/sandbox-managed-runtime.d.ts +5 -0
  87. package/dist/sandbox-managed-runtime.d.ts.map +1 -1
  88. package/dist/sandbox-managed-runtime.js +51 -13
  89. package/dist/sandbox-managed-runtime.js.map +1 -1
  90. package/dist/sandbox-managed-runtime.test.js +141 -2
  91. package/dist/sandbox-managed-runtime.test.js.map +1 -1
  92. package/dist/server-utils.d.ts +6 -3
  93. package/dist/server-utils.d.ts.map +1 -1
  94. package/dist/server-utils.js +38 -8
  95. package/dist/server-utils.js.map +1 -1
  96. package/dist/server-utils.test.js +35 -1
  97. package/dist/server-utils.test.js.map +1 -1
  98. package/dist/types.d.ts +76 -1
  99. package/dist/types.d.ts.map +1 -1
  100. package/dist/usage-checkpoint.d.ts +11 -0
  101. package/dist/usage-checkpoint.d.ts.map +1 -0
  102. package/dist/usage-checkpoint.js +165 -0
  103. package/dist/usage-checkpoint.js.map +1 -0
  104. package/dist/usage-checkpoint.test.d.ts +2 -0
  105. package/dist/usage-checkpoint.test.d.ts.map +1 -0
  106. package/dist/usage-checkpoint.test.js +131 -0
  107. package/dist/usage-checkpoint.test.js.map +1 -0
  108. package/dist/workspace-restore-diagnostics.d.ts +8 -1
  109. package/dist/workspace-restore-diagnostics.d.ts.map +1 -1
  110. package/dist/workspace-restore-diagnostics.js +35 -8
  111. package/dist/workspace-restore-diagnostics.js.map +1 -1
  112. package/dist/workspace-restore-diagnostics.test.js +31 -1
  113. package/dist/workspace-restore-diagnostics.test.js.map +1 -1
  114. package/node_modules/acpx/dist/live-checkpoint-ClPCSdrW.js +3 -0
  115. package/package.json +31 -3
  116. package/dist/acpx-engine/composed-run-characterization.test.d.ts +0 -2
  117. package/dist/acpx-engine/composed-run-characterization.test.d.ts.map +0 -1
  118. package/dist/acpx-engine/composed-run-characterization.test.js +0 -739
  119. package/dist/acpx-engine/composed-run-characterization.test.js.map +0 -1
  120. package/dist/acpx-engine/settlement-characterization.test.d.ts +0 -2
  121. package/dist/acpx-engine/settlement-characterization.test.d.ts.map +0 -1
  122. package/dist/acpx-engine/settlement-characterization.test.js +0 -985
  123. package/dist/acpx-engine/settlement-characterization.test.js.map +0 -1
  124. package/dist/acpx-engine/startup-characterization.test.d.ts +0 -2
  125. package/dist/acpx-engine/startup-characterization.test.d.ts.map +0 -1
  126. package/dist/acpx-engine/startup-characterization.test.js +0 -742
  127. package/dist/acpx-engine/startup-characterization.test.js.map +0 -1
  128. package/dist/acpx-engine/turn-characterization.test.d.ts +0 -2
  129. package/dist/acpx-engine/turn-characterization.test.d.ts.map +0 -1
  130. package/dist/acpx-engine/turn-characterization.test.js +0 -567
  131. package/dist/acpx-engine/turn-characterization.test.js.map +0 -1
  132. package/node_modules/@esbuild/linux-x64/README.md +0 -3
  133. package/node_modules/@esbuild/linux-x64/bin/esbuild +0 -0
  134. package/node_modules/@esbuild/linux-x64/package.json +0 -20
@@ -0,0 +1,5 @@
1
+ import type { AcpRuntimeStatus } from "acpx/runtime";
2
+ /** Use provider-selected IDs, including its default. A mid-turn model change
3
+ * cannot be priced as a single-model receipt; never guess from a display name. */
4
+ export declare function acpxAccountingModel(requested: string, before: AcpRuntimeStatus | null, after: AcpRuntimeStatus | null): string | null;
5
+ //# sourceMappingURL=accounting-model.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"accounting-model.d.ts","sourceRoot":"","sources":["../../src/acpx-engine/accounting-model.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAErD;kFACkF;AAClF,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,gBAAgB,GAAG,IAAI,EAAE,KAAK,EAAE,gBAAgB,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAKrI"}
@@ -0,0 +1,10 @@
1
+ /** Use provider-selected IDs, including its default. A mid-turn model change
2
+ * cannot be priced as a single-model receipt; never guess from a display name. */
3
+ export function acpxAccountingModel(requested, before, after) {
4
+ const pre = before?.models?.currentModelId?.trim();
5
+ const post = after?.models?.currentModelId?.trim();
6
+ if (pre && post && pre !== post)
7
+ return null;
8
+ return post || pre || requested.trim() || null;
9
+ }
10
+ //# sourceMappingURL=accounting-model.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"accounting-model.js","sourceRoot":"","sources":["../../src/acpx-engine/accounting-model.ts"],"names":[],"mappings":"AAEA;kFACkF;AAClF,MAAM,UAAU,mBAAmB,CAAC,SAAiB,EAAE,MAA+B,EAAE,KAA8B;IACpH,MAAM,GAAG,GAAG,MAAM,EAAE,MAAM,EAAE,cAAc,EAAE,IAAI,EAAE,CAAC;IACnD,MAAM,IAAI,GAAG,KAAK,EAAE,MAAM,EAAE,cAAc,EAAE,IAAI,EAAE,CAAC;IACnD,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAC7C,OAAO,IAAI,IAAI,GAAG,IAAI,SAAS,CAAC,IAAI,EAAE,IAAI,IAAI,CAAC;AACjD,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=accounting-model.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"accounting-model.test.d.ts","sourceRoot":"","sources":["../../src/acpx-engine/accounting-model.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,18 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { acpxAccountingModel } from "./accounting-model.js";
3
+ const selected = (id) => ({ models: { currentModelId: id, availableModelIds: [id] } });
4
+ describe("ACP accounting model", () => {
5
+ it("retains the runtime's default and effective model instead of the requested label", () => {
6
+ expect(acpxAccountingModel("", selected("gpt-6.1-sol"), selected("gpt-6.1-sol"))).toBe("gpt-6.1-sol");
7
+ expect(acpxAccountingModel("default", null, selected("gpt-6-astra"))).toBe("gpt-6-astra");
8
+ expect(acpxAccountingModel("", selected("gpt-6-astra"), null)).toBe("gpt-6-astra");
9
+ });
10
+ it("uses explicit configuration only when no selected model was reported", () => {
11
+ expect(acpxAccountingModel("gpt-6.1-sol", null, null)).toBe("gpt-6.1-sol");
12
+ expect(acpxAccountingModel("", { models: { availableModelIds: ["gpt-6.1-sol"] } }, null)).toBeNull();
13
+ });
14
+ it("does not price a turn that changed models as one model", () => {
15
+ expect(acpxAccountingModel("gpt-6.1-sol", selected("gpt-6.1-sol"), selected("gpt-6-astra"))).toBeNull();
16
+ });
17
+ });
18
+ //# sourceMappingURL=accounting-model.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"accounting-model.test.js","sourceRoot":"","sources":["../../src/acpx-engine/accounting-model.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAE5D,MAAM,QAAQ,GAAG,CAAC,EAAU,EAAE,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,cAAc,EAAE,EAAE,EAAE,iBAAiB,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;AAC/F,QAAQ,CAAC,sBAAsB,EAAE,GAAG,EAAE;IACpC,EAAE,CAAC,kFAAkF,EAAE,GAAG,EAAE;QAC1F,MAAM,CAAC,mBAAmB,CAAC,EAAE,EAAE,QAAQ,CAAC,aAAa,CAAC,EAAE,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QACtG,MAAM,CAAC,mBAAmB,CAAC,SAAS,EAAE,IAAI,EAAE,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QAC1F,MAAM,CAAC,mBAAmB,CAAC,EAAE,EAAE,QAAQ,CAAC,aAAa,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IACrF,CAAC,CAAC,CAAC;IACH,EAAE,CAAC,sEAAsE,EAAE,GAAG,EAAE;QAC9E,MAAM,CAAC,mBAAmB,CAAC,aAAa,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QAC3E,MAAM,CAAC,mBAAmB,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,iBAAiB,EAAE,CAAC,aAAa,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;IACvG,CAAC,CAAC,CAAC;IACH,EAAE,CAAC,wDAAwD,EAAE,GAAG,EAAE;QAChE,MAAM,CAAC,mBAAmB,CAAC,aAAa,EAAE,QAAQ,CAAC,aAAa,CAAC,EAAE,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;IAC1G,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -7,6 +7,7 @@ export declare const DEFAULT_ACP_ENGINE_WARM_HANDLE_IDLE_MS = 0;
7
7
  export declare const ACPX_HANDSHAKE_TIMEOUT_MS = 60000;
8
8
  export declare const ACPX_HANDSHAKE_TRANSPORT_POLL_MS = 250;
9
9
  export declare const ACPX_DUPLEX_LOSS_CANCEL_DEADLINE_MS = 30000;
10
+ export declare const ACP_TOOL_KINDS: readonly ["read", "edit", "delete", "move", "search", "execute", "think", "fetch", "switch_mode", "other"];
10
11
  export declare const ACPX_ADAPTER_AGENT_IDS: {
11
12
  readonly claude_local: "claude";
12
13
  readonly codex_local: "codex";
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/acpx-engine/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,wBAAwB,WAAW,CAAC;AACjD,eAAO,MAAM,uBAAuB,eAAe,CAAC;AACpD,eAAO,MAAM,kCAAkC,gBAAgB,CAAC;AAChE,eAAO,MAAM,8CAA8C,SAAS,CAAC;AACrE,eAAO,MAAM,8BAA8B,IAAI,CAAC;AAChD,eAAO,MAAM,sCAAsC,IAAI,CAAC;AAOxD,eAAO,MAAM,yBAAyB,QAAS,CAAC;AAMhD,eAAO,MAAM,gCAAgC,MAAM,CAAC;AAQpD,eAAO,MAAM,mCAAmC,QAAS,CAAC;AAE1D,eAAO,MAAM,sBAAsB;aACjC,YAAY,EAAE,QAAQ;aACtB,WAAW,EAAE,OAAO;aACpB,YAAY,EAAE,QAAQ;aACtB,UAAU,EAAE,MAAM;aAClB,UAAU,EAAE,QAAQ;CACZ,CAAC;AAEX,MAAM,MAAM,eAAe,GAAG,MAAM,OAAO,sBAAsB,CAAC;AAClE,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,sBAAsB,CAAC,CAAC,eAAe,CAAC,CAAC;AAE3E,wBAAgB,yBAAyB,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,WAAW,GAAG,IAAI,CAGpG"}
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/acpx-engine/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,wBAAwB,WAAW,CAAC;AACjD,eAAO,MAAM,uBAAuB,eAAe,CAAC;AACpD,eAAO,MAAM,kCAAkC,gBAAgB,CAAC;AAChE,eAAO,MAAM,8CAA8C,SAAS,CAAC;AACrE,eAAO,MAAM,8BAA8B,IAAI,CAAC;AAChD,eAAO,MAAM,sCAAsC,IAAI,CAAC;AAOxD,eAAO,MAAM,yBAAyB,QAAS,CAAC;AAMhD,eAAO,MAAM,gCAAgC,MAAM,CAAC;AAQpD,eAAO,MAAM,mCAAmC,QAAS,CAAC;AAK1D,eAAO,MAAM,cAAc,YACzB,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,OAAO,CACvF,CAAC;AAEX,eAAO,MAAM,sBAAsB;aACjC,YAAY,EAAE,QAAQ;aACtB,WAAW,EAAE,OAAO;aACpB,YAAY,EAAE,QAAQ;aACtB,UAAU,EAAE,MAAM;aAClB,UAAU,EAAE,QAAQ;CACZ,CAAC;AAEX,MAAM,MAAM,eAAe,GAAG,MAAM,OAAO,sBAAsB,CAAC;AAClE,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,sBAAsB,CAAC,CAAC,eAAe,CAAC,CAAC;AAE3E,wBAAgB,yBAAyB,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,WAAW,GAAG,IAAI,CAGpG"}
@@ -22,6 +22,12 @@ export const ACPX_HANDSHAKE_TRANSPORT_POLL_MS = 250;
22
22
  // is the host-side bound that ends the run without the agent's help. It is
23
23
  // much smaller than the whole-adapter execution timeout.
24
24
  export const ACPX_DUPLEX_LOSS_CANCEL_DEADLINE_MS = 30_000;
25
+ // The closed ACP `ToolKind` enum. Run diagnostics may report these labels for
26
+ // pending tool calls; tool titles, names, and inputs never leave the run.
27
+ // Any other reported kind is collapsed to "unknown".
28
+ export const ACP_TOOL_KINDS = [
29
+ "read", "edit", "delete", "move", "search", "execute", "think", "fetch", "switch_mode", "other",
30
+ ];
25
31
  export const ACPX_ADAPTER_AGENT_IDS = {
26
32
  claude_local: "claude",
27
33
  codex_local: "codex",
@@ -1 +1 @@
1
- {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/acpx-engine/constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,wBAAwB,GAAG,QAAQ,CAAC;AACjD,MAAM,CAAC,MAAM,uBAAuB,GAAG,YAAY,CAAC;AACpD,MAAM,CAAC,MAAM,kCAAkC,GAAG,aAAa,CAAC;AAChE,MAAM,CAAC,MAAM,8CAA8C,GAAG,MAAM,CAAC;AACrE,MAAM,CAAC,MAAM,8BAA8B,GAAG,CAAC,CAAC;AAChD,MAAM,CAAC,MAAM,sCAAsC,GAAG,CAAC,CAAC;AAExD,2EAA2E;AAC3E,sEAAsE;AACtE,8EAA8E;AAC9E,0EAA0E;AAC1E,8DAA8D;AAC9D,MAAM,CAAC,MAAM,yBAAyB,GAAG,MAAM,CAAC;AAEhD,4EAA4E;AAC5E,yEAAyE;AACzE,2EAA2E;AAC3E,qBAAqB;AACrB,MAAM,CAAC,MAAM,gCAAgC,GAAG,GAAG,CAAC;AAEpD,yEAAyE;AACzE,4EAA4E;AAC5E,8EAA8E;AAC9E,4EAA4E;AAC5E,2EAA2E;AAC3E,yDAAyD;AACzD,MAAM,CAAC,MAAM,mCAAmC,GAAG,MAAM,CAAC;AAE1D,MAAM,CAAC,MAAM,sBAAsB,GAAG;IACpC,YAAY,EAAE,QAAQ;IACtB,WAAW,EAAE,OAAO;IACpB,YAAY,EAAE,QAAQ;IACtB,UAAU,EAAE,MAAM;IAClB,UAAU,EAAE,QAAQ;CACZ,CAAC;AAKX,MAAM,UAAU,yBAAyB,CAAC,WAAsC;IAC9E,IAAI,CAAC,WAAW;QAAE,OAAO,IAAI,CAAC;IAC9B,OAAO,sBAAsB,CAAC,WAA8B,CAAC,IAAI,IAAI,CAAC;AACxE,CAAC"}
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/acpx-engine/constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,wBAAwB,GAAG,QAAQ,CAAC;AACjD,MAAM,CAAC,MAAM,uBAAuB,GAAG,YAAY,CAAC;AACpD,MAAM,CAAC,MAAM,kCAAkC,GAAG,aAAa,CAAC;AAChE,MAAM,CAAC,MAAM,8CAA8C,GAAG,MAAM,CAAC;AACrE,MAAM,CAAC,MAAM,8BAA8B,GAAG,CAAC,CAAC;AAChD,MAAM,CAAC,MAAM,sCAAsC,GAAG,CAAC,CAAC;AAExD,2EAA2E;AAC3E,sEAAsE;AACtE,8EAA8E;AAC9E,0EAA0E;AAC1E,8DAA8D;AAC9D,MAAM,CAAC,MAAM,yBAAyB,GAAG,MAAM,CAAC;AAEhD,4EAA4E;AAC5E,yEAAyE;AACzE,2EAA2E;AAC3E,qBAAqB;AACrB,MAAM,CAAC,MAAM,gCAAgC,GAAG,GAAG,CAAC;AAEpD,yEAAyE;AACzE,4EAA4E;AAC5E,8EAA8E;AAC9E,4EAA4E;AAC5E,2EAA2E;AAC3E,yDAAyD;AACzD,MAAM,CAAC,MAAM,mCAAmC,GAAG,MAAM,CAAC;AAE1D,8EAA8E;AAC9E,0EAA0E;AAC1E,qDAAqD;AACrD,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,OAAO;CACvF,CAAC;AAEX,MAAM,CAAC,MAAM,sBAAsB,GAAG;IACpC,YAAY,EAAE,QAAQ;IACtB,WAAW,EAAE,OAAO;IACpB,YAAY,EAAE,QAAQ;IACtB,UAAU,EAAE,MAAM;IAClB,UAAU,EAAE,QAAQ;CACZ,CAAC;AAKX,MAAM,UAAU,yBAAyB,CAAC,WAAsC;IAC9E,IAAI,CAAC,WAAW;QAAE,OAAO,IAAI,CAAC;IAC9B,OAAO,sBAAsB,CAAC,WAA8B,CAAC,IAAI,IAAI,CAAC;AACxE,CAAC"}
@@ -296,6 +296,19 @@ export declare function buildAcpxRunSummary(input: {
296
296
  outputSegments: string[];
297
297
  fallback?: string | null;
298
298
  }): string;
299
+ /**
300
+ * Activity as of the moment the turn's stop fired, for a stopped turn only.
301
+ * Separates a turn that went silent long before its deadline from one that
302
+ * was still working. Reports only ages and closed ACP tool-kind labels.
303
+ */
304
+ export declare function summarizeAcpStopActivity(stopRequestedAt: number | null, lastEventBeforeStopAt: number | null, pendingTools: ReadonlyArray<{
305
+ kind?: string;
306
+ firstSeenAt?: number;
307
+ }>): {
308
+ acpLastEventAgeAtStopMs?: number;
309
+ acpOldestPendingToolAgeAtStopMs?: number;
310
+ acpPendingToolKinds?: string;
311
+ };
299
312
  /**
300
313
  * Fold the ACP runtime's post-turn usage into the adapter execution result
301
314
  * shape. The runtime persists the latest turn's token breakdown (adapters like
@@ -1 +1 @@
1
- {"version":3,"file":"execute.d.ts","sourceRoot":"","sources":["../../src/acpx-engine/execute.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"execute.d.ts","sourceRoot":"","sources":["../../src/acpx-engine/execute.ts"],"names":[],"mappings":"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"}
@@ -18,8 +18,9 @@ import { DEFAULT_PAPERCLIP_AGENT_PROMPT_TEMPLATE, DEFAULT_PAPERCLIP_CONVERSATION
18
18
  import { shellQuote } from "@paperclipai/adapter-utils/ssh";
19
19
  import { createEphemeralSessionEnvironmentStore } from "./ephemeral-session-environment.js";
20
20
  import { createAcpRuntime, createAgentRegistry, createRuntimeStore, isAcpRuntimeError, } from "acpx/runtime";
21
- import { ACPX_DUPLEX_LOSS_CANCEL_DEADLINE_MS, ACPX_HANDSHAKE_TIMEOUT_MS, ACPX_HANDSHAKE_TRANSPORT_POLL_MS, DEFAULT_ACP_ENGINE_AGENT, DEFAULT_ACP_ENGINE_MODE, DEFAULT_ACP_ENGINE_NON_INTERACTIVE_PERMISSIONS, DEFAULT_ACP_ENGINE_PERMISSION_MODE, DEFAULT_ACP_ENGINE_TIMEOUT_SEC, DEFAULT_ACP_ENGINE_WARM_HANDLE_IDLE_MS, } from "./constants.js";
21
+ import { ACP_TOOL_KINDS, ACPX_DUPLEX_LOSS_CANCEL_DEADLINE_MS, ACPX_HANDSHAKE_TIMEOUT_MS, ACPX_HANDSHAKE_TRANSPORT_POLL_MS, DEFAULT_ACP_ENGINE_AGENT, DEFAULT_ACP_ENGINE_MODE, DEFAULT_ACP_ENGINE_NON_INTERACTIVE_PERMISSIONS, DEFAULT_ACP_ENGINE_PERMISSION_MODE, DEFAULT_ACP_ENGINE_TIMEOUT_SEC, DEFAULT_ACP_ENGINE_WARM_HANDLE_IDLE_MS, } from "./constants.js";
22
22
  import { createRunResourceLedger } from "./run-resource-ledger.js";
23
+ import { acpxAccountingModel } from "./accounting-model.js";
23
24
  import { settleAcpRun } from "./settlement-sequence.js";
24
25
  import { runAttempt, } from "./run-coordinator.js";
25
26
  import { runTurn as runTurnSequence, } from "./turn-sequence.js";
@@ -863,7 +864,7 @@ function normalizeRequestedThinkingEffort(config) {
863
864
  asString(config.effort, "")).trim();
864
865
  }
865
866
  function buildCodexStartupConfig(input) {
866
- const hasRuntimeConfig = Boolean(input.requestedModel || input.requestedThinkingEffort || input.fastMode);
867
+ const hasRuntimeConfig = Boolean(input.requestedModel || input.requestedThinkingEffort || input.fastMode || input.identityEnvironmentKeys);
867
868
  if (!hasRuntimeConfig)
868
869
  return { value: null, invalidExistingConfig: false };
869
870
  let existing = {};
@@ -893,6 +894,11 @@ function buildCodexStartupConfig(input) {
893
894
  },
894
895
  }
895
896
  : {}),
897
+ ...(input.identityEnvironmentKeys ? {
898
+ features: { ...parseObject(existing.features), ...(input.fastMode ? { fast_mode: true } : {}), shell_snapshot: false },
899
+ shell_environment_policy: { ...parseObject(existing.shell_environment_policy),
900
+ inherit: "all", ignore_default_excludes: true, include_only: input.identityEnvironmentKeys },
901
+ } : {}),
896
902
  }),
897
903
  invalidExistingConfig,
898
904
  };
@@ -1211,7 +1217,7 @@ async function buildRuntime(input) {
1211
1217
  const stateDir = path.resolve(asString(config.stateDir, "") || defaultStateDir(agent.companyId, agent.id));
1212
1218
  await fs.mkdir(stateDir, { recursive: true });
1213
1219
  const envConfig = parseObject(config.env);
1214
- const env = { ...buildPaperclipEnv(agent), PAPERCLIP_RUN_ID: runId };
1220
+ const env = { ...buildPaperclipEnv(agent, input.ctx.agentIdentity), PAPERCLIP_RUN_ID: runId };
1215
1221
  const wakeTaskId = (typeof context.taskId === "string" && context.taskId.trim()) ||
1216
1222
  (typeof context.issueId === "string" && context.issueId.trim()) ||
1217
1223
  "";
@@ -1300,9 +1306,22 @@ async function buildRuntime(input) {
1300
1306
  if (requestedModel && acpxAgent === "claude" && !env.ANTHROPIC_MODEL) {
1301
1307
  env.ANTHROPIC_MODEL = requestedModel;
1302
1308
  }
1309
+ // Gemini CLI reads GEMINI_MODEL when creating each ACP session. Its ACP
1310
+ // implementation supports set_model, but not set_config_option; configure
1311
+ // the selected model before startup without changing the transport.
1312
+ if (requestedModel && acpxAgent === "gemini") {
1313
+ env.GEMINI_MODEL = requestedModel;
1314
+ }
1303
1315
  if (acpxAgent === "codex") {
1304
1316
  const codexStartupConfig = buildCodexStartupConfig({
1305
1317
  existingConfig: env.CODEX_CONFIG,
1318
+ ...(input.ctx.agentIdentity ? { identityEnvironmentKeys: [...new Set([
1319
+ "PATH", "HOME", "LANG", "TMPDIR", "CODEX_HOME",
1320
+ "PAPERCLIP_AGENT_KEY_ID", "PAPERCLIP_AGENT_PUBLIC_KEY", "PAPERCLIP_AGENT_PRIVATE_KEY",
1321
+ // Preserve Codex's default secret-name exclusions. The short-lived
1322
+ // Paperclip API token is required by the agent skill's Bash/curl calls.
1323
+ ...Object.keys(env).filter(key => key === "PAPERCLIP_API_KEY" || !/key|secret|token/i.test(key)),
1324
+ ])] } : {}),
1306
1325
  requestedModel,
1307
1326
  requestedThinkingEffort,
1308
1327
  fastMode,
@@ -1429,8 +1448,9 @@ async function buildRuntime(input) {
1429
1448
  // (fingerprint, compat, persist, ensureSession, error) bind to THIS single
1430
1449
  // value so a warm/resumable session created with the in-sandbox cwd is reused
1431
1450
  // — not invalidated — on the next run. Remote runner-backed → the in-sandbox
1432
- // workspace dir; local and the runner-less fallback → the HOST cwd,
1433
- // byte-identical to today.
1451
+ // workspace dir; local and the runner-less fallback → the HOST cwd.
1452
+ // Local Gemini resolves tool paths through realpath. Give its ACP filesystem
1453
+ // client the same canonical root so workspace aliases stay within that root.
1434
1454
  //
1435
1455
  // PR 3: the staging transport derives the in-sandbox workspace dir
1436
1456
  // deterministically from the target's `remoteCwd` (it is exactly `remoteCwd`
@@ -1442,11 +1462,14 @@ async function buildRuntime(input) {
1442
1462
  // diverge from the cwd that fed the fingerprint.
1443
1463
  const sessionCwd = useRemoteProcessSession && executionTarget?.kind === "remote"
1444
1464
  ? executionTarget.remoteCwd
1445
- : cwd;
1465
+ : acpxAgent === "gemini" && !executionTargetIsRemote
1466
+ ? await fs.realpath(cwd)
1467
+ : cwd;
1446
1468
  // The 17 fields the session fingerprint hashes. Company, agent, and task
1447
1469
  // identifiers are NOT here; they scope the outer session key only (see
1448
1470
  // `keyIdentity`). The fingerprint builder accepts only this identity.
1449
1471
  const fingerprintIdentity = {
1472
+ ...(input.ctx.agentIdentity ? { agentIdentityKeyId: input.ctx.agentIdentity.keyId } : {}),
1450
1473
  acpxAgent,
1451
1474
  agentCommand: agentCommand ?? acpxAgent,
1452
1475
  cwd: path.resolve(sessionCwd),
@@ -1772,6 +1795,28 @@ async function buildRuntime(input) {
1772
1795
  await emitRunPhaseTiming(input.ctx, "start_transport", nowMs() - startTransportStart, "failed");
1773
1796
  throw err;
1774
1797
  }
1798
+ const currentSkillRoot = acpxAgent === "codex" && runtimeEnv.CODEX_HOME
1799
+ ? path.join(runtimeEnv.CODEX_HOME, "skills")
1800
+ : acpxAgent === "gemini" && !executionTargetIsRemote && typeof skillsIdentity.skillsHome === "string"
1801
+ ? skillsIdentity.skillsHome
1802
+ : null;
1803
+ if (currentSkillRoot && Array.isArray(skillsIdentity.selectedSkills) && skillsIdentity.selectedSkills.length > 0) {
1804
+ // Managed connection homes are disposable. A resumed conversation may
1805
+ // remember a previous home's skill paths; supply the current root on every
1806
+ // turn, after the remote launch environment has rebased CODEX_HOME.
1807
+ skillPromptInstructions = [
1808
+ `Paperclip has materialized selected runtime skills for this ACPX ${acpxAgent === "codex" ? "Codex" : "Gemini"} run.`,
1809
+ `Skill root for this run: ${currentSkillRoot}`,
1810
+ `Selected skills: ${skillsIdentity.selectedSkills.join(", ")}`,
1811
+ "When a task calls for one of these skills, read its SKILL.md from this root and follow it. Resolve referenced scripts and files relative to that skill. Use this run's root even when an earlier turn used a different path.",
1812
+ ...(acpxAgent === "gemini" && skillsIdentity.selectedSkills.includes("paperclip")
1813
+ ? [
1814
+ "Before calling Paperclip APIs or delivering task artifacts, read the selected paperclip skill's SKILL.md and its referenced artifact workflow. A completion comment does not upload an artifact or change task status.",
1815
+ "Gemini's shell tool rejects command substitution. Write JSON request bodies to a workspace file and use curl --data-binary @file, or use the selected skill's helpers, instead of constructing a body with command substitution.",
1816
+ ]
1817
+ : []),
1818
+ ].join("\n");
1819
+ }
1775
1820
  // The relay runs on the host with the sanitized remote launch environment.
1776
1821
  // Its /usr/bin/env node shebang cannot rely on that environment's PATH.
1777
1822
  const overrideCommand = processSessionBridge?.agentCommand
@@ -1837,12 +1882,13 @@ async function buildRuntime(input) {
1837
1882
  }
1838
1883
  function sessionConfigOptions(prepared) {
1839
1884
  const options = [];
1840
- // Claude and Codex runtime config is pre-set via startup env vars; skip
1885
+ // Claude, Codex and Gemini runtime config is pre-set via startup env vars; skip
1841
1886
  // set_config_option to avoid ACP-server picker validation rejecting valid
1842
1887
  // backend model IDs that are not advertised by the local ACP server.
1843
1888
  if (prepared.requestedModel &&
1844
1889
  prepared.acpxAgent !== "claude" &&
1845
- prepared.acpxAgent !== "codex") {
1890
+ prepared.acpxAgent !== "codex" &&
1891
+ prepared.acpxAgent !== "gemini") {
1846
1892
  options.push({ key: "model", value: prepared.requestedModel });
1847
1893
  }
1848
1894
  if (prepared.requestedThinkingEffort && prepared.acpxAgent !== "codex") {
@@ -2319,6 +2365,41 @@ async function emitRuntimeEvent(ctx, event, toolTitles, coalescePlaceholderToolU
2319
2365
  });
2320
2366
  }
2321
2367
  }
2368
+ function isPendingAcpTool(tool) {
2369
+ return tool.status !== "completed" && tool.status !== "failed" && tool.status !== "cancelled";
2370
+ }
2371
+ /**
2372
+ * Activity as of the moment the turn's stop fired, for a stopped turn only.
2373
+ * Separates a turn that went silent long before its deadline from one that
2374
+ * was still working. Reports only ages and closed ACP tool-kind labels.
2375
+ */
2376
+ export function summarizeAcpStopActivity(stopRequestedAt, lastEventBeforeStopAt, pendingTools) {
2377
+ const summary = {};
2378
+ if (pendingTools.length > 0) {
2379
+ const knownKinds = ACP_TOOL_KINDS;
2380
+ summary.acpPendingToolKinds = uniqueSorted(pendingTools.map((tool) => (tool.kind && knownKinds.includes(tool.kind) ? tool.kind : "unknown"))).join(",");
2381
+ }
2382
+ if (stopRequestedAt === null)
2383
+ return summary;
2384
+ const age = (since) => {
2385
+ const value = stopRequestedAt - since;
2386
+ return Number.isSafeInteger(value) && value >= 0 ? value : undefined;
2387
+ };
2388
+ if (lastEventBeforeStopAt !== null) {
2389
+ const value = age(lastEventBeforeStopAt);
2390
+ if (value !== undefined)
2391
+ summary.acpLastEventAgeAtStopMs = value;
2392
+ }
2393
+ const pendingSince = pendingTools
2394
+ .map((tool) => tool.firstSeenAt)
2395
+ .filter((at) => typeof at === "number" && at <= stopRequestedAt);
2396
+ if (pendingSince.length > 0) {
2397
+ const value = age(Math.min(...pendingSince));
2398
+ if (value !== undefined)
2399
+ summary.acpOldestPendingToolAgeAtStopMs = value;
2400
+ }
2401
+ return summary;
2402
+ }
2322
2403
  function resultErrorMessage(result) {
2323
2404
  if (result.status !== "failed")
2324
2405
  return null;
@@ -2907,6 +2988,7 @@ export function createAcpxEngineExecutor(deps = {}) {
2907
2988
  provider: billingIdentity?.provider ?? "acpx",
2908
2989
  ...(billingIdentity?.biller ? { biller: billingIdentity.biller } : {}),
2909
2990
  billingType: billingIdentity?.billingType ?? "unknown",
2991
+ pricingContext: undefined,
2910
2992
  };
2911
2993
  const warmIdleMs = asNumber(ctx.config.warmHandleIdleMs, DEFAULT_ACP_ENGINE_WARM_HANDLE_IDLE_MS);
2912
2994
  // The host run site owns the warm-handle store on this run. It operates over
@@ -3197,6 +3279,7 @@ export function createAcpxEngineExecutor(deps = {}) {
3197
3279
  stageRuntimeSpan: runStageSpan,
3198
3280
  }));
3199
3281
  buildRuntimeSettled = true;
3282
+ billingFields.pricingContext = prepared.fastMode ? { serviceTier: "fast" } : undefined;
3200
3283
  // Capture acquired resources before the cancellation boundary so the
3201
3284
  // normal settlement path also releases a just-completed build.
3202
3285
  releaseStagingLease = prepared.sessionStagingLeaseRelease;
@@ -3684,14 +3767,27 @@ export function createAcpxEngineExecutor(deps = {}) {
3684
3767
  };
3685
3768
  let eventBreakdown = null;
3686
3769
  let eventCostUsd = null;
3770
+ // Receipt persistence is fallible; retain the provider evidence before
3771
+ // calling the sink so the failure result can still return it to the host.
3772
+ let observedUsage = { usageComplete: false };
3687
3773
  let lastRuntimeEventAt = null;
3688
3774
  let observedRuntimeEvents = 0;
3775
+ // Activity as of the moment the turn's stop (wall-clock timeout or
3776
+ // operator stop) fired. The cancel can make the agent emit closing
3777
+ // events (including updates that close the stalled tool), so the
3778
+ // finalize-time age and pending set alone cannot tell a silent stall
3779
+ // from live work.
3780
+ let turnStopRequestedAt = null;
3781
+ let lastRuntimeEventBeforeStopAt = null;
3782
+ let pendingToolsAtStop = null;
3783
+ let turnDispatchAttempted = false;
3689
3784
  // The turn-local state the sequence steps share. `promptBuild` sets the
3690
3785
  // prompt, `preTurnUsage` sets the pre-turn status, `turnStart` sets the
3691
3786
  // active turn, and `turnFinalize` reads all three. `activeTurn` is the run-
3692
3787
  // scoped hoisted local, so the settlement `endSession` step can cancel it.
3693
3788
  let runPrompt = "";
3694
3789
  let preTurnStatus = null;
3790
+ let accountingModel = prepared.requestedModel || null;
3695
3791
  // Phase-timing markers for the prepare_turn and turn phases. The prepare
3696
3792
  // phase covers the prompt build and the pre-turn usage snapshot; the turn
3697
3793
  // phase covers the started turn and the event relay.
@@ -3740,7 +3836,9 @@ export function createAcpxEngineExecutor(deps = {}) {
3740
3836
  ? `Requested ACPX model: ${prepared.requestedModel} (set via ANTHROPIC_MODEL env at startup).`
3741
3837
  : prepared.acpxAgent === "codex"
3742
3838
  ? `Requested ACPX model: ${prepared.requestedModel} (set via CODEX_CONFIG at startup).`
3743
- : `Requested ACPX model: ${prepared.requestedModel}.`,
3839
+ : prepared.acpxAgent === "gemini"
3840
+ ? `Requested ACPX model: ${prepared.requestedModel} (set via GEMINI_MODEL at startup).`
3841
+ : `Requested ACPX model: ${prepared.requestedModel}.`,
3744
3842
  ]
3745
3843
  : []),
3746
3844
  ...(prepared.requestedThinkingEffort ? [`Requested ACPX thinking effort: ${prepared.requestedThinkingEffort}.`] : []),
@@ -3761,6 +3859,7 @@ export function createAcpxEngineExecutor(deps = {}) {
3761
3859
  // Snapshot pre-turn usage so cumulative agent-reported cost can be
3762
3860
  // attributed to this run alone.
3763
3861
  preTurnStatus = await readRuntimeStatus(runtime, sessionHandle);
3862
+ accountingModel = acpxAccountingModel(prepared.requestedModel, preTurnStatus, null);
3764
3863
  // The prepare phase (prompt build + usage snapshot) finished; the turn
3765
3864
  // phase starts next.
3766
3865
  await emitPhase("prepare_turn", preparePhaseStart, "ok");
@@ -3768,6 +3867,15 @@ export function createAcpxEngineExecutor(deps = {}) {
3768
3867
  };
3769
3868
  const stepTurnStart = (signal, startTimeoutMs) => {
3770
3869
  ctx.signal?.throwIfAborted();
3870
+ signal.addEventListener("abort", () => {
3871
+ if (turnStopRequestedAt !== null)
3872
+ return;
3873
+ turnStopRequestedAt = now();
3874
+ pendingToolsAtStop = [...interruptionTools.values()].filter(isPendingAcpTool);
3875
+ }, { once: true });
3876
+ // After entering startTurn, a thrown error cannot prove the provider
3877
+ // received no work. Only failures before this boundary are free to settle.
3878
+ turnDispatchAttempted = true;
3771
3879
  const turn = runtime.startTurn({
3772
3880
  handle: sessionHandle,
3773
3881
  text: runPrompt,
@@ -3859,6 +3967,8 @@ export function createAcpxEngineExecutor(deps = {}) {
3859
3967
  const drainEvents = (async () => {
3860
3968
  for await (const event of turn.events) {
3861
3969
  lastRuntimeEventAt = now();
3970
+ if (turnStopRequestedAt === null)
3971
+ lastRuntimeEventBeforeStopAt = lastRuntimeEventAt;
3862
3972
  observedRuntimeEvents += 1;
3863
3973
  // ACPX currently flattens client-side filesystem/terminal receipts
3864
3974
  // into status text. They cannot establish complete action outcomes.
@@ -3872,6 +3982,7 @@ export function createAcpxEngineExecutor(deps = {}) {
3872
3982
  interruptionTools.set(event.toolCallId, {
3873
3983
  kind: event.kind ?? previous?.kind,
3874
3984
  status: event.status ?? previous?.status,
3985
+ firstSeenAt: previous?.firstSeenAt ?? lastRuntimeEventAt,
3875
3986
  });
3876
3987
  }
3877
3988
  }
@@ -3888,6 +3999,10 @@ export function createAcpxEngineExecutor(deps = {}) {
3888
3999
  if (event.type === "status" && event.tag === "usage_update") {
3889
4000
  eventBreakdown = event.breakdown ?? eventBreakdown;
3890
4001
  eventCostUsd = usdCostAmount(event.cost) ?? eventCostUsd;
4002
+ const checkpoint = summarizeAcpxTurnUsage({ preStatus: preTurnStatus, postStatus: null, eventBreakdown, eventCostUsd });
4003
+ observedUsage = { usage: checkpoint.usage ?? undefined, costUsd: checkpoint.costUsd, usageBasis: "per_run", usageComplete: false };
4004
+ await ctx.onUsage?.({ ...billingFields, usage: checkpoint.usage ?? undefined, costUsd: checkpoint.costUsd,
4005
+ model: accountingModel, usageBasis: "per_run", complete: false });
3891
4006
  }
3892
4007
  await emitRuntimeEvent(ctx, event, toolTitles, prepared.coalescePlaceholderToolUpdates);
3893
4008
  }
@@ -3921,12 +4036,14 @@ export function createAcpxEngineExecutor(deps = {}) {
3921
4036
  // Capture runtime activity before usage reads, error logs, or cleanup
3922
4037
  // make an otherwise silent turn look active at its execution deadline.
3923
4038
  const lastEventAgeMs = lastRuntimeEventAt === null ? undefined : now() - lastRuntimeEventAt;
4039
+ const pendingTools = [...interruptionTools.values()].filter(isPendingAcpTool);
3924
4040
  const activityDiagnostics = {
3925
4041
  acpObservedEventCount: observedRuntimeEvents,
3926
4042
  ...(lastEventAgeMs !== undefined && Number.isSafeInteger(lastEventAgeMs) && lastEventAgeMs >= 0
3927
4043
  ? { acpLastEventAgeMs: lastEventAgeMs } : {}),
3928
- acpPendingToolCount: [...interruptionTools.values()].filter((tool) => tool.status !== "completed" && tool.status !== "failed" && tool.status !== "cancelled").length,
4044
+ acpPendingToolCount: pendingTools.length,
3929
4045
  acpToolInventoryComplete: !incompleteToolInventory,
4046
+ ...summarizeAcpStopActivity(turnStopRequestedAt, lastRuntimeEventBeforeStopAt, pendingToolsAtStop ?? pendingTools),
3930
4047
  };
3931
4048
  if (input.kind === "terminal") {
3932
4049
  const terminal = input.terminal;
@@ -3964,12 +4081,19 @@ export function createAcpxEngineExecutor(deps = {}) {
3964
4081
  const turnSucceeded = terminal.status === "completed" && !timedOut && !channelLost;
3965
4082
  // Read usage before the settlement can discard runtime state.
3966
4083
  const postTurnStatus = await readRuntimeStatus(runtime, sessionHandle);
4084
+ accountingModel = acpxAccountingModel(prepared.requestedModel, preTurnStatus, postTurnStatus);
3967
4085
  const turnUsage = summarizeAcpxTurnUsage({
3968
4086
  preStatus: preTurnStatus,
3969
4087
  postStatus: postTurnStatus,
3970
4088
  eventBreakdown,
3971
4089
  eventCostUsd,
3972
4090
  });
4091
+ // An interrupted stream is provisional unless the runtime supplies its
4092
+ // post-terminal receipt. An in-stream usage_update alone cannot close it.
4093
+ const usageComplete = !channelLost && (turnSucceeded || postTurnStatus?.usage != null);
4094
+ observedUsage = { usage: turnUsage.usage ?? undefined, costUsd: turnUsage.costUsd, usageBasis: "per_run", usageComplete };
4095
+ await ctx.onUsage?.({ ...billingFields, usage: turnUsage.usage ?? undefined, costUsd: turnUsage.costUsd,
4096
+ model: accountingModel, usageBasis: "per_run", complete: usageComplete });
3973
4097
  const failedTurn = terminal.status === "failed" || terminal.status === "cancelled" || timedOut;
3974
4098
  // ACPX can defer session/load until runTurn. Forget an unavailable
3975
4099
  // session so the next bounded turn receives the full task conversation.
@@ -4052,9 +4176,10 @@ export function createAcpxEngineExecutor(deps = {}) {
4052
4176
  sessionDisplayId: sessionHandle.agentSessionId ?? sessionHandle.backendSessionId ?? sessionHandle.runtimeSessionName,
4053
4177
  ...billingFields,
4054
4178
  ...referencedProjectStagingFailuresField,
4055
- model: prepared.requestedModel || null,
4179
+ model: accountingModel,
4056
4180
  ...(turnUsage.usage ? { usage: turnUsage.usage, usageBasis: "per_run" } : {}),
4057
4181
  costUsd: turnUsage.costUsd,
4182
+ usageComplete,
4058
4183
  resultJson: {
4059
4184
  status: channelLost ? "failed" : terminal.status,
4060
4185
  ...activityDiagnostics,
@@ -4185,9 +4310,11 @@ export function createAcpxEngineExecutor(deps = {}) {
4185
4310
  errorMessage: message,
4186
4311
  errorCode: timedOut ? "acpx_timeout" : (emitted?.classified.errorCode ?? null),
4187
4312
  errorMeta: emitted?.classified.errorMeta,
4313
+ ...observedUsage,
4314
+ ...(!turnDispatchAttempted ? { executionRecovery: { kind: "bootstrap", providerWorkStarted: false } } : {}),
4188
4315
  ...billingFields,
4189
4316
  ...referencedProjectStagingFailuresField,
4190
- model: prepared.requestedModel || null,
4317
+ model: accountingModel,
4191
4318
  clearSession: clearSession || timedOut,
4192
4319
  resultJson: { phase, ...activityDiagnostics },
4193
4320
  summary: message,