codex-chatgpt-control 0.1.0-alpha.1 → 0.2.0-alpha.1
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 +6 -0
- package/README.md +55 -0
- package/contracts/v1/fixtures/backend-capabilities.json +7 -0
- package/contracts/v1/fixtures/blocker-explanation-profiles.json +114 -0
- package/contracts/v1/fixtures/command-descriptors.json +192 -15
- package/contracts/v1/fixtures/doctor-bridge-upload.json +8 -0
- package/contracts/v1/fixtures/doctor-scenario-preflight.json +108 -0
- package/contracts/v1/fixtures/existing-tab-diagnostics-blocker.json +57 -0
- package/contracts/v1/fixtures/files-preflight-success.json +32 -0
- package/contracts/v1/fixtures/help-root.json +1 -1
- package/contracts/v1/fixtures/output-json-parse-success.json +17 -2
- package/contracts/v1/fixtures/project-sources-plan-add.json +71 -0
- package/contracts/v1/fixtures/read-latest-clipped.json +31 -0
- package/contracts/v1/fixtures/reports-create-redacted.json +15 -0
- package/contracts/v1/fixtures/responses-basic-success.json +11 -0
- package/contracts/v1/fixtures/run-basic-success.json +15 -0
- package/contracts/v1/fixtures/run-browser-bridge-blocker.json +2 -2
- package/contracts/v1/fixtures/run-timeout-partial.json +2 -2
- package/contracts/v1/fixtures/runner-budget-blocker.json +1 -1
- package/contracts/v1/fixtures/stream-blocked.ndjson +1 -1
- package/contracts/v1/fixtures/stream-submitted-completed.ndjson +1 -1
- package/contracts/v1/manifest.json +30 -0
- package/contracts/v1/parity-suite.json +72 -6
- package/contracts/v1/schemas/backend-request.schema.json +3 -0
- package/contracts/v1/schemas/command-result.schema.json +48 -0
- package/contracts/v1/schemas/response.schema.json +28 -0
- package/contracts/v1/schemas/run-result.schema.json +84 -0
- package/contracts/v1/surface-drift-policy.json +210 -0
- package/dist/codex-chatgpt-control-backend.mjs +5137 -488
- package/dist/codex-chatgpt-control.bundle.mjs +5001 -286
- package/dist/src/backend/client.d.ts +6 -1
- package/dist/src/backend/client.js +5 -0
- package/dist/src/backend/protocol.d.ts +1 -1
- package/dist/src/backend/protocol.js +7 -0
- package/dist/src/backend/session.js +14 -0
- package/dist/src/browser/attach.js +128 -20
- package/dist/src/browser/downloads.js +2 -1
- package/dist/src/browser/page-state.js +6 -3
- package/dist/src/client.d.ts +16 -1
- package/dist/src/client.js +86 -7
- package/dist/src/commands/artifacts.d.ts +5 -0
- package/dist/src/commands/artifacts.js +432 -0
- package/dist/src/commands/context.js +5 -2
- package/dist/src/commands/doctor.d.ts +10 -2
- package/dist/src/commands/doctor.js +242 -14
- package/dist/src/commands/files.d.ts +2 -1
- package/dist/src/commands/files.js +352 -18
- package/dist/src/commands/messages.d.ts +2 -1
- package/dist/src/commands/messages.js +232 -40
- package/dist/src/commands/modes.js +202 -20
- package/dist/src/commands/project-sources.d.ts +10 -0
- package/dist/src/commands/project-sources.js +643 -0
- package/dist/src/commands/registry.js +76 -14
- package/dist/src/commands/reports.d.ts +9 -0
- package/dist/src/commands/reports.js +83 -6
- package/dist/src/commands/response-actions.js +33 -0
- package/dist/src/commands/sequence.js +14 -0
- package/dist/src/commands/threads.js +2 -1
- package/dist/src/commands/timeouts.d.ts +2 -0
- package/dist/src/commands/timeouts.js +18 -0
- package/dist/src/diagnostics/blockers.d.ts +54 -0
- package/dist/src/diagnostics/blockers.js +299 -0
- package/dist/src/dom/artifacts.d.ts +7 -0
- package/dist/src/dom/artifacts.js +198 -0
- package/dist/src/dom/generation-state.d.ts +8 -0
- package/dist/src/dom/generation-state.js +103 -0
- package/dist/src/dom/locale/am.d.ts +28 -0
- package/dist/src/dom/locale/am.js +28 -0
- package/dist/src/dom/locale/ar.d.ts +28 -0
- package/dist/src/dom/locale/ar.js +28 -0
- package/dist/src/dom/locale/bg.d.ts +28 -0
- package/dist/src/dom/locale/bg.js +28 -0
- package/dist/src/dom/locale/bn.d.ts +28 -0
- package/dist/src/dom/locale/bn.js +28 -0
- package/dist/src/dom/locale/bs.d.ts +28 -0
- package/dist/src/dom/locale/bs.js +28 -0
- package/dist/src/dom/locale/ca.d.ts +28 -0
- package/dist/src/dom/locale/ca.js +28 -0
- package/dist/src/dom/locale/cs.d.ts +28 -0
- package/dist/src/dom/locale/cs.js +28 -0
- package/dist/src/dom/locale/da.d.ts +28 -0
- package/dist/src/dom/locale/da.js +28 -0
- package/dist/src/dom/locale/de.d.ts +30 -0
- package/dist/src/dom/locale/de.js +30 -0
- package/dist/src/dom/locale/el.d.ts +28 -0
- package/dist/src/dom/locale/el.js +28 -0
- package/dist/src/dom/locale/en.d.ts +50 -0
- package/dist/src/dom/locale/en.js +56 -0
- package/dist/src/dom/locale/es-419.d.ts +28 -0
- package/dist/src/dom/locale/es-419.js +28 -0
- package/dist/src/dom/locale/es-ES.d.ts +28 -0
- package/dist/src/dom/locale/es-ES.js +28 -0
- package/dist/src/dom/locale/et.d.ts +28 -0
- package/dist/src/dom/locale/et.js +28 -0
- package/dist/src/dom/locale/fa.d.ts +28 -0
- package/dist/src/dom/locale/fa.js +28 -0
- package/dist/src/dom/locale/fi.d.ts +28 -0
- package/dist/src/dom/locale/fi.js +28 -0
- package/dist/src/dom/locale/fr-CA.d.ts +29 -0
- package/dist/src/dom/locale/fr-CA.js +29 -0
- package/dist/src/dom/locale/fr-FR.d.ts +30 -0
- package/dist/src/dom/locale/fr-FR.js +30 -0
- package/dist/src/dom/locale/gu.d.ts +28 -0
- package/dist/src/dom/locale/gu.js +28 -0
- package/dist/src/dom/locale/hi.d.ts +28 -0
- package/dist/src/dom/locale/hi.js +28 -0
- package/dist/src/dom/locale/hr.d.ts +28 -0
- package/dist/src/dom/locale/hr.js +28 -0
- package/dist/src/dom/locale/hu.d.ts +28 -0
- package/dist/src/dom/locale/hu.js +28 -0
- package/dist/src/dom/locale/hy.d.ts +28 -0
- package/dist/src/dom/locale/hy.js +28 -0
- package/dist/src/dom/locale/id.d.ts +28 -0
- package/dist/src/dom/locale/id.js +28 -0
- package/dist/src/dom/locale/index.d.ts +79 -0
- package/dist/src/dom/locale/index.js +202 -0
- package/dist/src/dom/locale/is.d.ts +28 -0
- package/dist/src/dom/locale/is.js +28 -0
- package/dist/src/dom/locale/it.d.ts +27 -0
- package/dist/src/dom/locale/it.js +27 -0
- package/dist/src/dom/locale/ja.d.ts +27 -0
- package/dist/src/dom/locale/ja.js +27 -0
- package/dist/src/dom/locale/ka.d.ts +28 -0
- package/dist/src/dom/locale/ka.js +28 -0
- package/dist/src/dom/locale/kk.d.ts +28 -0
- package/dist/src/dom/locale/kk.js +28 -0
- package/dist/src/dom/locale/kn.d.ts +28 -0
- package/dist/src/dom/locale/kn.js +28 -0
- package/dist/src/dom/locale/ko.d.ts +28 -0
- package/dist/src/dom/locale/ko.js +28 -0
- package/dist/src/dom/locale/lt.d.ts +28 -0
- package/dist/src/dom/locale/lt.js +28 -0
- package/dist/src/dom/locale/lv.d.ts +28 -0
- package/dist/src/dom/locale/lv.js +28 -0
- package/dist/src/dom/locale/mk.d.ts +28 -0
- package/dist/src/dom/locale/mk.js +28 -0
- package/dist/src/dom/locale/ml.d.ts +28 -0
- package/dist/src/dom/locale/ml.js +28 -0
- package/dist/src/dom/locale/mn.d.ts +28 -0
- package/dist/src/dom/locale/mn.js +28 -0
- package/dist/src/dom/locale/mr.d.ts +28 -0
- package/dist/src/dom/locale/mr.js +28 -0
- package/dist/src/dom/locale/ms.d.ts +28 -0
- package/dist/src/dom/locale/ms.js +28 -0
- package/dist/src/dom/locale/my.d.ts +28 -0
- package/dist/src/dom/locale/my.js +28 -0
- package/dist/src/dom/locale/nb.d.ts +28 -0
- package/dist/src/dom/locale/nb.js +28 -0
- package/dist/src/dom/locale/nl.d.ts +28 -0
- package/dist/src/dom/locale/nl.js +28 -0
- package/dist/src/dom/locale/pa.d.ts +28 -0
- package/dist/src/dom/locale/pa.js +28 -0
- package/dist/src/dom/locale/pl.d.ts +28 -0
- package/dist/src/dom/locale/pl.js +28 -0
- package/dist/src/dom/locale/pt-BR.d.ts +28 -0
- package/dist/src/dom/locale/pt-BR.js +28 -0
- package/dist/src/dom/locale/pt-PT.d.ts +28 -0
- package/dist/src/dom/locale/pt-PT.js +28 -0
- package/dist/src/dom/locale/ro.d.ts +28 -0
- package/dist/src/dom/locale/ro.js +28 -0
- package/dist/src/dom/locale/ru.d.ts +28 -0
- package/dist/src/dom/locale/ru.js +28 -0
- package/dist/src/dom/locale/sk.d.ts +28 -0
- package/dist/src/dom/locale/sk.js +28 -0
- package/dist/src/dom/locale/sl.d.ts +28 -0
- package/dist/src/dom/locale/sl.js +28 -0
- package/dist/src/dom/locale/so.d.ts +28 -0
- package/dist/src/dom/locale/so.js +28 -0
- package/dist/src/dom/locale/sq.d.ts +28 -0
- package/dist/src/dom/locale/sq.js +28 -0
- package/dist/src/dom/locale/sr.d.ts +28 -0
- package/dist/src/dom/locale/sr.js +28 -0
- package/dist/src/dom/locale/sv.d.ts +28 -0
- package/dist/src/dom/locale/sv.js +28 -0
- package/dist/src/dom/locale/sw.d.ts +28 -0
- package/dist/src/dom/locale/sw.js +28 -0
- package/dist/src/dom/locale/ta.d.ts +28 -0
- package/dist/src/dom/locale/ta.js +28 -0
- package/dist/src/dom/locale/te.d.ts +28 -0
- package/dist/src/dom/locale/te.js +28 -0
- package/dist/src/dom/locale/th.d.ts +28 -0
- package/dist/src/dom/locale/th.js +28 -0
- package/dist/src/dom/locale/tl.d.ts +28 -0
- package/dist/src/dom/locale/tl.js +28 -0
- package/dist/src/dom/locale/tr.d.ts +28 -0
- package/dist/src/dom/locale/tr.js +28 -0
- package/dist/src/dom/locale/types.d.ts +45 -0
- package/dist/src/dom/locale/types.js +1 -0
- package/dist/src/dom/locale/uk.d.ts +28 -0
- package/dist/src/dom/locale/uk.js +28 -0
- package/dist/src/dom/locale/ur.d.ts +28 -0
- package/dist/src/dom/locale/ur.js +28 -0
- package/dist/src/dom/locale/vi.d.ts +28 -0
- package/dist/src/dom/locale/vi.js +28 -0
- package/dist/src/dom/locale/zh-HK.d.ts +28 -0
- package/dist/src/dom/locale/zh-HK.js +28 -0
- package/dist/src/dom/locale/zh-Hans.d.ts +28 -0
- package/dist/src/dom/locale/zh-Hans.js +28 -0
- package/dist/src/dom/locale/zh-TW.d.ts +29 -0
- package/dist/src/dom/locale/zh-TW.js +29 -0
- package/dist/src/dom/locale-labels.d.ts +26 -0
- package/dist/src/dom/locale-labels.js +26 -0
- package/dist/src/dom/menus.d.ts +6 -0
- package/dist/src/dom/menus.js +34 -8
- package/dist/src/dom/message-format.d.ts +2 -1
- package/dist/src/dom/message-format.js +67 -10
- package/dist/src/dom/messages.d.ts +2 -1
- package/dist/src/dom/messages.js +2 -4
- package/dist/src/dom/selectors.d.ts +1 -0
- package/dist/src/dom/selectors.js +42 -15
- package/dist/src/index.d.ts +5 -0
- package/dist/src/index.js +5 -0
- package/dist/src/platform/local-paths.d.ts +4 -0
- package/dist/src/platform/local-paths.js +20 -0
- package/dist/src/runner/interruptions.js +15 -4
- package/dist/src/runner/responses.js +18 -1
- package/dist/src/runner/result.js +15 -0
- package/dist/src/runner/resume.js +1 -0
- package/dist/src/runner/types.d.ts +3 -0
- package/dist/src/safety/risk.d.ts +7 -0
- package/dist/src/safety/risk.js +7 -0
- package/dist/src/safety/untrusted-output.d.ts +73 -0
- package/dist/src/safety/untrusted-output.js +199 -0
- package/dist/src/scripts/apply-intelligence-locale-captures.d.ts +1 -0
- package/dist/src/scripts/apply-intelligence-locale-captures.js +184 -0
- package/dist/src/scripts/capture-intelligence-locales.d.ts +25 -0
- package/dist/src/scripts/capture-intelligence-locales.js +669 -0
- package/dist/src/scripts/check-surface-drift.d.ts +1 -0
- package/dist/src/scripts/check-surface-drift.js +11 -0
- package/dist/src/scripts/live-smoke/scenarios.js +84 -0
- package/dist/src/scripts/locale-capture/language-coverage.d.ts +10 -0
- package/dist/src/scripts/locale-capture/language-coverage.js +39 -0
- package/dist/src/testing/surface-drift.d.ts +66 -0
- package/dist/src/testing/surface-drift.js +363 -0
- package/dist/src/types.d.ts +201 -2
- package/package.json +2 -1
- package/references/backend-protocol.md +93 -1
- package/references/language-coverage.md +142 -0
- package/references/localization.md +247 -0
- package/references/python-parity.md +63 -1
- package/references/safety.md +2 -0
- package/references/troubleshooting.md +58 -0
|
@@ -8,10 +8,10 @@ const descriptors = [
|
|
|
8
8
|
`await chatgpt.askInThread({ thread: { type: "url", url: "https://chatgpt.com/c/<conversation-id>" }, existingTab: true, prompt: "Continue." });`
|
|
9
9
|
]),
|
|
10
10
|
workflow("askWithFiles", "Attach absolute local file paths, optionally set mode, ask, wait, and read.", [
|
|
11
|
-
`await chatgpt.askWithFiles({ thread: { type: "url", url: "https://chatgpt.com/c/<conversation-id>" }, existingTab: true, mode: {
|
|
11
|
+
`await chatgpt.askWithFiles({ thread: { type: "url", url: "https://chatgpt.com/c/<conversation-id>" }, existingTab: true, mode: { model: "Pro" }, files: ["/absolute/host/path/brief.md"], prompt: "Summarize this.", wait: true, read: { format: "markdown" } });`
|
|
12
12
|
]),
|
|
13
13
|
workflow("askAndDownload", "Ask ChatGPT to produce a visible downloadable output and save the latest exposed file.", [
|
|
14
|
-
`await chatgpt.askAndDownload({ prompt: "Create a CSV.", download: { destDir: "/
|
|
14
|
+
`await chatgpt.askAndDownload({ prompt: "Create a CSV.", download: { destDir: "/absolute/host/output" }, wait: true });`
|
|
15
15
|
]),
|
|
16
16
|
workflow("runMessages", "Run sequential prompts where later prompts can use earlier step data.", [
|
|
17
17
|
`await chatgpt.runMessages({ messages: [{ id: "first", prompt: "alpha" }, { id: "second", prompt: "beta" }] });`
|
|
@@ -39,10 +39,10 @@ const descriptors = [
|
|
|
39
39
|
`await chatgpt.runPlan({ name: "find-open-copy-latest", input: { query: "SDK Design Proposal" } });`
|
|
40
40
|
]),
|
|
41
41
|
workflow("attach-ask-read", "Named macro: open a new thread, attach files, ask, wait, and read Markdown.", [
|
|
42
|
-
`await chatgpt.runPlan({ name: "attach-ask-read", input: { files: ["/absolute/path.md"], prompt: "Summarize." } });`
|
|
42
|
+
`await chatgpt.runPlan({ name: "attach-ask-read", input: { files: ["/absolute/host/path.md"], prompt: "Summarize." } });`
|
|
43
43
|
]),
|
|
44
44
|
workflow("ask-and-download", "Named macro: ask in a new thread and download the latest file affordance.", [
|
|
45
|
-
`await chatgpt.runPlan({ name: "ask-and-download", input: { prompt: "Create a CSV.", destDir: "/
|
|
45
|
+
`await chatgpt.runPlan({ name: "ask-and-download", input: { prompt: "Create a CSV.", destDir: "/absolute/host/output" } });`
|
|
46
46
|
]),
|
|
47
47
|
workflow("two-turn", "Named macro: run two sequential prompts in a new thread.", [
|
|
48
48
|
`await chatgpt.runPlan({ name: "two-turn", input: { first: "alpha", second: "beta" } });`
|
|
@@ -53,11 +53,14 @@ const descriptors = [
|
|
|
53
53
|
report("redacted-run-report", "Named macro: create a redacted report for a supplied CommandResult.", [
|
|
54
54
|
`await chatgpt.runPlan({ name: "redacted-run-report", input: { result } });`
|
|
55
55
|
]),
|
|
56
|
-
diagnostic("doctor", "Preflight browser bridge, login, upload,
|
|
57
|
-
`await chatgpt.doctor({ check: ["bridge", "login", "upload"] })
|
|
56
|
+
diagnostic("doctor", "Preflight browser bridge, login, upload, local files, existing-tab, artifact, localization, report, and selector readiness.", [
|
|
57
|
+
`await chatgpt.doctor({ check: ["bridge", "login", "upload"] });`,
|
|
58
|
+
`await chatgpt.doctor({ check: ["existing_tab"], existingTab: { target: { type: "conversationId", conversationId: "<conversation-id>" }, ifMissing: "block" } });`,
|
|
59
|
+
`await chatgpt.doctor({ check: ["file_preflight"], files: ["/absolute/host/path.md"] });`,
|
|
60
|
+
`await chatgpt.doctor({ check: ["localization", "reports"], report: { destDir: "/absolute/host/reports" } });`
|
|
58
61
|
]),
|
|
59
62
|
report("createReport", "Write a durable redacted run report for a command result.", [
|
|
60
|
-
`await chatgpt.createReport(result, { destDir: "/
|
|
63
|
+
`await chatgpt.createReport(result, { destDir: "/absolute/host/reports" });`
|
|
61
64
|
]),
|
|
62
65
|
primitive("session.bootstrap", "Attach to ChatGPT in Chrome and detect login/blocker state.", 30000),
|
|
63
66
|
primitive("threads.new", "Open a new ChatGPT thread.", 30000),
|
|
@@ -69,10 +72,17 @@ const descriptors = [
|
|
|
69
72
|
primitive("messages.wait", "Wait for the latest assistant response to stabilize.", 120000),
|
|
70
73
|
primitive("messages.readLatest", "Read the latest message as Markdown, normalized text, blocks, or HTML.", 30000),
|
|
71
74
|
primitive("messages.waitAndRead", "Wait for completion and read the latest message.", 120000),
|
|
75
|
+
primitive("artifacts.listLatest", "Detect the latest visible generated ChatGPT artifact, such as an image-only result.", 30000),
|
|
76
|
+
primitive("artifacts.wait", "Wait for a visible generated ChatGPT artifact to appear and stabilize.", 120000),
|
|
77
|
+
primitive("artifacts.downloadLatest", "Download or save the latest visible generated ChatGPT artifact.", 120000),
|
|
78
|
+
primitive("files.preflight", "Validate local file paths, size limits, duplicates, zero-byte files, and extension-based MIME/category guesses without opening ChatGPT.", 30000),
|
|
72
79
|
primitive("files.attach", "Attach absolute local file paths through visible ChatGPT upload controls.", 180000),
|
|
73
80
|
primitive("files.downloadLatest", "Download the latest visible ChatGPT file affordance.", 120000),
|
|
81
|
+
primitive("projects.sources.list", "Open or claim a visible ChatGPT Project Sources tab and list source names/statuses without source contents.", 30000),
|
|
82
|
+
primitive("projects.sources.planAdd", "Dry-run an append-only Project Sources file add from explicit local files without opening ChatGPT.", 30000),
|
|
83
|
+
primitive("projects.sources.add", "Append explicit local files to a visible ChatGPT Project Sources list after confirmMutation: true.", 180000),
|
|
74
84
|
primitive("response.copy", "Click Copy response and return clipboard Markdown, with DOM fallback.", 5000),
|
|
75
|
-
primitive("modes.set", "Select a visible model
|
|
85
|
+
primitive("modes.set", "Select a visible model, intelligence, effort, or nested model-version candidate when unambiguous.", 30000),
|
|
76
86
|
primitive("tools.select", "Select a visible ChatGPT tool when unambiguous.", 30000)
|
|
77
87
|
];
|
|
78
88
|
export function commandDescriptors() {
|
|
@@ -186,7 +196,7 @@ function workflowArgs(name) {
|
|
|
186
196
|
prompt: "message to send after files are attached",
|
|
187
197
|
thread: "optional thread selector",
|
|
188
198
|
existingTab: "true or explicit policy to claim a user-open Chrome tab instead of opening a replacement",
|
|
189
|
-
mode: "optional visible mode selection, e.g. {
|
|
199
|
+
mode: "optional visible mode selection, e.g. { model: \"Pro\" } or { intelligence: \"Pro\", modelVersion: \"5.4\" }",
|
|
190
200
|
wait: "true or wait options; defaults to true",
|
|
191
201
|
read: "true or read options such as { format: \"markdown\" }; defaults to Markdown",
|
|
192
202
|
report: "optional redacted report settings"
|
|
@@ -209,7 +219,12 @@ function workflowDefaults(name) {
|
|
|
209
219
|
function diagnosticArgs(name) {
|
|
210
220
|
if (name === "doctor-upload")
|
|
211
221
|
return {};
|
|
212
|
-
return {
|
|
222
|
+
return {
|
|
223
|
+
check: "optional list of readiness checks",
|
|
224
|
+
existingTab: "optional exact existing-tab policy for check: [\"existing_tab\"]",
|
|
225
|
+
files: "optional file paths for check: [\"file_preflight\"]",
|
|
226
|
+
report: "optional report output policy for check: [\"reports\"]"
|
|
227
|
+
};
|
|
213
228
|
}
|
|
214
229
|
function reportArgs(name) {
|
|
215
230
|
if (name === "redacted-run-report")
|
|
@@ -219,16 +234,33 @@ function reportArgs(name) {
|
|
|
219
234
|
function primitiveArgs(name) {
|
|
220
235
|
if (name === "messages.readLatest")
|
|
221
236
|
return { role: "assistant or user", format: "markdown, normalized_text, visible_text, html, blocks, or all" };
|
|
237
|
+
if (name === "artifacts.listLatest")
|
|
238
|
+
return { kind: "artifact kind; currently image", max: "maximum artifacts to return" };
|
|
239
|
+
if (name === "artifacts.wait")
|
|
240
|
+
return { kind: "artifact kind; currently image", afterArtifactCount: "baseline artifact count", requireDownload: "wait until a download affordance is visible" };
|
|
241
|
+
if (name === "artifacts.downloadLatest")
|
|
242
|
+
return { destDir: "download destination directory", prefer: "download_control or visible_image_source" };
|
|
222
243
|
if (name === "response.copy")
|
|
223
244
|
return { prefer: "clipboard or dom", format: "markdown, normalized_text, visible_text, html, blocks, or all" };
|
|
224
245
|
if (name.startsWith("threads.search"))
|
|
225
246
|
return { query: "history search query" };
|
|
247
|
+
if (name === "files.preflight")
|
|
248
|
+
return { paths: "absolute local file paths", maxBytesPerFile: "optional local per-file byte limit", maxTotalBytes: "optional local total byte limit" };
|
|
226
249
|
if (name.startsWith("files.attach"))
|
|
227
250
|
return { paths: "absolute local file paths" };
|
|
251
|
+
if (name === "projects.sources.list")
|
|
252
|
+
return { projectUrl: "ChatGPT Project URL such as https://chatgpt.com/g/g-p-.../project", existingTab: "optional exact existing-tab policy", timeoutMs: "optional browser timeout" };
|
|
253
|
+
if (name === "projects.sources.planAdd")
|
|
254
|
+
return { projectUrl: "ChatGPT Project URL", files: "explicit absolute local file paths", batchSize: "optional upload batch size" };
|
|
255
|
+
if (name === "projects.sources.add")
|
|
256
|
+
return { projectUrl: "ChatGPT Project URL", files: "explicit absolute local file paths", confirmMutation: "must be true to mutate Project Sources", batchSize: "optional upload batch size" };
|
|
228
257
|
if (name === "modes.set") {
|
|
229
258
|
return {
|
|
230
|
-
effort: "visible effort label such as Thinking or Extended",
|
|
231
|
-
|
|
259
|
+
effort: "visible legacy effort label such as Thinking or Extended",
|
|
260
|
+
intelligence: "visible intelligence label such as Medium, High, Extra High, or Pro",
|
|
261
|
+
model: "visible model label such as Pro, GPT-5.5, or another available model",
|
|
262
|
+
modelVersion: "visible nested model version such as 5.5, 5.4, 4.5, or o3",
|
|
263
|
+
version: "alias for modelVersion",
|
|
232
264
|
timeoutMs: "optional timeout for opening and selecting the visible mode menu"
|
|
233
265
|
};
|
|
234
266
|
}
|
|
@@ -237,20 +269,50 @@ function primitiveArgs(name) {
|
|
|
237
269
|
function primitiveExamples(name) {
|
|
238
270
|
if (name === "modes.set") {
|
|
239
271
|
return [
|
|
272
|
+
`await chatgpt.modes.set({ model: "Pro" });`,
|
|
273
|
+
`await chatgpt.modes.set({ intelligence: "Pro", modelVersion: "5.4" });`,
|
|
240
274
|
`await chatgpt.modes.set({ effort: "Thinking" });`,
|
|
241
|
-
`await chatgpt.askWithFiles({ mode: {
|
|
275
|
+
`await chatgpt.askWithFiles({ mode: { model: "Pro" }, files: ["/absolute/host/path.jpg"], prompt: "Describe this image.", wait: true });`
|
|
276
|
+
];
|
|
277
|
+
}
|
|
278
|
+
if (name === "files.preflight") {
|
|
279
|
+
return [
|
|
280
|
+
`await chatgpt.files.preflight({ paths: ["/absolute/host/path.md"] });`
|
|
242
281
|
];
|
|
243
282
|
}
|
|
244
283
|
if (name === "files.attach") {
|
|
245
|
-
return [
|
|
284
|
+
return [
|
|
285
|
+
`await chatgpt.files.attach({ paths: ["/absolute/host/path.jpg"] });`,
|
|
286
|
+
String.raw `// On Windows backend hosts, use paths such as C:\Users\you\Pictures\image.jpg.`
|
|
287
|
+
];
|
|
288
|
+
}
|
|
289
|
+
if (name === "projects.sources.list") {
|
|
290
|
+
return [`await chatgpt.projects.sources.list({ projectUrl: "https://chatgpt.com/g/g-p-example/project" });`];
|
|
291
|
+
}
|
|
292
|
+
if (name === "projects.sources.planAdd") {
|
|
293
|
+
return [`await chatgpt.projects.sources.planAdd({ projectUrl: "https://chatgpt.com/g/g-p-example/project", files: ["/absolute/host/path.md"] });`];
|
|
294
|
+
}
|
|
295
|
+
if (name === "projects.sources.add") {
|
|
296
|
+
return [`await chatgpt.projects.sources.add({ projectUrl: "https://chatgpt.com/g/g-p-example/project", files: ["/absolute/host/path.md"], confirmMutation: true });`];
|
|
297
|
+
}
|
|
298
|
+
if (name.startsWith("artifacts.")) {
|
|
299
|
+
return [`await chatgpt.artifacts.downloadLatest({ destDir: "/absolute/host/output" });`];
|
|
246
300
|
}
|
|
247
301
|
return [];
|
|
248
302
|
}
|
|
249
303
|
function primitiveBlockers(name) {
|
|
304
|
+
if (name === "files.preflight")
|
|
305
|
+
return ["not_found", "permission", "upload_failed"];
|
|
250
306
|
if (name.startsWith("files.attach"))
|
|
251
307
|
return ["browser_bridge_unavailable", "login_required", "permission", "upload_failed"];
|
|
252
308
|
if (name.startsWith("files.download"))
|
|
253
309
|
return ["browser_bridge_unavailable", "login_required", "download_unavailable"];
|
|
310
|
+
if (name === "projects.sources.planAdd")
|
|
311
|
+
return ["not_found", "permission", "upload_failed"];
|
|
312
|
+
if (name.startsWith("projects.sources."))
|
|
313
|
+
return ["browser_bridge_unavailable", "login_required", "selector_drift", "confirmation", "permission", "upload_failed"];
|
|
314
|
+
if (name.startsWith("artifacts."))
|
|
315
|
+
return ["browser_bridge_unavailable", "login_required", "artifact_unavailable", "artifact_selector_drift", "artifact_download_unavailable"];
|
|
254
316
|
if (name.startsWith("modes.") || name.startsWith("tools."))
|
|
255
317
|
return ["browser_bridge_unavailable", "login_required", "selector_drift"];
|
|
256
318
|
return commonBlockers();
|
|
@@ -1,14 +1,23 @@
|
|
|
1
|
+
import { type IntegritySidecar } from "../safety/untrusted-output.js";
|
|
1
2
|
import type { CommandResult, RuntimeEnv } from "../types.js";
|
|
3
|
+
export type RunReportIntegrityOptions = {
|
|
4
|
+
inputPaths?: string[];
|
|
5
|
+
prompt?: string;
|
|
6
|
+
outputText?: string;
|
|
7
|
+
};
|
|
2
8
|
export type RunReportOptions = {
|
|
3
9
|
enabled?: boolean;
|
|
4
10
|
destDir?: string;
|
|
5
11
|
basename?: string;
|
|
6
12
|
includeContent?: boolean;
|
|
7
13
|
maxPreviewChars?: number;
|
|
14
|
+
integrity?: boolean | RunReportIntegrityOptions;
|
|
8
15
|
};
|
|
9
16
|
export type RunReportData = {
|
|
10
17
|
path: string;
|
|
11
18
|
bytes: number;
|
|
12
19
|
includeContent: boolean;
|
|
20
|
+
metaPath?: string;
|
|
21
|
+
integrity?: Pick<IntegritySidecar, "schemaVersion" | "target" | "prompt" | "output" | "inputs">;
|
|
13
22
|
};
|
|
14
23
|
export declare function createRunReport(env: RuntimeEnv, result: CommandResult<unknown>, options?: RunReportOptions): Promise<CommandResult<RunReportData>>;
|
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
import { mkdir, stat, writeFile } from "node:fs/promises";
|
|
2
1
|
import { join } from "node:path";
|
|
3
2
|
import { resultError, resultOk } from "../errors.js";
|
|
4
3
|
import { redactReportValue } from "../safety/report-redaction.js";
|
|
4
|
+
import { writeFileAtomicNoOverwrite, writeJsonArtifactWithIntegrity } from "../safety/untrusted-output.js";
|
|
5
5
|
import { contextFromPage } from "./context.js";
|
|
6
6
|
export async function createRunReport(env, result, options = {}) {
|
|
7
7
|
try {
|
|
8
8
|
const destDir = options.destDir ?? "reports/runs";
|
|
9
|
-
|
|
10
|
-
const
|
|
9
|
+
const now = env.now?.() ?? new Date();
|
|
10
|
+
const createdAt = now.toISOString();
|
|
11
|
+
const stamp = createdAt.replaceAll(":", "-").replaceAll(".", "-");
|
|
11
12
|
const safeBase = sanitizeBasename(options.basename ?? "chatgpt-run-report");
|
|
12
13
|
const path = join(destDir, `${stamp}-${safeBase}.json`);
|
|
13
14
|
const includeContent = options.includeContent === true;
|
|
@@ -31,9 +32,36 @@ export async function createRunReport(env, result, options = {}) {
|
|
|
31
32
|
})),
|
|
32
33
|
data: redactReportValue(result.data, options)
|
|
33
34
|
};
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
if (options.integrity === false) {
|
|
36
|
+
const payload = `${JSON.stringify(report, null, 2)}\n`;
|
|
37
|
+
await writeFileAtomicNoOverwrite(path, payload);
|
|
38
|
+
return resultOk({ path, bytes: Buffer.byteLength(payload, "utf8"), includeContent }, await contextFromPage(env.page));
|
|
39
|
+
}
|
|
40
|
+
const integrity = integrityOptions(result, options.integrity);
|
|
41
|
+
const writeOptions = { createdAt };
|
|
42
|
+
if (integrity.prompt !== undefined)
|
|
43
|
+
writeOptions.prompt = integrity.prompt;
|
|
44
|
+
if (integrity.outputText !== undefined)
|
|
45
|
+
writeOptions.outputText = integrity.outputText;
|
|
46
|
+
if (integrity.inputPaths !== undefined)
|
|
47
|
+
writeOptions.inputPaths = integrity.inputPaths;
|
|
48
|
+
const saved = await writeJsonArtifactWithIntegrity(path, report, writeOptions);
|
|
49
|
+
const reportIntegrity = {
|
|
50
|
+
schemaVersion: saved.sidecar.schemaVersion,
|
|
51
|
+
target: saved.sidecar.target,
|
|
52
|
+
inputs: saved.sidecar.inputs
|
|
53
|
+
};
|
|
54
|
+
if (saved.sidecar.prompt !== undefined)
|
|
55
|
+
reportIntegrity.prompt = saved.sidecar.prompt;
|
|
56
|
+
if (saved.sidecar.output !== undefined)
|
|
57
|
+
reportIntegrity.output = saved.sidecar.output;
|
|
58
|
+
return resultOk({
|
|
59
|
+
path,
|
|
60
|
+
bytes: saved.bytes,
|
|
61
|
+
includeContent,
|
|
62
|
+
metaPath: saved.metaPath,
|
|
63
|
+
integrity: reportIntegrity
|
|
64
|
+
}, await contextFromPage(env.page));
|
|
37
65
|
}
|
|
38
66
|
catch (error) {
|
|
39
67
|
return resultError(error instanceof Error ? error : new Error(String(error)), await contextFromPage(env.page));
|
|
@@ -45,3 +73,52 @@ function sanitizeBasename(name) {
|
|
|
45
73
|
.replace(/^-+|-+$/g, "")
|
|
46
74
|
|| "chatgpt-run-report";
|
|
47
75
|
}
|
|
76
|
+
function integrityOptions(result, options) {
|
|
77
|
+
if (typeof options === "object") {
|
|
78
|
+
const normalized = {
|
|
79
|
+
inputPaths: [...new Set(options.inputPaths ?? [])]
|
|
80
|
+
};
|
|
81
|
+
const prompt = options.prompt ?? promptFromResult(result);
|
|
82
|
+
const outputText = options.outputText ?? outputTextFromResult(result);
|
|
83
|
+
if (prompt !== undefined)
|
|
84
|
+
normalized.prompt = prompt;
|
|
85
|
+
if (outputText !== undefined)
|
|
86
|
+
normalized.outputText = outputText;
|
|
87
|
+
return normalized;
|
|
88
|
+
}
|
|
89
|
+
const normalized = {
|
|
90
|
+
inputPaths: []
|
|
91
|
+
};
|
|
92
|
+
const prompt = promptFromResult(result);
|
|
93
|
+
const outputText = outputTextFromResult(result);
|
|
94
|
+
if (prompt !== undefined)
|
|
95
|
+
normalized.prompt = prompt;
|
|
96
|
+
if (outputText !== undefined)
|
|
97
|
+
normalized.outputText = outputText;
|
|
98
|
+
return normalized;
|
|
99
|
+
}
|
|
100
|
+
function promptFromResult(result) {
|
|
101
|
+
return findStringByKey(result.data, new Set(["prompt", "input", "userTurnText"]));
|
|
102
|
+
}
|
|
103
|
+
function outputTextFromResult(result) {
|
|
104
|
+
if (typeof result.output_text === "string")
|
|
105
|
+
return result.output_text;
|
|
106
|
+
return findStringByKey(result.data, new Set(["responseText", "markdown", "text", "normalizedText", "visibleText"]));
|
|
107
|
+
}
|
|
108
|
+
function findStringByKey(value, keys) {
|
|
109
|
+
if (!isRecord(value))
|
|
110
|
+
return undefined;
|
|
111
|
+
for (const [key, child] of Object.entries(value)) {
|
|
112
|
+
if (keys.has(key) && typeof child === "string" && child.length > 0)
|
|
113
|
+
return child;
|
|
114
|
+
}
|
|
115
|
+
for (const child of Object.values(value)) {
|
|
116
|
+
const nested = findStringByKey(child, keys);
|
|
117
|
+
if (nested !== undefined)
|
|
118
|
+
return nested;
|
|
119
|
+
}
|
|
120
|
+
return undefined;
|
|
121
|
+
}
|
|
122
|
+
function isRecord(value) {
|
|
123
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
124
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { readSystemClipboard, waitForClipboardChange } from "../browser/clipboard.js";
|
|
2
|
+
import { readAssistantGenerationState } from "../dom/generation-state.js";
|
|
2
3
|
import { formatClipboardMarkdown, normalizeResponseFormat } from "../dom/message-format.js";
|
|
3
4
|
import { resultError, resultOk } from "../errors.js";
|
|
4
5
|
import { readLatestMessage, readMessages } from "../dom/messages.js";
|
|
@@ -13,6 +14,31 @@ export async function copyResponse(env, args = {}) {
|
|
|
13
14
|
}
|
|
14
15
|
const page = env.page;
|
|
15
16
|
try {
|
|
17
|
+
if (isLatestSelection(args.which)) {
|
|
18
|
+
const generation = await readAssistantGenerationState(page);
|
|
19
|
+
if (generation.active || generation.stopped) {
|
|
20
|
+
const latest = await readSelectedAssistantMessage(page, args.which, args.format ?? "markdown").catch(() => undefined);
|
|
21
|
+
const warning = generation.active
|
|
22
|
+
? "Response is still generating; copied content may be partial."
|
|
23
|
+
: "Response appears to have been stopped before completion; copied content may be partial.";
|
|
24
|
+
const fallbackReason = generation.active
|
|
25
|
+
? "Response is still generating; returned DOM-derived partial content."
|
|
26
|
+
: "Response appears to have been stopped before completion; returned DOM-derived partial content.";
|
|
27
|
+
const data = latest === undefined ? undefined : copiedResponseFromExtracted(latest, "dom", fallbackReason);
|
|
28
|
+
const result = {
|
|
29
|
+
ok: false,
|
|
30
|
+
status: "partial",
|
|
31
|
+
warnings: [
|
|
32
|
+
warning,
|
|
33
|
+
...generation.signals.map(signal => `Generation state signal: ${signal}`)
|
|
34
|
+
],
|
|
35
|
+
context: await contextFromPage(page)
|
|
36
|
+
};
|
|
37
|
+
if (data !== undefined)
|
|
38
|
+
result.data = data;
|
|
39
|
+
return withCommandOutputText(result);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
16
42
|
if (args.prefer !== "dom") {
|
|
17
43
|
const before = await readClipboard(env);
|
|
18
44
|
const buttons = copyResponseButtons(page);
|
|
@@ -73,6 +99,9 @@ export async function copyResponse(env, args = {}) {
|
|
|
73
99
|
return resultError(error instanceof Error ? error : new Error(String(error)), await contextFromPage(page));
|
|
74
100
|
}
|
|
75
101
|
}
|
|
102
|
+
function isLatestSelection(which) {
|
|
103
|
+
return which === undefined || which === "latest";
|
|
104
|
+
}
|
|
76
105
|
function readClipboard(env) {
|
|
77
106
|
return env.clipboard?.read() ?? readSystemClipboard();
|
|
78
107
|
}
|
|
@@ -97,6 +126,8 @@ function copiedResponseFromExtracted(latest, source, fallbackReason) {
|
|
|
97
126
|
};
|
|
98
127
|
if (latest.fidelity !== undefined)
|
|
99
128
|
data.fidelity = latest.fidelity;
|
|
129
|
+
if (latest.captureLimit !== undefined)
|
|
130
|
+
data.captureLimit = latest.captureLimit;
|
|
100
131
|
if (latest.warnings !== undefined || fallbackReason !== undefined) {
|
|
101
132
|
data.warnings = [...(latest.warnings ?? []), ...(fallbackReason === undefined ? [] : [fallbackReason])];
|
|
102
133
|
}
|
|
@@ -110,6 +141,8 @@ function mergeResponseMetadata(data, latest) {
|
|
|
110
141
|
return;
|
|
111
142
|
if (latest.markdown !== undefined && data.markdown === undefined)
|
|
112
143
|
data.markdown = latest.markdown;
|
|
144
|
+
if (latest.captureLimit !== undefined)
|
|
145
|
+
data.captureLimit = latest.captureLimit;
|
|
113
146
|
if (latest.visibleText !== undefined)
|
|
114
147
|
data.visibleText = latest.visibleText;
|
|
115
148
|
if (latest.normalizedText !== undefined)
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import { downloadLatestArtifact, listLatestArtifacts, waitForArtifact } from "./artifacts.js";
|
|
1
2
|
import { attachFiles, downloadLatestFile } from "./files.js";
|
|
3
|
+
import { addProjectSources, buildProjectSourceAddPlan, listProjectSources } from "./project-sources.js";
|
|
2
4
|
import { askMessage, composeMessage, readLatest, submitMessage, waitAndRead, waitForMessage } from "./messages.js";
|
|
3
5
|
import { copyResponse } from "./response-actions.js";
|
|
4
6
|
import { bootstrap } from "./session.js";
|
|
@@ -59,10 +61,22 @@ export async function executeStep(step, env, previousResults) {
|
|
|
59
61
|
return readLatest(env, step.args);
|
|
60
62
|
case "messages.waitAndRead":
|
|
61
63
|
return waitAndRead(env, step.args);
|
|
64
|
+
case "artifacts.listLatest":
|
|
65
|
+
return listLatestArtifacts(env, step.args);
|
|
66
|
+
case "artifacts.wait":
|
|
67
|
+
return waitForArtifact(env, step.args);
|
|
68
|
+
case "artifacts.downloadLatest":
|
|
69
|
+
return downloadLatestArtifact(env, step.args);
|
|
62
70
|
case "files.attach":
|
|
63
71
|
return attachFiles(env, step.args);
|
|
64
72
|
case "files.downloadLatest":
|
|
65
73
|
return downloadLatestFile(env, step.args);
|
|
74
|
+
case "projects.sources.list":
|
|
75
|
+
return listProjectSources(env, step.args);
|
|
76
|
+
case "projects.sources.planAdd":
|
|
77
|
+
return buildProjectSourceAddPlan(env, step.args);
|
|
78
|
+
case "projects.sources.add":
|
|
79
|
+
return addProjectSources(env, step.args);
|
|
66
80
|
case "response.copy":
|
|
67
81
|
return copyResponse(env, step.args);
|
|
68
82
|
case "modes.set":
|
|
@@ -2,6 +2,7 @@ import { parseConversationId, readPageState } from "../browser/page-state.js";
|
|
|
2
2
|
import { resultError, resultOk } from "../errors.js";
|
|
3
3
|
import { countPageMessages, readLatestMessageText } from "../dom/messages.js";
|
|
4
4
|
import { requiredLocator, searchChatsButton, searchChatsInput, newChatButton } from "../dom/selectors.js";
|
|
5
|
+
import { anyLabelPattern, localeLabels } from "../dom/locale-labels.js";
|
|
5
6
|
import { normalizeWhitespace, stripTags } from "../dom/visible-text.js";
|
|
6
7
|
import { contextFromPage } from "./context.js";
|
|
7
8
|
import { bootstrap } from "./session.js";
|
|
@@ -237,7 +238,7 @@ async function openSearchUI(page) {
|
|
|
237
238
|
async function fillSearchQuery(page, query) {
|
|
238
239
|
const attempts = [
|
|
239
240
|
async () => searchChatsInput(page).fill?.(query),
|
|
240
|
-
async () => page.getByRole?.("textbox", { name:
|
|
241
|
+
async () => page.getByRole?.("textbox", { name: anyLabelPattern(localeLabels.searchChatsButton) }).fill?.(query),
|
|
241
242
|
async () => page.getByRole?.("textbox", { name: /Search chats/i }).fill?.(query),
|
|
242
243
|
async () => requiredLocator(page, "input[placeholder*='Search'], [role='dialog'] input").fill?.(query)
|
|
243
244
|
];
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export async function withTimeout(promise, timeoutMs, message) {
|
|
2
|
+
let timeout;
|
|
3
|
+
try {
|
|
4
|
+
return await Promise.race([
|
|
5
|
+
promise,
|
|
6
|
+
new Promise((_resolve, reject) => {
|
|
7
|
+
timeout = setTimeout(() => reject(new Error(message)), Math.max(0, timeoutMs));
|
|
8
|
+
})
|
|
9
|
+
]);
|
|
10
|
+
}
|
|
11
|
+
finally {
|
|
12
|
+
if (timeout !== undefined)
|
|
13
|
+
clearTimeout(timeout);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
export function localGuardTimeout(timeoutMs, capMs) {
|
|
17
|
+
return Math.max(1, Math.min(timeoutMs ?? capMs, capMs));
|
|
18
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { CommandContext, CommandResult, ExistingTabDiagnostics } from "../types.js";
|
|
2
|
+
type RemediationStep = NonNullable<NonNullable<CommandResult["blocker"]>["remediation"]>[number];
|
|
3
|
+
type VisibleCandidate = NonNullable<NonNullable<CommandResult["blocker"]>["candidates"]>[number];
|
|
4
|
+
export type BlockerSeverity = "info" | "warning" | "action_required" | "blocked";
|
|
5
|
+
export type BlockerCategory = "environment" | "auth" | "permission" | "ui_drift" | "user_confirmation" | "targeting" | "runtime" | "not_found" | "artifact" | "download" | "upload" | "unknown";
|
|
6
|
+
export type BlockerRetryGuidance = {
|
|
7
|
+
safe: true;
|
|
8
|
+
when: string;
|
|
9
|
+
command?: string;
|
|
10
|
+
} | {
|
|
11
|
+
safe: false;
|
|
12
|
+
reason: string;
|
|
13
|
+
};
|
|
14
|
+
export type BlockerResumeGuidance = {
|
|
15
|
+
supported: true;
|
|
16
|
+
stateId?: string;
|
|
17
|
+
command?: string;
|
|
18
|
+
} | {
|
|
19
|
+
supported: false;
|
|
20
|
+
reason: string;
|
|
21
|
+
};
|
|
22
|
+
export type BlockerExplanation = {
|
|
23
|
+
kind: string;
|
|
24
|
+
code?: string;
|
|
25
|
+
title: string;
|
|
26
|
+
summary: string;
|
|
27
|
+
severity: BlockerSeverity;
|
|
28
|
+
category: BlockerCategory;
|
|
29
|
+
userActionRequired: boolean;
|
|
30
|
+
retry: BlockerRetryGuidance;
|
|
31
|
+
resume: BlockerResumeGuidance;
|
|
32
|
+
remediation: RemediationStep[];
|
|
33
|
+
candidates?: VisibleCandidate[];
|
|
34
|
+
context?: {
|
|
35
|
+
command?: string;
|
|
36
|
+
url?: string;
|
|
37
|
+
conversationId?: string;
|
|
38
|
+
tabId?: string;
|
|
39
|
+
};
|
|
40
|
+
diagnostics?: {
|
|
41
|
+
existingTab?: ExistingTabDiagnostics;
|
|
42
|
+
};
|
|
43
|
+
nextCommands: string[];
|
|
44
|
+
markdown: string;
|
|
45
|
+
};
|
|
46
|
+
export type ExplainBlockerOptions = {
|
|
47
|
+
command?: string;
|
|
48
|
+
context?: Partial<CommandContext>;
|
|
49
|
+
stateId?: string;
|
|
50
|
+
nextCommands?: string[];
|
|
51
|
+
};
|
|
52
|
+
type Blocker = NonNullable<CommandResult["blocker"]>;
|
|
53
|
+
export declare function explainCommandBlocker(resultOrBlocker: CommandResult<unknown> | Blocker | undefined, options?: ExplainBlockerOptions): BlockerExplanation;
|
|
54
|
+
export {};
|