agents-relay 2.0.167 → 2.0.169
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/README.md +1 -1
- package/agents/chatgpt-worker.agent.md +6 -6
- package/dist/adapters.js +16 -7
- package/package.json +1 -1
- package/skills/agents-relay/SKILL.md +1 -1
package/README.md
CHANGED
|
@@ -255,7 +255,7 @@ Every model-backed task declares a durable output with `--output task-pr` or `--
|
|
|
255
255
|
|
|
256
256
|
For Codex and ChatGPT, **correlated worker events are authoritative lifecycle inputs**, not a separate durable store. Event publication uses the canonical Neo `events-bus` surface (`events__publish` for sandboxed/hosted workers, or `NEO_EVENTS_EMIT` for direct local workers); Agents Relay subscribes, validates correlation, applies graph transitions, persists results in RelayStore, and projects them to GitHub. Relay publishes `task.process.launched` only after successful adapter launch; `task.started` is worker-owned and must be a new, correlated start acknowledgement. Codex publishes `task.process.exited` when its synchronous runtime exits, while ChatGPT publishes `task.process.async_exited` after its one-shot submission runtime exits; neither substitutes for `task.completed`, `task.failed`, `task.blocked`, or `task.cancelled`. The executing agent must publish exactly one correlated terminal event. Relay persists the matching durable state only from that terminal event. Model-backed tasks require an event bus and time out explicitly if no terminal event arrives.
|
|
257
257
|
|
|
258
|
-
The ChatGPT adapter uses Relay's `agents/chatgpt-worker.agent.md` lifecycle contract
|
|
258
|
+
The ChatGPT adapter uses Relay's `agents/chatgpt-worker.agent.md` lifecycle contract. A new worker uses `webhelm platform run chatgpt new-thread --session-id SESSION_ID --config <file>` in a caller-owned Session. This is a regular persistent ChatGPT thread, which supports the connected Neo MCP in the verified account. Relay closes the Session after submission, but the ChatGPT thread remains in history. Existing-thread review and handoff continue through `new-turn`. File paths are included in the worker message for Neo MCP reading; they are not uploaded as browser attachments. Submission receipts retain `status: submitted`; the event bus owns task completion.
|
|
259
259
|
|
|
260
260
|
~~~sh
|
|
261
261
|
npx agents-relay task create --repo OWNER/REPO --pr 5 --id job-1 \
|
|
@@ -6,17 +6,17 @@ type: worker
|
|
|
6
6
|
|
|
7
7
|
# ChatGPT Worker Agent
|
|
8
8
|
|
|
9
|
-
You execute one complete Relay task by submitting it to a fresh
|
|
9
|
+
You execute one complete Relay task by submitting it to a fresh, regular ChatGPT Thread through Browser Workspace.
|
|
10
10
|
|
|
11
11
|
## Contract
|
|
12
12
|
|
|
13
|
-
- Browser Workspace `platforms/chatgpt` is the sole owner of ChatGPT selectors, readiness checks,
|
|
13
|
+
- Browser Workspace `platforms/chatgpt` is the sole owner of ChatGPT selectors, readiness checks, new-thread mechanics and submit verification.
|
|
14
14
|
- Relay owns worker lifecycle, task/event barriers, routing, and cancellation; Browser Workspace owns the one-shot auto-session lifecycle.
|
|
15
|
-
- Execute
|
|
16
|
-
-
|
|
15
|
+
- Execute one new worker submission with `platform run chatgpt new-thread --session-id SESSION_ID`. Existing-thread delivery uses `new-turn`. Never use Temporary Chat for workers that need Neo MCP.
|
|
16
|
+
- Relay creates and stops a caller-owned WebHelm Session for each delivery. New worker conversations persist in ChatGPT history; do not reuse a pre-existing user tab.
|
|
17
17
|
- Preserve the account's current default model/thinking settings.
|
|
18
18
|
- A submission is accepted only after Browser Workspace returns a verified submit receipt.
|
|
19
|
-
-
|
|
20
|
-
- Legacy ChatGPT tab-close policy values remain accepted by Relay for compatibility, but they do not control
|
|
19
|
+
- Require the real new-thread receipt to include a durable thread ID and URL. The thread identifies delivery, not task completion.
|
|
20
|
+
- Legacy ChatGPT tab-close policy values remain accepted by Relay for compatibility, but they do not control the caller-owned Session lifetime or add self-heal.
|
|
21
21
|
- Do not wait for the assistant response. Durable task success/failure is event-owned by Relay and the executing task.
|
|
22
22
|
- Stop on authentication, MFA, consent, or ambiguous browser state rather than bypassing it.
|
package/dist/adapters.js
CHANGED
|
@@ -148,7 +148,7 @@ function findSubmittedReceipt(value) {
|
|
|
148
148
|
if (!value || typeof value !== 'object')
|
|
149
149
|
return undefined;
|
|
150
150
|
const record = value;
|
|
151
|
-
if ((record.operation === 'submit' || record.operation === 'new-turn' || record.mode === 'new-turn') && record.status === 'submitted')
|
|
151
|
+
if ((record.operation === 'submit' || record.operation === 'new-turn' || record.mode === 'new-turn' || record.mode === 'new-thread') && record.status === 'submitted')
|
|
152
152
|
return record;
|
|
153
153
|
for (const key of ['result', 'output', 'data', 'stdout']) {
|
|
154
154
|
const nested = findSubmittedReceipt(record[key]);
|
|
@@ -285,13 +285,13 @@ export async function ensureChatGptBrowserWorkspace(command = process.env.AGENTS
|
|
|
285
285
|
}
|
|
286
286
|
await admin.ensureWorkspace(CHATGPT_BROWSER_WORKSPACE, CHATGPT_BROWSER_WORKSPACE_POOL_SIZE);
|
|
287
287
|
}
|
|
288
|
-
async function runBrowserWorker(cli, configFile, signal, action = '
|
|
288
|
+
async function runBrowserWorker(cli, configFile, signal, action = 'new-thread') {
|
|
289
289
|
const session = parseWorkspaceJson(await browserWorkspaceCommand(cli, ['session', 'start', '--workspace', CHATGPT_BROWSER_WORKSPACE], undefined, signal));
|
|
290
290
|
const sessionId = session.session_id;
|
|
291
291
|
if (typeof sessionId !== 'string' || !sessionId)
|
|
292
292
|
throw new Error('webhelm session start returned no session_id');
|
|
293
293
|
try {
|
|
294
|
-
return await browserWorkspaceCommand(cli, ['platform', 'run', 'chatgpt', action, '--session-id', sessionId, '--config', configFile], undefined, signal);
|
|
294
|
+
return await browserWorkspaceCommand(cli, ['platform', 'run', 'chatgpt', action, ...(action === 'new-turn' ? ['--mode', 'async'] : []), '--session-id', sessionId, '--config', configFile], undefined, signal);
|
|
295
295
|
}
|
|
296
296
|
finally {
|
|
297
297
|
await browserWorkspaceCommand(cli, ['session', 'stop', sessionId]).catch(() => { });
|
|
@@ -304,18 +304,23 @@ function browserWorkerRunner() {
|
|
|
304
304
|
const configFile = join(process.env.TMPDIR ?? '/tmp', `agents-relay-chatgpt-${randomUUID()}.json`);
|
|
305
305
|
try {
|
|
306
306
|
const delivery = request.thread;
|
|
307
|
+
// Temporary Chat lacks Neo MCP tools on this verified account.
|
|
308
|
+
// File paths remain accessible to normal workers through Neo MCP.
|
|
309
|
+
const message = request.files?.length
|
|
310
|
+
? `${request.prompt}\n\nTask file paths (read with Neo MCP; files are not browser-uploaded):\n${request.files.map(file => `- ${JSON.stringify(file)}`).join('\n')}`
|
|
311
|
+
: request.prompt;
|
|
307
312
|
await writeFile(configFile, JSON.stringify(delivery ? {
|
|
308
313
|
project_id: delivery.projectId ?? _route.projectId ?? null,
|
|
309
314
|
thread_id: delivery.threadId,
|
|
310
315
|
message: `${request.prompt}\n\nRelay delivery ID: ${delivery.requestId}`,
|
|
311
316
|
idempotency_key: delivery.requestId,
|
|
312
317
|
} : {
|
|
313
|
-
|
|
314
|
-
|
|
318
|
+
message,
|
|
319
|
+
temporary: false,
|
|
315
320
|
}));
|
|
316
321
|
if (signal.aborted)
|
|
317
322
|
throw new Error('browser-worker execution aborted');
|
|
318
|
-
const action = delivery ? 'new-turn' : '
|
|
323
|
+
const action = delivery ? 'new-turn' : 'new-thread';
|
|
319
324
|
const output = await runBrowserWorker(cli, configFile, signal, action);
|
|
320
325
|
return JSON.stringify(parseDriverJson(output));
|
|
321
326
|
}
|
|
@@ -338,6 +343,10 @@ function parseBrowserWorkerResponse(output) {
|
|
|
338
343
|
if (!value || typeof value !== 'object')
|
|
339
344
|
throw new Error('browser-worker returned an invalid JSON response');
|
|
340
345
|
const response = value;
|
|
346
|
+
if (response.mode === 'new-thread' && (response.temporary !== false ||
|
|
347
|
+
typeof response.thread_id !== 'string' || !/^[A-Za-z0-9_-]{8,160}$/.test(response.thread_id) ||
|
|
348
|
+
typeof response.thread_url !== 'string' || !/^https:\/\/chatgpt\.com\/c\//.test(response.thread_url)))
|
|
349
|
+
throw new Error('browser-worker did not return a durable ChatGPT thread');
|
|
341
350
|
const verified = response.verified === true || response.verified_by !== undefined;
|
|
342
351
|
if (response.status !== 'submitted' || !verified) {
|
|
343
352
|
throw new Error('browser-worker did not return a submitted receipt');
|
|
@@ -432,7 +441,7 @@ export class ChatGptAdapter {
|
|
|
432
441
|
summary: 'ChatGPT task submitted; terminal task state is event-owned',
|
|
433
442
|
data: {
|
|
434
443
|
submitted: true,
|
|
435
|
-
mode: response.mode ?? '
|
|
444
|
+
mode: response.mode ?? 'new-thread',
|
|
436
445
|
threadId: response.thread_id ?? response.diagnostic_thread_id ?? null,
|
|
437
446
|
diagnosticThreadId: response.diagnostic_thread_id ?? null,
|
|
438
447
|
userMessageId: response.user_message_id ?? null,
|
package/package.json
CHANGED
|
@@ -100,7 +100,7 @@ Leaf workers consume the resolved instruction/skill/agent paths, not the full to
|
|
|
100
100
|
|
|
101
101
|
## ChatGPT worker
|
|
102
102
|
|
|
103
|
-
The ChatGPT adapter uses Relay's `chatgpt-worker` agent contract and Browser Workspace ChatGPT platform; it does not depend on a Neo worker skill. It opens a fresh
|
|
103
|
+
The ChatGPT adapter uses Relay's `chatgpt-worker` agent contract and Browser Workspace ChatGPT platform; it does not depend on a Neo worker skill. It opens a fresh regular ChatGPT thread so the worker can use Neo MCP, submits the task with the account defaults, verifies the durable thread ID and submission receipt, and closes its caller-owned WebHelm Session after submission. File inputs are passed as explicit local paths for Neo MCP reading, not browser uploads.
|
|
104
104
|
|
|
105
105
|
ChatGPT thread identity is diagnostic only. It is not persisted as a resumable task handle, and Relay does not poll, resume, retrieve a result from, or delete a ChatGPT conversation as part of task lifecycle.
|
|
106
106
|
|