codex-chatgpt-control 0.5.1-alpha.2 → 0.5.1-alpha.3

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 (191) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/README.md +27 -0
  3. package/contracts/v1/fixtures/backend-capabilities.json +40 -1
  4. package/contracts/v1/fixtures/backend-compatibility.json +21 -0
  5. package/contracts/v1/fixtures/backend-version.json +6 -1
  6. package/contracts/v1/fixtures/operation-action-prepared-event.json +42 -0
  7. package/contracts/v1/fixtures/operation-action.json +13 -0
  8. package/contracts/v1/fixtures/operation-artifact-receipt.json +14 -0
  9. package/contracts/v1/fixtures/operation-artifact-transfer-intent-event.json +24 -0
  10. package/contracts/v1/fixtures/operation-artifact-transfer-receipt-event.json +26 -0
  11. package/contracts/v1/fixtures/operation-artifact-transfer-state.json +178 -0
  12. package/contracts/v1/fixtures/operation-blocker.json +10 -0
  13. package/contracts/v1/fixtures/operation-collect-request.json +17 -0
  14. package/contracts/v1/fixtures/operation-collect-result.json +42 -0
  15. package/contracts/v1/fixtures/operation-control-receipt.json +13 -0
  16. package/contracts/v1/fixtures/operation-control-request.json +18 -0
  17. package/contracts/v1/fixtures/operation-control-result.json +31 -0
  18. package/contracts/v1/fixtures/operation-event.json +18 -0
  19. package/contracts/v1/fixtures/operation-handle.json +10 -0
  20. package/contracts/v1/fixtures/operation-inspect-request.json +13 -0
  21. package/contracts/v1/fixtures/operation-inspect-result.json +205 -0
  22. package/contracts/v1/fixtures/operation-ownership-baseline-event.json +34 -0
  23. package/contracts/v1/fixtures/operation-receipt.json +32 -0
  24. package/contracts/v1/fixtures/operation-recovery-decision.json +7 -0
  25. package/contracts/v1/fixtures/operation-recovery-observation.json +12 -0
  26. package/contracts/v1/fixtures/operation-request.json +33 -0
  27. package/contracts/v1/fixtures/operation-state.json +144 -0
  28. package/contracts/v1/fixtures/operation-submission-witness-event.json +20 -0
  29. package/contracts/v1/fixtures/operation-submission-witness.json +11 -0
  30. package/contracts/v1/fixtures/operation-submit-result.json +16 -0
  31. package/contracts/v1/fixtures/operation-target-established-event.json +21 -0
  32. package/contracts/v1/manifest.json +155 -1
  33. package/contracts/v1/parity-suite.json +96 -1
  34. package/contracts/v1/schemas/backend-compatibility.schema.json +65 -0
  35. package/contracts/v1/schemas/backend-request.schema.json +8 -2
  36. package/contracts/v1/schemas/capabilities.schema.json +81 -1
  37. package/contracts/v1/schemas/manifest.schema.json +57 -0
  38. package/contracts/v1/schemas/operation-action.schema.json +155 -0
  39. package/contracts/v1/schemas/operation-artifact-receipt.schema.json +89 -0
  40. package/contracts/v1/schemas/operation-blocker.schema.json +70 -0
  41. package/contracts/v1/schemas/operation-collect-request.schema.json +46 -0
  42. package/contracts/v1/schemas/operation-collect-result.schema.json +74 -0
  43. package/contracts/v1/schemas/operation-control-receipt.schema.json +108 -0
  44. package/contracts/v1/schemas/operation-control-request.schema.json +111 -0
  45. package/contracts/v1/schemas/operation-control-result.schema.json +112 -0
  46. package/contracts/v1/schemas/operation-event.schema.json +756 -0
  47. package/contracts/v1/schemas/operation-handle.schema.json +55 -0
  48. package/contracts/v1/schemas/operation-inspect-request.schema.json +42 -0
  49. package/contracts/v1/schemas/operation-inspect-result.schema.json +1662 -0
  50. package/contracts/v1/schemas/operation-receipt.schema.json +153 -0
  51. package/contracts/v1/schemas/operation-recovery.schema.json +314 -0
  52. package/contracts/v1/schemas/operation-request.schema.json +158 -0
  53. package/contracts/v1/schemas/operation-state.schema.json +691 -0
  54. package/contracts/v1/schemas/operation-submission-witness.schema.json +48 -0
  55. package/contracts/v1/schemas/operation-submit-result.schema.json +94 -0
  56. package/contracts/v1/surface-drift-policy.json +50 -0
  57. package/contracts/v1/vectors/operation-request-digest-v1.json +43 -0
  58. package/dist/codex-chatgpt-control-backend.mjs +43897 -9094
  59. package/dist/codex-chatgpt-control.bundle.mjs +46360 -10262
  60. package/dist/src/backend/client.d.ts +103 -2
  61. package/dist/src/backend/client.js +1436 -97
  62. package/dist/src/backend/compatibility.d.ts +12 -0
  63. package/dist/src/backend/compatibility.js +208 -0
  64. package/dist/src/backend/protocol.d.ts +84 -1
  65. package/dist/src/backend/protocol.js +31 -5
  66. package/dist/src/backend/runtime-identity.d.ts +10 -0
  67. package/dist/src/backend/runtime-identity.js +141 -0
  68. package/dist/src/backend/session.d.ts +10 -2
  69. package/dist/src/backend/session.js +478 -7
  70. package/dist/src/backend/stdio-server.d.ts +4 -1
  71. package/dist/src/backend/stdio-server.js +240 -28
  72. package/dist/src/browser/active-composer-file-input.d.ts +9 -0
  73. package/dist/src/browser/active-composer-file-input.js +33 -0
  74. package/dist/src/browser/attach.d.ts +4 -1
  75. package/dist/src/browser/attach.js +136 -28
  76. package/dist/src/browser/downloads.d.ts +2 -0
  77. package/dist/src/client.d.ts +38 -0
  78. package/dist/src/client.js +1222 -59
  79. package/dist/src/commands/configuration.js +13 -7
  80. package/dist/src/commands/doctor.d.ts +1 -1
  81. package/dist/src/commands/doctor.js +26 -3
  82. package/dist/src/commands/experience.js +35 -0
  83. package/dist/src/commands/files.js +4 -27
  84. package/dist/src/commands/modes.js +49 -17
  85. package/dist/src/commands/power-discovery.d.ts +130 -0
  86. package/dist/src/commands/power-discovery.js +627 -0
  87. package/dist/src/commands/project-sources.js +325 -31
  88. package/dist/src/commands/sequence.js +59 -32
  89. package/dist/src/commands/session.js +7 -2
  90. package/dist/src/commands/work.js +31 -0
  91. package/dist/src/errors.d.ts +9 -0
  92. package/dist/src/errors.js +22 -0
  93. package/dist/src/index.d.ts +6 -0
  94. package/dist/src/index.js +9 -0
  95. package/dist/src/operations/artifact-output.d.ts +69 -0
  96. package/dist/src/operations/artifact-output.js +1748 -0
  97. package/dist/src/operations/artifact-stream.d.ts +19 -0
  98. package/dist/src/operations/artifact-stream.js +35 -0
  99. package/dist/src/operations/artifact-transfer.d.ts +149 -0
  100. package/dist/src/operations/artifact-transfer.js +1312 -0
  101. package/dist/src/operations/browser-adapter.d.ts +161 -0
  102. package/dist/src/operations/browser-adapter.js +2023 -0
  103. package/dist/src/operations/browser-observation.d.ts +110 -0
  104. package/dist/src/operations/browser-observation.js +1208 -0
  105. package/dist/src/operations/browser-target.d.ts +103 -0
  106. package/dist/src/operations/browser-target.js +489 -0
  107. package/dist/src/operations/canonical.d.ts +4 -0
  108. package/dist/src/operations/canonical.js +412 -0
  109. package/dist/src/operations/chatgpt-runtime.d.ts +72 -0
  110. package/dist/src/operations/chatgpt-runtime.js +1150 -0
  111. package/dist/src/operations/client.d.ts +138 -0
  112. package/dist/src/operations/client.js +1143 -0
  113. package/dist/src/operations/collector.d.ts +195 -0
  114. package/dist/src/operations/collector.js +1039 -0
  115. package/dist/src/operations/control.d.ts +372 -0
  116. package/dist/src/operations/control.js +1498 -0
  117. package/dist/src/operations/file-identity.d.ts +33 -0
  118. package/dist/src/operations/file-identity.js +153 -0
  119. package/dist/src/operations/handle.d.ts +19 -0
  120. package/dist/src/operations/handle.js +727 -0
  121. package/dist/src/operations/index.d.ts +22 -0
  122. package/dist/src/operations/index.js +22 -0
  123. package/dist/src/operations/journal.d.ts +142 -0
  124. package/dist/src/operations/journal.js +1931 -0
  125. package/dist/src/operations/production-attachments.d.ts +116 -0
  126. package/dist/src/operations/production-attachments.js +1018 -0
  127. package/dist/src/operations/production-chatgpt-artifacts.d.ts +74 -0
  128. package/dist/src/operations/production-chatgpt-artifacts.js +1146 -0
  129. package/dist/src/operations/production-chatgpt-attachments.d.ts +71 -0
  130. package/dist/src/operations/production-chatgpt-attachments.js +1563 -0
  131. package/dist/src/operations/production-configuration.d.ts +42 -0
  132. package/dist/src/operations/production-configuration.js +1363 -0
  133. package/dist/src/operations/production-primitives.d.ts +53 -0
  134. package/dist/src/operations/production-primitives.js +1073 -0
  135. package/dist/src/operations/production-work-steer.d.ts +203 -0
  136. package/dist/src/operations/production-work-steer.js +1218 -0
  137. package/dist/src/operations/recovery.d.ts +80 -0
  138. package/dist/src/operations/recovery.js +174 -0
  139. package/dist/src/operations/runtime-adapter.d.ts +118 -0
  140. package/dist/src/operations/runtime-adapter.js +786 -0
  141. package/dist/src/operations/send-once.d.ts +224 -0
  142. package/dist/src/operations/send-once.js +1081 -0
  143. package/dist/src/operations/service.d.ts +281 -0
  144. package/dist/src/operations/service.js +2810 -0
  145. package/dist/src/operations/staging.d.ts +136 -0
  146. package/dist/src/operations/staging.js +630 -0
  147. package/dist/src/operations/state-machine.d.ts +29 -0
  148. package/dist/src/operations/state-machine.js +2047 -0
  149. package/dist/src/operations/submission.d.ts +423 -0
  150. package/dist/src/operations/submission.js +1676 -0
  151. package/dist/src/operations/turn-ownership.d.ts +202 -0
  152. package/dist/src/operations/turn-ownership.js +700 -0
  153. package/dist/src/operations/types.d.ts +454 -0
  154. package/dist/src/operations/types.js +20 -0
  155. package/dist/src/operations/wire-requests.d.ts +21 -0
  156. package/dist/src/operations/wire-requests.js +396 -0
  157. package/dist/src/operations/wire-results.d.ts +97 -0
  158. package/dist/src/operations/wire-results.js +818 -0
  159. package/dist/src/runner/responses.d.ts +3 -1
  160. package/dist/src/runner/responses.js +19 -1
  161. package/dist/src/runner/result.js +227 -55
  162. package/dist/src/runner/types.d.ts +12 -0
  163. package/dist/src/runtime/command-routing.d.ts +149 -0
  164. package/dist/src/runtime/command-routing.js +431 -0
  165. package/dist/src/runtime/coordinated-browser.d.ts +24 -0
  166. package/dist/src/runtime/coordinated-browser.js +315 -0
  167. package/dist/src/runtime/coordinated-page.d.ts +39 -0
  168. package/dist/src/runtime/coordinated-page.js +634 -0
  169. package/dist/src/runtime/operation-context.d.ts +142 -0
  170. package/dist/src/runtime/operation-context.js +410 -0
  171. package/dist/src/runtime/runtime-session.d.ts +95 -0
  172. package/dist/src/runtime/runtime-session.js +314 -0
  173. package/dist/src/runtime/tab-coordinator.d.ts +200 -0
  174. package/dist/src/runtime/tab-coordinator.js +1200 -0
  175. package/dist/src/runtime/value-boundaries.d.ts +18 -0
  176. package/dist/src/runtime/value-boundaries.js +49 -0
  177. package/dist/src/safety/untrusted-output.js +2 -1
  178. package/dist/src/scripts/backend-server.js +4 -1
  179. package/dist/src/scripts/live-smoke/harness.js +79 -7
  180. package/dist/src/scripts/live-smoke/scenarios.d.ts +28 -0
  181. package/dist/src/scripts/live-smoke/scenarios.js +110 -18
  182. package/dist/src/scripts/live-smoke/types.d.ts +3 -0
  183. package/dist/src/scripts/release-canary-module.js +17 -4
  184. package/dist/src/types.d.ts +38 -1
  185. package/package.json +1 -1
  186. package/references/2026-08-16-transactional-operations.md +459 -0
  187. package/references/agents-runner.md +34 -0
  188. package/references/backend-protocol.md +73 -0
  189. package/references/python-parity.md +72 -0
  190. package/references/responses-adapter.md +19 -0
  191. package/references/streaming.md +6 -0
