@parall/agent-core 1.29.2 → 1.30.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.
@@ -4,6 +4,7 @@ export type GatewayLogger = {
4
4
  info: (msg: string) => void;
5
5
  warn: (msg: string) => void;
6
6
  error: (msg: string) => void;
7
+ child?: (sub: string) => GatewayLogger;
7
8
  };
8
9
  export type DispatchContext = {
9
10
  accountId: string;
@@ -1 +1 @@
1
- {"version":3,"file":"dispatch-adapter.d.ts","sourceRoot":"","sources":["../src/dispatch-adapter.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"dispatch-adapter.d.ts","sourceRoot":"","sources":["../src/dispatch-adapter.ts"],"names":[],"mappings":"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"}
@@ -35,6 +35,7 @@ export type ParallGatewayOptions = {
35
35
  runtimeLaneKey: string;
36
36
  }) => Promise<void> | void;
37
37
  onBeforeDisconnect?: () => Promise<void> | void;
38
+ onNewSession?: (previousSessionId: string) => Promise<void> | void;
38
39
  };
39
40
  export declare function parseShutdownDeadlineMs(raw: string | undefined): number | undefined;
40
41
  export declare class ParallAgentGateway {
@@ -56,6 +57,7 @@ export declare class ParallAgentGateway {
56
57
  private shuttingDown;
57
58
  private inFlightDispatches;
58
59
  private drainResolvers;
60
+ private pendingRestartNotification;
59
61
  private readonly DISPATCHED_MESSAGES_CAP;
60
62
  private readonly COLD_START_WINDOW_MS;
61
63
  private readonly SHUTDOWN_DEADLINE_MS;
@@ -1 +1 @@
1
- {"version":3,"file":"gateway-base.d.ts","sourceRoot":"","sources":["../src/gateway-base.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"gateway-base.d.ts","sourceRoot":"","sources":["../src/gateway-base.ts"],"names":[],"mappings":"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"}
@@ -78,6 +78,7 @@ export class ParallAgentGateway {
78
78
  shuttingDown = false;
79
79
  inFlightDispatches = 0;
80
80
  drainResolvers = [];
81
+ pendingRestartNotification = null;
81
82
  DISPATCHED_MESSAGES_CAP = 5000;
82
83
  COLD_START_WINDOW_MS;
83
84
  // SHUTDOWN_DEADLINE_MS is read by waitForDrain via the configured value
@@ -92,7 +93,7 @@ export class ParallAgentGateway {
92
93
  async run(abortSignal) {
93
94
  const { ws, log } = this.opts;
94
95
  ws.onStateChange((state) => {
95
- log?.info(`parall[${this.opts.accountId}]: connection state → ${state}`);
96
+ log?.info(`connection state → ${state}`);
96
97
  });
97
98
  ws.on("hello", async (data) => {
98
99
  await this.handleHello(data);
@@ -126,17 +127,32 @@ export class ParallAgentGateway {
126
127
  await this.handleMessage(data);
127
128
  });
128
129
  ws.on("agent_config.update", async (data) => {
129
- this.opts.log?.info(`parall[${this.opts.accountId}]: config update notification (version=${data.version})`);
130
+ this.opts.log?.info(`config update notification (version=${data.version})`);
130
131
  try {
131
132
  await this.opts.onConfigUpdate?.(data);
132
133
  }
133
134
  catch (err) {
134
- this.opts.log?.warn(`parall[${this.opts.accountId}]: config update failed: ${String(err)}`);
135
+ this.opts.log?.warn(`config update failed: ${String(err)}`);
136
+ }
137
+ });
138
+ ws.on("agent.new_session", async (data) => {
139
+ const prevId = data.previous_session_id ?? "";
140
+ this.opts.log?.info(`new session signal received (previous=${prevId})`);
141
+ this.sessionBindings.clear();
142
+ if (prevId) {
143
+ this.pendingRestartNotification =
144
+ `[Harness Notification] This is a fresh session. Your previous session (${prevId}) was ended by the user and you have been restarted.`;
145
+ }
146
+ try {
147
+ await this.opts.onNewSession?.(prevId);
148
+ }
149
+ catch (err) {
150
+ this.opts.log?.warn(`onNewSession callback failed: ${String(err)}`);
135
151
  }
136
152
  });
137
153
  ws.on("recovery.overflow", () => {
138
- this.opts.log?.warn(`parall[${this.opts.accountId}]: recovery.overflow — triggering full catch-up`);
139
- this.catchUpFromDispatch().catch((err) => this.opts.log?.warn(`parall[${this.opts.accountId}]: overflow catch-up failed: ${String(err)}`));
154
+ this.opts.log?.warn(`recovery.overflow — triggering full catch-up`);
155
+ this.catchUpFromDispatch().catch((err) => this.opts.log?.warn(`overflow catch-up failed: ${String(err)}`));
140
156
  });
141
157
  ws.on("task.assigned", async (data) => {
142
158
  if (data.assignee_id !== this.opts.agentUserId)
@@ -150,7 +166,7 @@ export class ParallAgentGateway {
150
166
  }
151
167
  }
152
168
  catch (err) {
153
- this.opts.log?.error(`parall[${this.opts.accountId}]: task dispatch failed for ${data.id}: ${String(err)}`);
169
+ this.opts.log?.error(`task dispatch failed for ${data.id}: ${String(err)}`);
154
170
  }
155
171
  });
156
172
  ws.on("dispatch.new", async (data) => {
@@ -164,7 +180,7 @@ export class ParallAgentGateway {
164
180
  }
165
181
  }
166
182
  catch (err) {
167
- this.opts.log?.error(`parall[${this.opts.accountId}]: task comment dispatch failed for ${data.source_id}: ${String(err)}`);
183
+ this.opts.log?.error(`task comment dispatch failed for ${data.source_id}: ${String(err)}`);
168
184
  }
169
185
  }
170
186
  else if (data.event_type === "task_update") {
@@ -177,7 +193,7 @@ export class ParallAgentGateway {
177
193
  }
178
194
  }
179
195
  catch (err) {
180
- this.opts.log?.error(`parall[${this.opts.accountId}]: task update dispatch failed for ${data.task_id}: ${String(err)}`);
196
+ this.opts.log?.error(`task update dispatch failed for ${data.task_id}: ${String(err)}`);
181
197
  }
182
198
  }
183
199
  else if (data.event_type === "schedule.fire") {
@@ -190,7 +206,7 @@ export class ParallAgentGateway {
190
206
  }
191
207
  }
192
208
  catch (err) {
193
- this.opts.log?.error(`parall[${this.opts.accountId}]: schedule fire dispatch failed for ${data.source_id}: ${String(err)}`);
209
+ this.opts.log?.error(`schedule fire dispatch failed for ${data.source_id}: ${String(err)}`);
194
210
  }
195
211
  }
196
212
  else if (data.event_type === "approval_decided") {
@@ -203,7 +219,7 @@ export class ParallAgentGateway {
203
219
  }
204
220
  }
205
221
  catch (err) {
206
- this.opts.log?.error(`parall[${this.opts.accountId}]: approval decided dispatch failed for ${data.source_id}: ${String(err)}`);
222
+ this.opts.log?.error(`approval decided dispatch failed for ${data.source_id}: ${String(err)}`);
207
223
  }
208
224
  }
209
225
  else if (data.event_type !== "message" && data.event_type !== "task_assign") {
@@ -214,10 +230,10 @@ export class ParallAgentGateway {
214
230
  // (message.new, task.assigned) above and would otherwise spam
215
231
  // info-level logs for every inbound chat message / task
216
232
  // assignment on a busy agent.
217
- this.opts.log?.info(`parall[${this.opts.accountId}]: dispatch.new with unhandled event_type=${String(data.event_type)} (id=${data.id}) — no-op`);
233
+ this.opts.log?.info(`dispatch.new with unhandled event_type=${String(data.event_type)} (id=${data.id}) — no-op`);
218
234
  }
219
235
  });
220
- this.opts.log?.info(`parall[${this.opts.accountId}]: connecting to ${this.opts.connectionLabel ?? "Parall WS"}...`);
236
+ this.opts.log?.info(`connecting to ${this.opts.connectionLabel ?? "Parall WS"}...`);
221
237
  await ws.connect();
222
238
  return new Promise((resolve) => {
223
239
  abortSignal.addEventListener("abort", async () => {
@@ -341,7 +357,7 @@ export class ParallAgentGateway {
341
357
  });
342
358
  }
343
359
  catch (err) {
344
- this.opts.log?.warn(`parall[${this.opts.accountId}]: failed to create input step: ${String(err)}`);
360
+ this.opts.log?.warn(`failed to create input step: ${String(err)}`);
345
361
  }
346
362
  }
347
363
  async createRuntimeStep(sessionId, event, runtimeEvent, stepIdFilePath, contextFilePath) {
@@ -421,13 +437,13 @@ export class ParallAgentGateway {
421
437
  target_type: target.target_type,
422
438
  target_id: target.target_id,
423
439
  content: { text: runtimeEvent.message, suppressed: false },
424
- projection: true,
440
+ projection: false,
425
441
  });
426
442
  break;
427
443
  }
428
444
  }
429
445
  catch (err) {
430
- this.opts.log?.warn(`parall[${this.opts.accountId}]: failed to create ${runtimeEvent.type} step: ${String(err)}`);
446
+ this.opts.log?.warn(`failed to create ${runtimeEvent.type} step: ${String(err)}`);
431
447
  }
432
448
  }
433
449
  writeContextFile(filePath, ctx) {
@@ -436,7 +452,7 @@ export class ParallAgentGateway {
436
452
  fs.writeFileSync(filePath, JSON.stringify(ctx), "utf8");
437
453
  }
438
454
  catch (err) {
439
- this.opts.log?.warn(`parall[${this.opts.accountId}]: failed to write context file ${filePath}: ${String(err)}`);
455
+ this.opts.log?.warn(`failed to write context file ${filePath}: ${String(err)}`);
440
456
  }
441
457
  }
442
458
  updateContextFileStepId(filePath, stepId) {
@@ -447,7 +463,7 @@ export class ParallAgentGateway {
447
463
  fs.writeFileSync(filePath, JSON.stringify(ctx), "utf8");
448
464
  }
449
465
  catch (err) {
450
- this.opts.log?.warn(`parall[${this.opts.accountId}]: failed to update context file step_id ${filePath}: ${String(err)}`);
466
+ this.opts.log?.warn(`failed to update context file step_id ${filePath}: ${String(err)}`);
451
467
  }
452
468
  }
453
469
  updateContextFileSessionId(filePath, sessionId) {
@@ -458,7 +474,7 @@ export class ParallAgentGateway {
458
474
  fs.writeFileSync(filePath, JSON.stringify(ctx), "utf8");
459
475
  }
460
476
  catch (err) {
461
- this.opts.log?.warn(`parall[${this.opts.accountId}]: failed to update context file session_id ${filePath}: ${String(err)}`);
477
+ this.opts.log?.warn(`failed to update context file session_id ${filePath}: ${String(err)}`);
462
478
  }
463
479
  }
464
480
  /** @deprecated Use writeContextFile / updateContextFileStepId. */
@@ -468,7 +484,7 @@ export class ParallAgentGateway {
468
484
  fs.writeFileSync(filePath, stepId, "utf8");
469
485
  }
470
486
  catch (err) {
471
- this.opts.log?.warn(`parall[${this.opts.accountId}]: failed to write step id file ${filePath}: ${String(err)}`);
487
+ this.opts.log?.warn(`failed to write step id file ${filePath}: ${String(err)}`);
472
488
  }
473
489
  }
474
490
  /** @deprecated Use writeContextFile / updateContextFileStepId. */
@@ -534,9 +550,13 @@ export class ParallAgentGateway {
534
550
  // In-flight dispatches that started before the flag flipped keep running
535
551
  // and are awaited by shutdown() up to SHUTDOWN_DEADLINE_MS.
536
552
  if (this.shuttingDown) {
537
- this.opts.log?.info(`parall[${this.opts.accountId}]: skipping dispatch for ${event.messageId} (shutting down) — leaving unacked for catch-up on replacement pod`);
553
+ this.opts.log?.info(`skipping dispatch for ${event.messageId} (shutting down) — leaving unacked for catch-up on replacement pod`);
538
554
  return false;
539
555
  }
556
+ if (this.pendingRestartNotification) {
557
+ bodyForAgent = this.pendingRestartNotification + "\n\n---\n\n" + bodyForAgent;
558
+ this.pendingRestartNotification = null;
559
+ }
540
560
  setSessionChatId(sessionKey, event.targetId);
541
561
  setSessionMessageId(sessionKey, event.messageId);
542
562
  setDispatchMessageId(sessionKey, event.messageId);
@@ -685,7 +705,7 @@ export class ParallAgentGateway {
685
705
  }
686
706
  }
687
707
  catch (err) {
688
- this.opts.log?.error(`parall[${this.opts.accountId}]: fork dispatch failed for ${last.messageId}: ${String(err)}`);
708
+ this.opts.log?.error(`fork dispatch failed for ${last.messageId}: ${String(err)}`);
689
709
  for (const item of items) {
690
710
  item.resolve(false);
691
711
  }
@@ -705,7 +725,7 @@ export class ParallAgentGateway {
705
725
  historyPath = this.opts.dispatchAdapter.getSessionHistoryPath?.(fork.fork.sessionKey);
706
726
  }
707
727
  catch (err) {
708
- this.opts.log?.warn?.(`parall[${this.opts.accountId}]: failed to resolve fork history path: ${String(err)}`);
728
+ this.opts.log?.warn?.(`failed to resolve fork history path: ${String(err)}`);
709
729
  }
710
730
  this.dispatchState.pendingForkResults.push({
711
731
  forkSessionKey: fork.fork.sessionKey,
@@ -761,7 +781,7 @@ export class ParallAgentGateway {
761
781
  // pendingForkResults intact so dispatch catch-up on the replacement
762
782
  // pod is the single source of truth for replay.
763
783
  if (this.shuttingDown) {
764
- this.opts.log?.info(`parall[${this.opts.accountId}]: drainMainBuffer halted (shutting down) — ${this.dispatchState.mainBuffer.length} buffered, ${this.dispatchState.pendingForkResults.length} pending fork results left for catch-up`);
784
+ this.opts.log?.info(`drainMainBuffer halted (shutting down) — ${this.dispatchState.mainBuffer.length} buffered, ${this.dispatchState.pendingForkResults.length} pending fork results left for catch-up`);
765
785
  break;
766
786
  }
767
787
  const targetId = this.dispatchState.mainBuffer[0].targetId;
@@ -842,7 +862,7 @@ export class ParallAgentGateway {
842
862
  if (this.dispatchState.mainCurrentTargetId === event.targetId &&
843
863
  await this.opts.dispatchAdapter.enqueueDuringDispatch?.(this.opts.runtimeKey, buildEventBody(event))) {
844
864
  this.startInjectedTyping(event);
845
- this.opts.log?.info(`parall[${this.opts.accountId}]: steer injected for ${event.messageId} (will drain for bookkeeping)`);
865
+ this.opts.log?.info(`steer injected for ${event.messageId} (will drain for bookkeeping)`);
846
866
  }
847
867
  // If the main dispatch cycle ended while we awaited the steer RPC,
848
868
  // our event is buffered but no drain is in flight. Re-enter the
@@ -874,7 +894,7 @@ export class ParallAgentGateway {
874
894
  preDispatchBranchPoint: this.dispatchState.mainPreDispatchBranchPoint,
875
895
  });
876
896
  if (!fork) {
877
- this.opts.log?.warn(`parall[${this.opts.accountId}]: fork failed, buffering event for main session`);
897
+ this.opts.log?.warn(`fork failed, buffering event for main session`);
878
898
  this.dispatchState.mainBuffer.push(event);
879
899
  return false;
880
900
  }
@@ -890,7 +910,7 @@ export class ParallAgentGateway {
890
910
  activeFork.queue.push({ event, resolve });
891
911
  });
892
912
  this.runForkDrainLoop(activeFork).catch((err) => {
893
- this.opts.log?.error(`parall[${this.opts.accountId}]: fork drain loop error: ${String(err)}`);
913
+ this.opts.log?.error(`fork drain loop error: ${String(err)}`);
894
914
  });
895
915
  return firstEventPromise;
896
916
  }
@@ -911,7 +931,7 @@ export class ParallAgentGateway {
911
931
  return chatInfo;
912
932
  }
913
933
  catch (err) {
914
- this.opts.log?.warn(`parall[${this.opts.accountId}]: failed to resolve chat ${chatId}: ${String(err)}`);
934
+ this.opts.log?.warn(`failed to resolve chat ${chatId}: ${String(err)}`);
915
935
  return null;
916
936
  }
917
937
  }
@@ -985,7 +1005,7 @@ export class ParallAgentGateway {
985
1005
  }
986
1006
  }
987
1007
  catch (err) {
988
- this.opts.log?.error(`parall[${this.opts.accountId}]: event dispatch failed for ${data.id}: ${String(err)}`);
1008
+ this.opts.log?.error(`event dispatch failed for ${data.id}: ${String(err)}`);
989
1009
  this.dispatchedMessages.delete(data.id);
990
1010
  }
991
1011
  }
