codex-chatgpt-control 0.5.1-alpha.2 → 0.5.1-alpha.4
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.
- package/CHANGELOG.md +42 -0
- package/README.md +43 -0
- package/contracts/v1/fixtures/backend-capabilities.json +40 -1
- package/contracts/v1/fixtures/backend-compatibility.json +21 -0
- package/contracts/v1/fixtures/backend-version.json +6 -1
- package/contracts/v1/fixtures/download-blocked-by-browser.json +22 -0
- package/contracts/v1/fixtures/download-receipt-failed.json +22 -0
- package/contracts/v1/fixtures/download-receipt-timeout.json +22 -0
- package/contracts/v1/fixtures/journal-rpc-indeterminate.json +32 -0
- package/contracts/v1/fixtures/journal-rpc-unsupported-platform.json +32 -0
- package/contracts/v1/fixtures/journal-runtime-unavailable.json +32 -0
- package/contracts/v1/fixtures/operation-action-prepared-event.json +42 -0
- package/contracts/v1/fixtures/operation-action.json +13 -0
- package/contracts/v1/fixtures/operation-artifact-receipt.json +14 -0
- package/contracts/v1/fixtures/operation-artifact-transfer-intent-event.json +24 -0
- package/contracts/v1/fixtures/operation-artifact-transfer-receipt-event.json +26 -0
- package/contracts/v1/fixtures/operation-artifact-transfer-state.json +178 -0
- package/contracts/v1/fixtures/operation-blocker.json +10 -0
- package/contracts/v1/fixtures/operation-collect-request.json +17 -0
- package/contracts/v1/fixtures/operation-collect-result.json +42 -0
- package/contracts/v1/fixtures/operation-control-receipt.json +13 -0
- package/contracts/v1/fixtures/operation-control-request.json +18 -0
- package/contracts/v1/fixtures/operation-control-result.json +31 -0
- package/contracts/v1/fixtures/operation-event.json +18 -0
- package/contracts/v1/fixtures/operation-handle.json +10 -0
- package/contracts/v1/fixtures/operation-inspect-request.json +13 -0
- package/contracts/v1/fixtures/operation-inspect-result.json +205 -0
- package/contracts/v1/fixtures/operation-ownership-baseline-event.json +34 -0
- package/contracts/v1/fixtures/operation-receipt.json +32 -0
- package/contracts/v1/fixtures/operation-recovery-decision.json +7 -0
- package/contracts/v1/fixtures/operation-recovery-observation.json +12 -0
- package/contracts/v1/fixtures/operation-request.json +33 -0
- package/contracts/v1/fixtures/operation-state.json +144 -0
- package/contracts/v1/fixtures/operation-submission-witness-event.json +20 -0
- package/contracts/v1/fixtures/operation-submission-witness.json +11 -0
- package/contracts/v1/fixtures/operation-submit-result.json +16 -0
- package/contracts/v1/fixtures/operation-target-established-event.json +21 -0
- package/contracts/v1/manifest.json +185 -1
- package/contracts/v1/parity-suite.json +106 -8
- package/contracts/v1/schemas/backend-compatibility.schema.json +65 -0
- package/contracts/v1/schemas/backend-request.schema.json +8 -2
- package/contracts/v1/schemas/capabilities.schema.json +81 -1
- package/contracts/v1/schemas/manifest.schema.json +57 -0
- package/contracts/v1/schemas/operation-action.schema.json +155 -0
- package/contracts/v1/schemas/operation-artifact-receipt.schema.json +89 -0
- package/contracts/v1/schemas/operation-blocker.schema.json +70 -0
- package/contracts/v1/schemas/operation-collect-request.schema.json +46 -0
- package/contracts/v1/schemas/operation-collect-result.schema.json +74 -0
- package/contracts/v1/schemas/operation-control-receipt.schema.json +108 -0
- package/contracts/v1/schemas/operation-control-request.schema.json +111 -0
- package/contracts/v1/schemas/operation-control-result.schema.json +112 -0
- package/contracts/v1/schemas/operation-event.schema.json +756 -0
- package/contracts/v1/schemas/operation-handle.schema.json +55 -0
- package/contracts/v1/schemas/operation-inspect-request.schema.json +42 -0
- package/contracts/v1/schemas/operation-inspect-result.schema.json +1662 -0
- package/contracts/v1/schemas/operation-receipt.schema.json +153 -0
- package/contracts/v1/schemas/operation-recovery.schema.json +314 -0
- package/contracts/v1/schemas/operation-request.schema.json +158 -0
- package/contracts/v1/schemas/operation-state.schema.json +691 -0
- package/contracts/v1/schemas/operation-submission-witness.schema.json +48 -0
- package/contracts/v1/schemas/operation-submit-result.schema.json +94 -0
- package/contracts/v1/surface-drift-policy.json +50 -0
- package/contracts/v1/vectors/operation-request-digest-v1.json +43 -0
- package/dist/codex-chatgpt-control-backend.mjs +45882 -9361
- package/dist/codex-chatgpt-control-journal.mjs +5547 -0
- package/dist/codex-chatgpt-control-live-smoke.bundle.mjs +51677 -0
- package/dist/codex-chatgpt-control-release-canary.bundle.mjs +52104 -0
- package/dist/codex-chatgpt-control.bundle.mjs +48392 -10260
- package/dist/src/backend/client.d.ts +103 -2
- package/dist/src/backend/client.js +1436 -97
- package/dist/src/backend/compatibility.d.ts +12 -0
- package/dist/src/backend/compatibility.js +208 -0
- package/dist/src/backend/protocol.d.ts +84 -1
- package/dist/src/backend/protocol.js +31 -5
- package/dist/src/backend/runtime-identity.d.ts +10 -0
- package/dist/src/backend/runtime-identity.js +141 -0
- package/dist/src/backend/session.d.ts +10 -2
- package/dist/src/backend/session.js +478 -7
- package/dist/src/backend/stdio-server.d.ts +4 -1
- package/dist/src/backend/stdio-server.js +240 -28
- package/dist/src/browser/active-composer-file-input.d.ts +9 -0
- package/dist/src/browser/active-composer-file-input.js +33 -0
- package/dist/src/browser/attach.d.ts +4 -1
- package/dist/src/browser/attach.js +136 -28
- package/dist/src/browser/chatgpt-url.d.ts +2 -0
- package/dist/src/browser/chatgpt-url.js +9 -0
- package/dist/src/browser/downloads.d.ts +17 -1
- package/dist/src/browser/downloads.js +150 -28
- package/dist/src/browser/page-state.js +6 -0
- package/dist/src/client.d.ts +43 -0
- package/dist/src/client.js +1279 -59
- package/dist/src/commands/artifacts.js +6 -4
- package/dist/src/commands/chat-popover.d.ts +37 -0
- package/dist/src/commands/chat-popover.js +537 -0
- package/dist/src/commands/configuration.d.ts +5 -0
- package/dist/src/commands/configuration.js +134 -21
- package/dist/src/commands/context.js +10 -3
- package/dist/src/commands/doctor.d.ts +1 -1
- package/dist/src/commands/doctor.js +27 -4
- package/dist/src/commands/experience.d.ts +5 -0
- package/dist/src/commands/experience.js +104 -21
- package/dist/src/commands/files.js +14 -33
- package/dist/src/commands/modes.js +85 -21
- package/dist/src/commands/power-discovery.d.ts +130 -0
- package/dist/src/commands/power-discovery.js +669 -0
- package/dist/src/commands/project-sources.js +325 -31
- package/dist/src/commands/sequence.js +59 -32
- package/dist/src/commands/session.js +19 -6
- package/dist/src/commands/work.js +31 -0
- package/dist/src/dom/composer-text.d.ts +6 -0
- package/dist/src/dom/composer-text.js +85 -0
- package/dist/src/errors.d.ts +9 -0
- package/dist/src/errors.js +22 -0
- package/dist/src/index.d.ts +6 -0
- package/dist/src/index.js +9 -0
- package/dist/src/operations/artifact-output.d.ts +69 -0
- package/dist/src/operations/artifact-output.js +1748 -0
- package/dist/src/operations/artifact-stream.d.ts +19 -0
- package/dist/src/operations/artifact-stream.js +35 -0
- package/dist/src/operations/artifact-transfer.d.ts +149 -0
- package/dist/src/operations/artifact-transfer.js +1312 -0
- package/dist/src/operations/browser-adapter.d.ts +167 -0
- package/dist/src/operations/browser-adapter.js +2103 -0
- package/dist/src/operations/browser-observation.d.ts +110 -0
- package/dist/src/operations/browser-observation.js +1256 -0
- package/dist/src/operations/browser-target.d.ts +105 -0
- package/dist/src/operations/browser-target.js +531 -0
- package/dist/src/operations/canonical.d.ts +4 -0
- package/dist/src/operations/canonical.js +412 -0
- package/dist/src/operations/chatgpt-runtime.d.ts +72 -0
- package/dist/src/operations/chatgpt-runtime.js +1232 -0
- package/dist/src/operations/client.d.ts +138 -0
- package/dist/src/operations/client.js +1145 -0
- package/dist/src/operations/collector.d.ts +195 -0
- package/dist/src/operations/collector.js +1039 -0
- package/dist/src/operations/configuration-routing.d.ts +4 -0
- package/dist/src/operations/configuration-routing.js +14 -0
- package/dist/src/operations/control.d.ts +372 -0
- package/dist/src/operations/control.js +1498 -0
- package/dist/src/operations/file-identity.d.ts +33 -0
- package/dist/src/operations/file-identity.js +153 -0
- package/dist/src/operations/handle.d.ts +19 -0
- package/dist/src/operations/handle.js +727 -0
- package/dist/src/operations/index.d.ts +25 -0
- package/dist/src/operations/index.js +25 -0
- package/dist/src/operations/journal-authority.d.ts +12 -0
- package/dist/src/operations/journal-authority.js +1 -0
- package/dist/src/operations/journal-rpc-client.d.ts +12 -0
- package/dist/src/operations/journal-rpc-client.js +225 -0
- package/dist/src/operations/journal-rpc-protocol.d.ts +32 -0
- package/dist/src/operations/journal-rpc-protocol.js +214 -0
- package/dist/src/operations/journal-rpc-server.d.ts +15 -0
- package/dist/src/operations/journal-rpc-server.js +272 -0
- package/dist/src/operations/journal.d.ts +143 -0
- package/dist/src/operations/journal.js +1957 -0
- package/dist/src/operations/production-attachments.d.ts +118 -0
- package/dist/src/operations/production-attachments.js +1035 -0
- package/dist/src/operations/production-chatgpt-artifacts.d.ts +74 -0
- package/dist/src/operations/production-chatgpt-artifacts.js +1146 -0
- package/dist/src/operations/production-chatgpt-attachments.d.ts +80 -0
- package/dist/src/operations/production-chatgpt-attachments.js +1639 -0
- package/dist/src/operations/production-configuration.d.ts +42 -0
- package/dist/src/operations/production-configuration.js +1544 -0
- package/dist/src/operations/production-primitives.d.ts +53 -0
- package/dist/src/operations/production-primitives.js +856 -0
- package/dist/src/operations/production-work-steer.d.ts +203 -0
- package/dist/src/operations/production-work-steer.js +1218 -0
- package/dist/src/operations/recovery.d.ts +80 -0
- package/dist/src/operations/recovery.js +174 -0
- package/dist/src/operations/runtime-adapter.d.ts +126 -0
- package/dist/src/operations/runtime-adapter.js +802 -0
- package/dist/src/operations/send-once.d.ts +224 -0
- package/dist/src/operations/send-once.js +1081 -0
- package/dist/src/operations/service.d.ts +286 -0
- package/dist/src/operations/service.js +2831 -0
- package/dist/src/operations/staging.d.ts +136 -0
- package/dist/src/operations/staging.js +630 -0
- package/dist/src/operations/state-machine.d.ts +29 -0
- package/dist/src/operations/state-machine.js +2047 -0
- package/dist/src/operations/submission.d.ts +423 -0
- package/dist/src/operations/submission.js +1676 -0
- package/dist/src/operations/transactional-chat-power.d.ts +17 -0
- package/dist/src/operations/transactional-chat-power.js +212 -0
- package/dist/src/operations/turn-ownership.d.ts +202 -0
- package/dist/src/operations/turn-ownership.js +700 -0
- package/dist/src/operations/types.d.ts +454 -0
- package/dist/src/operations/types.js +20 -0
- package/dist/src/operations/wire-requests.d.ts +21 -0
- package/dist/src/operations/wire-requests.js +396 -0
- package/dist/src/operations/wire-results.d.ts +97 -0
- package/dist/src/operations/wire-results.js +818 -0
- package/dist/src/runner/responses.d.ts +3 -1
- package/dist/src/runner/responses.js +19 -1
- package/dist/src/runner/result.js +227 -55
- package/dist/src/runner/types.d.ts +12 -0
- package/dist/src/runtime/command-routing.d.ts +149 -0
- package/dist/src/runtime/command-routing.js +431 -0
- package/dist/src/runtime/coordinated-browser.d.ts +24 -0
- package/dist/src/runtime/coordinated-browser.js +315 -0
- package/dist/src/runtime/coordinated-page.d.ts +41 -0
- package/dist/src/runtime/coordinated-page.js +651 -0
- package/dist/src/runtime/operation-context.d.ts +142 -0
- package/dist/src/runtime/operation-context.js +410 -0
- package/dist/src/runtime/runtime-session.d.ts +95 -0
- package/dist/src/runtime/runtime-session.js +314 -0
- package/dist/src/runtime/tab-coordinator.d.ts +200 -0
- package/dist/src/runtime/tab-coordinator.js +1200 -0
- package/dist/src/runtime/value-boundaries.d.ts +18 -0
- package/dist/src/runtime/value-boundaries.js +49 -0
- package/dist/src/safety/blockers.js +8 -1
- package/dist/src/safety/untrusted-output.js +2 -1
- package/dist/src/scripts/backend-server.js +4 -1
- package/dist/src/scripts/capture-surface-profile.js +7 -2
- package/dist/src/scripts/journal-server.d.ts +2 -0
- package/dist/src/scripts/journal-server.js +37 -0
- package/dist/src/scripts/live-smoke/harness.js +79 -7
- package/dist/src/scripts/live-smoke/scenarios.d.ts +42 -1
- package/dist/src/scripts/live-smoke/scenarios.js +147 -30
- package/dist/src/scripts/live-smoke/transactional.d.ts +17 -0
- package/dist/src/scripts/live-smoke/transactional.js +254 -0
- package/dist/src/scripts/live-smoke/types.d.ts +3 -0
- package/dist/src/scripts/release-canary-module.js +17 -4
- package/dist/src/types.d.ts +38 -1
- package/package.json +8 -3
- package/references/2026-08-16-transactional-operations.md +459 -0
- package/references/2026-09-06-journal-service.md +140 -0
- package/references/agents-runner.md +34 -0
- package/references/backend-protocol.md +176 -0
- package/references/python-parity.md +137 -0
- package/references/responses-adapter.md +19 -0
- 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,126 @@
|
|
|
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 { OperationCollectorAdapter, OperationSubmissionAdapter } from "./service.js";
|
|
6
|
+
import type { SubmissionFinalTransactionResult } from "./submission.js";
|
|
7
|
+
import type { BrowserTargetClaim, BrowserTargetEvidenceDigest } from "./browser-target.js";
|
|
8
|
+
import type { OwnershipTargetEvidence } from "./turn-ownership.js";
|
|
9
|
+
import type { OperationFileIdentity } from "./file-identity.js";
|
|
10
|
+
import type { OperationSurface, OperationTargetBindingV1, OperationTargetRequestV1 } from "./types.js";
|
|
11
|
+
/**
|
|
12
|
+
* Browser primitives that are safe to pass into an operation adapter.
|
|
13
|
+
*
|
|
14
|
+
* The callbacks receive the captured page explicitly. They must perform one
|
|
15
|
+
* bounded DOM transaction and return an already-redacted observation. In
|
|
16
|
+
* particular, a callback must not poll for generation, wait for attachment
|
|
17
|
+
* processing, read a mutable RuntimeEnv, or retry a non-repeatable browser
|
|
18
|
+
* action. Those waits belong to the operation collector and are deliberately
|
|
19
|
+
* outside the tab actor.
|
|
20
|
+
*/
|
|
21
|
+
export type OperationRuntimeBrowserPrimitives = Readonly<{
|
|
22
|
+
submission?: OperationBrowserSubmissionPrimitive;
|
|
23
|
+
staging?: OperationBrowserStagingPrimitive;
|
|
24
|
+
collector?: OperationBrowserCollectorPrimitive;
|
|
25
|
+
control?: OperationBrowserControlPrimitive;
|
|
26
|
+
artifacts?: OperationBrowserArtifactPrimitive;
|
|
27
|
+
}>;
|
|
28
|
+
/**
|
|
29
|
+
* One request-scoped capture. The capture factory is invoked lazily from
|
|
30
|
+
* `resolveTarget`, after OperationService has created the durable operation
|
|
31
|
+
* record. It is the only place that may attach/claim/create a browser page.
|
|
32
|
+
*
|
|
33
|
+
* `targetEvidence` is required when no resolver is supplied. A resolver is
|
|
34
|
+
* useful for an explicit target policy (for example a selected tab versus a
|
|
35
|
+
* caller-provided tab id), but it must remain read-only and return the same
|
|
36
|
+
* captured page object.
|
|
37
|
+
*/
|
|
38
|
+
export type OperationRuntimeBrowserCapture = Readonly<{
|
|
39
|
+
page: Readonly<PageLike>;
|
|
40
|
+
/** Optional immutable context captured by the provider bridge. */
|
|
41
|
+
runtimeContext?: OperationRuntimeContext<PageLike>;
|
|
42
|
+
targetEvidence?: OwnershipTargetEvidence;
|
|
43
|
+
authoritativeClaim?: BrowserTargetClaim;
|
|
44
|
+
capabilities?: Partial<OperationRuntimeCapabilities>;
|
|
45
|
+
/** Provider-proofed anchor evidence for a target whose ID is allocated by Send. */
|
|
46
|
+
newTargetAnchorDigest?: string;
|
|
47
|
+
blankTaskEvidenceDigest?: string;
|
|
48
|
+
resolveTargetEvidence?: (request: OperationBrowserTargetProbeRequest) => Promise<OperationBrowserTargetProbe> | OperationBrowserTargetProbe;
|
|
49
|
+
observeCurrentTarget?: (request: Parameters<NonNullable<OperationBrowserAdapterOptions["observeCurrentTarget"]>>[0]) => Promise<OperationBrowserCurrentTargetResult> | OperationBrowserCurrentTargetResult;
|
|
50
|
+
/** Request-local output destination; intentionally absent on recovery. */
|
|
51
|
+
outputDirectory?: string;
|
|
52
|
+
primitives?: OperationRuntimeBrowserPrimitives;
|
|
53
|
+
}>;
|
|
54
|
+
export type OperationRuntimeBrowserCaptureRequest = Readonly<{
|
|
55
|
+
operationId: string;
|
|
56
|
+
requestDigest: string;
|
|
57
|
+
surface: OperationSurface;
|
|
58
|
+
target: OperationTargetRequestV1;
|
|
59
|
+
signal: AbortSignal;
|
|
60
|
+
}>;
|
|
61
|
+
/**
|
|
62
|
+
* Frozen locator and complete durable target supplied by an authenticated
|
|
63
|
+
* post-restart handle factory. `targetRequest` is explicit because a durable
|
|
64
|
+
* binding must never be reconstructed by guessing a selected/replacement tab.
|
|
65
|
+
*/
|
|
66
|
+
export type OperationRuntimeBrowserRecoveryContext = Readonly<{
|
|
67
|
+
operationId: string;
|
|
68
|
+
requestDigest: string;
|
|
69
|
+
surface: OperationSurface;
|
|
70
|
+
target: OperationTargetBindingV1;
|
|
71
|
+
targetRequest: OperationTargetRequestV1;
|
|
72
|
+
}>;
|
|
73
|
+
export type OperationRuntimeAdapterOptions = Readonly<{
|
|
74
|
+
/** Backend process owner used by the process/tab coordinator. */
|
|
75
|
+
owner: CoordinatorOwner;
|
|
76
|
+
/** Journal-keyed evidence digest. It must never be a bare public hash. */
|
|
77
|
+
evidenceDigest: BrowserTargetEvidenceDigest;
|
|
78
|
+
/** Lazy, request-scoped page/context capture. */
|
|
79
|
+
capture: (request: OperationRuntimeBrowserCaptureRequest) => Promise<OperationRuntimeBrowserCapture> | OperationRuntimeBrowserCapture;
|
|
80
|
+
/** Static operation closures may safely retain request-local private input. */
|
|
81
|
+
primitives?: OperationRuntimeBrowserPrimitives;
|
|
82
|
+
/** Set when the lazy capture will return the corresponding optional port.
|
|
83
|
+
* Leaving this false keeps OperationService on its read-only submission
|
|
84
|
+
* precondition path; exposing an absent staging port would otherwise turn a
|
|
85
|
+
* safe pre-populated composer into an artificial mutation blocker. */
|
|
86
|
+
exposeStaging?: boolean;
|
|
87
|
+
/** Set when callers want structured unavailable control results. */
|
|
88
|
+
exposeControl?: boolean;
|
|
89
|
+
/** Set only for a request-local submit capture with an absolute destination. */
|
|
90
|
+
exposeArtifacts?: boolean;
|
|
91
|
+
coordinator?: ProcessTabCoordinator;
|
|
92
|
+
transactionTimeoutMs?: number;
|
|
93
|
+
files?: readonly OperationFileIdentity[];
|
|
94
|
+
fileManifestDigest?: OperationBrowserAdapterOptions["fileManifestDigest"];
|
|
95
|
+
/** Explicit lazy recovery path; submit adapters do not use this option. */
|
|
96
|
+
recovery?: OperationRuntimeBrowserRecoveryContext;
|
|
97
|
+
/** Separate read-only restart callback; cannot initialize a target:new capture. */
|
|
98
|
+
recoverAuthenticatedSend?: (request: Parameters<NonNullable<OperationSubmissionAdapter["recoverAuthenticatedSend"]>>[0]) => Promise<Readonly<{
|
|
99
|
+
result: SubmissionFinalTransactionResult;
|
|
100
|
+
/** Only read ports may survive recovery; no target resolution or mutation. */
|
|
101
|
+
collector?: OperationCollectorAdapter;
|
|
102
|
+
}>>;
|
|
103
|
+
}>;
|
|
104
|
+
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";
|
|
105
|
+
/** Stable, redacted error boundary for a request-scoped runtime adapter. */
|
|
106
|
+
export declare class OperationRuntimeAdapterError extends Error {
|
|
107
|
+
readonly code: OperationRuntimeAdapterErrorCode;
|
|
108
|
+
constructor(code: OperationRuntimeAdapterErrorCode);
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* This is the generic adapter's injection inventory, retained for compatibility
|
|
112
|
+
* with integrations that assemble their own provider runtime. It does not
|
|
113
|
+
* describe the default ChatGPT composite: `chatgpt-runtime.ts` injects the
|
|
114
|
+
* proven production modules for these seams. The generic adapter itself never
|
|
115
|
+
* guesses selectors or routes legacy polling helpers through a tab actor.
|
|
116
|
+
*/
|
|
117
|
+
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"];
|
|
118
|
+
/**
|
|
119
|
+
* Compose one lazy runtime capture over the existing operation browser
|
|
120
|
+
* adapter. The returned object is intentionally request-scoped: a caller
|
|
121
|
+
* should construct it in `OperationClient.adapterFactory` and retain it only
|
|
122
|
+
* for the resulting operation handle.
|
|
123
|
+
*/
|
|
124
|
+
export declare function createRuntimeOperationBrowserAdapter(options: OperationRuntimeAdapterOptions): ComposedOperationBrowserAdapter;
|
|
125
|
+
/** Alias for callers that put the runtime qualifier first. */
|
|
126
|
+
export declare const createOperationRuntimeAdapter: typeof createRuntimeOperationBrowserAdapter;
|