@@ -0,0 +1,80 @@
1
+ import type { OperationActionRecordV1, OperationReceiptV1, OperationStateV1 } from "./types.js";
2
+ import { OPERATION_RECOVERY_DECISION_SCHEMA_VERSION, OPERATION_RECOVERY_OBSERVATION_SCHEMA_VERSION } from "./types.js";
3
+ export type OperationTargetObservation = {
4
+ status: "matches";
5
+ } | {
6
+ status: "mismatch";
7
+ evidenceDigest?: string;
8
+ } | {
9
+ status: "unavailable";
10
+ evidenceDigest?: string;
11
+ };
12
+ export type OperationTurnObservation = {
13
+ status: "not_observed";
14
+ } | {
15
+ status: "owned_user_turn";
16
+ userTurnId: string;
17
+ evidenceDigest: string;
18
+ } | {
19
+ status: "owned_assistant_generating";
20
+ userTurnId: string;
21
+ assistantTurnId: string;
22
+ evidenceDigest: string;
23
+ } | {
24
+ status: "owned_assistant_terminal";
25
+ userTurnId: string;
26
+ assistantTurnId: string;
27
+ evidenceDigest: string;
28
+ } | {
29
+ status: "ambiguous";
30
+ evidenceDigest?: string;
31
+ };
32
+ export type OperationRecoveryObservationV1 = {
33
+ schemaVersion: typeof OPERATION_RECOVERY_OBSERVATION_SCHEMA_VERSION;
34
+ target: OperationTargetObservation;
35
+ turn: OperationTurnObservation;
36
+ };
37
+ export type OperationRecoveryDecisionV1 = {
38
+ kind: "return_completed_receipt";
39
+ schemaVersion: typeof OPERATION_RECOVERY_DECISION_SCHEMA_VERSION;
40
+ receipt: OperationReceiptV1;
41
+ } | {
42
+ kind: "continue_preparation";
43
+ schemaVersion: typeof OPERATION_RECOVERY_DECISION_SCHEMA_VERSION;
44
+ phase: "prepared" | "ready";
45
+ nonRepeatableActionMayStart: true;
46
+ } | {
47
+ kind: "observe_action_postcondition";
48
+ schemaVersion: typeof OPERATION_RECOVERY_DECISION_SCHEMA_VERSION;
49
+ actionId: string;
50
+ actionKind: OperationActionRecordV1["kind"];
51
+ mayRepeatAction: false;
52
+ } | {
53
+ kind: "continue_owned_turn_observation";
54
+ schemaVersion: typeof OPERATION_RECOVERY_DECISION_SCHEMA_VERSION;
55
+ phase: "submitted" | "generating";
56
+ userTurnId?: string;
57
+ assistantTurnId?: string;
58
+ evidenceDigest?: string;
59
+ } | {
60
+ kind: "capture_owned_turn";
61
+ schemaVersion: typeof OPERATION_RECOVERY_DECISION_SCHEMA_VERSION;
62
+ assistantTurnId: string;
63
+ evidenceDigest: string;
64
+ } | {
65
+ kind: "enter_uncertain";
66
+ schemaVersion: typeof OPERATION_RECOVERY_DECISION_SCHEMA_VERSION;
67
+ code: "target_evidence_unavailable" | "turn_ownership_ambiguous" | "capture_ownership_lost";
68
+ mayRepeatAction: false;
69
+ } | {
70
+ kind: "block";
71
+ schemaVersion: typeof OPERATION_RECOVERY_DECISION_SCHEMA_VERSION;
72
+ code: "target_binding_mismatch" | "target_evidence_unavailable" | "operation_state_inconsistent";
73
+ mayRepeatAction: false;
74
+ };
75
+ /**
76
+ * Decide what a restarted caller may do from durable state and a fresh,
77
+ * operation-bound observation. This function never authorizes replay of an
78
+ * action whose intent is already durable.
79
+ */
80
+ export declare function decideOperationRecovery(state: OperationStateV1, observation: OperationRecoveryObservationV1): OperationRecoveryDecisionV1;
@@ -0,0 +1,174 @@
1
+ import { OPERATION_RECOVERY_DECISION_SCHEMA_VERSION } from "./types.js";
2
+ /**
3
+ * Decide what a restarted caller may do from durable state and a fresh,
4
+ * operation-bound observation. This function never authorizes replay of an
5
+ * action whose intent is already durable.
6
+ */
7
+ export function decideOperationRecovery(state, observation) {
8
+ if (state.phase === "completed") {
9
+ if (state.receipt === undefined) {
10
+ return { schemaVersion: OPERATION_RECOVERY_DECISION_SCHEMA_VERSION, kind: "block", code: "operation_state_inconsistent", mayRepeatAction: false };
11
+ }
12
+ return { schemaVersion: OPERATION_RECOVERY_DECISION_SCHEMA_VERSION, kind: "return_completed_receipt", receipt: state.receipt };
13
+ }
14
+ if (observation.target.status === "mismatch") {
15
+ return { schemaVersion: OPERATION_RECOVERY_DECISION_SCHEMA_VERSION, kind: "block", code: "target_binding_mismatch", mayRepeatAction: false };
16
+ }
17
+ if (observation.target.status === "unavailable") {
18
+ if (state.mutationBoundary === "none") {
19
+ return { schemaVersion: OPERATION_RECOVERY_DECISION_SCHEMA_VERSION, kind: "block", code: "target_evidence_unavailable", mayRepeatAction: false };
20
+ }
21
+ return { schemaVersion: OPERATION_RECOVERY_DECISION_SCHEMA_VERSION, kind: "enter_uncertain", code: "target_evidence_unavailable", mayRepeatAction: false };
22
+ }
23
+ // The process can stop after fsyncing an intent (or its receipt) but before
24
+ // appending the corresponding phase event. Phase alone therefore never
25
+ // authorizes a second non-repeatable browser action.
26
+ const pendingIntent = pendingNonRepeatableAction(state);
27
+ if (pendingIntent !== undefined) {
28
+ return decisionForPendingAction(state, pendingIntent, observation.turn);
29
+ }
30
+ if (state.phase === "prepared" || state.phase === "ready") {
31
+ return { schemaVersion: OPERATION_RECOVERY_DECISION_SCHEMA_VERSION, kind: "continue_preparation", phase: state.phase, nonRepeatableActionMayStart: true };
32
+ }
33
+ if (state.phase === "handoff_pending" || state.phase === "send_pending") {
34
+ const expectedKind = state.phase === "handoff_pending" ? "file_handoff" : "send";
35
+ const action = latestAction(state, candidate => candidate.kind === expectedKind);
36
+ if (action === undefined) {
37
+ return { schemaVersion: OPERATION_RECOVERY_DECISION_SCHEMA_VERSION, kind: "block", code: "operation_state_inconsistent", mayRepeatAction: false };
38
+ }
39
+ return {
40
+ schemaVersion: OPERATION_RECOVERY_DECISION_SCHEMA_VERSION,
41
+ kind: "observe_action_postcondition",
42
+ actionId: action.actionId,
43
+ actionKind: action.kind,
44
+ mayRepeatAction: false
45
+ };
46
+ }
47
+ if (state.phase === "capturing") {
48
+ if (observation.turn.status === "owned_assistant_terminal") {
49
+ return {
50
+ schemaVersion: OPERATION_RECOVERY_DECISION_SCHEMA_VERSION,
51
+ kind: "capture_owned_turn",
52
+ assistantTurnId: observation.turn.assistantTurnId,
53
+ evidenceDigest: observation.turn.evidenceDigest
54
+ };
55
+ }
56
+ return { schemaVersion: OPERATION_RECOVERY_DECISION_SCHEMA_VERSION, kind: "enter_uncertain", code: "capture_ownership_lost", mayRepeatAction: false };
57
+ }
58
+ if (state.phase === "submitted" || state.phase === "generating") {
59
+ return ownedTurnDecision(state.phase, observation.turn);
60
+ }
61
+ // An uncertain operation can only observe the most advanced durable
62
+ // boundary. It cannot return to a mutation path merely because the page
63
+ // looks plausible.
64
+ if (state.phase === "uncertain") {
65
+ if (state.mutationBoundary === "handoff_may_have_occurred") {
66
+ const action = latestAction(state, candidate => candidate.kind === "file_handoff");
67
+ if (action === undefined) {
68
+ return { schemaVersion: OPERATION_RECOVERY_DECISION_SCHEMA_VERSION, kind: "block", code: "operation_state_inconsistent", mayRepeatAction: false };
69
+ }
70
+ return { schemaVersion: OPERATION_RECOVERY_DECISION_SCHEMA_VERSION, kind: "observe_action_postcondition", actionId: action.actionId, actionKind: action.kind, mayRepeatAction: false };
71
+ }
72
+ if (state.mutationBoundary === "send_may_have_occurred" || state.mutationBoundary === "control_may_have_occurred") {
73
+ if (observation.turn.status === "not_observed") {
74
+ const action = latestAction(state, candidate => candidate.kind === "send" || candidate.kind === "work_steer" || candidate.kind === "stop");
75
+ if (action !== undefined) {
76
+ return { schemaVersion: OPERATION_RECOVERY_DECISION_SCHEMA_VERSION, kind: "observe_action_postcondition", actionId: action.actionId, actionKind: action.kind, mayRepeatAction: false };
77
+ }
78
+ }
79
+ const turnDecision = ownedTurnDecision("generating", observation.turn);
80
+ if (turnDecision.kind === "enter_uncertain") {
81
+ const action = latestAction(state, candidate => candidate.kind === "send" || candidate.kind === "work_steer" || candidate.kind === "stop");
82
+ if (action !== undefined) {
83
+ return { schemaVersion: OPERATION_RECOVERY_DECISION_SCHEMA_VERSION, kind: "observe_action_postcondition", actionId: action.actionId, actionKind: action.kind, mayRepeatAction: false };
84
+ }
85
+ }
86
+ return turnDecision;
87
+ }
88
+ return { schemaVersion: OPERATION_RECOVERY_DECISION_SCHEMA_VERSION, kind: "block", code: "operation_state_inconsistent", mayRepeatAction: false };
89
+ }
90
+ return { schemaVersion: OPERATION_RECOVERY_DECISION_SCHEMA_VERSION, kind: "block", code: "operation_state_inconsistent", mayRepeatAction: false };
91
+ }
92
+ function decisionForPendingAction(state, action, turn) {
93
+ // Attachment ownership is established by the exact manifest
94
+ // postcondition, not by turn state. A durable handoff intent therefore
95
+ // always remains observation-only until that postcondition is reconciled.
96
+ if (action.kind === "file_handoff")
97
+ return observeAction(action);
98
+ // Send/steer/stop can be reconciled directly when an operation-owned turn
99
+ // is already proven. This matters for the crash gap after the browser
100
+ // acted but before the action receipt or phase event was appended. Merely
101
+ // having a durable intent still never authorizes a second mutation.
102
+ if (turn.status === "not_observed")
103
+ return observeAction(action);
104
+ if (turn.status === "ambiguous") {
105
+ return {
106
+ schemaVersion: OPERATION_RECOVERY_DECISION_SCHEMA_VERSION,
107
+ kind: "enter_uncertain",
108
+ code: "turn_ownership_ambiguous",
109
+ mayRepeatAction: false
110
+ };
111
+ }
112
+ const phase = action.kind === "stop"
113
+ ? "generating"
114
+ : state.phase === "generating"
115
+ ? "generating"
116
+ : "submitted";
117
+ return ownedTurnDecision(phase, turn);
118
+ }
119
+ function observeAction(action) {
120
+ return {
121
+ schemaVersion: OPERATION_RECOVERY_DECISION_SCHEMA_VERSION,
122
+ kind: "observe_action_postcondition",
123
+ actionId: action.actionId,
124
+ actionKind: action.kind,
125
+ mayRepeatAction: false
126
+ };
127
+ }
128
+ function ownedTurnDecision(phase, turn) {
129
+ if (turn.status === "ambiguous") {
130
+ return { schemaVersion: OPERATION_RECOVERY_DECISION_SCHEMA_VERSION, kind: "enter_uncertain", code: "turn_ownership_ambiguous", mayRepeatAction: false };
131
+ }
132
+ if (turn.status === "owned_assistant_terminal") {
133
+ return { schemaVersion: OPERATION_RECOVERY_DECISION_SCHEMA_VERSION, kind: "capture_owned_turn", assistantTurnId: turn.assistantTurnId, evidenceDigest: turn.evidenceDigest };
134
+ }
135
+ if (turn.status === "owned_assistant_generating") {
136
+ return {
137
+ schemaVersion: OPERATION_RECOVERY_DECISION_SCHEMA_VERSION,
138
+ kind: "continue_owned_turn_observation",
139
+ phase: "generating",
140
+ userTurnId: turn.userTurnId,
141
+ assistantTurnId: turn.assistantTurnId,
142
+ evidenceDigest: turn.evidenceDigest
143
+ };
144
+ }
145
+ if (turn.status === "owned_user_turn") {
146
+ return {
147
+ schemaVersion: OPERATION_RECOVERY_DECISION_SCHEMA_VERSION,
148
+ kind: "continue_owned_turn_observation",
149
+ phase,
150
+ userTurnId: turn.userTurnId,
151
+ evidenceDigest: turn.evidenceDigest
152
+ };
153
+ }
154
+ return { schemaVersion: OPERATION_RECOVERY_DECISION_SCHEMA_VERSION, kind: "continue_owned_turn_observation", phase };
155
+ }
156
+ function latestAction(state, predicate) {
157
+ return Object.values(state.actions)
158
+ .filter(predicate)
159
+ .sort((left, right) => right.intentRevision - left.intentRevision)[0];
160
+ }
161
+ function pendingNonRepeatableAction(state) {
162
+ return latestAction(state, action => {
163
+ if (action.kind === "file_handoff") {
164
+ return state.phase === "prepared" || state.phase === "handoff_pending" || state.phase === "uncertain";
165
+ }
166
+ if (action.kind === "send") {
167
+ return state.phase === "ready" || state.phase === "send_pending" || state.phase === "uncertain";
168
+ }
169
+ if (action.kind === "work_steer" || action.kind === "stop") {
170
+ return state.phase === "generating" || state.phase === "uncertain";
171
+ }
172
+ return false;
173
+ });
174
+ }
@@ -0,0 +1,118 @@
1
+ import type { PageLike } from "../types.js";
2
+ import type { CoordinatorOwner, ProcessTabCoordinator } from "../runtime/tab-coordinator.js";
3
+ import { OperationRuntimeContext, type OperationRuntimeCapabilities } from "../runtime/operation-context.js";
4
+ import { type ComposedOperationBrowserAdapter, type OperationBrowserAdapterOptions, type OperationBrowserCollectorPrimitive, type OperationBrowserControlPrimitive, type OperationBrowserArtifactPrimitive, type OperationBrowserCurrentTargetResult, type OperationBrowserStagingPrimitive, type OperationBrowserSubmissionPrimitive, type OperationBrowserTargetProbe, type OperationBrowserTargetProbeRequest } from "./browser-adapter.js";
5
+ import type { BrowserTargetClaim, BrowserTargetEvidenceDigest } from "./browser-target.js";
6
+ import type { OwnershipTargetEvidence } from "./turn-ownership.js";
7
+ import type { OperationFileIdentity } from "./file-identity.js";
8
+ import type { OperationSurface, OperationTargetBindingV1, OperationTargetRequestV1 } from "./types.js";
9
+ /**
10
+ * Browser primitives that are safe to pass into an operation adapter.
11
+ *
12
+ * The callbacks receive the captured page explicitly. They must perform one
13
+ * bounded DOM transaction and return an already-redacted observation. In
14
+ * particular, a callback must not poll for generation, wait for attachment
15
+ * processing, read a mutable RuntimeEnv, or retry a non-repeatable browser
16
+ * action. Those waits belong to the operation collector and are deliberately
17
+ * outside the tab actor.
18
+ */
19
+ export type OperationRuntimeBrowserPrimitives = Readonly<{
20
+ submission?: OperationBrowserSubmissionPrimitive;
21
+ staging?: OperationBrowserStagingPrimitive;
22
+ collector?: OperationBrowserCollectorPrimitive;
23
+ control?: OperationBrowserControlPrimitive;
24
+ artifacts?: OperationBrowserArtifactPrimitive;
25
+ }>;
26
+ /**
27
+ * One request-scoped capture. The capture factory is invoked lazily from
28
+ * `resolveTarget`, after OperationService has created the durable operation
29
+ * record. It is the only place that may attach/claim/create a browser page.
30
+ *
31
+ * `targetEvidence` is required when no resolver is supplied. A resolver is
32
+ * useful for an explicit target policy (for example a selected tab versus a
33
+ * caller-provided tab id), but it must remain read-only and return the same
34
+ * captured page object.
35
+ */
36
+ export type OperationRuntimeBrowserCapture = Readonly<{
37
+ page: Readonly<PageLike>;
38
+ /** Optional immutable context captured by the provider bridge. */
39
+ runtimeContext?: OperationRuntimeContext<PageLike>;
40
+ targetEvidence?: OwnershipTargetEvidence;
41
+ authoritativeClaim?: BrowserTargetClaim;
42
+ capabilities?: Partial<OperationRuntimeCapabilities>;
43
+ /** Provider-proofed anchor evidence for a target whose ID is allocated by Send. */
44
+ newTargetAnchorDigest?: string;
45
+ blankTaskEvidenceDigest?: string;
46
+ resolveTargetEvidence?: (request: OperationBrowserTargetProbeRequest) => Promise<OperationBrowserTargetProbe> | OperationBrowserTargetProbe;
47
+ observeCurrentTarget?: (request: Parameters<NonNullable<OperationBrowserAdapterOptions["observeCurrentTarget"]>>[0]) => Promise<OperationBrowserCurrentTargetResult> | OperationBrowserCurrentTargetResult;
48
+ /** Request-local output destination; intentionally absent on recovery. */
49
+ outputDirectory?: string;
50
+ primitives?: OperationRuntimeBrowserPrimitives;
51
+ }>;
52
+ export type OperationRuntimeBrowserCaptureRequest = Readonly<{
53
+ operationId: string;
54
+ requestDigest: string;
55
+ surface: OperationSurface;
56
+ target: OperationTargetRequestV1;
57
+ signal: AbortSignal;
58
+ }>;
59
+ /**
60
+ * Frozen locator and complete durable target supplied by an authenticated
61
+ * post-restart handle factory. `targetRequest` is explicit because a durable
62
+ * binding must never be reconstructed by guessing a selected/replacement tab.
63
+ */
64
+ export type OperationRuntimeBrowserRecoveryContext = Readonly<{
65
+ operationId: string;
66
+ requestDigest: string;
67
+ surface: OperationSurface;
68
+ target: OperationTargetBindingV1;
69
+ targetRequest: OperationTargetRequestV1;
70
+ }>;
71
+ export type OperationRuntimeAdapterOptions = Readonly<{
72
+ /** Backend process owner used by the process/tab coordinator. */
73
+ owner: CoordinatorOwner;
74
+ /** Journal-keyed evidence digest. It must never be a bare public hash. */
75
+ evidenceDigest: BrowserTargetEvidenceDigest;
76
+ /** Lazy, request-scoped page/context capture. */
77
+ capture: (request: OperationRuntimeBrowserCaptureRequest) => Promise<OperationRuntimeBrowserCapture> | OperationRuntimeBrowserCapture;
78
+ /** Static operation closures may safely retain request-local private input. */
79
+ primitives?: OperationRuntimeBrowserPrimitives;
80
+ /** Set when the lazy capture will return the corresponding optional port.
81
+ * Leaving this false keeps OperationService on its read-only submission
82
+ * precondition path; exposing an absent staging port would otherwise turn a
83
+ * safe pre-populated composer into an artificial mutation blocker. */
84
+ exposeStaging?: boolean;
85
+ /** Set when callers want structured unavailable control results. */
86
+ exposeControl?: boolean;
87
+ /** Set only for a request-local submit capture with an absolute destination. */
88
+ exposeArtifacts?: boolean;
89
+ coordinator?: ProcessTabCoordinator;
90
+ transactionTimeoutMs?: number;
91
+ files?: readonly OperationFileIdentity[];
92
+ fileManifestDigest?: OperationBrowserAdapterOptions["fileManifestDigest"];
93
+ /** Explicit lazy recovery path; submit adapters do not use this option. */
94
+ recovery?: OperationRuntimeBrowserRecoveryContext;
95
+ }>;
96
+ export type OperationRuntimeAdapterErrorCode = "adapter_incomplete" | "capture_failed" | "capture_incomplete" | "target_evidence_unavailable" | "target_binding_mismatch" | "page_affinity_mismatch" | "unsupported_browser_primitive" | "not_initialized" | "backend_unavailable" | "browser_bridge_unavailable" | "login_required" | "captcha" | "rate_limited" | "permission_required" | "needs_confirmation" | "runtime_incompatible";
97
+ /** Stable, redacted error boundary for a request-scoped runtime adapter. */
98
+ export declare class OperationRuntimeAdapterError extends Error {
99
+ readonly code: OperationRuntimeAdapterErrorCode;
100
+ constructor(code: OperationRuntimeAdapterErrorCode);
101
+ }
102
+ /**
103
+ * This is the generic adapter's injection inventory, retained for compatibility
104
+ * with integrations that assemble their own provider runtime. It does not
105
+ * describe the default ChatGPT composite: `chatgpt-runtime.ts` injects the
106
+ * proven production modules for these seams. The generic adapter itself never
107
+ * guesses selectors or routes legacy polling helpers through a tab actor.
108
+ */
109
+ export declare const UNWIRED_OPERATION_RUNTIME_PRIMITIVES: readonly ["new_thread_creation", "configuration_set", "tool_selection", "composer_population", "file_chooser_handoff", "send_activation", "stop_activation", "work_steer_activation"];
110
+ /**
111
+ * Compose one lazy runtime capture over the existing operation browser
112
+ * adapter. The returned object is intentionally request-scoped: a caller
113
+ * should construct it in `OperationClient.adapterFactory` and retain it only
114
+ * for the resulting operation handle.
115
+ */
116
+ export declare function createRuntimeOperationBrowserAdapter(options: OperationRuntimeAdapterOptions): ComposedOperationBrowserAdapter;
117
+ /** Alias for callers that put the runtime qualifier first. */
118
+ export declare const createOperationRuntimeAdapter: typeof createRuntimeOperationBrowserAdapter;