@@ -994,11 +1014,11 @@ export class ParallAgentGateway {
994
1014
  return false; // drain window — let server requeue via catch-up
995
1015
  const dedupeKey = `${task.id}:${task.updated_at}`;
996
1016
  if (this.dispatchedTasks.has(dedupeKey)) {
997
- this.opts.log?.info(`parall[${this.opts.accountId}]: skipping already-dispatched task ${task.identifier ?? task.id}`);
1017
+ this.opts.log?.info(`skipping already-dispatched task ${task.identifier ?? task.id}`);
998
1018
  return false;
999
1019
  }
1000
1020
  this.dispatchedTasks.add(dedupeKey);
1001
- this.opts.log?.info(`parall[${this.opts.accountId}]: task assigned: ${task.identifier ?? task.id} "${task.title}"`);
1021
+ this.opts.log?.info(`task assigned: ${task.identifier ?? task.id} "${task.title}"`);
1002
1022
  const parts = [`Title: ${task.title}`];
1003
1023
  parts.push(`Status: ${task.status}`, `Priority: ${task.priority}`);
1004
1024
  if (task.project_id)
@@ -1040,7 +1060,7 @@ export class ParallAgentGateway {
1040
1060
  const isAssignee = task.assignee_id === this.opts.agentUserId;
1041
1061
  const isCreatorUpdate = opts.allowCreator === true && task.creator_id === this.opts.agentUserId;
1042
1062
  if (!isAssignee && !isCreatorUpdate) {
1043
- this.opts.log?.info(`parall[${this.opts.accountId}]: skipping stale task dispatch ${ackSourceId ?? taskId} — assigned to ${task.assignee_id}, creator ${task.creator_id}`);
1063
+ this.opts.log?.info(`skipping stale task dispatch ${ackSourceId ?? taskId} — assigned to ${task.assignee_id}, creator ${task.creator_id}`);
1044
1064
  return true;
1045
1065
  }
1046
1066
  return this.handleTaskAssignment(task, ackSourceId);
@@ -1060,7 +1080,7 @@ export class ParallAgentGateway {
1060
1080
  const status = err?.status;
1061
1081
  if (status === 404) {
1062
1082
  // Comment deleted — ack stale dispatch so it doesn't pile up.
1063
- this.opts.log?.info(`parall[${this.opts.accountId}]: skipping deleted comment ${commentId}, acking stale dispatch`);
1083
+ this.opts.log?.info(`skipping deleted comment ${commentId}, acking stale dispatch`);
1064
1084
  this.dispatchedTasks.delete(dedupeKey);
1065
1085
  return true; // caller will ack
1066
1086
  }
@@ -1072,7 +1092,7 @@ export class ParallAgentGateway {
1072
1092
  return true; // null response = gone, ack stale dispatch
1073
1093
  }
1074
1094
  if (comment.hints?.no_reply) {
1075
- this.opts.log?.info(`parall[${this.opts.accountId}]: skipping no_reply task comment ${commentId}, acking stale dispatch`);
1095
+ this.opts.log?.info(`skipping no_reply task comment ${commentId}, acking stale dispatch`);
1076
1096
  this.dispatchedTasks.delete(dedupeKey);
1077
1097
  return true;
1078
1098
  }
@@ -1082,7 +1102,7 @@ export class ParallAgentGateway {
1082
1102
  }
1083
1103
  catch { /* task context is optional */ }
1084
1104
  const taskLabel = task ? `${task.identifier ?? task.id} "${task.title}"` : taskId;
1085
- this.opts.log?.info(`parall[${this.opts.accountId}]: task comment on ${taskLabel} by ${actorId ?? "unknown"}`);
1105
+ this.opts.log?.info(`task comment on ${taskLabel} by ${actorId ?? "unknown"}`);
1086
1106
  const parts = [];
1087
1107
  if (task) {
1088
1108
  parts.push(`Task: ${task.title} (prll://${task.id})`);
@@ -1141,10 +1161,10 @@ export class ParallAgentGateway {
1141
1161
  // already-delivered run — this is expected but operationally
1142
1162
  // visible, so warn (not info) keeps it findable during incident
1143
1163
  // triage. See docs/primitives/schedule.md § Snapshot 不变性.
1144
- this.opts.log?.warn(`parall[${this.opts.accountId}]: schedule run ${runId} not accessible (404), acking stale dispatch`);
1164
+ this.opts.log?.warn(`schedule run ${runId} not accessible (404), acking stale dispatch`);
1145
1165
  return true;
1146
1166
  }
1147
- this.opts.log?.warn(`parall[${this.opts.accountId}]: schedule run fetch failed for ${runId}, leaving pending: ${String(err)}`);
1167
+ this.opts.log?.warn(`schedule run fetch failed for ${runId}, leaving pending: ${String(err)}`);
1148
1168
  return false;
1149
1169
  }
1150
1170
  if (!run)
@@ -1158,7 +1178,7 @@ export class ParallAgentGateway {
1158
1178
  if (this.dispatchedTasks.has(dedupeKey))
1159
1179
  return false;
1160
1180
  this.dispatchedTasks.add(dedupeKey);
1161
- this.opts.log?.info(`parall[${this.opts.accountId}]: schedule fired: ${run.id} (schedule ${run.schedule_id})`);
1181
+ this.opts.log?.info(`schedule fired: ${run.id} (schedule ${run.schedule_id})`);
1162
1182
  const event = {
1163
1183
  type: "schedule",
1164
1184
  // Route by schedule_id (not attached chat_id) so concurrent fires of
@@ -1197,10 +1217,10 @@ export class ParallAgentGateway {
1197
1217
  catch (err) {
1198
1218
  const status = err?.status;
1199
1219
  if (status === 404 || status === 403) {
1200
- this.opts.log?.warn(`parall[${this.opts.accountId}]: approval ${approvalId} not accessible (${status}), acking stale dispatch`);
1220
+ this.opts.log?.warn(`approval ${approvalId} not accessible (${status}), acking stale dispatch`);
1201
1221
  return true;
1202
1222
  }
1203
- this.opts.log?.warn(`parall[${this.opts.accountId}]: approval fetch failed for ${approvalId}, leaving pending: ${String(err)}`);
1223
+ this.opts.log?.warn(`approval fetch failed for ${approvalId}, leaving pending: ${String(err)}`);
1204
1224
  return false;
1205
1225
  }
1206
1226
  if (!approval)
@@ -1211,7 +1231,7 @@ export class ParallAgentGateway {
1211
1231
  if (this.dispatchedTasks.has(dedupeKey))
1212
1232
  return false;
1213
1233
  this.dispatchedTasks.add(dedupeKey);
1214
- this.opts.log?.info(`parall[${this.opts.accountId}]: approval decided: ${approval.id} (${approval.status})`);
1234
+ this.opts.log?.info(`approval decided: ${approval.id} (${approval.status})`);
1215
1235
  const statusLabel = approval.status === "approved" ? "Approved" : "Rejected";
1216
1236
  const execInfo = approval.execution_status ? ` | execution: ${approval.execution_status}` : "";
1217
1237
  const body = `${statusLabel}: ${approval.title}${execInfo}`;
@@ -1264,7 +1284,7 @@ export class ParallAgentGateway {
1264
1284
  dispatched = await this.handleTaskDispatch(item.task_id, item.source_id ?? item.task_id);
1265
1285
  }
1266
1286
  catch (err) {
1267
- this.opts.log?.warn(`parall[${this.opts.accountId}]: catch-up task fetch failed for ${item.task_id}, leaving pending: ${String(err)}`);
1287
+ this.opts.log?.warn(`catch-up task fetch failed for ${item.task_id}, leaving pending: ${String(err)}`);
1268
1288
  continue;
1269
1289
  }
1270
1290
  }
@@ -1273,7 +1293,7 @@ export class ParallAgentGateway {
1273
1293
  dispatched = await this.handleTaskDispatch(item.task_id, item.source_id ?? item.task_id, { allowCreator: true });
1274
1294
  }
1275
1295
  catch (err) {
1276
- this.opts.log?.warn(`parall[${this.opts.accountId}]: catch-up task fetch failed for ${item.task_id}, leaving pending: ${String(err)}`);
1296
+ this.opts.log?.warn(`catch-up task fetch failed for ${item.task_id}, leaving pending: ${String(err)}`);
1277
1297
  continue;
1278
1298
  }
1279
1299
  }
@@ -1301,7 +1321,7 @@ export class ParallAgentGateway {
1301
1321
  }
1302
1322
  else {
1303
1323
  msgFetchFailed = true;
1304
- this.opts.log?.warn(`parall[${this.opts.accountId}]: catch-up message fetch failed for ${item.source_id}, leaving pending: ${String(err)}`);
1324
+ this.opts.log?.warn(`catch-up message fetch failed for ${item.source_id}, leaving pending: ${String(err)}`);
1305
1325
  }
1306
1326
  }
1307
1327
  if (msgFetchFailed) {
@@ -1330,7 +1350,7 @@ export class ParallAgentGateway {
1330
1350
  }
1331
1351
  }
1332
1352
  catch (err) {
1333
- this.opts.log?.warn(`parall[${this.opts.accountId}]: catch-up dispatch ${item.id} (${item.event_type}) failed: ${String(err)}`);
1353
+ this.opts.log?.warn(`catch-up dispatch ${item.id} (${item.event_type}) failed: ${String(err)}`);
1334
1354
  }
1335
1355
  }
1336
1356
  // Stop paginating once shutdown begins — the inner loop already broke,
@@ -1338,7 +1358,7 @@ export class ParallAgentGateway {
1338
1358
  cursor = !this.shuttingDown && page.has_more ? page.next_cursor : undefined;
1339
1359
  } while (cursor);
1340
1360
  if (processed > 0 || skippedOld > 0) {
1341
- this.opts.log?.info(`parall[${this.opts.accountId}]: dispatch catch-up: processed ${processed}, skipped ${skippedOld} old item(s)`);
1361
+ this.opts.log?.info(`dispatch catch-up: processed ${processed}, skipped ${skippedOld} old item(s)`);
1342
1362
  }
1343
1363
  }
1344
1364
  async handleHello(data) {
@@ -1347,7 +1367,7 @@ export class ParallAgentGateway {
1347
1367
  const intervalSec = data.heartbeat_interval > 0 ? data.heartbeat_interval : 30;
1348
1368
  try {
1349
1369
  const count = await fetchAllChats(client, config.org_id, this.chatInfoMap);
1350
- log?.info(`parall[${this.opts.accountId}]: WebSocket connected, ${count} chats cached`);
1370
+ log?.info(`WebSocket connected, ${count} chats cached`);
1351
1371
  await this.opts.onSessionReady?.({
1352
1372
  activeSessionId: this.activeSessionId,
1353
1373
  ws: this.opts.ws,
@@ -1361,7 +1381,7 @@ export class ParallAgentGateway {
1361
1381
  const expectedMs = intervalSec * 1000;
1362
1382
  const drift = now - this.lastHeartbeatAt - expectedMs;
1363
1383
  if (drift > 15000) {
1364
- log?.warn(`parall[${this.opts.accountId}]: heartbeat drift ${drift}ms — event loop may be blocked`);
1384
+ log?.warn(`heartbeat drift ${drift}ms — event loop may be blocked`);
1365
1385
  }
1366
1386
  this.lastHeartbeatAt = now;
1367
1387
  if (this.opts.ws.state !== "connected")
@@ -1377,11 +1397,11 @@ export class ParallAgentGateway {
1377
1397
  const isFirstHello = !this.hadSuccessfulHello;
1378
1398
  this.hadSuccessfulHello = true;
1379
1399
  this.catchUpFromDispatch(isFirstHello).catch((err) => {
1380
- log?.warn(`parall[${this.opts.accountId}]: dispatch catch-up failed: ${String(err)}`);
1400
+ log?.warn(`dispatch catch-up failed: ${String(err)}`);
1381
1401
  });
1382
1402
  }
1383
1403
  catch (err) {
1384
- log?.error(`parall[${this.opts.accountId}]: failed to fetch chats: ${String(err)}`);
1404
+ log?.error(`failed to fetch chats: ${String(err)}`);
1385
1405
  }
1386
1406
  }
1387
1407
  // Resolves when in-flight dispatches hit 0 or the deadline elapses.
@@ -1414,13 +1434,13 @@ export class ParallAgentGateway {
1414
1434
  // the process exit — that's acceptable because K8s will retry the event
1415
1435
  // via dispatch catch-up after the new pod starts.
1416
1436
  if (this.inFlightDispatches > 0) {
1417
- this.opts.log?.info(`parall[${this.opts.accountId}]: draining ${this.inFlightDispatches} in-flight dispatch(es), deadline ${this.SHUTDOWN_DEADLINE_MS}ms`);
1437
+ this.opts.log?.info(`draining ${this.inFlightDispatches} in-flight dispatch(es), deadline ${this.SHUTDOWN_DEADLINE_MS}ms`);
1418
1438
  await this.waitForDrain(this.SHUTDOWN_DEADLINE_MS);
1419
1439
  if (this.inFlightDispatches > 0) {
1420
- this.opts.log?.warn(`parall[${this.opts.accountId}]: drain deadline hit; ${this.inFlightDispatches} dispatch(es) still running — they will be killed by process exit`);
1440
+ this.opts.log?.warn(`drain deadline hit; ${this.inFlightDispatches} dispatch(es) still running — they will be killed by process exit`);
1421
1441
  }
1422
1442
  else {
1423
- this.opts.log?.info(`parall[${this.opts.accountId}]: drain complete`);
1443
+ this.opts.log?.info(`drain complete`);
1424
1444
  }
1425
1445
  }
1426
1446
  if (this.heartbeatTimer)
@@ -1431,6 +1451,6 @@ export class ParallAgentGateway {
1431
1451
  this.activeDispatches.clear();
1432
1452
  await this.opts.onBeforeDisconnect?.();
1433
1453
  this.opts.ws.disconnect();
1434
- this.opts.log?.info(`parall[${this.opts.accountId}]: disconnected`);
1454
+ this.opts.log?.info(`disconnected`);
1435
1455
  }
1436
1456
  }
package/dist/index.d.ts CHANGED
@@ -5,7 +5,7 @@ export * from "./event-format.js";
5
5
  export * from "./prompt-fragments.js";
6
6
  export * from "./bridge-workspace.js";
7
7
  export * from "./dispatch-adapter.js";
8
- export { createLogger } from "./logger.js";
8
+ export { createLogger, childLogger } from "./logger.js";
9
9
  export * from "./gateway-base.js";
10
10
  export * from "./platform-config.js";
11
11
  export { writeSkillFiles, buildSkillReferences, SKILLS } from "./skills/index.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,oBAAoB,CAAC;AACnC,cAAc,cAAc,CAAC;AAC7B,cAAc,mBAAmB,CAAC;AAClC,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,cAAc,mBAAmB,CAAC;AAClC,cAAc,sBAAsB,CAAC;AACrC,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAClF,YAAY,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,oBAAoB,CAAC;AACnC,cAAc,cAAc,CAAC;AAC7B,cAAc,mBAAmB,CAAC;AAClC,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACxD,cAAc,mBAAmB,CAAC;AAClC,cAAc,sBAAsB,CAAC;AACrC,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAClF,YAAY,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC"}
package/dist/index.js CHANGED
@@ -5,7 +5,7 @@ export * from "./event-format.js";
5
5
  export * from "./prompt-fragments.js";
6
6
  export * from "./bridge-workspace.js";
7
7
  export * from "./dispatch-adapter.js";
8
- export { createLogger } from "./logger.js";
8
+ export { createLogger, childLogger } from "./logger.js";
9
9
  export * from "./gateway-base.js";
10
10
  export * from "./platform-config.js";
11
11
  export { writeSkillFiles, buildSkillReferences, SKILLS } from "./skills/index.js";
package/dist/logger.d.ts CHANGED
@@ -1,3 +1,4 @@
1
1
  import type { GatewayLogger } from "./dispatch-adapter.js";
2
2
  export declare function createLogger(prefix: string): GatewayLogger;
3
+ export declare function childLogger(logger: GatewayLogger, sub: string): GatewayLogger;
3
4
  //# sourceMappingURL=logger.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAE3D,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,aAAa,CAM1D"}
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAE3D,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,aAAa,CAO1D;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,aAAa,EAAE,GAAG,EAAE,MAAM,GAAG,aAAa,CAE7E"}
package/dist/logger.js CHANGED
@@ -3,5 +3,9 @@ export function createLogger(prefix) {
3
3
  info: (msg) => console.log(`${new Date().toISOString()} [${prefix}] ${msg}`),
4
4
  warn: (msg) => console.warn(`${new Date().toISOString()} [${prefix}] ${msg}`),
5
5
  error: (msg) => console.error(`${new Date().toISOString()} [${prefix}] ${msg}`),
6
+ child: (sub) => createLogger(`${prefix}:${sub}`),
6
7
  };
7
8
  }
9
+ export function childLogger(logger, sub) {
10
+ return logger.child ? logger.child(sub) : logger;
11
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@parall/agent-core",
3
- "version": "1.29.2",
3
+ "version": "1.30.0",
4
4
  "description": "Shared agent runtime orchestration helpers for Parall",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -26,7 +26,7 @@
26
26
  "src"
27
27
  ],
28
28
  "dependencies": {
29
- "@parall/sdk": "1.29.2"
29
+ "@parall/sdk": "1.30.0"
30
30
  },
31
31
  "devDependencies": {
32
32
  "@types/node": "^22.0.0",
@@ -5,6 +5,7 @@ export type GatewayLogger = {
5
5
  info: (msg: string) => void;
6
6
  warn: (msg: string) => void;
7
7
  error: (msg: string) => void;
8
+ child?: (sub: string) => GatewayLogger;
8
9
  };
9
10
 
10
11
  export type DispatchContext = {
@@ -4,6 +4,7 @@ import * as path from "node:path";
4
4
  import { MENTION_ALL_USER_ID, ParallClient, ParallWs } from "@parall/sdk";
5
5
  import type {
6
6
  AgentConfigUpdateData,
7
+ AgentNewSessionData,
7
8
  AgentSessionDB,
8
9
  Approval,
9
10
  Chat,
@@ -107,6 +108,7 @@ export type ParallGatewayOptions = {
107
108
  onSessionReady?: (state: { activeSessionId?: string; ws: ParallWs; runtimeKey: string }) => Promise<void> | void;
108
109
  onSessionBinding?: (state: { sessionKey: string; agentSessionId: string; runtimeSessionId: string; runtimeLaneKey: string }) => Promise<void> | void;
109
110
  onBeforeDisconnect?: () => Promise<void> | void;
111
+ onNewSession?: (previousSessionId: string) => Promise<void> | void;
110
112
  };
111
113
 
112
114
  type AgentSessionBinding = {
@@ -196,6 +198,7 @@ export class ParallAgentGateway {
196
198
  private shuttingDown = false;
197
199
  private inFlightDispatches = 0;
198
200
  private drainResolvers: Array<() => void> = [];
201
+ private pendingRestartNotification: string | null = null;
199
202
 
200
203
  private readonly DISPATCHED_MESSAGES_CAP = 5000;
201
204
  private readonly COLD_START_WINDOW_MS: number;
@@ -213,7 +216,7 @@ export class ParallAgentGateway {
213
216
  const { ws, log } = this.opts;
214
217
 
215
218
  ws.onStateChange((state) => {
216
- log?.info(`parall[${this.opts.accountId}]: connection state → ${state}`);
219
+ log?.info(`connection state → ${state}`);
217
220
  });
218
221
 
219
222
  ws.on("hello", async (data: HelloData) => {
@@ -249,18 +252,33 @@ export class ParallAgentGateway {
249
252
  });
250
253
 
251
254
  ws.on("agent_config.update", async (data: AgentConfigUpdateData) => {
252
- this.opts.log?.info(`parall[${this.opts.accountId}]: config update notification (version=${data.version})`);
255
+ this.opts.log?.info(`config update notification (version=${data.version})`);
253
256
  try {
254
257
  await this.opts.onConfigUpdate?.(data);
255
258
  } catch (err) {
256
- this.opts.log?.warn(`parall[${this.opts.accountId}]: config update failed: ${String(err)}`);
259
+ this.opts.log?.warn(`config update failed: ${String(err)}`);
260
+ }
261
+ });
262
+
263
+ ws.on("agent.new_session", async (data: AgentNewSessionData) => {
264
+ const prevId = data.previous_session_id ?? "";
265
+ this.opts.log?.info(`new session signal received (previous=${prevId})`);
266
+ this.sessionBindings.clear();
267
+ if (prevId) {
268
+ this.pendingRestartNotification =
269
+ `[Harness Notification] This is a fresh session. Your previous session (${prevId}) was ended by the user and you have been restarted.`;
270
+ }
271
+ try {
272
+ await this.opts.onNewSession?.(prevId);
273
+ } catch (err) {
274
+ this.opts.log?.warn(`onNewSession callback failed: ${String(err)}`);
257
275
  }
258
276
  });
259
277
 
260
278
  ws.on("recovery.overflow", () => {
261
- this.opts.log?.warn(`parall[${this.opts.accountId}]: recovery.overflow — triggering full catch-up`);
279
+ this.opts.log?.warn(`recovery.overflow — triggering full catch-up`);
262
280
  this.catchUpFromDispatch().catch((err) =>
263
- this.opts.log?.warn(`parall[${this.opts.accountId}]: overflow catch-up failed: ${String(err)}`));
281
+ this.opts.log?.warn(`overflow catch-up failed: ${String(err)}`));
264
282
  });
265
283
 
266
284
  ws.on("task.assigned", async (data: TaskAssignedData) => {
@@ -272,7 +290,7 @@ export class ParallAgentGateway {
272
290
  this.opts.client.ackDispatch(this.opts.config.org_id, { source_type: "task_activity", source_id: data.id }).catch(() => {});
273
291
  }
274
292
  } catch (err) {
275
- this.opts.log?.error(`parall[${this.opts.accountId}]: task dispatch failed for ${data.id}: ${String(err)}`);
293
+ this.opts.log?.error(`task dispatch failed for ${data.id}: ${String(err)}`);
276
294
  }
277
295
  });
278
296
 
@@ -285,7 +303,7 @@ export class ParallAgentGateway {
285
303
  this.opts.client.ackDispatchByID(this.opts.config.org_id, data.id).catch(() => {});
286
304
  }
287
305
  } catch (err) {
288
- this.opts.log?.error(`parall[${this.opts.accountId}]: task comment dispatch failed for ${data.source_id}: ${String(err)}`);
306
+ this.opts.log?.error(`task comment dispatch failed for ${data.source_id}: ${String(err)}`);
289
307
  }
290
308
  } else if (data.event_type === "task_update") {
291
309
  if (!data.task_id) return;
@@ -295,7 +313,7 @@ export class ParallAgentGateway {
295
313
  this.opts.client.ackDispatchByID(this.opts.config.org_id, data.id).catch(() => {});
296
314
  }
297
315
  } catch (err) {
298
- this.opts.log?.error(`parall[${this.opts.accountId}]: task update dispatch failed for ${data.task_id}: ${String(err)}`);
316
+ this.opts.log?.error(`task update dispatch failed for ${data.task_id}: ${String(err)}`);
299
317
  }
300
318
  } else if (data.event_type === "schedule.fire") {
301
319
  if (!data.source_id) return;
@@ -305,7 +323,7 @@ export class ParallAgentGateway {
305
323
  this.opts.client.ackDispatchByID(this.opts.config.org_id, data.id).catch(() => {});
306
324
  }
307
325
  } catch (err) {
308
- this.opts.log?.error(`parall[${this.opts.accountId}]: schedule fire dispatch failed for ${data.source_id}: ${String(err)}`);
326
+ this.opts.log?.error(`schedule fire dispatch failed for ${data.source_id}: ${String(err)}`);
309
327
  }
310
328
  } else if (data.event_type === "approval_decided") {
311
329
  if (!data.source_id) return;
@@ -315,7 +333,7 @@ export class ParallAgentGateway {
315
333
  this.opts.client.ackDispatchByID(this.opts.config.org_id, data.id).catch(() => {});
316
334
  }
317
335
  } catch (err) {
318
- this.opts.log?.error(`parall[${this.opts.accountId}]: approval decided dispatch failed for ${data.source_id}: ${String(err)}`);
336
+ this.opts.log?.error(`approval decided dispatch failed for ${data.source_id}: ${String(err)}`);
319
337
  }
320
338
  } else if (data.event_type !== "message" && data.event_type !== "task_assign") {
321
339
  // Truly unknown event_type — log so a newly-added dispatch type
@@ -325,11 +343,11 @@ export class ParallAgentGateway {
325
343
  // (message.new, task.assigned) above and would otherwise spam
326
344
  // info-level logs for every inbound chat message / task
327
345
  // assignment on a busy agent.
328
- this.opts.log?.info(`parall[${this.opts.accountId}]: dispatch.new with unhandled event_type=${String(data.event_type)} (id=${data.id}) — no-op`);
346
+ this.opts.log?.info(`dispatch.new with unhandled event_type=${String(data.event_type)} (id=${data.id}) — no-op`);
329
347
  }
330
348
  });
331
349
 
332
- this.opts.log?.info(`parall[${this.opts.accountId}]: connecting to ${this.opts.connectionLabel ?? "Parall WS"}...`);
350
+ this.opts.log?.info(`connecting to ${this.opts.connectionLabel ?? "Parall WS"}...`);
333
351
  await ws.connect();
334
352
 
335
353
  return new Promise<void>((resolve) => {
@@ -462,7 +480,7 @@ export class ParallAgentGateway {
462
480
  },
463
481
  });
464
482
  } catch (err) {
465
- this.opts.log?.warn(`parall[${this.opts.accountId}]: failed to create input step: ${String(err)}`);
483
+ this.opts.log?.warn(`failed to create input step: ${String(err)}`);
466
484
  }
467
485
  }
468
486
 
@@ -546,12 +564,12 @@ export class ParallAgentGateway {
546
564
  target_type: target.target_type,
547
565
  target_id: target.target_id,
548
566
  content: { text: runtimeEvent.message, suppressed: false },
549
- projection: true,
567
+ projection: false,
550
568
  });
551
569
  break;
552
570
  }
