chatroom-cli 1.58.1 → 1.58.2

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/index.js CHANGED
@@ -75701,6 +75701,12 @@ function getPlannerToUserReportTemplate() {
75701
75701
  ## Template Disclosure Confirmation
75702
75702
  - [ ] I confirm that I have seen this template at the start of any planning, before working on or delegating any task to the team
75703
75703
 
75704
+ ## Proof of Planning
75705
+ <!-- Demonstrate the goal was decomposed into actionable steps with clear outcomes before implementation. -->
75706
+ - <step 1: concrete artifact or outcome>
75707
+ - <step 2: concrete artifact or outcome>
75708
+ <List the planned slices/steps the planner defined (or would have defined) before delegating. Each step should name a verifiable deliverable — not vague layers like "backend work". Write \`Not Applicable\` only for trivial single-step tasks.>
75709
+
75704
75710
  ## Proof of Principle
75705
75711
  <!-- Demonstrate adherence to:
75706
75712
  - Organization & Maintainability: a small change in requirements should result in a small change in code in a small number of files and folders.
@@ -88953,6 +88959,9 @@ class WorkingSnapshot {
88953
88959
  getByKey(key) {
88954
88960
  return this.rows.get(key);
88955
88961
  }
88962
+ upsertRow(row) {
88963
+ this.rows.set(this.opts.rowKey(row), row);
88964
+ }
88956
88965
  getBySignal(signal) {
88957
88966
  return this.rows.get(this.opts.signalKey(signal));
88958
88967
  }
@@ -88990,8 +88999,32 @@ function mergeSignalIntoTaskSnapshot(existing, signal) {
88990
88999
  }
88991
89000
  };
88992
89001
  }
89002
+ function mergePresenceIntoTaskSnapshot(existing, presence) {
89003
+ if (!existing) {
89004
+ return;
89005
+ }
89006
+ return {
89007
+ ...existing,
89008
+ participant: {
89009
+ lastSeenAction: presence.lastSeenAction ?? existing.participant?.lastSeenAction ?? null,
89010
+ lastSeenAt: presence.lastSeenAt,
89011
+ lastStatus: existing.participant?.lastStatus ?? null
89012
+ }
89013
+ };
89014
+ }
88993
89015
  function createTaskMonitorSnapshot() {
88994
- return new WorkingSnapshot(taskMonitorSnapshotOptions);
89016
+ const base = new WorkingSnapshot(taskMonitorSnapshotOptions);
89017
+ return Object.assign(base, {
89018
+ mergePresence(presence) {
89019
+ const key = taskSnapshotKey(presence.taskId, presence.role);
89020
+ const existing = base.getByKey(key);
89021
+ const merged = mergePresenceIntoTaskSnapshot(existing, presence);
89022
+ if (merged) {
89023
+ base.upsertRow(merged);
89024
+ }
89025
+ return merged;
89026
+ }
89027
+ });
88995
89028
  }
88996
89029
  var taskMonitorSnapshotOptions;
88997
89030
  var init_task_monitor_snapshot = __esm(() => {
@@ -89241,106 +89274,46 @@ var runIncrementalSubscribeLive = (opts) => exports_Effect.gen(function* () {
89241
89274
  yield* exports_Fiber.interrupt(workerFiber);
89242
89275
  })
89243
89276
  };
89244
- }), runReconcilePoll = (opts) => exports_Effect.gen(function* () {
89245
- const clock4 = yield* IntervalClock;
89246
- const backoffCfg = opts.backoff ?? { initialMs: 1000, maxMs: 30000 };
89247
- let backoffMs = opts.intervalMs;
89248
- let stopped = false;
89249
- const loopFiber = yield* exports_Effect.forkDaemon(exports_Effect.gen(function* () {
89250
- while (!stopped) {
89251
- const pollOutcome = yield* exports_Effect.either(exports_Effect.tryPromise(() => opts.poll(opts.args)));
89252
- if (pollOutcome._tag === "Left") {
89253
- backoffMs = Math.min(backoffMs === opts.intervalMs ? backoffCfg.initialMs : backoffMs * 2, backoffCfg.maxMs);
89254
- yield* clock4.sleep(backoffMs);
89255
- continue;
89256
- }
89257
- yield* opts.onResult(pollOutcome.right);
89258
- backoffMs = opts.intervalMs;
89259
- yield* clock4.sleep(opts.intervalMs);
89260
- }
89261
- }));
89262
- return {
89263
- stop: () => exports_Effect.gen(function* () {
89264
- stopped = true;
89265
- yield* exports_Fiber.interrupt(loopFiber);
89266
- })
89267
- };
89268
- }), runReconcilePollLive = (opts) => runReconcilePoll(opts).pipe(exports_Effect.provide(IntervalClockLive));
89277
+ });
89269
89278
  var init_feed_runtime = __esm(() => {
89270
89279
  init_esm();
89271
89280
  init_layers();
89272
89281
  init_subscribe_loop();
89273
89282
  });
89274
89283
 
89275
- // src/infrastructure/incremental-sync/dual-channel-feed.ts
89276
- var runDualChannelFeedLive = (opts) => exports_Effect.gen(function* () {
89277
- const initial = yield* exports_Effect.tryPromise(() => opts.fetchReconcile()).pipe(exports_Effect.orElseSucceed(() => null));
89278
- if (initial !== null) {
89279
- const rows = opts.extractReconcileRows(initial);
89280
- opts.snapshot.replaceAll(rows);
89281
- if (rows.length > 0) {
89282
- yield* opts.onReconcileRows(rows).pipe(exports_Effect.catchAll(() => exports_Effect.void));
89283
- }
89284
- }
89285
- const seedKey = yield* exports_Effect.tryPromise(() => opts.seedCursor()).pipe(exports_Effect.orElseSucceed(() => null));
89286
- const hydrateFromReconcile = async () => {
89287
- const result = await opts.fetchReconcile();
89288
- opts.snapshot.replaceAll(opts.extractReconcileRows(result));
89284
+ // src/infrastructure/incremental-sync/feeds/assigned-task-presence.ts
89285
+ var assignedTaskPresenceFeedDef, assignedTaskPresenceSubscribeTarget, ASSIGNED_TASK_PRESENCE_FEED_LIMIT = 50, ASSIGNED_TASK_PRESENCE_FEED_BUFFER;
89286
+ var init_assigned_task_presence = __esm(() => {
89287
+ init_api3();
89288
+ assignedTaskPresenceFeedDef = {
89289
+ name: "assigned-task-presence",
89290
+ itemKey: (item) => `${item.presenceUpdatedAt}:${item.taskId}:${item.role}`
89289
89291
  };
89290
- const resolveRowForSignal = async (signal) => {
89291
- const merged = opts.snapshot.mergeSignal(signal);
89292
- if (merged) {
89293
- return merged;
89292
+ assignedTaskPresenceSubscribeTarget = {
89293
+ query: api.machines.subscribeAssignedTaskPresenceSince,
89294
+ buildArgs: (args2, afterKey, limit) => ({
89295
+ sessionId: args2.sessionId,
89296
+ machineId: args2.machineId,
89297
+ afterPresenceKey: afterKey ?? undefined,
89298
+ limit
89299
+ }),
89300
+ parsePage: (result) => {
89301
+ const page = result;
89302
+ return {
89303
+ items: page.items,
89304
+ highKey: page.highPresenceKey,
89305
+ hasMore: page.hasMore
89306
+ };
89294
89307
  }
89295
- await hydrateFromReconcile();
89296
- return opts.snapshot.mergeSignal(signal) ?? opts.snapshot.getBySignal(signal);
89297
89308
  };
89298
- const signalHandle = yield* runIncrementalSubscribeLive({
89299
- wsClient: opts.wsClient,
89300
- def: opts.def,
89301
- target: opts.target,
89302
- args: opts.args,
89303
- buffer: opts.buffer,
89304
- subscribe: opts.subscribe,
89305
- initialAfterKey: seedKey,
89306
- onError: opts.onSubscribeError,
89307
- onItem: ({ item: signal, ack }) => exports_Effect.gen(function* () {
89308
- ack();
89309
- if (opts.isStopped()) {
89310
- return;
89311
- }
89312
- const row = yield* exports_Effect.tryPromise(() => resolveRowForSignal(signal));
89313
- if (!row) {
89314
- return;
89315
- }
89316
- yield* opts.onSignalRow(row).pipe(exports_Effect.catchAll(() => exports_Effect.void));
89317
- })
89318
- });
89319
- const reconcileHandle = yield* runReconcilePollLive({
89320
- name: `${opts.name}-reconcile`,
89321
- poll: () => opts.fetchReconcile(),
89322
- args: undefined,
89323
- intervalMs: opts.reconcileIntervalMs,
89324
- onResult: (result) => exports_Effect.gen(function* () {
89325
- const rows = opts.extractReconcileRows(result);
89326
- opts.snapshot.replaceAll(rows);
89327
- yield* opts.onReconcileRows(rows).pipe(exports_Effect.catchAll(() => exports_Effect.void));
89328
- })
89329
- });
89330
- return {
89331
- stop: () => exports_Effect.gen(function* () {
89332
- yield* signalHandle.stop();
89333
- yield* reconcileHandle.stop();
89334
- })
89309
+ ASSIGNED_TASK_PRESENCE_FEED_BUFFER = {
89310
+ maxSize: 200,
89311
+ dedupe: true
89335
89312
  };
89336
89313
  });
89337
- var init_dual_channel_feed = __esm(() => {
89338
- init_esm();
89339
- init_feed_runtime();
89340
- });
89341
89314
 
89342
89315
  // src/infrastructure/incremental-sync/feeds/assigned-task-signals.ts
89343
- var assignedTaskSignalsFeedDef, assignedTaskSignalsSubscribeTarget, ASSIGNED_TASK_SIGNAL_FEED_LIMIT = 50, ASSIGNED_TASK_SIGNAL_FEED_BUFFER, ASSIGNED_TASK_RECONCILE_INTERVAL_MS = 15000;
89316
+ var assignedTaskSignalsFeedDef, assignedTaskSignalsSubscribeTarget, ASSIGNED_TASK_SIGNAL_FEED_LIMIT = 50, ASSIGNED_TASK_SIGNAL_FEED_BUFFER;
89344
89317
  var init_assigned_task_signals = __esm(() => {
89345
89318
  init_api3();
89346
89319
  assignedTaskSignalsFeedDef = {
@@ -89364,6 +89337,22 @@ var init_assigned_task_signals = __esm(() => {
89364
89337
  });
89365
89338
 
89366
89339
  // src/commands/machine/daemon-start/task-monitor.ts
89340
+ async function seedSignalCursor(session2) {
89341
+ const seedPage = await session2.backend.query(api.machines.subscribeAssignedTaskSignalsSince, {
89342
+ sessionId: session2.sessionId,
89343
+ machineId: session2.machineId,
89344
+ limit: ASSIGNED_TASK_SIGNAL_FEED_LIMIT
89345
+ });
89346
+ return seedPage?.highKey ?? null;
89347
+ }
89348
+ async function seedPresenceCursor(session2) {
89349
+ const seedPage = await session2.backend.query(api.machines.subscribeAssignedTaskPresenceSince, {
89350
+ sessionId: session2.sessionId,
89351
+ machineId: session2.machineId,
89352
+ limit: ASSIGNED_TASK_PRESENCE_FEED_LIMIT
89353
+ });
89354
+ return seedPage?.highPresenceKey ?? null;
89355
+ }
89367
89356
  function resolveTaskWantResume(task) {
89368
89357
  return sessionAugmentationToWantResume(resolveSessionAugmentationForRole(task.taskContent ?? "", task.agentConfig.role));
89369
89358
  }
@@ -89486,7 +89475,7 @@ async function processTasksUpdate(tasks, runtime4, effectContext2, cooldown, age
89486
89475
  sessionDeps,
89487
89476
  machineId
89488
89477
  });
89489
- if (pass === "reconcile") {
89478
+ if (pass === "presence") {
89490
89479
  await nudgeStuckTasks(tasks, now, cooldown, runtime4, effectContext2, agentMgr, sessionDeps, machineId);
89491
89480
  }
89492
89481
  }
@@ -89517,12 +89506,22 @@ var startTaskMonitorEffect = (wsClient2) => exports_Effect.gen(function* () {
89517
89506
  monitorPassInFlight = false;
89518
89507
  });
89519
89508
  };
89520
- const queryReconcileSnapshots = () => session2.backend.query(api.machines.listAssignedTasksForReconcile, {
89509
+ yield* exports_Effect.tryPromise(() => session2.backend.mutation(api.machines.syncMachineAssignedTaskSnapshotsMutation, {
89521
89510
  sessionId: session2.sessionId,
89522
89511
  machineId: session2.machineId
89523
- });
89524
- const feedHandle = yield* runDualChannelFeedLive({
89525
- name: "assigned-tasks",
89512
+ })).pipe(exports_Effect.catchAll(() => exports_Effect.void));
89513
+ const hydrate = yield* exports_Effect.tryPromise(() => session2.backend.query(api.machines.listMachineAssignedTaskSnapshots, {
89514
+ sessionId: session2.sessionId,
89515
+ machineId: session2.machineId
89516
+ })).pipe(exports_Effect.orElseSucceed(() => ({ tasks: [] })));
89517
+ const hydrateTasks = hydrate.tasks ?? [];
89518
+ snapshot.replaceAll(hydrateTasks);
89519
+ if (hydrateTasks.length > 0) {
89520
+ yield* exports_Effect.tryPromise(() => processTasksUpdate(hydrateTasks, runtime4, effectContext2, cooldown, agentMgr, sessionDeps, session2.machineId, "presence")).pipe(exports_Effect.catchAll(() => exports_Effect.void));
89521
+ }
89522
+ const signalSeedKey = yield* exports_Effect.tryPromise(() => seedSignalCursor(session2)).pipe(exports_Effect.orElseSucceed(() => null));
89523
+ const presenceSeedKey = yield* exports_Effect.tryPromise(() => seedPresenceCursor(session2)).pipe(exports_Effect.orElseSucceed(() => null));
89524
+ const signalHandle = yield* runIncrementalSubscribeLive({
89526
89525
  wsClient: wsClient2,
89527
89526
  def: assignedTaskSignalsFeedDef,
89528
89527
  target: assignedTaskSignalsSubscribeTarget,
@@ -89532,31 +89531,49 @@ var startTaskMonitorEffect = (wsClient2) => exports_Effect.gen(function* () {
89532
89531
  },
89533
89532
  buffer: ASSIGNED_TASK_SIGNAL_FEED_BUFFER,
89534
89533
  subscribe: { limit: ASSIGNED_TASK_SIGNAL_FEED_LIMIT },
89535
- snapshot,
89536
- seedCursor: async () => {
89537
- const seedPage = await session2.backend.query(api.machines.subscribeAssignedTaskSignalsSince, {
89538
- sessionId: session2.sessionId,
89539
- machineId: session2.machineId,
89540
- limit: ASSIGNED_TASK_SIGNAL_FEED_LIMIT
89534
+ initialAfterKey: signalSeedKey,
89535
+ onError: (err) => console.warn(`[${formatTimestamp()}] ⚠️ Task signal subscription error: ${getErrorMessage(err)}`),
89536
+ onItem: ({ item: signal, ack }) => exports_Effect.gen(function* () {
89537
+ ack();
89538
+ if (stopped)
89539
+ return;
89540
+ const row = snapshot.mergeSignal(signal);
89541
+ if (!row)
89542
+ return;
89543
+ yield* exports_Effect.sync(() => {
89544
+ runMonitorPass([row], "signal");
89545
+ });
89546
+ })
89547
+ });
89548
+ const presenceHandle = yield* runIncrementalSubscribeLive({
89549
+ wsClient: wsClient2,
89550
+ def: assignedTaskPresenceFeedDef,
89551
+ target: assignedTaskPresenceSubscribeTarget,
89552
+ args: {
89553
+ sessionId: session2.sessionId,
89554
+ machineId: session2.machineId
89555
+ },
89556
+ buffer: ASSIGNED_TASK_PRESENCE_FEED_BUFFER,
89557
+ subscribe: { limit: ASSIGNED_TASK_PRESENCE_FEED_LIMIT },
89558
+ initialAfterKey: presenceSeedKey,
89559
+ onError: (err) => console.warn(`[${formatTimestamp()}] ⚠️ Task presence subscription error: ${getErrorMessage(err)}`),
89560
+ onItem: ({ item: presence, ack }) => exports_Effect.gen(function* () {
89561
+ ack();
89562
+ if (stopped)
89563
+ return;
89564
+ const row = snapshot.mergePresence(presence);
89565
+ if (!row)
89566
+ return;
89567
+ yield* exports_Effect.sync(() => {
89568
+ runMonitorPass([row], "presence");
89541
89569
  });
89542
- return seedPage?.highKey ?? null;
89543
- },
89544
- fetchReconcile: () => queryReconcileSnapshots(),
89545
- extractReconcileRows: (result) => result?.tasks ?? [],
89546
- reconcileIntervalMs: ASSIGNED_TASK_RECONCILE_INTERVAL_MS,
89547
- isStopped: () => stopped,
89548
- onSubscribeError: (err) => console.warn(`[${formatTimestamp()}] ⚠️ Task signal subscription error: ${getErrorMessage(err)}`),
89549
- onSignalRow: (row) => exports_Effect.sync(() => {
89550
- runMonitorPass([row], "signal");
89551
- }),
89552
- onReconcileRows: (tasks) => exports_Effect.sync(() => {
89553
- runMonitorPass([...tasks], "reconcile");
89554
89570
  })
89555
89571
  });
89556
89572
  return {
89557
89573
  stop() {
89558
89574
  stopped = true;
89559
- exports_Effect.runPromise(feedHandle.stop());
89575
+ exports_Effect.runPromise(signalHandle.stop());
89576
+ exports_Effect.runPromise(presenceHandle.stop());
89560
89577
  console.log(`[${formatTimestamp()}] \uD83D\uDCCB Task-monitor stopped`);
89561
89578
  }
89562
89579
  };
@@ -89570,7 +89587,8 @@ var init_task_monitor = __esm(() => {
89570
89587
  init_task_monitor_logic();
89571
89588
  init_task_monitor_snapshot();
89572
89589
  init_api3();
89573
- init_dual_channel_feed();
89590
+ init_feed_runtime();
89591
+ init_assigned_task_presence();
89574
89592
  init_assigned_task_signals();
89575
89593
  init_convex_error();
89576
89594
  });
@@ -91078,4 +91096,4 @@ program2.hook("preAction", async (_thisCommand, actionCommand) => {
91078
91096
  });
91079
91097
  program2.parse();
91080
91098
 
91081
- //# debugId=D22ED479E2182D5A64756E2164756E21
91099
+ //# debugId=9DA8A47CE355B57D64756E2164756E21