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,17 @@
|
|
|
1
|
+
import { type ChatPopoverSnapshot } from "../commands/chat-popover.js";
|
|
2
|
+
import type { LocatorLike, PageLike } from "../types.js";
|
|
3
|
+
export type TransactionalChatPower = Readonly<{
|
|
4
|
+
presentation: "closed" | "simple";
|
|
5
|
+
triggerId: string;
|
|
6
|
+
currentLabel: string;
|
|
7
|
+
modelMarker: string;
|
|
8
|
+
popover?: ChatPopoverSnapshot;
|
|
9
|
+
}>;
|
|
10
|
+
/** Read current scoped Chat effort without opening a menu or probing a value. */
|
|
11
|
+
export declare function readTransactionalChatPower(page: Readonly<PageLike>): Promise<TransactionalChatPower | undefined>;
|
|
12
|
+
export declare function transactionalPowerTrigger(page: Readonly<PageLike>, snapshot: TransactionalChatPower): LocatorLike | undefined;
|
|
13
|
+
export declare function preflightTransactionalPowerTrigger(locator: LocatorLike, snapshot: TransactionalChatPower): Promise<boolean>;
|
|
14
|
+
export declare function transactionalPowerMenu(page: Readonly<PageLike>, snapshot: TransactionalChatPower): LocatorLike | undefined;
|
|
15
|
+
export declare function transactionalPowerSlider(page: Readonly<PageLike>, snapshot: TransactionalChatPower): LocatorLike | undefined;
|
|
16
|
+
/** Locator preflight is read-only and uses the same active/owned rules as discovery. */
|
|
17
|
+
export declare function preflightTransactionalPowerSlider(locator: LocatorLike, snapshot: TransactionalChatPower): Promise<boolean>;
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import { localeLabels } from "../dom/locale-labels.js";
|
|
2
|
+
import { readChatPopover } from "../commands/chat-popover.js";
|
|
3
|
+
/** Read current scoped Chat effort without opening a menu or probing a value. */
|
|
4
|
+
export async function readTransactionalChatPower(page) {
|
|
5
|
+
const popover = (await readChatPopover(page)).snapshot;
|
|
6
|
+
if (page.evaluate === undefined)
|
|
7
|
+
return undefined;
|
|
8
|
+
const expandedTriggerLabels = ["Thinking effort"];
|
|
9
|
+
const trigger = await page.evaluate((config) => {
|
|
10
|
+
const normalize = (value) => value.replace(/\s+/g, " ").trim();
|
|
11
|
+
const visible = (element) => {
|
|
12
|
+
let current = element;
|
|
13
|
+
for (let depth = 0; current !== null && depth < 64; depth += 1) {
|
|
14
|
+
if (current.nodeType !== 1)
|
|
15
|
+
return true;
|
|
16
|
+
const node = current;
|
|
17
|
+
if (node.hidden || node.hasAttribute("hidden") || node.hasAttribute("inert") || node.getAttribute("aria-hidden") === "true"
|
|
18
|
+
|| node.getAttribute("aria-disabled") === "true" || node.getAttribute("data-active") === "false")
|
|
19
|
+
return false;
|
|
20
|
+
const style = window.getComputedStyle(node);
|
|
21
|
+
if (style.display === "none" || style.visibility === "hidden" || style.opacity === "0" || style.pointerEvents === "none")
|
|
22
|
+
return false;
|
|
23
|
+
if (current === element) {
|
|
24
|
+
const rect = node.getBoundingClientRect();
|
|
25
|
+
if (rect.width <= 0 || rect.height <= 0)
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
current = current.parentNode;
|
|
29
|
+
}
|
|
30
|
+
return current === null;
|
|
31
|
+
};
|
|
32
|
+
const forms = document.querySelectorAll("main form");
|
|
33
|
+
if (forms.length > 8)
|
|
34
|
+
return undefined;
|
|
35
|
+
const candidates = [];
|
|
36
|
+
let visited = 0;
|
|
37
|
+
for (const form of Array.from(forms)) {
|
|
38
|
+
if (!visible(form))
|
|
39
|
+
continue;
|
|
40
|
+
const nodes = [];
|
|
41
|
+
let node = form.firstChild;
|
|
42
|
+
while (node !== null) {
|
|
43
|
+
if (++visited > 4096)
|
|
44
|
+
return undefined;
|
|
45
|
+
if (node.nodeType === 1)
|
|
46
|
+
nodes.push(node);
|
|
47
|
+
if (node.firstChild !== null) {
|
|
48
|
+
node = node.firstChild;
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
while (node !== null && node !== form && node.nextSibling === null)
|
|
52
|
+
node = node.parentNode;
|
|
53
|
+
if (node === form || node === null)
|
|
54
|
+
break;
|
|
55
|
+
node = node.nextSibling;
|
|
56
|
+
}
|
|
57
|
+
const editors = nodes.filter(node => (node.tagName === "TEXTAREA" || node.getAttribute("contenteditable") === "true" || node.getAttribute("role") === "textbox") && visible(node));
|
|
58
|
+
if (editors.length !== 1)
|
|
59
|
+
continue;
|
|
60
|
+
const editor = editors[0];
|
|
61
|
+
const editorLabel = normalize(editor.getAttribute("aria-label") ?? editor.getAttribute("placeholder") ?? "").toLocaleLowerCase();
|
|
62
|
+
if (!config.chatLabels.some(label => normalize(label).toLocaleLowerCase() === editorLabel)
|
|
63
|
+
|| config.workLabels.some(label => normalize(label).toLocaleLowerCase() === editorLabel))
|
|
64
|
+
continue;
|
|
65
|
+
for (const button of nodes) {
|
|
66
|
+
if (button.tagName !== "BUTTON" || !visible(button) || button.disabled
|
|
67
|
+
|| button.getAttribute("aria-haspopup") !== "menu"
|
|
68
|
+
|| !(button.getAttribute("class") ?? "").split(/\s+/).includes("__composer-pill"))
|
|
69
|
+
continue;
|
|
70
|
+
const expanded = button.getAttribute("aria-expanded");
|
|
71
|
+
const id = button.getAttribute("id");
|
|
72
|
+
if ((expanded !== "true" && expanded !== "false") || id === null || id.length === 0 || id.length > 240 || /\s/.test(id))
|
|
73
|
+
continue;
|
|
74
|
+
let raw = "";
|
|
75
|
+
let child = button.firstChild;
|
|
76
|
+
while (child !== null) {
|
|
77
|
+
if (++visited > 4096)
|
|
78
|
+
return undefined;
|
|
79
|
+
const hidden = child.nodeType === 1 && !visible(child);
|
|
80
|
+
if (child.nodeType === 3) {
|
|
81
|
+
raw += child.nodeValue ?? "";
|
|
82
|
+
if (raw.length > 240)
|
|
83
|
+
return undefined;
|
|
84
|
+
}
|
|
85
|
+
if (!hidden && child.firstChild !== null) {
|
|
86
|
+
child = child.firstChild;
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
while (child !== null && child !== button && child.nextSibling === null)
|
|
90
|
+
child = child.parentNode;
|
|
91
|
+
if (child === button || child === null)
|
|
92
|
+
break;
|
|
93
|
+
child = child.nextSibling;
|
|
94
|
+
}
|
|
95
|
+
const text = normalize(raw);
|
|
96
|
+
const labels = [...config.effortLabels, ...(expanded === "true" ? config.expandedTriggerLabels : [])]
|
|
97
|
+
.filter(label => text.toLocaleLowerCase().endsWith(label.toLocaleLowerCase()))
|
|
98
|
+
.sort((left, right) => right.length - left.length);
|
|
99
|
+
const currentLabel = labels[0];
|
|
100
|
+
if (currentLabel === undefined)
|
|
101
|
+
continue;
|
|
102
|
+
const prefix = normalize(text.slice(0, text.length - currentLabel.length));
|
|
103
|
+
if (prefix.length > 0 && !/^(?:latest|(?:gpt[\s-]?)?\d+(?:\.\d+)?(?:[ .-][a-z]+)?)$/i.test(prefix))
|
|
104
|
+
continue;
|
|
105
|
+
candidates.push({ triggerId: id, currentLabel: text.slice(text.length - currentLabel.length), modelMarker: prefix, expanded: expanded === "true" });
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return candidates.length === 1 ? candidates[0] : undefined;
|
|
109
|
+
}, {
|
|
110
|
+
chatLabels: localeLabels.composerTextbox,
|
|
111
|
+
workLabels: localeLabels.workComposerTextbox,
|
|
112
|
+
effortLabels: Array.from(new Set([...Object.values(localeLabels.configurationOptions).flat(), ...Object.entries(localeLabels.modeOptions).filter(([key]) => key !== "latest").flatMap(([, labels]) => labels)])),
|
|
113
|
+
expandedTriggerLabels
|
|
114
|
+
}).catch(() => undefined);
|
|
115
|
+
if (trigger === undefined || trigger === null || typeof trigger.currentLabel !== "string")
|
|
116
|
+
return undefined;
|
|
117
|
+
if (!trigger.expanded) {
|
|
118
|
+
if (popover !== undefined)
|
|
119
|
+
return undefined;
|
|
120
|
+
return { presentation: "closed", triggerId: trigger.triggerId, currentLabel: trigger.currentLabel, modelMarker: trigger.modelMarker };
|
|
121
|
+
}
|
|
122
|
+
if (popover?.view !== "simple" || popover.slider === undefined || popover.effort === undefined
|
|
123
|
+
|| popover.triggerId !== trigger.triggerId
|
|
124
|
+
|| (popover.effort !== trigger.currentLabel && !expandedTriggerLabels.includes(trigger.currentLabel)))
|
|
125
|
+
return undefined;
|
|
126
|
+
return { presentation: "simple", triggerId: trigger.triggerId, currentLabel: popover.effort, modelMarker: trigger.modelMarker, popover };
|
|
127
|
+
}
|
|
128
|
+
function idSelector(id) { return `[id="${id.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"]`; }
|
|
129
|
+
export function transactionalPowerTrigger(page, snapshot) {
|
|
130
|
+
return page.locator?.(idSelector(snapshot.triggerId));
|
|
131
|
+
}
|
|
132
|
+
export async function preflightTransactionalPowerTrigger(locator, snapshot) {
|
|
133
|
+
if (locator.evaluate === undefined || await locator.count?.() !== 1)
|
|
134
|
+
return false;
|
|
135
|
+
const state = await locator.evaluate(element => {
|
|
136
|
+
let current = element;
|
|
137
|
+
let form = false, main = false;
|
|
138
|
+
for (let depth = 0; current !== null && depth < 64; depth += 1) {
|
|
139
|
+
if (current.nodeType !== 1)
|
|
140
|
+
break;
|
|
141
|
+
const node = current;
|
|
142
|
+
if (node.hidden || node.hasAttribute("hidden") || node.hasAttribute("inert") || node.getAttribute("aria-hidden") === "true"
|
|
143
|
+
|| node.getAttribute("aria-disabled") === "true" || node.getAttribute("data-active") === "false")
|
|
144
|
+
return undefined;
|
|
145
|
+
const style = window.getComputedStyle(node);
|
|
146
|
+
if (style.display === "none" || style.visibility === "hidden" || style.opacity === "0" || style.pointerEvents === "none")
|
|
147
|
+
return undefined;
|
|
148
|
+
if (node.tagName === "FORM")
|
|
149
|
+
form = true;
|
|
150
|
+
if (node.tagName === "MAIN" && form)
|
|
151
|
+
main = true;
|
|
152
|
+
current = current.parentNode;
|
|
153
|
+
}
|
|
154
|
+
const rect = element.getBoundingClientRect();
|
|
155
|
+
if (current?.nodeType === 1 || !form || !main || rect.width <= 0 || rect.height <= 0 || element.tagName !== "BUTTON"
|
|
156
|
+
|| element.disabled || element.hasAttribute("disabled")
|
|
157
|
+
|| !(element.getAttribute("class") ?? "").split(/\s+/).includes("__composer-pill"))
|
|
158
|
+
return undefined;
|
|
159
|
+
return { id: element.getAttribute("id"), expanded: element.getAttribute("aria-expanded"), popup: element.getAttribute("aria-haspopup") };
|
|
160
|
+
}).catch(() => undefined);
|
|
161
|
+
return state !== undefined && state.id === snapshot.triggerId && state.expanded === "false" && state.popup === "menu";
|
|
162
|
+
}
|
|
163
|
+
export function transactionalPowerMenu(page, snapshot) {
|
|
164
|
+
return page.locator?.(`[role="menu"][aria-labelledby="${snapshot.triggerId.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"]`);
|
|
165
|
+
}
|
|
166
|
+
export function transactionalPowerSlider(page, snapshot) {
|
|
167
|
+
const popover = snapshot.popover;
|
|
168
|
+
if (popover?.slider === undefined)
|
|
169
|
+
return undefined;
|
|
170
|
+
const roots = page.locator?.('[data-testid="composer-intelligence-picker-content"]');
|
|
171
|
+
const root = roots?.nth?.(popover.rootIndex) ?? (popover.rootIndex === 0 ? roots : undefined);
|
|
172
|
+
const sliders = root?.locator?.('[data-testid="composer-model-picker-slider-simple-view"][data-active="true"] [role="slider"]');
|
|
173
|
+
return sliders?.nth?.(popover.slider.index) ?? (popover.slider.index === 0 ? sliders : undefined);
|
|
174
|
+
}
|
|
175
|
+
/** Locator preflight is read-only and uses the same active/owned rules as discovery. */
|
|
176
|
+
export async function preflightTransactionalPowerSlider(locator, snapshot) {
|
|
177
|
+
if (locator.evaluate === undefined || await locator.count?.() !== 1 || snapshot.popover?.slider === undefined)
|
|
178
|
+
return false;
|
|
179
|
+
const state = await locator.evaluate(element => {
|
|
180
|
+
let current = element;
|
|
181
|
+
let owner = false, panel = false, view = false;
|
|
182
|
+
let triggerId = null;
|
|
183
|
+
for (let depth = 0; current !== null && depth < 64; depth += 1) {
|
|
184
|
+
if (current.nodeType !== 1)
|
|
185
|
+
break;
|
|
186
|
+
const node = current;
|
|
187
|
+
if (node.hidden || node.hasAttribute("hidden") || node.hasAttribute("inert") || node.getAttribute("data-active") === "false"
|
|
188
|
+
|| node.getAttribute("aria-disabled") === "true" || node.getAttribute("data-locked") === "true"
|
|
189
|
+
|| (current !== element && node.getAttribute("aria-hidden") === "true"))
|
|
190
|
+
return undefined;
|
|
191
|
+
const style = window.getComputedStyle(node);
|
|
192
|
+
if (style.display === "none" || style.visibility === "hidden" || style.opacity === "0" || style.pointerEvents === "none")
|
|
193
|
+
return undefined;
|
|
194
|
+
if (node.getAttribute("data-testid") === "composer-intelligence-picker-content")
|
|
195
|
+
owner = true;
|
|
196
|
+
if (node.getAttribute("data-testid") === "composer-model-picker-slider-simple-view" && node.getAttribute("data-active") === "true")
|
|
197
|
+
panel = true;
|
|
198
|
+
if (node.getAttribute("data-view") === "simple" && node.getAttribute("data-has-slider") === "true"
|
|
199
|
+
&& node.getAttribute("data-has-advanced-view") === "true" && node.getAttribute("data-model-selection-view") === "true")
|
|
200
|
+
view = true;
|
|
201
|
+
if (node.getAttribute("role") === "menu" && node.getAttribute("data-state") === "open")
|
|
202
|
+
triggerId = node.getAttribute("aria-labelledby");
|
|
203
|
+
current = current.parentNode;
|
|
204
|
+
}
|
|
205
|
+
const rect = element.getBoundingClientRect();
|
|
206
|
+
if (current?.nodeType === 1 || !owner || !panel || !view || rect.width <= 0 || rect.height <= 0 || element.getAttribute("role") !== "slider")
|
|
207
|
+
return undefined;
|
|
208
|
+
return { triggerId, minimum: element.getAttribute("aria-valuemin"), maximum: element.getAttribute("aria-valuemax"), current: element.getAttribute("aria-valuenow") };
|
|
209
|
+
}).catch(() => undefined);
|
|
210
|
+
return state !== undefined && state.triggerId === snapshot.triggerId && state.minimum === String(snapshot.popover.slider.minimum)
|
|
211
|
+
&& state.maximum === String(snapshot.popover.slider.maximum) && state.current === String(snapshot.popover.slider.current);
|
|
212
|
+
}
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The turn ownership classifier deliberately accepts normalized, already
|
|
3
|
+
* redacted observations. It must never be handed DOM nodes or prompt text.
|
|
4
|
+
* Adapters are responsible for producing the bounded digests in these types.
|
|
5
|
+
*/
|
|
6
|
+
export declare const TURN_OWNERSHIP_SCHEMA_VERSION: "chatgpt.browser_control.turn_ownership.v1";
|
|
7
|
+
export type OwnershipDigest = string;
|
|
8
|
+
export type OwnershipIdentityEvidence = {
|
|
9
|
+
readonly status: "available";
|
|
10
|
+
/** Stable provider/browser/tab/thread identity, never user content. */
|
|
11
|
+
readonly value: string;
|
|
12
|
+
} | {
|
|
13
|
+
readonly status: "unavailable";
|
|
14
|
+
readonly reason: "not_exposed" | "not_observed" | "redacted";
|
|
15
|
+
};
|
|
16
|
+
export type OwnershipTargetEvidence = {
|
|
17
|
+
readonly provider: OwnershipIdentityEvidence;
|
|
18
|
+
readonly browser: OwnershipIdentityEvidence;
|
|
19
|
+
readonly tab: OwnershipIdentityEvidence;
|
|
20
|
+
readonly thread: OwnershipIdentityEvidence;
|
|
21
|
+
readonly conversation: OwnershipIdentityEvidence;
|
|
22
|
+
readonly canonicalThreadUrl: OwnershipIdentityEvidence;
|
|
23
|
+
readonly authoritativeTabClaim: OwnershipIdentityEvidence;
|
|
24
|
+
readonly coordinationScope: "process" | "provider";
|
|
25
|
+
};
|
|
26
|
+
export type OwnershipEvidenceProfile = {
|
|
27
|
+
readonly stableConversationId: "required" | "unavailable";
|
|
28
|
+
readonly stableUserTurnId: "required" | "unavailable";
|
|
29
|
+
readonly stableAssistantTurnId: "required" | "unavailable";
|
|
30
|
+
readonly stableBranchId: "required" | "unavailable";
|
|
31
|
+
readonly authoritativeTabClaim: "required" | "unavailable";
|
|
32
|
+
};
|
|
33
|
+
export type OwnershipBinding = {
|
|
34
|
+
readonly schemaVersion: typeof TURN_OWNERSHIP_SCHEMA_VERSION;
|
|
35
|
+
readonly operationId: string;
|
|
36
|
+
readonly targetBindingDigest: OwnershipDigest;
|
|
37
|
+
readonly target: OwnershipTargetEvidence;
|
|
38
|
+
readonly evidenceProfile: OwnershipEvidenceProfile;
|
|
39
|
+
readonly replacementTabRecovery: boolean;
|
|
40
|
+
readonly actionId: string;
|
|
41
|
+
readonly actionKind: "send" | "work_steer";
|
|
42
|
+
};
|
|
43
|
+
export type OwnershipTurn = {
|
|
44
|
+
/** Stable turn ID, when the provider exposes one. Never raw turn text. */
|
|
45
|
+
readonly stableId?: string;
|
|
46
|
+
/** HMAC/cryptographic evidence digest for the normalized turn. */
|
|
47
|
+
readonly evidenceDigest: OwnershipDigest;
|
|
48
|
+
/** Deterministic structure digest; text is never accepted by this module. */
|
|
49
|
+
readonly structureDigest: OwnershipDigest;
|
|
50
|
+
/** Ordered position in the normalized provider snapshot. */
|
|
51
|
+
readonly ordinal: number;
|
|
52
|
+
/** Stable parent identity for assistant turns. */
|
|
53
|
+
readonly parentStableId?: string;
|
|
54
|
+
/** Stable branch identity for assistant turns. */
|
|
55
|
+
readonly branchStableId?: string;
|
|
56
|
+
readonly state?: "generating" | "terminal";
|
|
57
|
+
readonly artifactEvidenceDigests?: readonly OwnershipDigest[];
|
|
58
|
+
};
|
|
59
|
+
export type OwnershipSnapshotCompleteness = "complete" | "truncated" | "incomplete" | "out_of_order";
|
|
60
|
+
export type OwnershipSnapshot = {
|
|
61
|
+
readonly schemaVersion: typeof TURN_OWNERSHIP_SCHEMA_VERSION;
|
|
62
|
+
readonly snapshotDigest: OwnershipDigest;
|
|
63
|
+
readonly target: OwnershipTargetEvidence;
|
|
64
|
+
readonly userTurns: readonly OwnershipTurn[];
|
|
65
|
+
readonly assistantTurns: readonly OwnershipTurn[];
|
|
66
|
+
readonly completeness: OwnershipSnapshotCompleteness;
|
|
67
|
+
readonly terminalState: "idle" | "generating" | "terminal" | "unknown";
|
|
68
|
+
/** Captured by the adapter after Send using the exact before/after delta. */
|
|
69
|
+
readonly postSendDelta?: OwnershipDeltaEvidence;
|
|
70
|
+
};
|
|
71
|
+
export type OwnershipBaseline = {
|
|
72
|
+
readonly schemaVersion: typeof TURN_OWNERSHIP_SCHEMA_VERSION;
|
|
73
|
+
/** Digest of the complete pre-Send normalized snapshot. */
|
|
74
|
+
readonly snapshotDigest: OwnershipDigest;
|
|
75
|
+
readonly target: OwnershipTargetEvidence;
|
|
76
|
+
readonly userTurns: readonly OwnershipTurn[];
|
|
77
|
+
readonly assistantTurns: readonly OwnershipTurn[];
|
|
78
|
+
readonly completeness: "complete";
|
|
79
|
+
};
|
|
80
|
+
export type OwnershipDeltaEvidence = {
|
|
81
|
+
readonly baselineSnapshotDigest: OwnershipDigest;
|
|
82
|
+
/** Exact new-user evidence digests from the normalized before/after delta. */
|
|
83
|
+
readonly addedUserEvidenceDigests: readonly OwnershipDigest[];
|
|
84
|
+
/** Digest over the canonical delta object, generated by the adapter. */
|
|
85
|
+
readonly deltaDigest: OwnershipDigest;
|
|
86
|
+
};
|
|
87
|
+
export type OwnershipSubmissionWitness = {
|
|
88
|
+
readonly actionId: string;
|
|
89
|
+
readonly actionKind: "send" | "work_steer";
|
|
90
|
+
/** Digest of the complete authenticated pre-Send ownership snapshot. */
|
|
91
|
+
readonly baselineSnapshotDigest: OwnershipDigest;
|
|
92
|
+
/** Durable action evidence for the exact post-Send user-turn delta. */
|
|
93
|
+
readonly postSendDeltaDigest: OwnershipDigest;
|
|
94
|
+
/** Durable evidence for the operation's submitted user turn. */
|
|
95
|
+
readonly operationUserEvidenceDigest: OwnershipDigest;
|
|
96
|
+
/** Optional immediate stable ID returned by the provider. */
|
|
97
|
+
readonly userTurnStableId?: string;
|
|
98
|
+
};
|
|
99
|
+
export type OwnershipCursorPhase = "owned_user_turn" | "owned_assistant_generating" | "owned_assistant_terminal";
|
|
100
|
+
export type OwnershipCursor = Readonly<{
|
|
101
|
+
readonly schemaVersion: typeof TURN_OWNERSHIP_SCHEMA_VERSION;
|
|
102
|
+
readonly operationId: string;
|
|
103
|
+
readonly targetBindingDigest: OwnershipDigest;
|
|
104
|
+
readonly phase: OwnershipCursorPhase;
|
|
105
|
+
readonly userTurnId: string;
|
|
106
|
+
readonly userTurnEvidenceDigest: OwnershipDigest;
|
|
107
|
+
readonly assistantTurnId?: string;
|
|
108
|
+
readonly assistantBranchId?: string;
|
|
109
|
+
/** Digest of the normalized snapshot from which this cursor was issued. */
|
|
110
|
+
readonly snapshotDigest: OwnershipDigest;
|
|
111
|
+
/** Frozen assistant evidence used to detect mutation after terminal capture. */
|
|
112
|
+
readonly assistantEvidenceDigest?: OwnershipDigest;
|
|
113
|
+
readonly assistantStructureDigest?: OwnershipDigest;
|
|
114
|
+
}>;
|
|
115
|
+
export type OwnershipResultStatus = "no_operation_turn" | "owned_user_turn" | "owned_assistant_generating" | "owned_assistant_terminal" | "target_mismatch" | "target_evidence_unavailable" | "concurrent_user_turn" | "regeneration_ambiguous" | "ownership_ambiguous";
|
|
116
|
+
export type OwnershipReason = "none" | "target_binding_mismatch" | "target_evidence_unavailable" | "replacement_tab_requires_owned_user" | "incomplete_snapshot" | "out_of_order_snapshot" | "baseline_turn_missing" | "baseline_turn_changed" | "intervening_user_turn" | "multiple_new_user_turns" | "operation_user_evidence_mismatch" | "post_send_delta_missing" | "post_send_delta_mismatch" | "stable_user_turn_id_unavailable" | "stable_assistant_turn_id_unavailable" | "stable_parent_identity_unavailable" | "stable_branch_identity_unavailable" | "assistant_parent_mismatch" | "assistant_state_unknown" | "terminal_state_mismatch" | "regeneration_siblings" | "prior_owned_turn_missing" | "prior_owned_turn_changed" | "prior_cursor_mismatch" | "unexpected_new_assistant_turn" | "baseline_target_mismatch";
|
|
117
|
+
export type OwnershipRecoveryObservation = {
|
|
118
|
+
readonly status: "not_observed";
|
|
119
|
+
} | {
|
|
120
|
+
readonly status: "owned_user_turn";
|
|
121
|
+
readonly userTurnId: string;
|
|
122
|
+
readonly evidenceDigest: OwnershipDigest;
|
|
123
|
+
} | {
|
|
124
|
+
readonly status: "owned_assistant_generating";
|
|
125
|
+
readonly userTurnId: string;
|
|
126
|
+
readonly assistantTurnId: string;
|
|
127
|
+
readonly evidenceDigest: OwnershipDigest;
|
|
128
|
+
} | {
|
|
129
|
+
readonly status: "owned_assistant_terminal";
|
|
130
|
+
readonly userTurnId: string;
|
|
131
|
+
readonly assistantTurnId: string;
|
|
132
|
+
readonly evidenceDigest: OwnershipDigest;
|
|
133
|
+
} | {
|
|
134
|
+
readonly status: "ambiguous";
|
|
135
|
+
readonly evidenceDigest?: OwnershipDigest;
|
|
136
|
+
};
|
|
137
|
+
export type OwnershipEvidenceMaterial = Readonly<{
|
|
138
|
+
readonly schemaVersion: typeof TURN_OWNERSHIP_SCHEMA_VERSION;
|
|
139
|
+
readonly operationId: string;
|
|
140
|
+
readonly status: OwnershipResultStatus;
|
|
141
|
+
readonly reason: OwnershipReason;
|
|
142
|
+
readonly target: Readonly<{
|
|
143
|
+
readonly provider: "available" | "unavailable";
|
|
144
|
+
readonly browser: "available" | "unavailable";
|
|
145
|
+
readonly tab: "available" | "unavailable";
|
|
146
|
+
readonly thread: "available" | "unavailable";
|
|
147
|
+
readonly conversation: "available" | "unavailable";
|
|
148
|
+
readonly canonicalThreadUrl: "available" | "unavailable";
|
|
149
|
+
readonly authoritativeTabClaim: "available" | "unavailable";
|
|
150
|
+
readonly replacedTab: boolean;
|
|
151
|
+
}>;
|
|
152
|
+
readonly baselineSnapshotDigest: OwnershipDigest;
|
|
153
|
+
readonly snapshotDigest: OwnershipDigest;
|
|
154
|
+
readonly postSendDeltaDigest?: OwnershipDigest;
|
|
155
|
+
readonly addedUserCount: number;
|
|
156
|
+
readonly addedAssistantCount: number;
|
|
157
|
+
readonly terminalState: OwnershipSnapshot["terminalState"];
|
|
158
|
+
readonly userTurn?: Readonly<{
|
|
159
|
+
readonly evidenceDigest: OwnershipDigest;
|
|
160
|
+
readonly structureDigest: OwnershipDigest;
|
|
161
|
+
readonly ordinal: number;
|
|
162
|
+
readonly stableIdAvailable: boolean;
|
|
163
|
+
readonly parentStableIdAvailable: boolean;
|
|
164
|
+
readonly branchStableIdAvailable: boolean;
|
|
165
|
+
readonly artifactEvidenceDigests: readonly OwnershipDigest[];
|
|
166
|
+
readonly state?: OwnershipTurn["state"];
|
|
167
|
+
}>;
|
|
168
|
+
readonly assistantTurn?: Readonly<{
|
|
169
|
+
readonly evidenceDigest: OwnershipDigest;
|
|
170
|
+
readonly structureDigest: OwnershipDigest;
|
|
171
|
+
readonly ordinal: number;
|
|
172
|
+
readonly stableIdAvailable: boolean;
|
|
173
|
+
readonly parentStableIdAvailable: boolean;
|
|
174
|
+
readonly branchStableIdAvailable: boolean;
|
|
175
|
+
readonly artifactEvidenceDigests: readonly OwnershipDigest[];
|
|
176
|
+
readonly state?: OwnershipTurn["state"];
|
|
177
|
+
}>;
|
|
178
|
+
}>;
|
|
179
|
+
export type OwnershipClassification = Readonly<{
|
|
180
|
+
readonly status: OwnershipResultStatus;
|
|
181
|
+
readonly reason: OwnershipReason;
|
|
182
|
+
readonly evidence: OwnershipEvidenceMaterial;
|
|
183
|
+
readonly recoveryObservation: OwnershipRecoveryObservation;
|
|
184
|
+
readonly cursor?: OwnershipCursor;
|
|
185
|
+
}>;
|
|
186
|
+
export type TurnOwnershipInput = {
|
|
187
|
+
readonly binding: OwnershipBinding;
|
|
188
|
+
readonly baseline: OwnershipBaseline;
|
|
189
|
+
readonly snapshot: OwnershipSnapshot;
|
|
190
|
+
readonly submissionWitness?: OwnershipSubmissionWitness;
|
|
191
|
+
readonly prior?: OwnershipCursor;
|
|
192
|
+
};
|
|
193
|
+
/**
|
|
194
|
+
* Classify one normalized snapshot. This function has no browser, DOM, or
|
|
195
|
+
* I/O dependency. It only permits an owned user turn when the adapter has
|
|
196
|
+
* supplied the exact post-Send delta digest and operation-specific evidence.
|
|
197
|
+
*/
|
|
198
|
+
export declare function classifyTurnOwnership(input: TurnOwnershipInput): OwnershipClassification;
|
|
199
|
+
/** Return the deterministic, redacted JSON input a caller may HMAC. */
|
|
200
|
+
export declare function ownershipEvidenceJson(material: OwnershipEvidenceMaterial): string;
|
|
201
|
+
/** Validate a cursor before persisting or supplying it to a later snapshot. */
|
|
202
|
+
export declare function validateOwnershipCursor(cursor: OwnershipCursor): void;
|