553
571
  } catch (err) {
554
- this.opts.log?.warn(`parall[${this.opts.accountId}]: failed to create ${runtimeEvent.type} step: ${String(err)}`);
572
+ this.opts.log?.warn(`failed to create ${runtimeEvent.type} step: ${String(err)}`);
555
573
  }
556
574
  }
557
575
 
@@ -560,7 +578,7 @@ export class ParallAgentGateway {
560
578
  fs.mkdirSync(path.dirname(filePath), { recursive: true });
561
579
  fs.writeFileSync(filePath, JSON.stringify(ctx), "utf8");
562
580
  } catch (err) {
563
- this.opts.log?.warn(`parall[${this.opts.accountId}]: failed to write context file ${filePath}: ${String(err)}`);
581
+ this.opts.log?.warn(`failed to write context file ${filePath}: ${String(err)}`);
564
582
  }
565
583
  }
566
584
 
@@ -571,7 +589,7 @@ export class ParallAgentGateway {
571
589
  ctx.step_id = stepId;
572
590
  fs.writeFileSync(filePath, JSON.stringify(ctx), "utf8");
573
591
  } catch (err) {
574
- this.opts.log?.warn(`parall[${this.opts.accountId}]: failed to update context file step_id ${filePath}: ${String(err)}`);
592
+ this.opts.log?.warn(`failed to update context file step_id ${filePath}: ${String(err)}`);
575
593
  }
