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.
- package/CHANGELOG.md +15 -0
- package/README.md +27 -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/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 +155 -1
- package/contracts/v1/parity-suite.json +96 -1
- 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 +43897 -9094
- package/dist/codex-chatgpt-control.bundle.mjs +46360 -10262
- 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/downloads.d.ts +2 -0
- package/dist/src/client.d.ts +38 -0
- package/dist/src/client.js +1222 -59
- package/dist/src/commands/configuration.js +13 -7
- package/dist/src/commands/doctor.d.ts +1 -1
- package/dist/src/commands/doctor.js +26 -3
- package/dist/src/commands/experience.js +35 -0
- package/dist/src/commands/files.js +4 -27
- package/dist/src/commands/modes.js +49 -17
- package/dist/src/commands/power-discovery.d.ts +130 -0
- package/dist/src/commands/power-discovery.js +627 -0
- package/dist/src/commands/project-sources.js +325 -31
- package/dist/src/commands/sequence.js +59 -32
- package/dist/src/commands/session.js +7 -2
- package/dist/src/commands/work.js +31 -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 +161 -0
- package/dist/src/operations/browser-adapter.js +2023 -0
- package/dist/src/operations/browser-observation.d.ts +110 -0
- package/dist/src/operations/browser-observation.js +1208 -0
- package/dist/src/operations/browser-target.d.ts +103 -0
- package/dist/src/operations/browser-target.js +489 -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 +1150 -0
- package/dist/src/operations/client.d.ts +138 -0
- package/dist/src/operations/client.js +1143 -0
- package/dist/src/operations/collector.d.ts +195 -0
- package/dist/src/operations/collector.js +1039 -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 +22 -0
- package/dist/src/operations/index.js +22 -0
- package/dist/src/operations/journal.d.ts +142 -0
- package/dist/src/operations/journal.js +1931 -0
- package/dist/src/operations/production-attachments.d.ts +116 -0
- package/dist/src/operations/production-attachments.js +1018 -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 +71 -0
- package/dist/src/operations/production-chatgpt-attachments.js +1563 -0
- package/dist/src/operations/production-configuration.d.ts +42 -0
- package/dist/src/operations/production-configuration.js +1363 -0
- package/dist/src/operations/production-primitives.d.ts +53 -0
- package/dist/src/operations/production-primitives.js +1073 -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 +118 -0
- package/dist/src/operations/runtime-adapter.js +786 -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 +281 -0
- package/dist/src/operations/service.js +2810 -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/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 +39 -0
- package/dist/src/runtime/coordinated-page.js +634 -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/untrusted-output.js +2 -1
- package/dist/src/scripts/backend-server.js +4 -1
- package/dist/src/scripts/live-smoke/harness.js +79 -7
- package/dist/src/scripts/live-smoke/scenarios.d.ts +28 -0
- package/dist/src/scripts/live-smoke/scenarios.js +110 -18
- 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 +1 -1
- package/references/2026-08-16-transactional-operations.md +459 -0
- package/references/agents-runner.md +34 -0
- package/references/backend-protocol.md +73 -0
- package/references/python-parity.md +72 -0
- package/references/responses-adapter.md +19 -0
- package/references/streaming.md +6 -0
|
@@ -0,0 +1,396 @@
|
|
|
1
|
+
import { OPERATION_COLLECT_REQUEST_SCHEMA_VERSION, OPERATION_CONTROL_REQUEST_SCHEMA_VERSION, OPERATION_HANDLE_SCHEMA_VERSION, OPERATION_INSPECT_REQUEST_SCHEMA_VERSION, OPERATION_REQUEST_SCHEMA_VERSION } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Raised by the closed runtime validators in this module.
|
|
4
|
+
*
|
|
5
|
+
* The message intentionally contains no field name or value. Operation
|
|
6
|
+
* requests can contain prompts and local paths, and validation failures must
|
|
7
|
+
* be safe to send across a backend boundary.
|
|
8
|
+
*/
|
|
9
|
+
export class OperationWireRequestError extends Error {
|
|
10
|
+
code = "invalid_operation_request";
|
|
11
|
+
recoverable = false;
|
|
12
|
+
constructor() {
|
|
13
|
+
super("Transactional operation request is invalid.");
|
|
14
|
+
this.name = "OperationWireRequestError";
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
/** Validate the canonical direct v1 submit payload. */
|
|
18
|
+
export function validateOperationSubmitRequest(value) {
|
|
19
|
+
const request = operationRecord(value);
|
|
20
|
+
operationExactKeys(request, [
|
|
21
|
+
"schemaVersion", "operationId", "surface", "prompt", "target", "configuration", "files", "capture", "timeoutMs"
|
|
22
|
+
]);
|
|
23
|
+
operationConst(propertyValue(request, "schemaVersion"), OPERATION_REQUEST_SCHEMA_VERSION);
|
|
24
|
+
operationId(propertyValue(request, "operationId"));
|
|
25
|
+
operationSurface(propertyValue(request, "surface"));
|
|
26
|
+
operationText(propertyValue(request, "prompt"), 8 * 1024 * 1024, false);
|
|
27
|
+
validateOperationTarget(propertyValue(request, "target"));
|
|
28
|
+
const configuration = propertyValue(request, "configuration");
|
|
29
|
+
if (configuration !== undefined)
|
|
30
|
+
validateOperationConfiguration(configuration);
|
|
31
|
+
const files = propertyValue(request, "files");
|
|
32
|
+
if (files !== undefined) {
|
|
33
|
+
const entries = arrayValues(files, 256);
|
|
34
|
+
for (const file of entries) {
|
|
35
|
+
const entry = operationRecord(file);
|
|
36
|
+
operationExactKeys(entry, ["path", "displayName"]);
|
|
37
|
+
operationText(propertyValue(entry, "path"), 4096, true);
|
|
38
|
+
const displayName = propertyValue(entry, "displayName");
|
|
39
|
+
if (displayName !== undefined)
|
|
40
|
+
operationText(displayName, 512, true);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
const capture = propertyValue(request, "capture");
|
|
44
|
+
if (capture !== undefined)
|
|
45
|
+
validateOperationCapture(capture);
|
|
46
|
+
validateOperationTimeout(propertyValue(request, "timeoutMs"));
|
|
47
|
+
}
|
|
48
|
+
/** Validate the canonical direct v1 collect payload. */
|
|
49
|
+
export function validateOperationCollectRequest(value) {
|
|
50
|
+
const request = operationRecord(value);
|
|
51
|
+
operationExactKeys(request, ["schemaVersion", "handle", "wait", "timeoutMs", "pollIntervalMs", "responseContent"]);
|
|
52
|
+
operationConst(propertyValue(request, "schemaVersion"), OPERATION_COLLECT_REQUEST_SCHEMA_VERSION);
|
|
53
|
+
validateOperationHandlePayload(propertyValue(request, "handle"));
|
|
54
|
+
const wait = propertyValue(request, "wait");
|
|
55
|
+
if (wait !== undefined && typeof wait !== "boolean")
|
|
56
|
+
throw invalidOperationRequest();
|
|
57
|
+
validateOperationTimeout(propertyValue(request, "timeoutMs"));
|
|
58
|
+
const pollIntervalMs = propertyValue(request, "pollIntervalMs");
|
|
59
|
+
if (pollIntervalMs !== undefined
|
|
60
|
+
&& (typeof pollIntervalMs !== "number" || !Number.isSafeInteger(pollIntervalMs) || pollIntervalMs < 0 || pollIntervalMs > 60_000)) {
|
|
61
|
+
throw invalidOperationRequest();
|
|
62
|
+
}
|
|
63
|
+
const responseContent = propertyValue(request, "responseContent");
|
|
64
|
+
if (responseContent !== undefined && responseContent !== "include" && responseContent !== "metadata") {
|
|
65
|
+
throw invalidOperationRequest();
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/** Validate the canonical direct v1 inspect payload. */
|
|
69
|
+
export function validateOperationInspectRequest(value) {
|
|
70
|
+
const request = operationRecord(value);
|
|
71
|
+
operationExactKeys(request, ["schemaVersion", "handle"]);
|
|
72
|
+
operationConst(propertyValue(request, "schemaVersion"), OPERATION_INSPECT_REQUEST_SCHEMA_VERSION);
|
|
73
|
+
validateOperationHandlePayload(propertyValue(request, "handle"));
|
|
74
|
+
}
|
|
75
|
+
/** Validate the canonical direct v1 control payload. */
|
|
76
|
+
export function validateOperationControlRequest(value) {
|
|
77
|
+
const request = operationRecord(value);
|
|
78
|
+
operationExactKeys(request, [
|
|
79
|
+
"schemaVersion", "controlActionId", "parent", "action", "expectedAssistantTurnId", "steerPrompt", "timeoutMs"
|
|
80
|
+
]);
|
|
81
|
+
operationConst(propertyValue(request, "schemaVersion"), OPERATION_CONTROL_REQUEST_SCHEMA_VERSION);
|
|
82
|
+
operationId(propertyValue(request, "controlActionId"));
|
|
83
|
+
const parent = validateOperationHandlePayload(propertyValue(request, "parent"));
|
|
84
|
+
if (propertyValue(parent, "phase") !== "generating" || propertyValue(parent, "targetBindingDigest") === undefined) {
|
|
85
|
+
throw invalidOperationRequest();
|
|
86
|
+
}
|
|
87
|
+
const action = propertyValue(request, "action");
|
|
88
|
+
if (action !== "stop" && action !== "steer")
|
|
89
|
+
throw invalidOperationRequest();
|
|
90
|
+
operationOpaqueId(propertyValue(request, "expectedAssistantTurnId"), 512);
|
|
91
|
+
const steerPrompt = propertyValue(request, "steerPrompt");
|
|
92
|
+
if (action === "steer") {
|
|
93
|
+
if (steerPrompt === undefined)
|
|
94
|
+
throw invalidOperationRequest();
|
|
95
|
+
operationText(steerPrompt, 8 * 1024 * 1024, true);
|
|
96
|
+
}
|
|
97
|
+
else if (steerPrompt !== undefined) {
|
|
98
|
+
throw invalidOperationRequest();
|
|
99
|
+
}
|
|
100
|
+
validateOperationTimeout(propertyValue(request, "timeoutMs"));
|
|
101
|
+
}
|
|
102
|
+
function validateOperationTarget(value) {
|
|
103
|
+
const target = operationRecord(value);
|
|
104
|
+
const type = propertyValue(target, "type");
|
|
105
|
+
if (typeof type !== "string")
|
|
106
|
+
throw invalidOperationRequest();
|
|
107
|
+
switch (type) {
|
|
108
|
+
case "new":
|
|
109
|
+
case "selected_tab":
|
|
110
|
+
operationExactKeys(target, ["type"]);
|
|
111
|
+
return;
|
|
112
|
+
case "tab_id":
|
|
113
|
+
operationExactKeys(target, ["type", "tabId"]);
|
|
114
|
+
operationOpaqueId(propertyValue(target, "tabId"), 512);
|
|
115
|
+
return;
|
|
116
|
+
case "conversation_id":
|
|
117
|
+
operationExactKeys(target, ["type", "conversationId"]);
|
|
118
|
+
operationOpaqueId(propertyValue(target, "conversationId"), 512);
|
|
119
|
+
return;
|
|
120
|
+
case "url": {
|
|
121
|
+
operationExactKeys(target, ["type", "url"]);
|
|
122
|
+
const url = propertyValue(target, "url");
|
|
123
|
+
operationText(url, 4096, true);
|
|
124
|
+
if (typeof url !== "string" || /[\u0000-\u001f\u007f]/u.test(url)) {
|
|
125
|
+
throw invalidOperationRequest();
|
|
126
|
+
}
|
|
127
|
+
try {
|
|
128
|
+
const parsed = new URL(url);
|
|
129
|
+
if ((parsed.protocol !== "https:" && parsed.protocol !== "http:") || parsed.username || parsed.password) {
|
|
130
|
+
throw new Error("invalid");
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
catch {
|
|
134
|
+
throw invalidOperationRequest();
|
|
135
|
+
}
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
default:
|
|
139
|
+
throw invalidOperationRequest();
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
function validateOperationConfiguration(value) {
|
|
143
|
+
const configuration = operationRecord(value);
|
|
144
|
+
operationExactKeys(configuration, ["experience", "model", "modelVersion", "reasoning", "mode", "tools", "additional"]);
|
|
145
|
+
const experience = propertyValue(configuration, "experience");
|
|
146
|
+
if (experience !== undefined && experience !== "chat" && experience !== "work")
|
|
147
|
+
throw invalidOperationRequest();
|
|
148
|
+
for (const field of ["model", "modelVersion", "reasoning", "mode"]) {
|
|
149
|
+
const requested = propertyValue(configuration, field);
|
|
150
|
+
if (requested !== undefined)
|
|
151
|
+
operationText(requested, 256, true);
|
|
152
|
+
}
|
|
153
|
+
const tools = propertyValue(configuration, "tools");
|
|
154
|
+
if (tools !== undefined) {
|
|
155
|
+
for (const tool of arrayValues(tools, 256))
|
|
156
|
+
operationText(tool, 256, true);
|
|
157
|
+
}
|
|
158
|
+
const additional = propertyValue(configuration, "additional");
|
|
159
|
+
if (additional !== undefined) {
|
|
160
|
+
if (!isPlainRecord(additional))
|
|
161
|
+
throw invalidOperationRequest();
|
|
162
|
+
validateOperationJson(additional);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
function validateOperationCapture(value) {
|
|
166
|
+
const capture = operationRecord(value);
|
|
167
|
+
operationExactKeys(capture, ["responseContent", "responseFormat", "artifacts", "outputDirectory"]);
|
|
168
|
+
const responseContent = propertyValue(capture, "responseContent");
|
|
169
|
+
const responseFormat = propertyValue(capture, "responseFormat");
|
|
170
|
+
const artifacts = propertyValue(capture, "artifacts");
|
|
171
|
+
const outputDirectory = propertyValue(capture, "outputDirectory");
|
|
172
|
+
if (responseContent !== "include" && responseContent !== "metadata")
|
|
173
|
+
throw invalidOperationRequest();
|
|
174
|
+
if (responseFormat !== undefined && responseFormat !== "markdown" && responseFormat !== "text")
|
|
175
|
+
throw invalidOperationRequest();
|
|
176
|
+
if (artifacts !== "receipt_only" && artifacts !== "transfer")
|
|
177
|
+
throw invalidOperationRequest();
|
|
178
|
+
if (outputDirectory !== undefined)
|
|
179
|
+
operationText(outputDirectory, 4096, true);
|
|
180
|
+
if (artifacts === "transfer" && outputDirectory === undefined)
|
|
181
|
+
throw invalidOperationRequest();
|
|
182
|
+
if (artifacts === "receipt_only" && outputDirectory !== undefined)
|
|
183
|
+
throw invalidOperationRequest();
|
|
184
|
+
}
|
|
185
|
+
function validateOperationHandlePayload(value) {
|
|
186
|
+
const handle = operationRecord(value);
|
|
187
|
+
operationExactKeys(handle, [
|
|
188
|
+
"schemaVersion", "operationId", "requestDigest", "surface", "revision", "phase", "mutationBoundary", "targetBindingDigest"
|
|
189
|
+
]);
|
|
190
|
+
operationConst(propertyValue(handle, "schemaVersion"), OPERATION_HANDLE_SCHEMA_VERSION);
|
|
191
|
+
operationId(propertyValue(handle, "operationId"));
|
|
192
|
+
operationDigest(propertyValue(handle, "requestDigest"));
|
|
193
|
+
operationSurface(propertyValue(handle, "surface"));
|
|
194
|
+
const revision = propertyValue(handle, "revision");
|
|
195
|
+
if (!Number.isSafeInteger(revision) || revision < 1)
|
|
196
|
+
throw invalidOperationRequest();
|
|
197
|
+
if (!OPERATION_PHASES.has(propertyValue(handle, "phase"))
|
|
198
|
+
|| !OPERATION_BOUNDARIES.has(propertyValue(handle, "mutationBoundary"))) {
|
|
199
|
+
throw invalidOperationRequest();
|
|
200
|
+
}
|
|
201
|
+
const targetBindingDigest = propertyValue(handle, "targetBindingDigest");
|
|
202
|
+
if (targetBindingDigest !== undefined)
|
|
203
|
+
operationDigest(targetBindingDigest);
|
|
204
|
+
return handle;
|
|
205
|
+
}
|
|
206
|
+
function validateOperationTimeout(value) {
|
|
207
|
+
if (value !== undefined && (!Number.isSafeInteger(value) || value < 0))
|
|
208
|
+
throw invalidOperationRequest();
|
|
209
|
+
}
|
|
210
|
+
function validateOperationJson(value, depth = 0, budget = { nodes: 0, utf8Bytes: 0 }) {
|
|
211
|
+
budget.nodes += 1;
|
|
212
|
+
if (budget.nodes > MAX_OPERATION_JSON_NODES || depth > MAX_OPERATION_JSON_DEPTH)
|
|
213
|
+
throw invalidOperationRequest();
|
|
214
|
+
if (value === null || typeof value === "boolean")
|
|
215
|
+
return;
|
|
216
|
+
if (typeof value === "string") {
|
|
217
|
+
addOperationJsonBytes(budget, value);
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
if (typeof value === "number") {
|
|
221
|
+
if (!Number.isFinite(value))
|
|
222
|
+
throw invalidOperationRequest();
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
if (Array.isArray(value)) {
|
|
226
|
+
for (const entry of arrayValues(value, MAX_OPERATION_JSON_NODES))
|
|
227
|
+
validateOperationJson(entry, depth + 1, budget);
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
if (!isPlainRecord(value))
|
|
231
|
+
throw invalidOperationRequest();
|
|
232
|
+
const record = operationRecord(value);
|
|
233
|
+
for (const key of ownStringKeys(record)) {
|
|
234
|
+
operationText(key, 256, false);
|
|
235
|
+
if (/[\u0000-\u001f\u007f]/u.test(key))
|
|
236
|
+
throw invalidOperationRequest();
|
|
237
|
+
addOperationJsonBytes(budget, key);
|
|
238
|
+
validateOperationJson(propertyValue(record, key), depth + 1, budget);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
function addOperationJsonBytes(budget, value) {
|
|
242
|
+
if (!isWellFormedUnicode(value))
|
|
243
|
+
throw invalidOperationRequest();
|
|
244
|
+
budget.utf8Bytes += Buffer.byteLength(value, "utf8");
|
|
245
|
+
if (!Number.isSafeInteger(budget.utf8Bytes) || budget.utf8Bytes > MAX_OPERATION_JSON_UTF8_BYTES) {
|
|
246
|
+
throw invalidOperationRequest();
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
function operationRecord(value) {
|
|
250
|
+
if (!isPlainRecord(value))
|
|
251
|
+
throw invalidOperationRequest();
|
|
252
|
+
try {
|
|
253
|
+
for (const key of Reflect.ownKeys(value)) {
|
|
254
|
+
if (typeof key !== "string")
|
|
255
|
+
throw invalidOperationRequest();
|
|
256
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
257
|
+
if (descriptor === undefined || !("value" in descriptor) || descriptor.enumerable !== true) {
|
|
258
|
+
throw invalidOperationRequest();
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
catch (error) {
|
|
263
|
+
if (error instanceof OperationWireRequestError)
|
|
264
|
+
throw error;
|
|
265
|
+
throw invalidOperationRequest();
|
|
266
|
+
}
|
|
267
|
+
return value;
|
|
268
|
+
}
|
|
269
|
+
function operationExactKeys(value, allowed) {
|
|
270
|
+
const allowedSet = new Set(allowed);
|
|
271
|
+
if (ownStringKeys(value).some(key => !allowedSet.has(key)))
|
|
272
|
+
throw invalidOperationRequest();
|
|
273
|
+
}
|
|
274
|
+
function ownStringKeys(value) {
|
|
275
|
+
try {
|
|
276
|
+
const keys = Reflect.ownKeys(value);
|
|
277
|
+
if (keys.some(key => typeof key !== "string"))
|
|
278
|
+
throw invalidOperationRequest();
|
|
279
|
+
return keys;
|
|
280
|
+
}
|
|
281
|
+
catch (error) {
|
|
282
|
+
if (error instanceof OperationWireRequestError)
|
|
283
|
+
throw error;
|
|
284
|
+
throw invalidOperationRequest();
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
function propertyValue(value, key) {
|
|
288
|
+
try {
|
|
289
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
290
|
+
if (descriptor === undefined)
|
|
291
|
+
return undefined;
|
|
292
|
+
if (!("value" in descriptor) || descriptor.enumerable !== true)
|
|
293
|
+
throw invalidOperationRequest();
|
|
294
|
+
return descriptor.value;
|
|
295
|
+
}
|
|
296
|
+
catch (error) {
|
|
297
|
+
if (error instanceof OperationWireRequestError)
|
|
298
|
+
throw error;
|
|
299
|
+
throw invalidOperationRequest();
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
function arrayValues(value, maxLength) {
|
|
303
|
+
if (!Array.isArray(value))
|
|
304
|
+
throw invalidOperationRequest();
|
|
305
|
+
try {
|
|
306
|
+
const length = value.length;
|
|
307
|
+
if (length > maxLength)
|
|
308
|
+
throw invalidOperationRequest();
|
|
309
|
+
const keys = Reflect.ownKeys(value);
|
|
310
|
+
const allowed = new Set(["length", ...Array.from({ length }, (_, index) => String(index))]);
|
|
311
|
+
if (keys.some(key => typeof key !== "string" || !allowed.has(key)))
|
|
312
|
+
throw invalidOperationRequest();
|
|
313
|
+
const values = [];
|
|
314
|
+
for (let index = 0; index < length; index += 1) {
|
|
315
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, String(index));
|
|
316
|
+
if (descriptor === undefined || !("value" in descriptor) || descriptor.enumerable !== true) {
|
|
317
|
+
throw invalidOperationRequest();
|
|
318
|
+
}
|
|
319
|
+
values.push(descriptor.value);
|
|
320
|
+
}
|
|
321
|
+
return values;
|
|
322
|
+
}
|
|
323
|
+
catch (error) {
|
|
324
|
+
if (error instanceof OperationWireRequestError)
|
|
325
|
+
throw error;
|
|
326
|
+
throw invalidOperationRequest();
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
function operationConst(value, expected) {
|
|
330
|
+
if (value !== expected)
|
|
331
|
+
throw invalidOperationRequest();
|
|
332
|
+
}
|
|
333
|
+
function operationSurface(value) {
|
|
334
|
+
if (value !== "chat" && value !== "work")
|
|
335
|
+
throw invalidOperationRequest();
|
|
336
|
+
}
|
|
337
|
+
function operationId(value) {
|
|
338
|
+
if (typeof value !== "string" || !OPERATION_UUID_PATTERN.test(value))
|
|
339
|
+
throw invalidOperationRequest();
|
|
340
|
+
}
|
|
341
|
+
function operationDigest(value) {
|
|
342
|
+
if (typeof value !== "string" || !OPERATION_DIGEST_PATTERN.test(value))
|
|
343
|
+
throw invalidOperationRequest();
|
|
344
|
+
}
|
|
345
|
+
function operationText(value, maxBytes, nonEmpty) {
|
|
346
|
+
if (typeof value !== "string"
|
|
347
|
+
|| (nonEmpty && value.length === 0)
|
|
348
|
+
|| !isWellFormedUnicode(value)
|
|
349
|
+
|| Buffer.byteLength(value, "utf8") > maxBytes)
|
|
350
|
+
throw invalidOperationRequest();
|
|
351
|
+
}
|
|
352
|
+
function isWellFormedUnicode(value) {
|
|
353
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
354
|
+
const code = value.charCodeAt(index);
|
|
355
|
+
if (code >= 0xd800 && code <= 0xdbff) {
|
|
356
|
+
const next = value.charCodeAt(index + 1);
|
|
357
|
+
if (!(next >= 0xdc00 && next <= 0xdfff))
|
|
358
|
+
return false;
|
|
359
|
+
index += 1;
|
|
360
|
+
}
|
|
361
|
+
else if (code >= 0xdc00 && code <= 0xdfff) {
|
|
362
|
+
return false;
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
return true;
|
|
366
|
+
}
|
|
367
|
+
function operationOpaqueId(value, maxBytes) {
|
|
368
|
+
operationText(value, maxBytes, true);
|
|
369
|
+
if (typeof value !== "string"
|
|
370
|
+
|| value.trim().length === 0
|
|
371
|
+
|| /[\u0000-\u001f\u007f]/u.test(value))
|
|
372
|
+
throw invalidOperationRequest();
|
|
373
|
+
}
|
|
374
|
+
function invalidOperationRequest() {
|
|
375
|
+
return new OperationWireRequestError();
|
|
376
|
+
}
|
|
377
|
+
function isPlainRecord(value) {
|
|
378
|
+
if (value === null || typeof value !== "object" || Array.isArray(value))
|
|
379
|
+
return false;
|
|
380
|
+
try {
|
|
381
|
+
const prototype = Object.getPrototypeOf(value);
|
|
382
|
+
return prototype === Object.prototype || prototype === null;
|
|
383
|
+
}
|
|
384
|
+
catch {
|
|
385
|
+
return false;
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
const OPERATION_UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/u;
|
|
389
|
+
const OPERATION_DIGEST_PATTERN = /^hmac-sha256:[0-9a-f]{64}$/u;
|
|
390
|
+
const OPERATION_PHASES = new Set([
|
|
391
|
+
"prepared", "handoff_pending", "ready", "send_pending", "submitted", "generating", "capturing", "completed", "uncertain"
|
|
392
|
+
]);
|
|
393
|
+
const OPERATION_BOUNDARIES = new Set(["none", "handoff_may_have_occurred", "send_may_have_occurred", "control_may_have_occurred"]);
|
|
394
|
+
const MAX_OPERATION_JSON_DEPTH = 16;
|
|
395
|
+
const MAX_OPERATION_JSON_NODES = 10_000;
|
|
396
|
+
const MAX_OPERATION_JSON_UTF8_BYTES = 1024 * 1024;
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import type { CollectorResult } from "./collector.js";
|
|
2
|
+
import type { ControlResult } from "./control.js";
|
|
3
|
+
import type { OperationBlockerV1, OperationControlReceiptV1, OperationHandleV1, OperationResponseFormatV1, OperationReceiptV1, OperationStateV1 } from "./types.js";
|
|
4
|
+
import type { OperationInspectResult, OperationSubmitResult } from "./service.js";
|
|
5
|
+
import type { BackendCompatibilityReport } from "../backend/protocol.js";
|
|
6
|
+
/** Versioned result envelopes used at backend/SDK boundaries. */
|
|
7
|
+
export declare const OPERATION_SUBMIT_RESULT_SCHEMA_VERSION: "chatgpt.browser_control.operation_submit_result.v1";
|
|
8
|
+
export declare const OPERATION_COLLECT_RESULT_SCHEMA_VERSION: "chatgpt.browser_control.operation_collect_result.v1";
|
|
9
|
+
export declare const OPERATION_INSPECT_RESULT_SCHEMA_VERSION: "chatgpt.browser_control.operation_inspect_result.v1";
|
|
10
|
+
export declare const OPERATION_CONTROL_RESULT_SCHEMA_VERSION: "chatgpt.browser_control.operation_control_result.v1";
|
|
11
|
+
export declare const OPERATION_LIVE_RESPONSE_SCHEMA_VERSION: "chatgpt.browser_control.operation_live_response.v1";
|
|
12
|
+
export declare const MAX_WIRE_RESPONSE_BYTES: number;
|
|
13
|
+
export declare const MAX_WIRE_RESPONSE_CHARS: number;
|
|
14
|
+
export declare const MAX_WIRE_BLOCKER_MESSAGE_LENGTH = 512;
|
|
15
|
+
export declare const MAX_WIRE_ARTIFACTS = 32;
|
|
16
|
+
export type OperationWireStatus = "accepted" | "completed" | "pending" | "blocked" | "uncertain";
|
|
17
|
+
/**
|
|
18
|
+
* Raw response content is deliberately a separate, explicitly ephemeral
|
|
19
|
+
* value. It is never accepted by a receipt or durable state validator.
|
|
20
|
+
*/
|
|
21
|
+
export type OperationLiveResponseV1 = Readonly<{
|
|
22
|
+
schemaVersion: typeof OPERATION_LIVE_RESPONSE_SCHEMA_VERSION;
|
|
23
|
+
durability: "ephemeral";
|
|
24
|
+
durable: false;
|
|
25
|
+
content: string;
|
|
26
|
+
responseFormat?: OperationResponseFormatV1;
|
|
27
|
+
bytes: number;
|
|
28
|
+
chars: number;
|
|
29
|
+
}>;
|
|
30
|
+
type OperationWireBase = Readonly<{
|
|
31
|
+
operationId: string;
|
|
32
|
+
requestDigest: string;
|
|
33
|
+
handle: OperationHandleV1;
|
|
34
|
+
}>;
|
|
35
|
+
export type OperationSubmitWireResult = (OperationWireBase & Readonly<{
|
|
36
|
+
schemaVersion: typeof OPERATION_SUBMIT_RESULT_SCHEMA_VERSION;
|
|
37
|
+
status: "accepted";
|
|
38
|
+
}>) | (OperationWireBase & Readonly<{
|
|
39
|
+
schemaVersion: typeof OPERATION_SUBMIT_RESULT_SCHEMA_VERSION;
|
|
40
|
+
status: "completed";
|
|
41
|
+
receipt: OperationReceiptV1;
|
|
42
|
+
}>) | (OperationWireBase & Readonly<{
|
|
43
|
+
schemaVersion: typeof OPERATION_SUBMIT_RESULT_SCHEMA_VERSION;
|
|
44
|
+
status: "blocked" | "uncertain";
|
|
45
|
+
blocker: OperationBlockerV1;
|
|
46
|
+
}>);
|
|
47
|
+
export type OperationCollectWireResult = (OperationWireBase & Readonly<{
|
|
48
|
+
schemaVersion: typeof OPERATION_COLLECT_RESULT_SCHEMA_VERSION;
|
|
49
|
+
status: "completed";
|
|
50
|
+
receipt: OperationReceiptV1;
|
|
51
|
+
liveResponse?: OperationLiveResponseV1;
|
|
52
|
+
}>) | (OperationWireBase & Readonly<{
|
|
53
|
+
schemaVersion: typeof OPERATION_COLLECT_RESULT_SCHEMA_VERSION;
|
|
54
|
+
status: "pending";
|
|
55
|
+
}>) | (OperationWireBase & Readonly<{
|
|
56
|
+
schemaVersion: typeof OPERATION_COLLECT_RESULT_SCHEMA_VERSION;
|
|
57
|
+
status: "blocked" | "uncertain";
|
|
58
|
+
blocker: OperationBlockerV1;
|
|
59
|
+
}>);
|
|
60
|
+
export type OperationInspectWireResult = OperationWireBase & Readonly<{
|
|
61
|
+
schemaVersion: typeof OPERATION_INSPECT_RESULT_SCHEMA_VERSION;
|
|
62
|
+
status: "completed" | "pending" | "uncertain";
|
|
63
|
+
state: OperationStateV1;
|
|
64
|
+
/** Additive transport provenance; absent for direct in-process backends. */
|
|
65
|
+
compatibility?: BackendCompatibilityReport;
|
|
66
|
+
}>;
|
|
67
|
+
export type OperationControlWireResult = OperationWireBase & Readonly<{
|
|
68
|
+
schemaVersion: typeof OPERATION_CONTROL_RESULT_SCHEMA_VERSION;
|
|
69
|
+
status: "completed" | "blocked" | "uncertain";
|
|
70
|
+
parentRequestDigest: string;
|
|
71
|
+
parentTargetBindingDigest: string;
|
|
72
|
+
controlActionId: string;
|
|
73
|
+
action: "stop" | "steer";
|
|
74
|
+
expectedAssistantTurnId: string;
|
|
75
|
+
receipt?: OperationControlReceiptV1;
|
|
76
|
+
blocker?: OperationBlockerV1;
|
|
77
|
+
}>;
|
|
78
|
+
export declare class OperationWireResultError extends Error {
|
|
79
|
+
readonly code: string;
|
|
80
|
+
constructor(code: string, message: string);
|
|
81
|
+
}
|
|
82
|
+
/** Convert the internal submission result into a strict, versioned envelope. */
|
|
83
|
+
export declare function toOperationSubmitWireResult(result: OperationSubmitResult, receipt?: OperationReceiptV1): OperationSubmitWireResult;
|
|
84
|
+
/** Convert the collector result using the freshly reloaded handle and receipt. */
|
|
85
|
+
export declare function toOperationCollectWireResult(
|
|
86
|
+
/** The handle freshly reloaded after the collector attempt (including pending). */
|
|
87
|
+
handle: OperationHandleV1, result: CollectorResult, receipt?: OperationReceiptV1): OperationCollectWireResult;
|
|
88
|
+
/** Inspect is a durable read, so its status is derived from the fresh state. */
|
|
89
|
+
export declare function toOperationInspectWireResult(result: OperationInspectResult): OperationInspectWireResult;
|
|
90
|
+
/** Convert a control result with the current parent handle reloaded by the service. */
|
|
91
|
+
export declare function toOperationControlWireResult(result: ControlResult, handle: OperationHandleV1): OperationControlWireResult;
|
|
92
|
+
export declare function liveResponseFromText(content: string, responseFormat?: OperationResponseFormatV1): OperationLiveResponseV1;
|
|
93
|
+
export declare function validateOperationSubmitWireResult(value: unknown): OperationSubmitWireResult;
|
|
94
|
+
export declare function validateOperationCollectWireResult(value: unknown): OperationCollectWireResult;
|
|
95
|
+
export declare function validateOperationInspectWireResult(value: unknown): OperationInspectWireResult;
|
|
96
|
+
export declare function validateOperationControlWireResult(value: unknown): OperationControlWireResult;
|
|
97
|
+
export {};
|