agent-tempo 1.3.1 → 1.4.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.
Files changed (199) hide show
  1. package/CLAUDE.md +39 -5
  2. package/README.md +6 -2
  3. package/dashboard/dist/assets/{index-D6Xyje_n.js → index-jmYe6rmS.js} +2 -2
  4. package/dashboard/dist/assets/index-jmYe6rmS.js.map +1 -0
  5. package/dashboard/dist/index.html +1 -1
  6. package/dashboard/package.json +1 -1
  7. package/dist/activities/outbox.d.ts +30 -1
  8. package/dist/activities/outbox.js +96 -3
  9. package/dist/adapters/base.js +5 -0
  10. package/dist/adapters/index.d.ts +1 -1
  11. package/dist/adapters/index.js +7 -0
  12. package/dist/adapters/pi/adapter.d.ts +2 -0
  13. package/dist/adapters/pi/adapter.js +43 -0
  14. package/dist/adapters/pi/index.d.ts +16 -0
  15. package/dist/adapters/pi/index.js +10 -0
  16. package/dist/client/core.js +9 -2
  17. package/dist/client/interface.d.ts +6 -0
  18. package/dist/config.d.ts +79 -0
  19. package/dist/config.js +74 -0
  20. package/dist/daemon.js +32 -1
  21. package/dist/http/aggregate.d.ts +22 -1
  22. package/dist/http/aggregate.js +41 -0
  23. package/dist/http/auth.d.ts +94 -8
  24. package/dist/http/auth.js +93 -9
  25. package/dist/http/body.d.ts +4 -1
  26. package/dist/http/body.js +6 -3
  27. package/dist/http/event-bus.js +1 -0
  28. package/dist/http/event-types.d.ts +34 -2
  29. package/dist/http/event-types.js +1 -0
  30. package/dist/http/gate-audit.d.ts +12 -0
  31. package/dist/http/gate-audit.js +95 -0
  32. package/dist/http/gate-registry.d.ts +167 -0
  33. package/dist/http/gate-registry.js +163 -0
  34. package/dist/http/gate-routes.d.ts +48 -0
  35. package/dist/http/gate-routes.js +102 -0
  36. package/dist/http/ingest-registry.d.ts +30 -0
  37. package/dist/http/ingest-registry.js +108 -0
  38. package/dist/http/inner-loop-routes.d.ts +66 -0
  39. package/dist/http/inner-loop-routes.js +182 -0
  40. package/dist/http/inner-loop.d.ts +92 -0
  41. package/dist/http/inner-loop.js +155 -0
  42. package/dist/http/server.d.ts +38 -3
  43. package/dist/http/server.js +211 -6
  44. package/dist/http/snapshot.d.ts +6 -0
  45. package/dist/http/snapshot.js +6 -0
  46. package/dist/pi/cue-pump.d.ts +61 -0
  47. package/dist/pi/cue-pump.js +95 -0
  48. package/dist/pi/extension.d.ts +45 -0
  49. package/dist/pi/extension.js +407 -0
  50. package/dist/pi/gate-client.d.ts +54 -0
  51. package/dist/pi/gate-client.js +136 -0
  52. package/dist/pi/headless.d.ts +85 -0
  53. package/dist/pi/headless.js +250 -0
  54. package/dist/pi/index.d.ts +28 -0
  55. package/dist/pi/index.js +43 -0
  56. package/dist/pi/inner-loop-client.d.ts +67 -0
  57. package/dist/pi/inner-loop-client.js +164 -0
  58. package/dist/pi/inner-loop-publisher.d.ts +187 -0
  59. package/dist/pi/inner-loop-publisher.js +236 -0
  60. package/dist/pi/lazy-proxy.d.ts +37 -0
  61. package/dist/pi/lazy-proxy.js +55 -0
  62. package/dist/pi/mission-control/actions.d.ts +48 -0
  63. package/dist/pi/mission-control/actions.js +98 -0
  64. package/dist/pi/mission-control/board.d.ts +88 -0
  65. package/dist/pi/mission-control/board.js +141 -0
  66. package/dist/pi/mission-control/extension.d.ts +51 -0
  67. package/dist/pi/mission-control/extension.js +330 -0
  68. package/dist/pi/mission-control/index.d.ts +15 -0
  69. package/dist/pi/mission-control/index.js +32 -0
  70. package/dist/pi/mission-control/inner-tail.d.ts +48 -0
  71. package/dist/pi/mission-control/inner-tail.js +76 -0
  72. package/dist/pi/mission-control/pi-ui.d.ts +43 -0
  73. package/dist/pi/mission-control/pi-ui.js +10 -0
  74. package/dist/pi/mission-control/render.d.ts +6 -0
  75. package/dist/pi/mission-control/render.js +98 -0
  76. package/dist/pi/phase-driver.d.ts +74 -0
  77. package/dist/pi/phase-driver.js +122 -0
  78. package/dist/pi/pi-types.d.ts +222 -0
  79. package/dist/pi/pi-types.js +21 -0
  80. package/dist/pi/probe.d.ts +99 -0
  81. package/dist/pi/probe.js +179 -0
  82. package/dist/pi/render-tools.d.ts +17 -0
  83. package/dist/pi/render-tools.js +56 -0
  84. package/dist/pi/reset-pump.d.ts +47 -0
  85. package/dist/pi/reset-pump.js +85 -0
  86. package/dist/pi/session-seed.d.ts +74 -0
  87. package/dist/pi/session-seed.js +103 -0
  88. package/dist/pi/tool-capability.d.ts +60 -0
  89. package/dist/pi/tool-capability.js +156 -0
  90. package/dist/pi/workflow-client.d.ts +158 -0
  91. package/dist/pi/workflow-client.js +289 -0
  92. package/dist/pi/zod-to-typebox.d.ts +74 -0
  93. package/dist/pi/zod-to-typebox.js +191 -0
  94. package/dist/server-tools.d.ts +2 -0
  95. package/dist/server-tools.js +50 -46
  96. package/dist/spawn.d.ts +55 -0
  97. package/dist/spawn.js +72 -0
  98. package/dist/tools/agent-types.d.ts +2 -2
  99. package/dist/tools/agent-types.js +22 -17
  100. package/dist/tools/attachment-info.d.ts +2 -2
  101. package/dist/tools/attachment-info.js +38 -33
  102. package/dist/tools/broadcast.d.ts +2 -2
  103. package/dist/tools/broadcast.js +69 -64
  104. package/dist/tools/cancel-stage.d.ts +2 -2
  105. package/dist/tools/cancel-stage.js +20 -15
  106. package/dist/tools/clear-state.d.ts +2 -2
  107. package/dist/tools/clear-state.js +25 -20
  108. package/dist/tools/coat-check-evict.d.ts +2 -2
  109. package/dist/tools/coat-check-evict.js +29 -24
  110. package/dist/tools/coat-check-get.d.ts +2 -2
  111. package/dist/tools/coat-check-get.js +38 -33
  112. package/dist/tools/coat-check-list.d.ts +2 -2
  113. package/dist/tools/coat-check-list.js +48 -43
  114. package/dist/tools/coat-check-put.d.ts +2 -2
  115. package/dist/tools/coat-check-put.js +38 -33
  116. package/dist/tools/cue.d.ts +2 -2
  117. package/dist/tools/cue.js +57 -52
  118. package/dist/tools/descriptor.d.ts +72 -0
  119. package/dist/tools/descriptor.js +39 -0
  120. package/dist/tools/destroy.d.ts +2 -2
  121. package/dist/tools/destroy.js +153 -148
  122. package/dist/tools/ensemble.d.ts +2 -2
  123. package/dist/tools/ensemble.js +71 -66
  124. package/dist/tools/evaluate-gate.d.ts +2 -2
  125. package/dist/tools/evaluate-gate.js +33 -27
  126. package/dist/tools/fetch-state.d.ts +2 -2
  127. package/dist/tools/fetch-state.js +42 -37
  128. package/dist/tools/gates.d.ts +2 -2
  129. package/dist/tools/gates.js +39 -34
  130. package/dist/tools/hosts.d.ts +2 -2
  131. package/dist/tools/hosts.js +25 -20
  132. package/dist/tools/listen.d.ts +2 -2
  133. package/dist/tools/listen.js +23 -18
  134. package/dist/tools/load-lineup.d.ts +2 -2
  135. package/dist/tools/load-lineup.js +324 -319
  136. package/dist/tools/migrate.d.ts +2 -2
  137. package/dist/tools/migrate.js +45 -40
  138. package/dist/tools/pause.d.ts +2 -2
  139. package/dist/tools/pause.js +34 -29
  140. package/dist/tools/play.d.ts +2 -2
  141. package/dist/tools/play.js +53 -48
  142. package/dist/tools/quality-gate.d.ts +2 -2
  143. package/dist/tools/quality-gate.js +26 -21
  144. package/dist/tools/recall.d.ts +2 -2
  145. package/dist/tools/recall.js +32 -27
  146. package/dist/tools/recruit.d.ts +2 -2
  147. package/dist/tools/recruit.js +340 -256
  148. package/dist/tools/release.d.ts +2 -2
  149. package/dist/tools/release.js +85 -80
  150. package/dist/tools/report.d.ts +2 -2
  151. package/dist/tools/report.js +28 -23
  152. package/dist/tools/reset.d.ts +3 -0
  153. package/dist/tools/reset.js +51 -0
  154. package/dist/tools/restart.d.ts +2 -2
  155. package/dist/tools/restart.js +51 -46
  156. package/dist/tools/restore.d.ts +2 -2
  157. package/dist/tools/restore.js +76 -71
  158. package/dist/tools/save-lineup.d.ts +2 -2
  159. package/dist/tools/save-lineup.js +32 -27
  160. package/dist/tools/save-state.d.ts +2 -2
  161. package/dist/tools/save-state.js +31 -26
  162. package/dist/tools/schedule.d.ts +2 -2
  163. package/dist/tools/schedule.js +133 -128
  164. package/dist/tools/schedules.d.ts +2 -2
  165. package/dist/tools/schedules.js +41 -36
  166. package/dist/tools/set-ensemble-description.d.ts +2 -2
  167. package/dist/tools/set-ensemble-description.js +26 -21
  168. package/dist/tools/set-name.d.ts +2 -2
  169. package/dist/tools/set-name.js +38 -33
  170. package/dist/tools/set-part.d.ts +2 -2
  171. package/dist/tools/set-part.js +20 -15
  172. package/dist/tools/shutdown.d.ts +2 -2
  173. package/dist/tools/shutdown.js +39 -34
  174. package/dist/tools/stage.d.ts +2 -2
  175. package/dist/tools/stage.js +28 -23
  176. package/dist/tools/stages.d.ts +2 -2
  177. package/dist/tools/stages.js +36 -31
  178. package/dist/tools/unschedule.d.ts +2 -2
  179. package/dist/tools/unschedule.js +30 -25
  180. package/dist/tools/who-am-i.d.ts +2 -2
  181. package/dist/tools/who-am-i.js +36 -31
  182. package/dist/tools/worktree.d.ts +2 -2
  183. package/dist/tools/worktree.js +134 -129
  184. package/dist/tui/index.js +6 -6
  185. package/dist/types.d.ts +47 -2
  186. package/dist/types.js +1 -1
  187. package/dist/utils/default-part.js +1 -0
  188. package/dist/utils/sdk-probe.d.ts +23 -0
  189. package/dist/utils/sdk-probe.js +46 -7
  190. package/dist/worker.d.ts +3 -1
  191. package/dist/worker.js +6 -2
  192. package/dist/workflows/session.js +70 -2
  193. package/dist/workflows/signals.d.ts +32 -2
  194. package/dist/workflows/signals.js +25 -2
  195. package/package.json +4 -1
  196. package/workflow-bundle.js +97 -6
  197. package/dashboard/dist/assets/index-D6Xyje_n.js.map +0 -1
  198. package/dist/tools/helpers.d.ts +0 -21
  199. package/dist/tools/helpers.js +0 -25