576
594
  }
577
595
 
@@ -582,7 +600,7 @@ export class ParallAgentGateway {
582
600
  ctx.session_id = sessionId;
583
601
  fs.writeFileSync(filePath, JSON.stringify(ctx), "utf8");
584
602
  } catch (err) {
585
- this.opts.log?.warn(`parall[${this.opts.accountId}]: failed to update context file session_id ${filePath}: ${String(err)}`);
603
+ this.opts.log?.warn(`failed to update context file session_id ${filePath}: ${String(err)}`);
586
604
  }
587
605
  }
588
606
 
@@ -592,7 +610,7 @@ export class ParallAgentGateway {
592
610
  fs.mkdirSync(path.dirname(filePath), { recursive: true });
593
611
  fs.writeFileSync(filePath, stepId, "utf8");
594
612
  } catch (err) {
595
- this.opts.log?.warn(`parall[${this.opts.accountId}]: failed to write step id file ${filePath}: ${String(err)}`);
613
+ this.opts.log?.warn(`failed to write step id file ${filePath}: ${String(err)}`);
596
614
  }
597
615
  }
598
616
 
@@ -675,11 +693,16 @@ export class ParallAgentGateway {
675
693
  // and are awaited by shutdown() up to SHUTDOWN_DEADLINE_MS.
676
694
  if (this.shuttingDown) {
677
695
  this.opts.log?.info(
678
- `parall[${this.opts.accountId}]: skipping dispatch for ${event.messageId} (shutting down) — leaving unacked for catch-up on replacement pod`,
696
+ `skipping dispatch for ${event.messageId} (shutting down) — leaving unacked for catch-up on replacement pod`,
679
697
  );
680
698
  return false;
681
699
  }
682
700
 
701
+ if (this.pendingRestartNotification) {
702
+ bodyForAgent = this.pendingRestartNotification + "\n\n---\n\n" + bodyForAgent;
703
+ this.pendingRestartNotification = null;
704
+ }
705
+
683
706
  setSessionChatId(sessionKey, event.targetId);
684
707
  setSessionMessageId(sessionKey, event.messageId);
685
708
  setDispatchMessageId(sessionKey, event.messageId);
@@ -832,7 +855,7 @@ export class ParallAgentGateway {
832
855
  item.resolve(true);
833
856
  }
834
857
  } catch (err) {
835
- this.opts.log?.error(`parall[${this.opts.accountId}]: fork dispatch failed for ${last.messageId}: ${String(err)}`);
858
+ this.opts.log?.error(`fork dispatch failed for ${last.messageId}: ${String(err)}`);
836
859
  for (const item of items) {
837
860
  item.resolve(false);
838
861
  }
@@ -851,7 +874,7 @@ export class ParallAgentGateway {
851
874
  try {
852
875
  historyPath = this.opts.dispatchAdapter.getSessionHistoryPath?.(fork.fork.sessionKey);
853
876
  } catch (err) {
854
- this.opts.log?.warn?.(`parall[${this.opts.accountId}]: failed to resolve fork history path: ${String(err)}`);
877
+ this.opts.log?.warn?.(`failed to resolve fork history path: ${String(err)}`);
855
878
  }
856
879
  this.dispatchState.pendingForkResults.push({
857
880
  forkSessionKey: fork.fork.sessionKey,
@@ -911,7 +934,7 @@ export class ParallAgentGateway {
911
934
  // pod is the single source of truth for replay.
912
935
  if (this.shuttingDown) {
913
936
  this.opts.log?.info(
914
- `parall[${this.opts.accountId}]: drainMainBuffer halted (shutting down) — ${this.dispatchState.mainBuffer.length} buffered, ${this.dispatchState.pendingForkResults.length} pending fork results left for catch-up`,
937
+ `drainMainBuffer halted (shutting down) — ${this.dispatchState.mainBuffer.length} buffered, ${this.dispatchState.pendingForkResults.length} pending fork results left for catch-up`,
915
938
  );
916
939
  break;
917
940
  }
@@ -1006,7 +1029,7 @@ export class ParallAgentGateway {
1006
1029
  ) {
1007
1030
  this.startInjectedTyping(event);
1008
1031
  this.opts.log?.info(
1009
- `parall[${this.opts.accountId}]: steer injected for ${event.messageId} (will drain for bookkeeping)`,
1032
+ `steer injected for ${event.messageId} (will drain for bookkeeping)`,
1010
1033
  );
1011
1034
  }
1012
1035
  // If the main dispatch cycle ended while we awaited the steer RPC,
@@ -1043,7 +1066,7 @@ export class ParallAgentGateway {
1043
1066
  });
1044
1067
 
1045
1068
  if (!fork) {
1046
- this.opts.log?.warn(`parall[${this.opts.accountId}]: fork failed, buffering event for main session`);
1069
+ this.opts.log?.warn(`fork failed, buffering event for main session`);
1047
1070
  this.dispatchState.mainBuffer.push(event);
1048
1071
  return false;
1049
1072
  }
@@ -1061,7 +1084,7 @@ export class ParallAgentGateway {
1061
1084
  activeFork.queue.push({ event, resolve });
1062
1085
  });
1063
1086
  this.runForkDrainLoop(activeFork).catch((err) => {
1064
- this.opts.log?.error(`parall[${this.opts.accountId}]: fork drain loop error: ${String(err)}`);
1087
+ this.opts.log?.error(`fork drain loop error: ${String(err)}`);
1065
1088
  });
1066
1089
  return firstEventPromise;
1067
1090
  }
@@ -1081,7 +1104,7 @@ export class ParallAgentGateway {
1081
1104
  this.chatInfoMap.set(chatId, chatInfo);
1082
1105
  return chatInfo;
1083
1106
  } catch (err) {
1084
- this.opts.log?.warn(`parall[${this.opts.accountId}]: failed to resolve chat ${chatId}: ${String(err)}`);
1107
+ this.opts.log?.warn(`failed to resolve chat ${chatId}: ${String(err)}`);
1085
1108
  return null;
1086
1109
  }
1087
1110
  }
@@ -1161,7 +1184,7 @@ export class ParallAgentGateway {
1161
1184
  this.dispatchedMessages.delete(data.id);
1162
1185
  }
1163
1186
  } catch (err) {
1164
- this.opts.log?.error(`parall[${this.opts.accountId}]: event dispatch failed for ${data.id}: ${String(err)}`);
1187
+ this.opts.log?.error(`event dispatch failed for ${data.id}: ${String(err)}`);
1165
1188
  this.dispatchedMessages.delete(data.id);
1166
1189
  }
