@youdie006/prodex 0.23.0 → 0.24.0
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/dist/chatgpt-browser.js +6 -1
- package/dist/cli-help.js +10 -0
- package/dist/cli-pro.js +29 -5
- package/dist/cli.js +14 -3
- package/dist/mcp.js +11 -1
- package/docs/claude.md +4 -1
- package/docs/clients.md +7 -0
- package/package.json +1 -1
package/dist/chatgpt-browser.js
CHANGED
|
@@ -3082,6 +3082,7 @@ export function transcriptAnswerExpression(conversationId) {
|
|
|
3082
3082
|
}
|
|
3083
3083
|
// ChatGPT marks citations with private-use delimiters (U+E200 opens, U+E202
|
|
3084
3084
|
// separates, U+E201 closes) and keeps the real sources in content_references.
|
|
3085
|
+
const CITATION_DELIMITER_PATTERN = /[\uE200-\uE206]/;
|
|
3085
3086
|
const CITATION_MARKER_PATTERN = /\uE200[^\uE200-\uE206]*(?:[\uE202\uE204-\uE206][^\uE200-\uE206]*)*[\uE201\uE203]/g;
|
|
3086
3087
|
/**
|
|
3087
3088
|
* Turn those markers into ordinary markdown links, so a saved answer keeps the
|
|
@@ -3091,7 +3092,11 @@ const CITATION_MARKER_PATTERN = /\uE200[^\uE200-\uE206]*(?:[\uE202\uE204-\uE206]
|
|
|
3091
3092
|
export function resolveTranscriptCitations(text, references = []) {
|
|
3092
3093
|
const byMarker = new Map();
|
|
3093
3094
|
for (const reference of references) {
|
|
3094
|
-
|
|
3095
|
+
// Only substitute on text that IS a marker. A `sources_footnote` reference
|
|
3096
|
+
// carries matched_text " " - a single space - and substituting on that
|
|
3097
|
+
// replaced every space in the document, fusing a 47k-character report into
|
|
3098
|
+
// one run-on word.
|
|
3099
|
+
if (reference && typeof reference.matched_text === "string" && CITATION_DELIMITER_PATTERN.test(reference.matched_text)) {
|
|
3095
3100
|
byMarker.set(reference.matched_text, reference);
|
|
3096
3101
|
}
|
|
3097
3102
|
}
|
package/dist/cli-help.js
CHANGED
|
@@ -257,6 +257,14 @@ export function printProBrowserHelp(stdout, sourceCli) {
|
|
|
257
257
|
const modelsUsage = sourceCli
|
|
258
258
|
? `${cli} pro browser models${sourceCliOption} [--port 9333] [--timeout-ms 15000]`
|
|
259
259
|
: "prodex pro browser models [--source-cli /absolute/path/to/dist/cli.js] [--port 9333] [--timeout-ms 15000]";
|
|
260
|
+
const projectsUsage = sourceCli
|
|
261
|
+
? `${cli} pro browser projects${sourceCliOption} [--port 9333] [--timeout-ms 15000] # read-only: exact sidebar project names`
|
|
262
|
+
: "prodex pro browser projects [--source-cli /absolute/path/to/dist/cli.js] [--port 9333] [--timeout-ms 15000] # read-only: exact sidebar project names";
|
|
263
|
+
// A send that outlives its budget is not a lost answer, but only if agents
|
|
264
|
+
// know this exists - and this help is where onboarding sends them.
|
|
265
|
+
const recoverUsage = sourceCli
|
|
266
|
+
? `${cli} pro browser recover${sourceCliOption} [--cwd /absolute/path/to/repo] [--port 9333] --target-url <thread-url> [--timeout-ms 60000] # fetch a finished answer (deep research reports too) from a thread whose send timed out`
|
|
267
|
+
: "prodex pro browser recover [--source-cli /absolute/path/to/dist/cli.js] [--cwd /absolute/path/to/repo] [--port 9333] --target-url <thread-url> [--timeout-ms 60000] # fetch a finished answer (deep research reports too) from a thread whose send timed out";
|
|
260
268
|
stdout(`${cli} pro browser
|
|
261
269
|
|
|
262
270
|
Commands:
|
|
@@ -264,7 +272,9 @@ Commands:
|
|
|
264
272
|
${checkUsage}
|
|
265
273
|
${smokeUsage}
|
|
266
274
|
${modelsUsage}
|
|
275
|
+
${projectsUsage}
|
|
267
276
|
${askUsage}
|
|
277
|
+
${recoverUsage}
|
|
268
278
|
|
|
269
279
|
Visible-browser sends require a manual browser session and stop on login, captcha, Cloudflare, permission, rate-limit, or usage-limit blockers.
|
|
270
280
|
Model/project selection (ask):
|
package/dist/cli-pro.js
CHANGED
|
@@ -1155,12 +1155,36 @@ Rules:
|
|
|
1155
1155
|
Write the debate in the language of the topic.`;
|
|
1156
1156
|
}
|
|
1157
1157
|
/**
|
|
1158
|
-
* MCP-
|
|
1159
|
-
*
|
|
1160
|
-
*
|
|
1161
|
-
*
|
|
1162
|
-
* never on the HTTP MCP surface, which is exposed to ChatGPT itself.
|
|
1158
|
+
* MCP-side counterpart to `pro browser recover`. A consult that outlives its
|
|
1159
|
+
* budget hands back the thread it landed in, but until now the only way to act
|
|
1160
|
+
* on that was a shell command - which an agent reaching prodex over MCP may not
|
|
1161
|
+
* be able to run. Recovery has to be reachable the same way the consult was.
|
|
1163
1162
|
*/
|
|
1163
|
+
export async function performBrowserRecoverForMcp(cwd, input) {
|
|
1164
|
+
const stdoutLines = [];
|
|
1165
|
+
const stderrLines = [];
|
|
1166
|
+
const argv = [
|
|
1167
|
+
"browser",
|
|
1168
|
+
"recover",
|
|
1169
|
+
"--target-url",
|
|
1170
|
+
input.thread,
|
|
1171
|
+
...(input.timeout_ms !== undefined ? ["--timeout-ms", String(input.timeout_ms)] : [])
|
|
1172
|
+
];
|
|
1173
|
+
await runProCommand(argv, {
|
|
1174
|
+
cwd,
|
|
1175
|
+
stdout: (line) => stdoutLines.push(line),
|
|
1176
|
+
stderr: (line) => stderrLines.push(line)
|
|
1177
|
+
}, async () => 0);
|
|
1178
|
+
const header = stdoutLines[0] ?? "";
|
|
1179
|
+
const [taskId = "", status = "", thread = ""] = header.split("\t");
|
|
1180
|
+
return {
|
|
1181
|
+
task_id: taskId,
|
|
1182
|
+
status,
|
|
1183
|
+
thread,
|
|
1184
|
+
answer: stdoutLines.slice(2).join("\n"),
|
|
1185
|
+
notes: stderrLines
|
|
1186
|
+
};
|
|
1187
|
+
}
|
|
1164
1188
|
export async function performBrowserConsultForMcp(cwd, input, onProgress) {
|
|
1165
1189
|
const stdoutLines = [];
|
|
1166
1190
|
const stderrLines = [];
|
package/dist/cli.js
CHANGED
|
@@ -19,7 +19,7 @@ import { printHelpIfRequested, assertNoExtraArgs, assertOnlyOptions, formatCliCo
|
|
|
19
19
|
import { listRawResultsForInspection, listTasksForInspection, runReceiptsCommand, runResultsCommand, runSessionsCommand, runTasksCommand } from "./cli-ledger.js";
|
|
20
20
|
import { isMissingFileError, errorMessage, formatBrowserCheckCommand, formatBrowserLoginCommand, formatInitCommand, formatReleaseStatusCommand, formatSetupCommand, sourceAwareReleaseMessage, sourceAwareSetupMessage } from "./cli-shared.js";
|
|
21
21
|
import { TOKEN_BEARING_MCP_URL_AUTHORITY_WARNING, redactServerUrl, runInitCommand, runSetupCommand, runStartCommand, runStatusCommand, runTunnelCommand } from "./cli-server.js";
|
|
22
|
-
import { assertNoMissingTerminalConsultResults, assertNoOrphanConsultResults, formatConfigWarningLine, isConsultRecord, performBrowserConsultForMcp, runAskProCommand, runChatgptCommand, runConsultsCommand, runProCommand } from "./cli-pro.js";
|
|
22
|
+
import { assertNoMissingTerminalConsultResults, assertNoOrphanConsultResults, formatConfigWarningLine, isConsultRecord, performBrowserConsultForMcp, performBrowserRecoverForMcp, runAskProCommand, runChatgptCommand, runConsultsCommand, runProCommand } from "./cli-pro.js";
|
|
23
23
|
import { CLI_VERSION, printClaudeHelp, printDoctorHelp, printHelp, printMcpHelp, printOnboardHelp, printProjectHelp, printReleaseHelp } from "./cli-help.js";
|
|
24
24
|
const execFileAsync = promisify(execFile);
|
|
25
25
|
const packageRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
@@ -208,7 +208,8 @@ export async function runCli(args, io = defaultIo()) {
|
|
|
208
208
|
// pro_consult is stdio-only: the HTTP MCP surface is exposed to ChatGPT
|
|
209
209
|
// itself (and possibly a tunnel) and must never drive the user's browser.
|
|
210
210
|
await runMcpServer(mcpCwd, {
|
|
211
|
-
browserConsult: (input, onProgress) => performBrowserConsultForMcp(mcpCwd, input, onProgress)
|
|
211
|
+
browserConsult: (input, onProgress) => performBrowserConsultForMcp(mcpCwd, input, onProgress),
|
|
212
|
+
browserRecover: (input) => performBrowserRecoverForMcp(mcpCwd, input)
|
|
212
213
|
});
|
|
213
214
|
return 0;
|
|
214
215
|
}
|
|
@@ -322,11 +323,21 @@ repo: ${cwd}
|
|
|
322
323
|
${cli} pro browser check${sourceCliOption} --cwd ${quotedCwd}
|
|
323
324
|
${cli} pro browser smoke${sourceCliOption} --cwd ${quotedCwd}
|
|
324
325
|
Sharing the browser with other agents? Sends queue behind an in-flight response automatically; pass --busy-wait-ms 0 to fail fast instead.
|
|
326
|
+
Hand ChatGPT a real file - the only way it can open a pdf, pptx, xlsx or image:
|
|
327
|
+
${cli} ask --cwd ${quotedCwd} --attach deck.pptx "Review slides 40-60" # uploads the file itself
|
|
328
|
+
${cli} ask --cwd ${quotedCwd} --file notes.md "Summarize" # pastes a text file's CONTENTS into the prompt
|
|
329
|
+
Both are restricted to paths inside the repo. Repeat either flag for several files.
|
|
330
|
+
Turn on a composer tool for one send:
|
|
331
|
+
${cli} ask --cwd ${quotedCwd} --tool web-search "What shipped in Node 24?" # current facts with sources
|
|
332
|
+
${cli} ask --cwd ${quotedCwd} --tool deep-research "Compare managed Postgres providers" # full browsed report; runs ~10 minutes, budget rises to 30
|
|
333
|
+
Any other label the composer menu shows works too, so a tool ChatGPT adds later needs no prodex release.
|
|
334
|
+
A send that outlives its budget did not lose the answer - ChatGPT usually finishes after prodex stops waiting:
|
|
335
|
+
${cli} pro browser recover --target-url <thread-url> --cwd ${quotedCwd} # fetches the finished answer (deep research reports too) and records it
|
|
325
336
|
|
|
326
337
|
2. Let coding agents consult ChatGPT (stdio MCP: Claude, Codex, Cursor, ...):
|
|
327
338
|
${cli} claude config --cwd ${quotedCwd}${sourceCliOption}
|
|
328
339
|
${cli} claude prompt --cwd ${quotedCwd}${sourceCliOption}
|
|
329
|
-
Agents get the bridge/ledger tools plus pro_consult (ask ChatGPT Pro directly; see docs/clients.md for Codex timeout and approval notes).
|
|
340
|
+
Agents get the bridge/ledger tools plus pro_consult (ask ChatGPT Pro directly; see docs/clients.md for Codex timeout and approval notes) and pro_recover (collect an answer that finished after a consult stopped waiting - including a deep research report).
|
|
330
341
|
Saved setup defaults (--model/--project) apply to agent consults too - pin them once per repo so consults stop landing in the general chat list.
|
|
331
342
|
Agents often run the MCP as \`prodex mcp\` with no --cwd, which misses a per-repo default. For a default that applies from ANY directory, set PRODEX_DEFAULT_PROJECT and PRODEX_DEFAULT_MODEL (in the agent's MCP env block, or your shell) to YOUR project/model. No project? Consults just go to the general chat. List your exact project names with \`${cli} pro browser projects\`.
|
|
332
343
|
${cli} pro debate-prompt --topic "your question"${sourceCliOption} # structured GPT Pro debate prompt for your agent
|
package/dist/mcp.js
CHANGED
|
@@ -154,7 +154,7 @@ export function createServer(cwd = process.cwd(), options = {}) {
|
|
|
154
154
|
.array(McpShortTextSchema)
|
|
155
155
|
.max(4)
|
|
156
156
|
.optional()
|
|
157
|
-
.describe("ChatGPT composer tools to enable for this consult: \"deep-research\" (a
|
|
157
|
+
.describe("ChatGPT composer tools to enable for this consult: \"deep-research\" (a browsed report; prodex presses start and waits out the run, which takes about ten minutes, so the timeout rises to 30 minutes automatically and the FULL report comes back as the answer - if the budget still runs out, the blocker carries the thread and pro_recover collects the report later), \"web-search\" (current facts, with the sources kept as links), \"create-image\". Deep research sometimes replies with a CLARIFYING QUESTION instead; answer it with a normal follow-up consult in the same thread."),
|
|
158
158
|
attach: z
|
|
159
159
|
.array(McpShortTextSchema)
|
|
160
160
|
.max(10)
|
|
@@ -187,6 +187,16 @@ export function createServer(cwd = process.cwd(), options = {}) {
|
|
|
187
187
|
return asText(await browserConsult(input, onProgress));
|
|
188
188
|
});
|
|
189
189
|
}
|
|
190
|
+
const browserRecover = options.browserRecover;
|
|
191
|
+
if (browserRecover) {
|
|
192
|
+
server.registerTool("pro_recover", {
|
|
193
|
+
description: "Fetch a ChatGPT answer that finished AFTER a consult stopped waiting, and record it as a normal consult receipt. Use this whenever pro_consult came back with a timeout or a still-running blocker: those carry the thread URL, and the answer is almost always sitting in that thread. This is also how a deep research report is collected - a research run takes about ten minutes and keeps going even when the consult that started it has already returned. Reading is cheap and does not send anything, so it is safe to retry.",
|
|
194
|
+
inputSchema: {
|
|
195
|
+
thread: McpShortTextSchema.min(1).describe("The ChatGPT conversation URL from the blocker (its `thread` field)."),
|
|
196
|
+
timeout_ms: z.number().int().positive().max(600_000).optional()
|
|
197
|
+
}
|
|
198
|
+
}, async (input) => asText(await browserRecover(input)));
|
|
199
|
+
}
|
|
190
200
|
return server;
|
|
191
201
|
}
|
|
192
202
|
export async function runMcpServer(cwd = process.cwd(), options = {}) {
|
package/docs/claude.md
CHANGED
|
@@ -99,6 +99,7 @@ The server currently exposes ledger-first tools:
|
|
|
99
99
|
- `repo_write_file_apply`
|
|
100
100
|
- `repo_stage_reviewed_paths`
|
|
101
101
|
- `pro_consult`
|
|
102
|
+
- `pro_recover`
|
|
102
103
|
|
|
103
104
|
`bridge_complete_task` and `bridge_block_task` close tasks by writing durable `.bridge/results` records; they do not modify repo files. `bridge_fetch_result_artifact` only returns text artifacts that are listed on a result record and stored under `.bridge/artifacts/pro-consults/` or `.bridge/artifacts/results/`; it does not expose arbitrary `.bridge/artifacts` files. Newly finalized result artifacts record a sha256, and fetch rejects the artifact if its content changed afterward. The bridge rejects oversized result artifacts before task finalization; if a Pro browser answer is too large for `bridge_fetch_result_artifact`, it stays in the result summary with `answer_artifact_warning` instead of listing an unfetchable artifact.
|
|
104
105
|
|
|
@@ -106,7 +107,9 @@ Write tools are narrow and receipt-gated, and they require a git worktree with a
|
|
|
106
107
|
|
|
107
108
|
`pro_consult` lets Claude ask your logged-in ChatGPT (Pro) directly: it drives the same explicit visible-browser consult as `prodex pro browser ask` (human-paced, blocker-gated, receipt-recorded, answer saved under `.bridge/artifacts/pro-consults/`) and can take minutes for Pro extended reasoning. It requires a prior `prodex pro browser login` session and is registered only on the local stdio MCP server — the HTTP MCP surface never exposes it, so nothing reachable through a tunnel or ChatGPT itself can drive your browser.
|
|
108
109
|
|
|
109
|
-
|
|
110
|
+
`pro_recover` collects an answer that finished after a consult stopped waiting. A timed-out or still-running consult returns the thread it landed in, and the answer is almost always sitting there; this is also how a deep research report is collected, since a research run keeps going after the consult that started it has returned. It reads a thread and sends nothing, so retrying it is safe. Like `pro_consult`, it is registered only on the local stdio MCP server.
|
|
111
|
+
|
|
112
|
+
No shell, public tunnel, direct ungated write, or direct ungated staging tools are exposed through the Claude stdio MCP server; the only browser-facing tools are the explicit `pro_consult` consult and the read-only `pro_recover` described above.
|
|
110
113
|
|
|
111
114
|
## First Prompt
|
|
112
115
|
|
package/docs/clients.md
CHANGED
|
@@ -48,6 +48,13 @@ consult you expect. Claude Code needs no change: its default stdio tool
|
|
|
48
48
|
timeout is effectively unlimited (~28h) unless you tightened `MCP_TOOL_TIMEOUT`
|
|
49
49
|
or a per-server `"timeout"`.
|
|
50
50
|
|
|
51
|
+
A deep research consult (`tools: ["deep-research"]`) is the longest of these:
|
|
52
|
+
the run takes about ten minutes and prodex raises its own budget to 30, so a
|
|
53
|
+
client timeout below that aborts the call while the research keeps going. That
|
|
54
|
+
is recoverable rather than lost - `pro_recover` with the thread from the
|
|
55
|
+
blocker collects the report afterwards - but a client budget that covers the
|
|
56
|
+
run avoids the round trip.
|
|
57
|
+
|
|
51
58
|
Approval gate (verified on Codex 0.142.5): Codex asks for per-call approval
|
|
52
59
|
before invoking prodex MCP tools. In interactive `codex` sessions you simply
|
|
53
60
|
approve the prompt. In non-interactive `codex exec`, the approval cannot be
|