@@ -16,7 +16,7 @@ const attachment_math_1 = require("./attachment-math");
16
16
  const signals_1 = require("./signals");
17
17
  const validation_1 = require("../utils/validation");
18
18
  // ── Outbox Activity Proxies ──
19
- const { deliverCue, deliverReport, terminateSession, startRecruitedSession, releasePlayer, deliverDetach, deliverDestroy, deliverRestart } = (0, workflow_1.proxyActivities)({
19
+ const { deliverCue, deliverReport, terminateSession, startRecruitedSession, releasePlayer, deliverDetach, deliverDestroy, deliverRestart, deliverReset } = (0, workflow_1.proxyActivities)({
20
20
  startToCloseTimeout: '30 seconds',
21
21
  retry: { maximumAttempts: 3 },
22
22
  });
@@ -117,6 +117,9 @@ async function agentSessionWorkflow(input) {
117
117
  const messages = input.messages ?? [];
118
118
  const sentMessages = input.sentMessages ?? [];
119
119
  const outbox = input.outbox ?? [];
120
+ // D14 — pending context-reset flag, polled + acked by the Pi extension. Single
121
+ // slot, latest-wins; survives continue-as-new until the extension acks it.
122
+ let pendingReset = input.pendingReset ?? null;
120
123
  let lastActivityTime = workflowNow().getTime();
121
124
  let lastOutboundTime = input.lastOutboundTime ?? workflowNow().getTime();
122
125
  let lastInboundRRTime = input.lastInboundRRTime ?? 0;
@@ -128,6 +131,13 @@ async function agentSessionWorkflow(input) {
128
131
  let activityCount = input.activityCount ?? 0;
129
132
  let receivedCount = input.receivedCount ?? 0;
130
133
  let sentCount = input.sentCount ?? 0;
134
+ // ── 3c Tier-1 — coarse activity (currentTool + context usage) ──
135
+ // Refreshed by the heartbeat piggyback; surfaced by `getCoarseActivityQuery`.
136
+ // Deliberately volatile/live — NOT carried across continueAsNew (no input
137
+ // field), so a fresh run reports `{currentTool:null}` until the next ~30s
138
+ // heartbeat repopulates it. Acceptable for coarse observability; the live,
139
+ // fine-grained tail is the off-wire /inner side-channel.
140
+ let coarseActivity = { currentTool: null };
131
141
  // ── Warm Hold + Pause State ──
132
142
  let outboxLocked = input.outboxLocked ?? false;
133
143
  let heldMessage = input.heldMessage;
@@ -308,6 +318,9 @@ async function agentSessionWorkflow(input) {
308
318
  else if (entry.type === 'release') {
309
319
  sentMessages.push({ id: entry.id, to: entry.targetPlayerId, text: '[release requested]', timestamp: entry.createdAt });
310
320
  }
321
+ else if (entry.type === 'reset') {
322
+ sentMessages.push({ id: entry.id, to: entry.targetPlayerId, text: '[reset requested]', timestamp: entry.createdAt });
323
+ }
311
324
  lastActivityTime = workflowNow().getTime();
312
325
  activityCount++;
313
326
  lastOutboundTime = workflowNow().getTime();
@@ -368,6 +381,29 @@ async function agentSessionWorkflow(input) {
368
381
  lastActivityTime = workflowNow().getTime();
369
382
  activityCount++;
370
383
  });
384
+ // ── Reset (D14) — set by deliverReset, polled + acked by the Pi extension ──
385
+ (0, workflow_1.setHandler)(signals_1.setPendingResetSignal, (r) => {
386
+ // Latest-wins; stamp requestedAt deterministically (workflowNow, not the activity's clock).
387
+ pendingReset = {
388
+ resetId: r.resetId,
389
+ fresh: r.fresh,
390
+ ...(r.reason !== undefined ? { reason: r.reason } : {}),
391
+ ...(r.requestedBy !== undefined ? { requestedBy: r.requestedBy } : {}),
392
+ requestedAt: workflowNow().toISOString(),
393
+ };
394
+ lastActivityTime = workflowNow().getTime();
395
+ activityCount++;
396
+ });
397
+ (0, workflow_1.setHandler)(signals_1.pendingResetQuery, () => pendingReset);
398
+ (0, workflow_1.setHandler)(signals_1.ackResetSignal, (resetId) => {
399
+ // Race-safe: only clear if the ack matches the current pending reset, so a
400
+ // newer reset landing during the extension's wipe isn't silently dropped.
401
+ if (pendingReset?.resetId === resetId) {
402
+ pendingReset = null;
403
+ }
404
+ lastActivityTime = workflowNow().getTime();
405
+ activityCount++;
406
+ });
371
407
  (0, workflow_1.setHandler)(signals_1.updateMetadataSignal, (update) => {
372
408
  if (update.hostname != null)
373
409
  input.metadata.hostname = update.hostname;
@@ -434,6 +470,8 @@ async function agentSessionWorkflow(input) {
434
470
  leaseMs: currentAttachment.leaseMs,
435
471
  };
436
472
  });
473
+ // 3c Tier-1 — surface the latest coarse activity for the snapshot fan-out.
474
+ (0, workflow_1.setHandler)(signals_1.getCoarseActivityQuery, () => ({ ...coarseActivity }));
437
475
  // ── Hold / Release Handlers ──
438
476
  (0, workflow_1.setHandler)(signals_1.releaseHeldSignal, () => {
439
477
  if (heldMessage) {
@@ -807,7 +845,7 @@ async function agentSessionWorkflow(input) {
807
845
  * `heartbeat` signal — extend the lease. Last-write-wins via the `attachmentId` guard;
808
846
  * heartbeats for superseded attachments are ignored.
809
847
  */
810
- (0, workflow_1.setHandler)(signals_1.heartbeatSignal, ({ attachmentId }) => {
848
+ (0, workflow_1.setHandler)(signals_1.heartbeatSignal, ({ attachmentId, currentTool, contextTokens, contextPercent }) => {
811
849
  if (!currentAttachment || currentAttachment.attachmentId !== attachmentId)
812
850
  return;
813
851
  const now = workflowNow();
@@ -818,6 +856,16 @@ async function agentSessionWorkflow(input) {
818
856
  currentAttachment.expiresAt = new Date(now.getTime() + currentAttachment.leaseMs).toISOString();
819
857
  lastActivityTime = now.getTime();
820
858
  activityCount++;
859
+ // 3c Tier-1 — refresh coarse activity from the heartbeat piggyback. Field-wise
860
+ // merge: only fields the sender included are updated. `currentTool` can be a
861
+ // legitimate `null` (idle), so `!== undefined` distinguishes "sent null" from
862
+ // "not sent" (a non-reporting sender leaves prior coarse intact).
863
+ if (currentTool !== undefined)
864
+ coarseActivity.currentTool = currentTool;
865
+ if (contextTokens !== undefined)
866
+ coarseActivity.contextTokens = contextTokens;
867
+ if (contextPercent !== undefined)
868
+ coarseActivity.contextPercent = contextPercent;
821
869
  });
822
870
  /**
823
871
  * `requestDetach` signal — adapter-initiated graceful detach. Transitions to `draining`;
@@ -1415,6 +1463,9 @@ async function agentSessionWorkflow(input) {
1415
1463
  // #131 Phase C — forward to spawnProcess so spawnClaudeApiAdapter
1416
1464
  // can plumb it into the subprocess env (AGENT_TEMPO_API_MODEL).
1417
1465
  ...(entry.model !== undefined ? { model: entry.model } : {}),
1466
+ // Phase 3a / MD-C — forward the headless Pi tool-access policy so
1467
+ // spawnPiHeadless plumbs AGENT_TEMPO_TOOL_ACCESS into the subprocess.
1468
+ ...(entry.toolAccess !== undefined ? { toolAccess: entry.toolAccess } : {}),
1418
1469
  });
1419
1470
  break;
1420
1471
  }
@@ -1468,6 +1519,21 @@ async function agentSessionWorkflow(input) {
1468
1519
  });
1469
1520
  break;
1470
1521
  }
1522
+ case 'reset': {
1523
+ // D14: operator/conductor CLEAN-WIPE. Sets a pendingReset flag the
1524
+ // Pi extension polls + acts on (newSession). POLL-delivery, not a
1525
+ // direct subprocess signal. resetId = this outbox entry id (the
1526
+ // extension acks with it). Does NOT route through the MD-G gate.
1527
+ await deliverReset({
1528
+ ensemble: input.metadata.ensemble,
1529
+ targetPlayerId: entry.targetPlayerId,
1530
+ resetId: entry.id,
1531
+ fresh: entry.fresh ?? true,
1532
+ ...(entry.reason !== undefined ? { reason: entry.reason } : {}),
1533
+ requestedBy: entry.invokerPlayerId ?? input.metadata.playerId,
1534
+ });
1535
+ break;
1536
+ }
1471
1537
  case 'spawn': {
1472
1538
  // PR-D: forward the pre-claimed attachment token + pinned runId +
1473
1539
  // resolved adapterId to the spawn activity. The child process picks
@@ -1599,6 +1665,8 @@ async function agentSessionWorkflow(input) {
1599
1665
  messages: messages.filter((m) => !m.delivered),
1600
1666
  sentMessages: sentMessages.slice(-50),
1601
1667
  outbox: outbox.filter((e) => e.status === 'pending' || e.status === 'processing'),
1668
+ // D14 — carry an un-acked pending reset across CAN (omit when null).
1669
+ ...(pendingReset ? { pendingReset } : {}),
1602
1670
  lastInboundRRTime,
1603
1671
  lastOutboundTime,
1604
1672
  // #399 W2 — counters carried across continueAsNew so the
@@ -1,5 +1,5 @@
1
- import type { SessionMetadata, Message, SentMessage, HistoryEntry, OutboxEntry, OutboxEntryInput, QualityGate, WorktreeEntry, StageEntry, AttachmentToken, AttachmentInfo, AdapterClass, DetachReason, OrphanSummary, PlayerStateEntry } from '../types';
2
- export type { SessionMetadata, SessionInput, Message, Command, PlayerReport, SentMessage, HistoryEntry, OutboxEntry, OutboxEntryInput, OutboxEntryStatus, CueOutboxEntry, RecruitOutboxEntry, ReportOutboxEntry, StopOutboxEntry, ReleaseOutboxEntry, SpawnOutboxEntry, AgentType, QualityGate, QualityGateCriterion, WorktreeEntry, StageEntry, StagePlayerStatus, AttachmentToken, AttachmentInfo, AttachmentPhase, Attachment, AdapterClass, AdapterDescriptor, DetachReason, AdapterDirective, OrphanSummary, PlayerStateEntry, } from '../types';
1
+ import type { SessionMetadata, Message, SentMessage, HistoryEntry, OutboxEntry, OutboxEntryInput, QualityGate, WorktreeEntry, StageEntry, AttachmentToken, AttachmentInfo, AdapterClass, DetachReason, OrphanSummary, PlayerStateEntry, PendingReset } from '../types';
2
+ export type { SessionMetadata, SessionInput, Message, Command, PlayerReport, SentMessage, HistoryEntry, OutboxEntry, OutboxEntryInput, OutboxEntryStatus, CueOutboxEntry, RecruitOutboxEntry, ReportOutboxEntry, StopOutboxEntry, ReleaseOutboxEntry, SpawnOutboxEntry, PendingReset, AgentType, QualityGate, QualityGateCriterion, WorktreeEntry, StageEntry, StagePlayerStatus, AttachmentToken, AttachmentInfo, AttachmentPhase, Attachment, AdapterClass, AdapterDescriptor, DetachReason, AdapterDirective, OrphanSummary, PlayerStateEntry, } from '../types';
3
3
  export declare const receiveMessageSignal: import("@temporalio/workflow").SignalDefinition<[{
4
4
  from: string;
5
5
  text: string;
@@ -34,6 +34,14 @@ export declare const getMetadataQuery: import("@temporalio/workflow").QueryDefin
34
34
  export declare const pendingMessagesQuery: import("@temporalio/workflow").QueryDefinition<Message[], [], string>;
35
35
  export declare const allMessagesQuery: import("@temporalio/workflow").QueryDefinition<Message[], [], string>;
36
36
  export declare const allSentMessagesQuery: import("@temporalio/workflow").QueryDefinition<SentMessage[], [], string>;
37
+ export declare const setPendingResetSignal: import("@temporalio/workflow").SignalDefinition<[{
38
+ resetId: string;
39
+ fresh: boolean;
40
+ reason?: string;
41
+ requestedBy?: string;
42
+ }], string>;
43
+ export declare const pendingResetQuery: import("@temporalio/workflow").QueryDefinition<PendingReset | null, [], string>;
44
+ export declare const ackResetSignal: import("@temporalio/workflow").SignalDefinition<[string], string>;
37
45
  /** Release a held session — unlocks the outbox and delivers the stored initial message. */
38
46
  export declare const releaseHeldSignal: import("@temporalio/workflow").SignalDefinition<[], "releaseHeld">;
39
47
  /** Query whether the session's outbox is locked (warm hold). */
@@ -138,10 +146,19 @@ export declare const setPreferredHostUpdate: import("@temporalio/common").Update
138
146
  /**
139
147
  * Liveness heartbeat from the adapter. Resets `lastHeartbeatAt` and extends `expiresAt` to
140
148
  * `workflow.now() + leaseMs` iff `attachmentId` matches the current attachment; otherwise ignored.
149
+ *
150
+ * 3c Tier-1 (additive, optional, non-breaking): the heartbeat doubles as the
151
+ * coarse-activity piggyback. `currentTool` (null = idle), `contextTokens`, and
152
+ * `contextPercent` (Pi `getContextUsage`, pull-only — no token event exists)
153
+ * refresh the workflow's queryable coarse state read by `getCoarseActivityQuery`.
154
+ * Omitted by senders that don't report coarse — the handler merges field-wise.
141
155
  */
142
156
  export declare const heartbeatSignal: import("@temporalio/workflow").SignalDefinition<[{
143
157
  attachmentId: string;
144
158
  at: string;
159
+ currentTool?: string | null;
160
+ contextTokens?: number;
161
+ contextPercent?: number;
145
162
  }], string>;
146
163
  /**
147
164
  * Adapter-, conductor-, or operator-initiated request to detach gracefully.
@@ -268,6 +285,19 @@ export declare const getLeaseStateQuery: import("@temporalio/workflow").QueryDef
268
285
  expiresAt: number | null;
269
286
  leaseMs: number | null;
270
287
  }, [], string>;
288
+ /**
289
+ * 3c Tier-1 coarse activity — the player's current tool + context-token usage,
290
+ * refreshed by the heartbeat piggyback (`heartbeatSignal`). Read by the snapshot
291
+ * fan-out (`getPlayerWireMeta`) → projected onto `PlayerSummaryV1` → the aggregate
292
+ * poll/diff emits `player.activity`. `currentTool` is `null` when idle/between
293
+ * tools; the context fields are absent when Pi can't report usage (e.g. right
294
+ * after compaction). A live read of volatile state — NOT durable metadata.
295
+ */
296
+ export declare const getCoarseActivityQuery: import("@temporalio/workflow").QueryDefinition<{
297
+ currentTool: string | null;
298
+ contextTokens?: number;
299
+ contextPercent?: number;
300
+ }, [], string>;
271
301
  export declare const testForceContinueAsNewSignal: import("@temporalio/workflow").SignalDefinition<[], "testForceContinueAsNew">;
272
302
  export declare const setQualityGateSignal: import("@temporalio/workflow").SignalDefinition<[{
273
303
  task: string;
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.setStageSignal = exports.worktreesQuery = exports.removeWorktreeSignal = exports.setWorktreeSignal = exports.qualityGatesQuery = exports.evaluateGateCriteriaSignal = exports.setQualityGateSignal = exports.testForceContinueAsNewSignal = exports.getLeaseStateQuery = exports.getActivityStateQuery = exports.getMessagingStateQuery = exports.getRunIdQuery = exports.outboxQuery = exports.submitOutboxUpdate = exports.playerStateKeysQuery = exports.playerStateQuery = exports.clearPlayerStateUpdate = exports.savePlayerStateUpdate = exports.orphanSummaryQuery = exports.attachmentInfoQuery = exports.adapterExitedSignal = exports.requestDetachSignal = exports.heartbeatSignal = exports.setPreferredHostUpdate = exports.enqueueSpawnUpdate = exports.forceDetachUpdate = exports.claimAttachmentUpdate = exports.isDestroyedQuery = exports.destroyUpdate = exports.inFlightMessagesQuery = exports.processingEndUpdate = exports.processingStartUpdate = exports.historyQuery = exports.playerReportSignal = exports.commandSignal = exports.pausedQuery = exports.setPausedSignal = exports.outboxLockedQuery = exports.releaseHeldSignal = exports.allSentMessagesQuery = exports.allMessagesQuery = exports.pendingMessagesQuery = exports.getMetadataQuery = exports.getPartQuery = exports.updateMetadataSignal = exports.setNameSignal = exports.markDeliveredSignal = exports.setPartSignal = exports.recordSentMessageSignal = exports.receiveMessageSignal = void 0;
4
- exports.stagesQuery = exports.cancelStageSignal = void 0;
3
+ exports.qualityGatesQuery = exports.evaluateGateCriteriaSignal = exports.setQualityGateSignal = exports.testForceContinueAsNewSignal = exports.getCoarseActivityQuery = exports.getLeaseStateQuery = exports.getActivityStateQuery = exports.getMessagingStateQuery = exports.getRunIdQuery = exports.outboxQuery = exports.submitOutboxUpdate = exports.playerStateKeysQuery = exports.playerStateQuery = exports.clearPlayerStateUpdate = exports.savePlayerStateUpdate = exports.orphanSummaryQuery = exports.attachmentInfoQuery = exports.adapterExitedSignal = exports.requestDetachSignal = exports.heartbeatSignal = exports.setPreferredHostUpdate = exports.enqueueSpawnUpdate = exports.forceDetachUpdate = exports.claimAttachmentUpdate = exports.isDestroyedQuery = exports.destroyUpdate = exports.inFlightMessagesQuery = exports.processingEndUpdate = exports.processingStartUpdate = exports.historyQuery = exports.playerReportSignal = exports.commandSignal = exports.pausedQuery = exports.setPausedSignal = exports.outboxLockedQuery = exports.releaseHeldSignal = exports.ackResetSignal = exports.pendingResetQuery = exports.setPendingResetSignal = exports.allSentMessagesQuery = exports.allMessagesQuery = exports.pendingMessagesQuery = exports.getMetadataQuery = exports.getPartQuery = exports.updateMetadataSignal = exports.setNameSignal = exports.markDeliveredSignal = exports.setPartSignal = exports.recordSentMessageSignal = exports.receiveMessageSignal = void 0;
4
+ exports.stagesQuery = exports.cancelStageSignal = exports.setStageSignal = exports.worktreesQuery = exports.removeWorktreeSignal = exports.setWorktreeSignal = void 0;
5
5
  const workflow_1 = require("@temporalio/workflow");
6
6
  // ── Player Signals ──
7
7
  // `isScheduled` + `scheduleName` are set by `src/activities/schedule-fire.ts`
@@ -27,6 +27,14 @@ exports.getMetadataQuery = (0, workflow_1.defineQuery)('getMetadata');
27
27
  exports.pendingMessagesQuery = (0, workflow_1.defineQuery)('pendingMessages');
28
28
  exports.allMessagesQuery = (0, workflow_1.defineQuery)('allMessages');
29
29
  exports.allSentMessagesQuery = (0, workflow_1.defineQuery)('allSentMessages');
30
+ // ── Reset (D14) — context clean-wipe poll-delivery ──
31
+ // `deliverReset` sets the pending flag via `setPendingResetSignal`; the Pi
32
+ // extension polls `pendingResetQuery`, performs the wipe (newSession), then
33
+ // clears it via `ackResetSignal(resetId)`. Single-slot, latest-wins. The
34
+ // workflow stamps `requestedAt` (deterministic). See WIRE-PROTOCOL.md.
35
+ exports.setPendingResetSignal = (0, workflow_1.defineSignal)('setPendingReset');
36
+ exports.pendingResetQuery = (0, workflow_1.defineQuery)('pendingReset');
37
+ exports.ackResetSignal = (0, workflow_1.defineSignal)('ackReset');
30
38
  // ── Hold / Release ──
31
39
  /** Release a held session — unlocks the outbox and delivers the stored initial message. */
32
40
  exports.releaseHeldSignal = (0, workflow_1.defineSignal)('releaseHeld');
@@ -95,6 +103,12 @@ exports.setPreferredHostUpdate = (0, workflow_1.defineUpdate)('setPreferredHost'
95
103
  /**
96
104
  * Liveness heartbeat from the adapter. Resets `lastHeartbeatAt` and extends `expiresAt` to
97
105
  * `workflow.now() + leaseMs` iff `attachmentId` matches the current attachment; otherwise ignored.
106
+ *
107
+ * 3c Tier-1 (additive, optional, non-breaking): the heartbeat doubles as the
108
+ * coarse-activity piggyback. `currentTool` (null = idle), `contextTokens`, and
109
+ * `contextPercent` (Pi `getContextUsage`, pull-only — no token event exists)
110
+ * refresh the workflow's queryable coarse state read by `getCoarseActivityQuery`.
111
+ * Omitted by senders that don't report coarse — the handler merges field-wise.
98
112
  */
99
113
  exports.heartbeatSignal = (0, workflow_1.defineSignal)('heartbeat');
100
114
  /**
@@ -210,6 +224,15 @@ exports.getActivityStateQuery = (0, workflow_1.defineQuery)('getActivityState');
210
224
  * boundary.
211
225
  */
212
226
  exports.getLeaseStateQuery = (0, workflow_1.defineQuery)('getLeaseState');
227
+ /**
228
+ * 3c Tier-1 coarse activity — the player's current tool + context-token usage,
229
+ * refreshed by the heartbeat piggyback (`heartbeatSignal`). Read by the snapshot
230
+ * fan-out (`getPlayerWireMeta`) → projected onto `PlayerSummaryV1` → the aggregate
231
+ * poll/diff emits `player.activity`. `currentTool` is `null` when idle/between
232
+ * tools; the context fields are absent when Pi can't report usage (e.g. right
233
+ * after compaction). A live read of volatile state — NOT durable metadata.
234
+ */
235
+ exports.getCoarseActivityQuery = (0, workflow_1.defineQuery)('getCoarseActivity');
213
236
  // ── Test-only Signals ──
214
237
  //
215
238
  // **Test-only.** Forces the session workflow's main loop to take the
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-tempo",
3
- "version": "1.3.1",
3
+ "version": "1.4.1",
4
4
  "description": "Many agents, one tempo. Durable coordination for multi-agent work via Temporal.",
5
5
  "keywords": [
6
6
  "mcp",
@@ -85,6 +85,8 @@
85
85
  },
86
86
  "optionalDependencies": {
87
87
  "@anthropic-ai/sdk": "~0.91.1",
88
+ "@earendil-works/pi-ai": "~0.78",
89
+ "@earendil-works/pi-coding-agent": "~0.78",
88
90
  "@github/copilot-sdk": "1.0.0-beta.6",
89
91
  "@opencode-ai/sdk": "~1.14.29"
90
92
  },
@@ -104,6 +106,7 @@
104
106
  "qrcode-terminal": "^0.12.0",
105
107
  "react": "^19.2.4",
106
108
  "semver": "^7.7.4",
109
+ "typebox": "^1.0.1",
107
110
  "yaml": "^2.8.3",
108
111
  "zod": "~3.25.76"
109
112
  },