1167
1190
  }
@@ -1170,11 +1193,11 @@ export class ParallAgentGateway {
1170
1193
  if (this.shuttingDown) return false; // drain window — let server requeue via catch-up
1171
1194
  const dedupeKey = `${task.id}:${task.updated_at}`;
1172
1195
  if (this.dispatchedTasks.has(dedupeKey)) {
1173
- this.opts.log?.info(`parall[${this.opts.accountId}]: skipping already-dispatched task ${task.identifier ?? task.id}`);
1196
+ this.opts.log?.info(`skipping already-dispatched task ${task.identifier ?? task.id}`);
1174
1197
  return false;
1175
1198
  }
1176
1199
  this.dispatchedTasks.add(dedupeKey);
1177
- this.opts.log?.info(`parall[${this.opts.accountId}]: task assigned: ${task.identifier ?? task.id} "${task.title}"`);
1200
+ this.opts.log?.info(`task assigned: ${task.identifier ?? task.id} "${task.title}"`);
1178
1201
 
1179
1202
  const parts = [`Title: ${task.title}`];
1180
1203
  parts.push(`Status: ${task.status}`, `Priority: ${task.priority}`);
@@ -1220,7 +1243,7 @@ export class ParallAgentGateway {
1220
1243
  const isCreatorUpdate = opts.allowCreator === true && task.creator_id === this.opts.agentUserId;
1221
1244
  if (!isAssignee && !isCreatorUpdate) {
1222
1245
  this.opts.log?.info(
1223
- `parall[${this.opts.accountId}]: skipping stale task dispatch ${ackSourceId ?? taskId} — assigned to ${task.assignee_id}, creator ${task.creator_id}`,
1246
+ `skipping stale task dispatch ${ackSourceId ?? taskId} — assigned to ${task.assignee_id}, creator ${task.creator_id}`,
1224
1247
  );
1225
1248
  return true;
1226
1249
  }
@@ -1245,7 +1268,7 @@ export class ParallAgentGateway {
1245
1268
  const status = (err as { status?: number })?.status;
1246
1269
  if (status === 404) {
1247
1270
  // Comment deleted — ack stale dispatch so it doesn't pile up.
1248
- this.opts.log?.info(`parall[${this.opts.accountId}]: skipping deleted comment ${commentId}, acking stale dispatch`);
1271
+ this.opts.log?.info(`skipping deleted comment ${commentId}, acking stale dispatch`);
1249
1272
  this.dispatchedTasks.delete(dedupeKey);
1250
1273
  return true; // caller will ack
1251
1274
  }
@@ -1257,7 +1280,7 @@ export class ParallAgentGateway {
1257
1280
  return true; // null response = gone, ack stale dispatch
1258
1281
  }
1259
1282
  if (comment.hints?.no_reply) {
1260
- this.opts.log?.info(`parall[${this.opts.accountId}]: skipping no_reply task comment ${commentId}, acking stale dispatch`);
1283
+ this.opts.log?.info(`skipping no_reply task comment ${commentId}, acking stale dispatch`);
1261
1284
  this.dispatchedTasks.delete(dedupeKey);
1262
1285
  return true;
1263
1286
  }
@@ -1268,7 +1291,7 @@ export class ParallAgentGateway {
1268
1291
  } catch { /* task context is optional */ }
1269
1292
 
1270
1293
  const taskLabel = task ? `${task.identifier ?? task.id} "${task.title}"` : taskId;
1271
- this.opts.log?.info(`parall[${this.opts.accountId}]: task comment on ${taskLabel} by ${actorId ?? "unknown"}`);
1294
+ this.opts.log?.info(`task comment on ${taskLabel} by ${actorId ?? "unknown"}`);
1272
1295
 
1273
1296
  const parts: string[] = [];
1274
1297
  if (task) {
@@ -1328,10 +1351,10 @@ export class ParallAgentGateway {
1328
1351
  // already-delivered run — this is expected but operationally
1329
1352
  // visible, so warn (not info) keeps it findable during incident
1330
1353
  // triage. See docs/primitives/schedule.md § Snapshot 不变性.
1331
- this.opts.log?.warn(`parall[${this.opts.accountId}]: schedule run ${runId} not accessible (404), acking stale dispatch`);
1354
+ this.opts.log?.warn(`schedule run ${runId} not accessible (404), acking stale dispatch`);
1332
1355
  return true;
1333
1356
  }
1334
- this.opts.log?.warn(`parall[${this.opts.accountId}]: schedule run fetch failed for ${runId}, leaving pending: ${String(err)}`);
1357
+ this.opts.log?.warn(`schedule run fetch failed for ${runId}, leaving pending: ${String(err)}`);
1335
1358
  return false;
1336
1359
  }
1337
1360
  if (!run) return true;
@@ -1343,7 +1366,7 @@ export class ParallAgentGateway {
1343
1366
  const dedupeKey = `schedule_run:${run.id}`;
1344
1367
  if (this.dispatchedTasks.has(dedupeKey)) return false;
1345
1368
  this.dispatchedTasks.add(dedupeKey);
1346
- this.opts.log?.info(`parall[${this.opts.accountId}]: schedule fired: ${run.id} (schedule ${run.schedule_id})`);
1369
+ this.opts.log?.info(`schedule fired: ${run.id} (schedule ${run.schedule_id})`);
1347
1370
 
1348
1371
  const event: ParallEvent = {
1349
1372
  type: "schedule",
@@ -1383,10 +1406,10 @@ export class ParallAgentGateway {
1383
1406
  } catch (err: unknown) {
1384
1407
  const status = (err as { status?: number })?.status;
1385
1408
  if (status === 404 || status === 403) {
1386
- this.opts.log?.warn(`parall[${this.opts.accountId}]: approval ${approvalId} not accessible (${status}), acking stale dispatch`);
1409
+ this.opts.log?.warn(`approval ${approvalId} not accessible (${status}), acking stale dispatch`);
1387
1410
  return true;
1388
1411
  }
1389
- this.opts.log?.warn(`parall[${this.opts.accountId}]: approval fetch failed for ${approvalId}, leaving pending: ${String(err)}`);
1412
+ this.opts.log?.warn(`approval fetch failed for ${approvalId}, leaving pending: ${String(err)}`);
1390
1413
  return false;
1391
1414
  }
1392
1415
  if (!approval) return true;
@@ -1395,7 +1418,7 @@ export class ParallAgentGateway {
1395
1418
  const dedupeKey = `approval:${approval.id}`;
1396
1419
  if (this.dispatchedTasks.has(dedupeKey)) return false;
1397
1420
  this.dispatchedTasks.add(dedupeKey);
1398
- this.opts.log?.info(`parall[${this.opts.accountId}]: approval decided: ${approval.id} (${approval.status})`);
1421
+ this.opts.log?.info(`approval decided: ${approval.id} (${approval.status})`);
1399
1422
 
1400
1423
  const statusLabel = approval.status === "approved" ? "Approved" : "Rejected";
1401
1424
  const execInfo = approval.execution_status ? ` | execution: ${approval.execution_status}` : "";
@@ -1452,14 +1475,14 @@ export class ParallAgentGateway {
1452
1475
  try {
1453
1476
  dispatched = await this.handleTaskDispatch(item.task_id, item.source_id ?? item.task_id);
1454
1477
  } catch (err: unknown) {
1455
- this.opts.log?.warn(`parall[${this.opts.accountId}]: catch-up task fetch failed for ${item.task_id}, leaving pending: ${String(err)}`);
1478
+ this.opts.log?.warn(`catch-up task fetch failed for ${item.task_id}, leaving pending: ${String(err)}`);
1456
1479
  continue;
1457
1480
  }
1458
1481
  } else if (item.event_type === "task_update" && item.task_id) {
1459
1482
  try {
1460
1483
  dispatched = await this.handleTaskDispatch(item.task_id, item.source_id ?? item.task_id, { allowCreator: true });
1461
1484
  } catch (err: unknown) {
1462
- this.opts.log?.warn(`parall[${this.opts.accountId}]: catch-up task fetch failed for ${item.task_id}, leaving pending: ${String(err)}`);
1485
+ this.opts.log?.warn(`catch-up task fetch failed for ${item.task_id}, leaving pending: ${String(err)}`);
1463
1486
  continue;
1464
1487
  }
1465
1488
  } else if (item.event_type === "task_comment" && item.source_id && item.task_id) {
@@ -1480,7 +1503,7 @@ export class ParallAgentGateway {
1480
1503
  msg = null;
1481
1504
  } else {
1482
1505
  msgFetchFailed = true;
1483
- this.opts.log?.warn(`parall[${this.opts.accountId}]: catch-up message fetch failed for ${item.source_id}, leaving pending: ${String(err)}`);
1506
+ this.opts.log?.warn(`catch-up message fetch failed for ${item.source_id}, leaving pending: ${String(err)}`);
1484
1507
  }
1485
1508
  }
1486
1509
  if (msgFetchFailed) {
@@ -1510,7 +1533,7 @@ export class ParallAgentGateway {
1510
1533
  this.opts.client.ackDispatchByID(this.opts.config.org_id, item.id).catch(() => {});
1511
1534
  }
1512
1535
  } catch (err) {
1513
- this.opts.log?.warn(`parall[${this.opts.accountId}]: catch-up dispatch ${item.id} (${item.event_type}) failed: ${String(err)}`);
1536
+ this.opts.log?.warn(`catch-up dispatch ${item.id} (${item.event_type}) failed: ${String(err)}`);
1514
1537
  }
1515
1538
  }
1516
1539
  // Stop paginating once shutdown begins — the inner loop already broke,
@@ -1519,7 +1542,7 @@ export class ParallAgentGateway {
1519
1542
  } while (cursor);
1520
1543
 
1521
1544
  if (processed > 0 || skippedOld > 0) {
1522
- this.opts.log?.info(`parall[${this.opts.accountId}]: dispatch catch-up: processed ${processed}, skipped ${skippedOld} old item(s)`);
1545
+ this.opts.log?.info(`dispatch catch-up: processed ${processed}, skipped ${skippedOld} old item(s)`);
1523
1546
  }
1524
1547
  }
1525
1548
 
@@ -1529,7 +1552,7 @@ export class ParallAgentGateway {
1529
1552
  const intervalSec = data.heartbeat_interval > 0 ? data.heartbeat_interval : 30;
1530
1553
  try {
1531
1554
  const count = await fetchAllChats(client, config.org_id, this.chatInfoMap);
1532
- log?.info(`parall[${this.opts.accountId}]: WebSocket connected, ${count} chats cached`);
1555
+ log?.info(`WebSocket connected, ${count} chats cached`);
1533
1556
 
1534
1557
  await this.opts.onSessionReady?.({
1535
1558
  activeSessionId: this.activeSessionId,
@@ -1544,7 +1567,7 @@ export class ParallAgentGateway {
1544
1567
  const expectedMs = intervalSec * 1000;
1545
1568
  const drift = now - this.lastHeartbeatAt - expectedMs;
1546
1569
  if (drift > 15000) {
1547
- log?.warn(`parall[${this.opts.accountId}]: heartbeat drift ${drift}ms — event loop may be blocked`);
1570
+ log?.warn(`heartbeat drift ${drift}ms — event loop may be blocked`);
1548
1571
  }
1549
1572
  this.lastHeartbeatAt = now;
1550
1573
  if (this.opts.ws.state !== "connected") return;
@@ -1560,10 +1583,10 @@ export class ParallAgentGateway {
1560
1583
  const isFirstHello = !this.hadSuccessfulHello;
1561
1584
  this.hadSuccessfulHello = true;
1562
1585
  this.catchUpFromDispatch(isFirstHello).catch((err) => {
1563
- log?.warn(`parall[${this.opts.accountId}]: dispatch catch-up failed: ${String(err)}`);
1586
+ log?.warn(`dispatch catch-up failed: ${String(err)}`);
1564
1587
  });
1565
1588
  } catch (err) {
1566
- log?.error(`parall[${this.opts.accountId}]: failed to fetch chats: ${String(err)}`);
1589
+ log?.error(`failed to fetch chats: ${String(err)}`);
1567
1590
  }
1568
1591
  }
1569
1592
 
@@ -1598,15 +1621,15 @@ export class ParallAgentGateway {
1598
1621
  // via dispatch catch-up after the new pod starts.
1599
1622
  if (this.inFlightDispatches > 0) {
1600
1623
  this.opts.log?.info(
1601
- `parall[${this.opts.accountId}]: draining ${this.inFlightDispatches} in-flight dispatch(es), deadline ${this.SHUTDOWN_DEADLINE_MS}ms`,
1624
+ `draining ${this.inFlightDispatches} in-flight dispatch(es), deadline ${this.SHUTDOWN_DEADLINE_MS}ms`,
1602
1625
  );
1603
1626
  await this.waitForDrain(this.SHUTDOWN_DEADLINE_MS);
1604
1627
  if (this.inFlightDispatches > 0) {
1605
1628
  this.opts.log?.warn(
1606
- `parall[${this.opts.accountId}]: drain deadline hit; ${this.inFlightDispatches} dispatch(es) still running — they will be killed by process exit`,
1629
+ `drain deadline hit; ${this.inFlightDispatches} dispatch(es) still running — they will be killed by process exit`,
1607
1630
  );
1608
1631
  } else {
1609
- this.opts.log?.info(`parall[${this.opts.accountId}]: drain complete`);
1632
+ this.opts.log?.info(`drain complete`);
1610
1633
  }
1611
1634
  }
1612
1635
 
@@ -1619,6 +1642,6 @@ export class ParallAgentGateway {
1619
1642
  await this.opts.onBeforeDisconnect?.();
1620
1643
 
1621
1644
  this.opts.ws.disconnect();
1622
- this.opts.log?.info(`parall[${this.opts.accountId}]: disconnected`);
1645
+ this.opts.log?.info(`disconnected`);
1623
1646
  }
1624
1647
  }
package/src/index.ts CHANGED
@@ -5,7 +5,7 @@ export * from "./event-format.js";
5
5
  export * from "./prompt-fragments.js";
6
6
  export * from "./bridge-workspace.js";
7
7
  export * from "./dispatch-adapter.js";
8
- export { createLogger } from "./logger.js";
8
+ export { createLogger, childLogger } from "./logger.js";
9
9
  export * from "./gateway-base.js";
10
10
  export * from "./platform-config.js";
11
11
  export { writeSkillFiles, buildSkillReferences, SKILLS } from "./skills/index.js";
package/src/logger.ts CHANGED
@@ -5,5 +5,10 @@ export function createLogger(prefix: string): GatewayLogger {
5
5
  info: (msg: string) => console.log(`${new Date().toISOString()} [${prefix}] ${msg}`),
6
6
  warn: (msg: string) => console.warn(`${new Date().toISOString()} [${prefix}] ${msg}`),
7
7
  error: (msg: string) => console.error(`${new Date().toISOString()} [${prefix}] ${msg}`),
8
+ child: (sub: string) => createLogger(`${prefix}:${sub}`),
8
9
  };
9
10
  }
11
+
12
+ export function childLogger(logger: GatewayLogger, sub: string): GatewayLogger {
13
+ return logger.child ? logger.child(sub) : logger;
14
+ }