@parall/codex-agent 1.31.0 → 1.32.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/dist/config.d.ts.map +1 -1
- package/dist/config.js +34 -35
- package/dist/dispatch.d.ts +6 -5
- package/dist/dispatch.d.ts.map +1 -1
- package/dist/dispatch.js +101 -81
- package/dist/event-mapping.d.ts +1 -1
- package/dist/event-mapping.d.ts.map +1 -1
- package/dist/event-mapping.js +102 -82
- package/dist/index.js +154 -118
- package/dist/jsonrpc-client.d.ts +4 -4
- package/dist/jsonrpc-client.d.ts.map +1 -1
- package/dist/jsonrpc-client.js +15 -15
- package/dist/session-manager.d.ts +1 -1
- package/dist/session-manager.d.ts.map +1 -1
- package/dist/session-manager.js +7 -5
- package/dist/workspace.d.ts +1 -1
- package/dist/workspace.d.ts.map +1 -1
- package/dist/workspace.js +40 -39
- package/package.json +4 -4
- package/src/config.ts +41 -36
- package/src/dispatch.ts +139 -109
- package/src/event-mapping.ts +135 -109
- package/src/index.ts +187 -121
- package/src/jsonrpc-client.ts +22 -20
- package/src/session-manager.ts +10 -6
- package/src/workspace.ts +50 -43
package/dist/dispatch.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { execSync, spawn } from
|
|
2
|
-
import { randomUUID } from
|
|
3
|
-
import * as fs from
|
|
4
|
-
import { appendPreparedLocalAttachmentRefs, ensureLocalAttachmentGitExclude, pinLocalAttachmentPaths, } from
|
|
5
|
-
import { normalizeApprovalPolicy, normalizeSandbox } from
|
|
6
|
-
import { EventMapper } from
|
|
7
|
-
import { JsonRpcStdioClient } from
|
|
1
|
+
import { execSync, spawn } from 'node:child_process';
|
|
2
|
+
import { randomUUID } from 'node:crypto';
|
|
3
|
+
import * as fs from 'node:fs';
|
|
4
|
+
import { appendPreparedLocalAttachmentRefs, ensureLocalAttachmentGitExclude, pinLocalAttachmentPaths, } from '@parall/agent-core/internal/attachment-input';
|
|
5
|
+
import { normalizeApprovalPolicy, normalizeSandbox } from './config.js';
|
|
6
|
+
import { EventMapper } from './event-mapping.js';
|
|
7
|
+
import { JsonRpcStdioClient } from './jsonrpc-client.js';
|
|
8
8
|
/**
|
|
9
9
|
* Bridge driver backed by `codex app-server --listen stdio://`.
|
|
10
10
|
*
|
|
@@ -19,7 +19,7 @@ import { JsonRpcStdioClient } from "./jsonrpc-client.js";
|
|
|
19
19
|
* main + fork can interleave turns on the same stdio pipe. We route
|
|
20
20
|
* notifications by threadId the server stamps on every item/turn event.
|
|
21
21
|
*/
|
|
22
|
-
const IS_WIN32 = process.platform ===
|
|
22
|
+
const IS_WIN32 = process.platform === 'win32';
|
|
23
23
|
function quoteWin32Arg(arg) {
|
|
24
24
|
if (!/[\s"&|^<>()]/.test(arg))
|
|
25
25
|
return arg;
|
|
@@ -27,7 +27,7 @@ function quoteWin32Arg(arg) {
|
|
|
27
27
|
}
|
|
28
28
|
function killWin32Tree(pid) {
|
|
29
29
|
try {
|
|
30
|
-
execSync(`taskkill /T /F /PID ${pid}`, { windowsHide: true, stdio:
|
|
30
|
+
execSync(`taskkill /T /F /PID ${pid}`, { windowsHide: true, stdio: 'ignore' });
|
|
31
31
|
return true;
|
|
32
32
|
}
|
|
33
33
|
catch {
|
|
@@ -57,7 +57,7 @@ export class CodexAppServerAdapter {
|
|
|
57
57
|
const existing = this.activeTurns.get(threadId);
|
|
58
58
|
if (existing) {
|
|
59
59
|
(log ?? this.opts.log)?.warn?.(`thread ${threadId} already had an active turn; failing the previous dispatch`);
|
|
60
|
-
existing.push({ kind:
|
|
60
|
+
existing.push({ kind: 'error', message: `thread ${threadId} replaced by concurrent turn` });
|
|
61
61
|
existing.close();
|
|
62
62
|
}
|
|
63
63
|
this.activeTurns.set(threadId, sink);
|
|
@@ -82,7 +82,7 @@ export class CodexAppServerAdapter {
|
|
|
82
82
|
if (!turnId)
|
|
83
83
|
return false;
|
|
84
84
|
try {
|
|
85
|
-
await client.sendRequest(
|
|
85
|
+
await client.sendRequest('turn/steer', {
|
|
86
86
|
threadId,
|
|
87
87
|
expectedTurnId: turnId,
|
|
88
88
|
input: buildTurnInput(body, []),
|
|
@@ -95,10 +95,21 @@ export class CodexAppServerAdapter {
|
|
|
95
95
|
return false;
|
|
96
96
|
}
|
|
97
97
|
}
|
|
98
|
+
abortDispatch(sessionKey) {
|
|
99
|
+
this.pendingInjections.delete(sessionKey);
|
|
100
|
+
const threadId = this.opts.sessionManager.getThreadId(sessionKey);
|
|
101
|
+
if (!threadId)
|
|
102
|
+
return;
|
|
103
|
+
const sink = this.activeTurns.get(threadId);
|
|
104
|
+
if (!sink)
|
|
105
|
+
return;
|
|
106
|
+
sink.push({ kind: 'error', message: 'dispatch deadline exceeded' });
|
|
107
|
+
sink.close();
|
|
108
|
+
}
|
|
98
109
|
hasPendingInjections(sessionKey) {
|
|
99
110
|
return (this.pendingInjections.get(sessionKey) ?? 0) > 0;
|
|
100
111
|
}
|
|
101
|
-
async *dispatch({ event, bodyForAgent, sessionKey, context }) {
|
|
112
|
+
async *dispatch({ event, bodyForAgent, sessionKey, context, }) {
|
|
102
113
|
const pending = this.pendingInjections.get(sessionKey) ?? 0;
|
|
103
114
|
if (pending > 0) {
|
|
104
115
|
this.pendingInjections.delete(sessionKey);
|
|
@@ -106,7 +117,7 @@ export class CodexAppServerAdapter {
|
|
|
106
117
|
if (threadId && this.client && !this.client.isDisposed()) {
|
|
107
118
|
(this.opts.log ?? context.log)?.info?.(`${pending} steer injection(s) already sent; skipping turn/start`);
|
|
108
119
|
yield {
|
|
109
|
-
type:
|
|
120
|
+
type: 'runtime_session',
|
|
110
121
|
runtimeSessionId: threadId,
|
|
111
122
|
runtimeLaneKey: sessionKey,
|
|
112
123
|
};
|
|
@@ -121,7 +132,10 @@ export class CodexAppServerAdapter {
|
|
|
121
132
|
// throw a TypeError on the next sendRequest call.
|
|
122
133
|
const client = this.client;
|
|
123
134
|
if (!client) {
|
|
124
|
-
yield {
|
|
135
|
+
yield {
|
|
136
|
+
type: 'error',
|
|
137
|
+
message: 'Codex app-server not available (subprocess died during dispatch start)',
|
|
138
|
+
};
|
|
125
139
|
return;
|
|
126
140
|
}
|
|
127
141
|
const log = this.opts.log ?? context.log;
|
|
@@ -140,7 +154,7 @@ export class CodexAppServerAdapter {
|
|
|
140
154
|
this.resumedThreadIds.add(threadId);
|
|
141
155
|
}
|
|
142
156
|
catch (err) {
|
|
143
|
-
yield { type:
|
|
157
|
+
yield { type: 'error', message: `Codex thread/start failed: ${errToString(err)}` };
|
|
144
158
|
return;
|
|
145
159
|
}
|
|
146
160
|
}
|
|
@@ -163,7 +177,7 @@ export class CodexAppServerAdapter {
|
|
|
163
177
|
}
|
|
164
178
|
catch (innerErr) {
|
|
165
179
|
yield {
|
|
166
|
-
type:
|
|
180
|
+
type: 'error',
|
|
167
181
|
message: `Codex thread/start failed after resume error (persisted thread retained): ${errToString(innerErr)}`,
|
|
168
182
|
};
|
|
169
183
|
return;
|
|
@@ -201,7 +215,7 @@ export class CodexAppServerAdapter {
|
|
|
201
215
|
// this contract, we want a hard error surfaced to the operator, not a
|
|
202
216
|
// silent fallback that hides real protocol drift.
|
|
203
217
|
const turnInput = buildTurnInput(preparedBody, preparedImages);
|
|
204
|
-
const startTurn = (targetThreadId) => client.sendRequest(
|
|
218
|
+
const startTurn = (targetThreadId) => client.sendRequest('turn/start', {
|
|
205
219
|
threadId: targetThreadId,
|
|
206
220
|
input: turnInput,
|
|
207
221
|
});
|
|
@@ -222,11 +236,11 @@ export class CodexAppServerAdapter {
|
|
|
222
236
|
// Fork sessions don't retry: agent-core spawns a fresh fork next trigger.
|
|
223
237
|
if (!isMainSession) {
|
|
224
238
|
yield {
|
|
225
|
-
type:
|
|
239
|
+
type: 'runtime_session',
|
|
226
240
|
runtimeSessionId: threadId,
|
|
227
241
|
runtimeLaneKey: sessionKey,
|
|
228
242
|
};
|
|
229
|
-
yield { type:
|
|
243
|
+
yield { type: 'error', message: `Codex turn/start failed: ${message}` };
|
|
230
244
|
return;
|
|
231
245
|
}
|
|
232
246
|
log?.warn?.(`turn/start on thread ${threadId} failed (${message}); attempting one-shot fresh-thread retry`);
|
|
@@ -237,11 +251,14 @@ export class CodexAppServerAdapter {
|
|
|
237
251
|
}
|
|
238
252
|
catch (createErr) {
|
|
239
253
|
yield {
|
|
240
|
-
type:
|
|
254
|
+
type: 'runtime_session',
|
|
241
255
|
runtimeSessionId: threadId,
|
|
242
256
|
runtimeLaneKey: sessionKey,
|
|
243
257
|
};
|
|
244
|
-
yield {
|
|
258
|
+
yield {
|
|
259
|
+
type: 'error',
|
|
260
|
+
message: `Codex turn/start failed; could not create replacement thread: ${errToString(createErr)}`,
|
|
261
|
+
};
|
|
245
262
|
return;
|
|
246
263
|
}
|
|
247
264
|
this.setActiveTurn(freshThreadId, sink, log);
|
|
@@ -254,11 +271,14 @@ export class CodexAppServerAdapter {
|
|
|
254
271
|
// resume again.
|
|
255
272
|
this.activeTurns.delete(freshThreadId);
|
|
256
273
|
yield {
|
|
257
|
-
type:
|
|
274
|
+
type: 'runtime_session',
|
|
258
275
|
runtimeSessionId: threadId,
|
|
259
276
|
runtimeLaneKey: sessionKey,
|
|
260
277
|
};
|
|
261
|
-
yield {
|
|
278
|
+
yield {
|
|
279
|
+
type: 'error',
|
|
280
|
+
message: `Codex turn/start failed after retry: ${errToString(retryErr)}`,
|
|
281
|
+
};
|
|
262
282
|
return;
|
|
263
283
|
}
|
|
264
284
|
// Retry accepted — the original thread really was unusable. Now safe
|
|
@@ -272,30 +292,30 @@ export class CodexAppServerAdapter {
|
|
|
272
292
|
if (turnId)
|
|
273
293
|
this.activeTurnIds.set(threadId, turnId);
|
|
274
294
|
yield {
|
|
275
|
-
type:
|
|
295
|
+
type: 'runtime_session',
|
|
276
296
|
runtimeSessionId: threadId,
|
|
277
297
|
runtimeLaneKey: sessionKey,
|
|
278
298
|
};
|
|
279
299
|
while (true) {
|
|
280
300
|
const envelope = await sink.next();
|
|
281
|
-
if (envelope.kind ===
|
|
301
|
+
if (envelope.kind === 'turn_end') {
|
|
282
302
|
sawTurnEnd = true;
|
|
283
303
|
break;
|
|
284
304
|
}
|
|
285
|
-
if (envelope.kind ===
|
|
286
|
-
yield { type:
|
|
305
|
+
if (envelope.kind === 'error') {
|
|
306
|
+
yield { type: 'error', message: envelope.message };
|
|
287
307
|
continue;
|
|
288
308
|
}
|
|
289
309
|
const runtimeEvent = envelope.event;
|
|
290
|
-
if (runtimeEvent.type ===
|
|
310
|
+
if (runtimeEvent.type === 'error') {
|
|
291
311
|
yield runtimeEvent;
|
|
292
312
|
continue;
|
|
293
313
|
}
|
|
294
|
-
if (runtimeEvent.type ===
|
|
314
|
+
if (runtimeEvent.type === 'runtime_session') {
|
|
295
315
|
yield runtimeEvent;
|
|
296
316
|
continue;
|
|
297
317
|
}
|
|
298
|
-
if (runtimeEvent.type ===
|
|
318
|
+
if (runtimeEvent.type === 'text') {
|
|
299
319
|
// Layer 0 symmetric output contract: Codex's plain text is never
|
|
300
320
|
// projected as a chat message. Outbound messages must come from the
|
|
301
321
|
// agent explicitly invoking `@parall/cli messages send` / `dm` via
|
|
@@ -335,17 +355,17 @@ export class CodexAppServerAdapter {
|
|
|
335
355
|
ephemeral: true,
|
|
336
356
|
};
|
|
337
357
|
if (this.opts.useParallProvider) {
|
|
338
|
-
forkParams.modelProvider =
|
|
358
|
+
forkParams.modelProvider = 'parall';
|
|
339
359
|
}
|
|
340
360
|
if (this.opts.model)
|
|
341
361
|
forkParams.model = this.opts.model;
|
|
342
362
|
if (this.opts.reasoningEffort) {
|
|
343
363
|
forkParams.config = { modelReasoningEffort: this.opts.reasoningEffort };
|
|
344
364
|
}
|
|
345
|
-
const result = await client.sendRequest(
|
|
365
|
+
const result = await client.sendRequest('thread/fork', forkParams);
|
|
346
366
|
const forkedThreadId = extractThreadId(result);
|
|
347
367
|
if (!forkedThreadId) {
|
|
348
|
-
this.opts.log?.warn?.(
|
|
368
|
+
this.opts.log?.warn?.('thread/fork returned no thread id');
|
|
349
369
|
return null;
|
|
350
370
|
}
|
|
351
371
|
this.opts.sessionManager.recordThreadId(handle.sessionKey, forkedThreadId);
|
|
@@ -372,17 +392,17 @@ export class CodexAppServerAdapter {
|
|
|
372
392
|
this.activeTurnIds.clear();
|
|
373
393
|
this.pendingInjections.clear();
|
|
374
394
|
if (client)
|
|
375
|
-
client.dispose(new Error(
|
|
395
|
+
client.dispose(new Error('adapter stopped'));
|
|
376
396
|
if (proc && proc.exitCode === null && proc.signalCode === null) {
|
|
377
397
|
if (!IS_WIN32 || !proc.pid || !killWin32Tree(proc.pid)) {
|
|
378
|
-
proc.kill(
|
|
398
|
+
proc.kill('SIGTERM');
|
|
379
399
|
}
|
|
380
400
|
}
|
|
381
401
|
}
|
|
382
402
|
async ensureStarted(log) {
|
|
383
403
|
if (this.client?.isDisposed()) {
|
|
384
404
|
for (const activeSink of this.activeTurns.values()) {
|
|
385
|
-
activeSink.push({ kind:
|
|
405
|
+
activeSink.push({ kind: 'error', message: 'Codex app-server disposed; resetting adapter' });
|
|
386
406
|
activeSink.close();
|
|
387
407
|
}
|
|
388
408
|
this.activeTurns.clear();
|
|
@@ -422,22 +442,22 @@ export class CodexAppServerAdapter {
|
|
|
422
442
|
const env = {
|
|
423
443
|
...process.env,
|
|
424
444
|
CODEX_HOME: this.opts.codexHome,
|
|
425
|
-
FORCE_COLOR:
|
|
426
|
-
NO_COLOR:
|
|
445
|
+
FORCE_COLOR: '0',
|
|
446
|
+
NO_COLOR: '1',
|
|
427
447
|
};
|
|
428
448
|
if (this.opts.contextFilePath) {
|
|
429
449
|
env.PRLL_CONTEXT_FILE = this.opts.contextFilePath;
|
|
430
450
|
}
|
|
431
|
-
const args = [
|
|
432
|
-
(log ?? this.opts.log)?.info?.(`spawning ${this.opts.codexBin} ${args.join(
|
|
451
|
+
const args = ['app-server', '--listen', 'stdio://'];
|
|
452
|
+
(log ?? this.opts.log)?.info?.(`spawning ${this.opts.codexBin} ${args.join(' ')}`);
|
|
433
453
|
const proc = spawn(IS_WIN32 ? quoteWin32Arg(this.opts.codexBin) : this.opts.codexBin, IS_WIN32 ? args.map(quoteWin32Arg) : args, {
|
|
434
454
|
cwd: this.opts.workspaceDir,
|
|
435
455
|
env,
|
|
436
|
-
stdio: [
|
|
456
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
437
457
|
shell: IS_WIN32,
|
|
438
458
|
});
|
|
439
|
-
proc.stderr.setEncoding(
|
|
440
|
-
proc.stderr.on(
|
|
459
|
+
proc.stderr.setEncoding('utf8');
|
|
460
|
+
proc.stderr.on('data', (chunk) => {
|
|
441
461
|
(log ?? this.opts.log)?.warn?.(`[stderr] ${chunk.trim()}`);
|
|
442
462
|
});
|
|
443
463
|
// Don't publish proc/client until the initialize handshake succeeds. If
|
|
@@ -447,24 +467,24 @@ export class CodexAppServerAdapter {
|
|
|
447
467
|
// next ensureStarted() to spawn a second app-server on top of it.
|
|
448
468
|
const client = new JsonRpcStdioClient(proc, undefined, (p) => {
|
|
449
469
|
if (!IS_WIN32 || !p.pid || !killWin32Tree(p.pid)) {
|
|
450
|
-
p.kill(
|
|
470
|
+
p.kill('SIGTERM');
|
|
451
471
|
}
|
|
452
472
|
});
|
|
453
473
|
client.setNotificationHandler((method, params) => this.routeNotification(method, params));
|
|
454
|
-
proc.once(
|
|
455
|
-
proc.once(
|
|
474
|
+
proc.once('close', (code, signal) => this.handleSubprocessClose(proc, code, signal, log));
|
|
475
|
+
proc.once('error', (err) => this.handleSubprocessClose(proc, null, null, log, err));
|
|
456
476
|
try {
|
|
457
|
-
await client.sendRequest(
|
|
458
|
-
clientInfo: { name:
|
|
477
|
+
await client.sendRequest('initialize', {
|
|
478
|
+
clientInfo: { name: 'parall-codex-agent', version: '1' },
|
|
459
479
|
capabilities: { experimentalApi: false },
|
|
460
480
|
});
|
|
461
|
-
client.sendNotification(
|
|
481
|
+
client.sendNotification('initialized', {});
|
|
462
482
|
}
|
|
463
483
|
catch (err) {
|
|
464
484
|
client.dispose(err instanceof Error ? err : new Error(String(err)));
|
|
465
485
|
if (proc.exitCode === null && proc.signalCode === null) {
|
|
466
486
|
if (!IS_WIN32 || !proc.pid || !killWin32Tree(proc.pid)) {
|
|
467
|
-
proc.kill(
|
|
487
|
+
proc.kill('SIGTERM');
|
|
468
488
|
}
|
|
469
489
|
}
|
|
470
490
|
throw err;
|
|
@@ -482,7 +502,7 @@ export class CodexAppServerAdapter {
|
|
|
482
502
|
return;
|
|
483
503
|
const reason = err
|
|
484
504
|
? `spawn error: ${err.message}`
|
|
485
|
-
: `exited (code=${code ??
|
|
505
|
+
: `exited (code=${code ?? 'null'}${signal ? `, signal=${signal}` : ''})`;
|
|
486
506
|
const logger = log ?? this.opts.log;
|
|
487
507
|
if (this.stopping) {
|
|
488
508
|
logger?.info?.(`app-server subprocess ${reason} during graceful stop`);
|
|
@@ -492,7 +512,7 @@ export class CodexAppServerAdapter {
|
|
|
492
512
|
}
|
|
493
513
|
this.client?.dispose(err ?? new Error(`app-server ${reason}`));
|
|
494
514
|
for (const activeSink of this.activeTurns.values()) {
|
|
495
|
-
activeSink.push({ kind:
|
|
515
|
+
activeSink.push({ kind: 'error', message: `Codex app-server ${reason}` });
|
|
496
516
|
activeSink.close();
|
|
497
517
|
}
|
|
498
518
|
this.activeTurns.clear();
|
|
@@ -517,7 +537,7 @@ export class CodexAppServerAdapter {
|
|
|
517
537
|
approvalPolicy: normalizeApprovalPolicy(this.opts.approvalPolicy),
|
|
518
538
|
};
|
|
519
539
|
if (this.opts.useParallProvider) {
|
|
520
|
-
commonParams.modelProvider =
|
|
540
|
+
commonParams.modelProvider = 'parall';
|
|
521
541
|
}
|
|
522
542
|
commonParams.sandbox = normalizeSandbox(this.opts.sandbox);
|
|
523
543
|
if (this.opts.model)
|
|
@@ -530,7 +550,7 @@ export class CodexAppServerAdapter {
|
|
|
530
550
|
// `thread/start` / `thread/resume` takes the camelCase form.
|
|
531
551
|
commonParams.config = { modelReasoningEffort: this.opts.reasoningEffort };
|
|
532
552
|
}
|
|
533
|
-
const method = opts.resumeId ?
|
|
553
|
+
const method = opts.resumeId ? 'thread/resume' : 'thread/start';
|
|
534
554
|
const params = opts.resumeId
|
|
535
555
|
? { threadId: opts.resumeId, ...commonParams }
|
|
536
556
|
: { cwd: this.opts.workspaceDir, ...commonParams };
|
|
@@ -545,10 +565,10 @@ export class CodexAppServerAdapter {
|
|
|
545
565
|
const threadId = extractThreadIdFromNotification(params);
|
|
546
566
|
if (!threadId) {
|
|
547
567
|
// Surface server-initiated generic errors to every active turn.
|
|
548
|
-
if (method ===
|
|
549
|
-
const msg = params?.message ??
|
|
568
|
+
if (method === 'error') {
|
|
569
|
+
const msg = params?.message ?? 'Codex app-server error';
|
|
550
570
|
for (const sink of this.activeTurns.values()) {
|
|
551
|
-
sink.push({ kind:
|
|
571
|
+
sink.push({ kind: 'error', message: String(msg) });
|
|
552
572
|
}
|
|
553
573
|
}
|
|
554
574
|
return;
|
|
@@ -560,11 +580,11 @@ export class CodexAppServerAdapter {
|
|
|
560
580
|
// RuntimeEvent error if `turn.status === "failed"`. Enqueue those events
|
|
561
581
|
// before the turn_end sentinel so the dispatch loop can yield them.
|
|
562
582
|
for (const event of sink.mapper.map(method, params)) {
|
|
563
|
-
sink.push({ kind:
|
|
583
|
+
sink.push({ kind: 'runtime', event });
|
|
564
584
|
}
|
|
565
|
-
if (method ===
|
|
585
|
+
if (method === 'turn/completed') {
|
|
566
586
|
this.activeTurnIds.delete(threadId);
|
|
567
|
-
sink.push({ kind:
|
|
587
|
+
sink.push({ kind: 'turn_end', threadId });
|
|
568
588
|
}
|
|
569
589
|
}
|
|
570
590
|
}
|
|
@@ -594,7 +614,7 @@ class TurnSink {
|
|
|
594
614
|
if (pending)
|
|
595
615
|
return Promise.resolve(pending);
|
|
596
616
|
if (this.closed) {
|
|
597
|
-
return Promise.resolve({ kind:
|
|
617
|
+
return Promise.resolve({ kind: 'turn_end' });
|
|
598
618
|
}
|
|
599
619
|
return new Promise((resolve) => {
|
|
600
620
|
this.resolver = resolve;
|
|
@@ -604,7 +624,7 @@ class TurnSink {
|
|
|
604
624
|
this.closed = true;
|
|
605
625
|
const r = this.resolver;
|
|
606
626
|
this.resolver = null;
|
|
607
|
-
r?.({ kind:
|
|
627
|
+
r?.({ kind: 'turn_end' });
|
|
608
628
|
}
|
|
609
629
|
}
|
|
610
630
|
function ensureGitRepo(workingDirectory) {
|
|
@@ -614,7 +634,7 @@ function ensureGitRepo(workingDirectory) {
|
|
|
614
634
|
// PRLL_WORKSPACE_DIR at a subdirectory of their existing project,
|
|
615
635
|
// and silently creating a nested repo there would mangle their layout.
|
|
616
636
|
try {
|
|
617
|
-
execSync(
|
|
637
|
+
execSync('git rev-parse --is-inside-work-tree', { cwd: workingDirectory, stdio: 'pipe' });
|
|
618
638
|
ensureLocalAttachmentGitExclude(workingDirectory);
|
|
619
639
|
return;
|
|
620
640
|
}
|
|
@@ -623,14 +643,14 @@ function ensureGitRepo(workingDirectory) {
|
|
|
623
643
|
}
|
|
624
644
|
const env = {
|
|
625
645
|
...process.env,
|
|
626
|
-
GIT_AUTHOR_NAME:
|
|
627
|
-
GIT_AUTHOR_EMAIL:
|
|
628
|
-
GIT_COMMITTER_NAME:
|
|
629
|
-
GIT_COMMITTER_EMAIL:
|
|
646
|
+
GIT_AUTHOR_NAME: 'parall-codex-agent',
|
|
647
|
+
GIT_AUTHOR_EMAIL: 'agent@parall.local',
|
|
648
|
+
GIT_COMMITTER_NAME: 'parall-codex-agent',
|
|
649
|
+
GIT_COMMITTER_EMAIL: 'agent@parall.local',
|
|
630
650
|
};
|
|
631
651
|
try {
|
|
632
|
-
execSync(
|
|
633
|
-
execSync(
|
|
652
|
+
execSync('git init', { cwd: workingDirectory, stdio: 'pipe', env });
|
|
653
|
+
execSync('git commit --allow-empty -m init', { cwd: workingDirectory, stdio: 'pipe', env });
|
|
634
654
|
ensureLocalAttachmentGitExclude(workingDirectory);
|
|
635
655
|
}
|
|
636
656
|
catch {
|
|
@@ -639,43 +659,43 @@ function ensureGitRepo(workingDirectory) {
|
|
|
639
659
|
}
|
|
640
660
|
function buildTurnInput(body, images) {
|
|
641
661
|
return [
|
|
642
|
-
{ type:
|
|
643
|
-
...images.map((image) => ({ type:
|
|
662
|
+
{ type: 'text', text: body },
|
|
663
|
+
...images.map((image) => ({ type: 'localImage', path: image.localPath })),
|
|
644
664
|
];
|
|
645
665
|
}
|
|
646
666
|
function extractThreadId(result) {
|
|
647
|
-
if (!result || typeof result !==
|
|
667
|
+
if (!result || typeof result !== 'object')
|
|
648
668
|
return undefined;
|
|
649
669
|
const r = result;
|
|
650
|
-
if (typeof r.threadId ===
|
|
670
|
+
if (typeof r.threadId === 'string')
|
|
651
671
|
return r.threadId;
|
|
652
672
|
const thread = r.thread;
|
|
653
|
-
if (thread && typeof thread.id ===
|
|
673
|
+
if (thread && typeof thread.id === 'string')
|
|
654
674
|
return thread.id;
|
|
655
675
|
return undefined;
|
|
656
676
|
}
|
|
657
677
|
function extractTurnId(result) {
|
|
658
|
-
if (!result || typeof result !==
|
|
678
|
+
if (!result || typeof result !== 'object')
|
|
659
679
|
return undefined;
|
|
660
680
|
const r = result;
|
|
661
|
-
if (typeof r.turnId ===
|
|
681
|
+
if (typeof r.turnId === 'string')
|
|
662
682
|
return r.turnId;
|
|
663
683
|
const turn = r.turn;
|
|
664
|
-
if (turn && typeof turn.id ===
|
|
684
|
+
if (turn && typeof turn.id === 'string')
|
|
665
685
|
return turn.id;
|
|
666
686
|
return undefined;
|
|
667
687
|
}
|
|
668
688
|
function extractThreadIdFromNotification(params) {
|
|
669
|
-
if (!params || typeof params !==
|
|
689
|
+
if (!params || typeof params !== 'object')
|
|
670
690
|
return undefined;
|
|
671
691
|
const p = params;
|
|
672
|
-
if (typeof p.threadId ===
|
|
692
|
+
if (typeof p.threadId === 'string')
|
|
673
693
|
return p.threadId;
|
|
674
694
|
const thread = p.thread;
|
|
675
|
-
if (thread && typeof thread.id ===
|
|
695
|
+
if (thread && typeof thread.id === 'string')
|
|
676
696
|
return thread.id;
|
|
677
697
|
const meta = (p._meta ?? p.meta);
|
|
678
|
-
if (meta && typeof meta.threadId ===
|
|
698
|
+
if (meta && typeof meta.threadId === 'string')
|
|
679
699
|
return meta.threadId;
|
|
680
700
|
return undefined;
|
|
681
701
|
}
|
package/dist/event-mapping.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"event-mapping.d.ts","sourceRoot":"","sources":["../src/event-mapping.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,aAAa,CAA6B;IAE3D;;;OAGG;IACH,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,YAAY,EAAE;IA8CpD,OAAO,CAAC,OAAO;
|
|
1
|
+
{"version":3,"file":"event-mapping.d.ts","sourceRoot":"","sources":["../src/event-mapping.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,aAAa,CAA6B;IAE3D;;;OAGG;IACH,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,YAAY,EAAE;IA8CpD,OAAO,CAAC,OAAO;IA4Jf;;;;;OAKG;IACH,OAAO,CAAC,eAAe;CAaxB"}
|