@astrosheep/square 0.3.11 → 0.3.13

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 (127) hide show
  1. package/codex-plugin/.codex-plugin/plugin.json +1 -1
  2. package/codex-plugin/hooks/hooks.json +9 -0
  3. package/dist/activity-feed.d.ts +14 -0
  4. package/dist/activity-feed.js +5 -5
  5. package/dist/activity.d.ts +9 -0
  6. package/dist/activity.js +112 -96
  7. package/dist/artifact.d.ts +20 -0
  8. package/dist/artifact.js +317 -648
  9. package/dist/automatic-session.d.ts +5 -0
  10. package/dist/automatic-session.js +86 -0
  11. package/dist/boundary-presentation.d.ts +5 -0
  12. package/dist/boundary-presentation.js +6 -5
  13. package/dist/claude-hook.d.ts +9 -0
  14. package/dist/claude-hook.js +35 -3
  15. package/dist/cli/context.d.ts +35 -0
  16. package/dist/cli/context.js +26 -31
  17. package/dist/cli/harness-command.d.ts +28 -0
  18. package/dist/cli/harness-command.js +30 -15
  19. package/dist/cli/maintenance-commands.d.ts +7 -0
  20. package/dist/cli/maintenance-commands.js +12 -69
  21. package/dist/cli/meta-commands.d.ts +5 -0
  22. package/dist/cli/observation-commands.d.ts +20 -0
  23. package/dist/cli/observation-commands.js +159 -139
  24. package/dist/cli/program.d.ts +2 -0
  25. package/dist/cli/program.js +3 -12
  26. package/dist/cli/registry.d.ts +9 -0
  27. package/dist/cli/registry.js +2 -4
  28. package/dist/cli/square-commands.d.ts +34 -0
  29. package/dist/cli/square-commands.js +90 -84
  30. package/dist/cmd/notify-once.d.ts +2 -0
  31. package/dist/codex-hook.d.ts +10 -0
  32. package/dist/codex-hook.js +35 -3
  33. package/dist/decisions.d.ts +92 -0
  34. package/dist/decisions.js +93 -81
  35. package/dist/delivery-health.d.ts +21 -0
  36. package/dist/delivery-health.js +41 -34
  37. package/dist/delivery.d.ts +81 -0
  38. package/dist/delivery.js +71 -69
  39. package/dist/file-lock.d.ts +6 -0
  40. package/dist/harness-claude.d.ts +19 -0
  41. package/dist/harness-claude.js +8 -3
  42. package/dist/harness-codex.d.ts +29 -0
  43. package/dist/harness-codex.js +2 -2
  44. package/dist/harness-links.d.ts +17 -0
  45. package/dist/harness-links.js +2 -2
  46. package/dist/harness-pi.d.ts +11 -0
  47. package/dist/harness-pi.js +2 -2
  48. package/dist/harness-stage.d.ts +6 -0
  49. package/dist/harness.d.ts +20 -0
  50. package/dist/harness.js +5 -3
  51. package/dist/help.d.ts +6 -0
  52. package/dist/help.js +12 -13
  53. package/dist/identity.d.ts +13 -0
  54. package/dist/inbox.d.ts +2 -0
  55. package/dist/inbox.js +15 -19
  56. package/dist/index.d.ts +13 -0
  57. package/dist/index.js +31 -67
  58. package/dist/landing.d.ts +10 -0
  59. package/dist/landing.js +95 -0
  60. package/dist/list.d.ts +1 -0
  61. package/dist/list.js +39 -61
  62. package/dist/model.d.ts +147 -0
  63. package/dist/model.js +12 -8
  64. package/dist/notifications.d.ts +30 -0
  65. package/dist/notifications.js +83 -91
  66. package/dist/open-square.d.ts +11 -0
  67. package/dist/open-square.js +4 -0
  68. package/dist/participant-identity.d.ts +1 -0
  69. package/dist/participant-identity.js +3 -0
  70. package/dist/paseo-connection.d.ts +15 -0
  71. package/dist/paseo-delivery.d.ts +14 -0
  72. package/dist/paseo-state.d.ts +11 -0
  73. package/dist/paseo-timeline.d.ts +16 -0
  74. package/dist/presence.d.ts +3 -0
  75. package/dist/presence.js +42 -0
  76. package/dist/presentation.d.ts +91 -0
  77. package/dist/presentation.js +52 -63
  78. package/dist/presented.d.ts +11 -0
  79. package/dist/registry.d.ts +58 -0
  80. package/dist/registry.js +36 -3
  81. package/dist/routes.d.ts +42 -0
  82. package/dist/runtime.d.ts +45 -0
  83. package/dist/runtime.js +48 -55
  84. package/dist/search.d.ts +11 -0
  85. package/dist/square-core.d.ts +111 -0
  86. package/dist/square-core.js +63 -9
  87. package/dist/square-facade.d.ts +86 -0
  88. package/dist/square-facade.js +1 -0
  89. package/dist/square-file-adapter.d.ts +18 -0
  90. package/dist/square-file-adapter.js +70 -0
  91. package/dist/square-storage.d.ts +20 -0
  92. package/dist/square-storage.js +171 -0
  93. package/dist/square-wiring.d.ts +19 -0
  94. package/dist/square-wiring.js +70 -0
  95. package/dist/square.d.ts +2 -0
  96. package/dist/state-cell.d.ts +14 -0
  97. package/dist/state-cell.js +1 -0
  98. package/dist/stream.d.ts +3 -0
  99. package/dist/stream.js +19 -23
  100. package/dist/time.d.ts +6 -0
  101. package/dist/views.d.ts +95 -0
  102. package/dist/views.js +81 -0
  103. package/dist/wake-attempts.d.ts +39 -0
  104. package/dist/wake-attempts.js +8 -4
  105. package/dist/wake-evidence.d.ts +12 -0
  106. package/dist/wake-evidence.js +7 -10
  107. package/dist/wake-port.d.ts +20 -0
  108. package/dist/wake-sink.d.ts +12 -0
  109. package/dist/wakes.d.ts +40 -0
  110. package/dist/wakes.js +62 -0
  111. package/dist/watch.d.ts +2 -0
  112. package/dist/watch.js +89 -210
  113. package/extensions/square-opencode.js +27 -1
  114. package/extensions/square-pi.js +13 -0
  115. package/guides/participant.md +7 -174
  116. package/package.json +5 -4
  117. package/skills/brainstorm/SKILL.md +30 -30
  118. package/skills/square/.claude-plugin/plugin.json +1 -1
  119. package/skills/square/SKILL.md +56 -29
  120. package/skills/square/hooks/hooks.json +9 -0
  121. package/skills/square-feedback/SKILL.md +9 -9
  122. package/dist/compact.js +0 -26
  123. package/dist/doctor.js +0 -36
  124. package/dist/square-application.js +0 -262
  125. package/template.md +0 -4
  126. package/templates/architect.md +0 -4
  127. package/templates/brainstorm.md +0 -4
@@ -3,28 +3,24 @@ import { randomUUID } from 'node:crypto';
3
3
  import { homedir } from 'node:os';
4
4
  import { setTimeout as sleep } from 'node:timers/promises';
5
5
  import { fileURLToPath } from 'node:url';
6
- import { loadSquare } from './artifact.js';
7
- import { deriveDeliveryModel, isDeliveryDelivered, isPendingNotification, leaseOwnsNotification, planActNotifications, } from './delivery.js';
6
+ import { leaseOwnsNotification, planActNotifications, } from './delivery.js';
8
7
  import { sessionInbox } from './inbox.js';
9
8
  import { hasPresentedAttention } from './presented.js';
10
- import { nameKey, SquareError } from './model.js';
11
- import { SLEEP_MS, matchesMentionTarget, resolveRosterName, rosterNames } from './runtime.js';
9
+ import { SquareError } from './model.js';
10
+ import { SLEEP_MS, matchesMentionTarget } from './runtime.js';
11
+ import { parseActivityId } from './square-core.js';
12
12
  import { PaseoAdapter } from './paseo-delivery.js';
13
- import { quoteShell } from './presentation.js';
13
+ import { participantIdentity, quoteShell } from './presentation.js';
14
14
  import { lookupParticipant } from './registry.js';
15
- import { isCurrentlyJoined } from './runtime.js';
16
- import { execute } from './square-application.js';
15
+ import { openSquare } from './square-file-adapter.js';
16
+ import { closeOpenSquare } from './open-square.js';
17
+ import { entryPresentation, notificationDelivered, notificationForAct, pendingDeliveries, resolveParticipant } from './views.js';
18
+ import { claimNotificationLease, releaseNotificationLease, transitionNotificationLease } from './wakes.js';
17
19
  import { nextWakeAttemptNumber, recordRecoveredUnknown, recordWakeAttempt, } from './wake-attempts.js';
18
- import { joinedRecipients, wakeEvidence, wakeIsEligible } from './wake-evidence.js';
20
+ import { wakeEvidence, wakeIsEligible } from './wake-evidence.js';
19
21
  import { WakePort } from './wake-port.js';
20
22
  const NOTIFY_LEASE_MS = 5 * 60 * 1000;
21
23
  export { planActNotifications, matchesMentionTarget };
22
- function known(doc, name) {
23
- const value = resolveRosterName(doc, name);
24
- if (value === undefined)
25
- throw new SquareError('invalid_args', `Unknown participant "${name}". Expected one of: ${rosterNames(doc).join(', ')}.`);
26
- return value;
27
- }
28
24
  export { notificationMessageId } from './delivery.js';
29
25
  export function wakeGraceMs(env = process.env) {
30
26
  const value = Number.parseInt(env.SQUARE_NOTIFY_DELIVERY_WAIT_MS ?? '5000', 10);
@@ -42,7 +38,7 @@ function renderWakePayload(request) {
42
38
  : request.squarePath;
43
39
  return [
44
40
  '<system-reminder source="square">',
45
- `${request.route === 'bell' ? 'Bell' : request.route === 'beside' ? 'Beside' : 'Mention'} from @${request.actor} in \`${display}\``,
41
+ `${request.route === 'bell' ? 'Bell' : 'Mention'} from ${participantIdentity(request.actor)} in \`${display}\``,
46
42
  'The native adapter will present it at the next boundary. If no native wake is available, pull from the square yourself.',
47
43
  `\`${catchCommand(request.squarePath, request.recipient)}\``,
48
44
  '</system-reminder>',
@@ -51,23 +47,21 @@ function renderWakePayload(request) {
51
47
  async function waitForCatch(route, request, body) {
52
48
  const binding = lookupParticipant(request.squarePath, request.recipient)
53
49
  .find((item) => item.ownerId === route.ownerId);
54
- const activeCatch = binding && sessionInbox(binding.sessionId)
50
+ const activeCatch = binding && (await sessionInbox(binding.sessionId))
55
51
  .find((item) => item.name === request.recipient)?.catchLease;
56
52
  if (!activeCatch || !leaseOwnsNotification(activeCatch, {
57
53
  actor: request.actor,
58
54
  body,
59
55
  route: request.route,
60
- recipient: request.recipient,
61
56
  }))
62
57
  return false;
63
58
  const deadline = Date.now() + 180_000;
64
59
  while (Date.now() < deadline) {
65
- const doc = loadSquare(request.squarePath);
66
- if (isDeliveryDelivered(doc, request.recipient, request.actIndex))
60
+ if (await hasDeliveredNotification(request.squarePath, request.recipient, request.actIndex))
67
61
  return true;
68
62
  const currentBinding = lookupParticipant(request.squarePath, request.recipient)
69
63
  .find((item) => item.ownerId === route.ownerId);
70
- const lease = currentBinding && sessionInbox(currentBinding.sessionId)
64
+ const lease = currentBinding && (await sessionInbox(currentBinding.sessionId))
71
65
  .find((item) => item.name === request.recipient)?.catchLease;
72
66
  if (!lease || lease.expiresAt <= Date.now())
73
67
  return false;
@@ -75,58 +69,53 @@ async function waitForCatch(route, request, body) {
75
69
  }
76
70
  return false;
77
71
  }
78
- export function hasDeliveredNotification(squarePath, name, ref) {
79
- const doc = loadSquare(squarePath);
80
- return isDeliveryDelivered(doc, known(doc, name), typeof ref === 'number' ? ref : Number(ref.slice(4)));
72
+ function notificationIndex(ref) {
73
+ if (typeof ref === 'number')
74
+ return ref;
75
+ const index = parseActivityId(ref);
76
+ if (index === undefined)
77
+ throw new Error(`Invalid act ref: ${ref}`);
78
+ return index;
81
79
  }
82
- export function hasAttentionNotification(squarePath, name, ref, env = process.env) {
83
- const doc = loadSquare(squarePath);
84
- const recipient = known(doc, name);
85
- const index = typeof ref === 'number' ? ref : Number(ref.slice(4));
86
- return isDeliveryDelivered(doc, recipient, index) || hasPresentedAttention(squarePath, recipient, index, env);
80
+ export async function hasDeliveredNotification(squarePath, name, ref) {
81
+ const square = await openSquare(squarePath);
82
+ try {
83
+ const recipient = (await resolveParticipant(square, name)).name;
84
+ return notificationDelivered(square, recipient, notificationIndex(ref));
85
+ }
86
+ finally {
87
+ await closeOpenSquare(square);
88
+ }
89
+ }
90
+ export async function hasAttentionNotification(squarePath, name, ref, env = process.env) {
91
+ const square = await openSquare(squarePath);
92
+ try {
93
+ const recipient = (await resolveParticipant(square, name)).name;
94
+ const index = notificationIndex(ref);
95
+ return await notificationDelivered(square, recipient, index) || hasPresentedAttention(squarePath, recipient, index, env);
96
+ }
97
+ finally {
98
+ await closeOpenSquare(square);
99
+ }
87
100
  }
88
101
  export async function waitForDeliveredNotification(squarePath, name, ref, opts = {}) {
89
102
  const deadline = Date.now() + (opts.timeoutMs ?? 30000);
90
103
  while (Date.now() <= deadline) {
91
- if (hasDeliveredNotification(squarePath, name, ref))
104
+ if (await hasDeliveredNotification(squarePath, name, ref))
92
105
  return true;
93
106
  await sleep(Math.min(SLEEP_MS, Math.max(1, deadline - Date.now())));
94
107
  }
95
108
  return false;
96
109
  }
97
- function notifyLeaseKey(recipient, actIndex) {
98
- return JSON.stringify([`act_${actIndex}`, nameKey(recipient)]);
99
- }
100
- async function claimNotifyLease(squarePath, recipient, actIndex) {
101
- const at = Date.now();
102
- const committed = await execute(squarePath, {
103
- type: 'claim-notify',
104
- key: notifyLeaseKey(recipient, actIndex),
105
- leaseId: randomUUID(),
106
- at,
107
- expiresAt: at + NOTIFY_LEASE_MS,
108
- });
109
- return committed.result;
110
+ async function claimNotifyLease(square, recipient, actIndex) {
111
+ const leaseId = randomUUID();
112
+ return claimNotificationLease(square, recipient, actIndex, leaseId, NOTIFY_LEASE_MS);
110
113
  }
111
- async function transitionNotifyLease(squarePath, recipient, actIndex, leaseId, phase, routeKind, attemptN) {
112
- const at = Date.now();
113
- const committed = await execute(squarePath, {
114
- type: 'transition-notify',
115
- key: notifyLeaseKey(recipient, actIndex),
116
- leaseId,
117
- expiresAt: at + NOTIFY_LEASE_MS,
118
- phase,
119
- ...(routeKind === undefined ? {} : { routeKind }),
120
- ...(attemptN === undefined ? {} : { attemptN }),
121
- });
122
- return committed.result.updated;
114
+ async function transitionNotifyLease(square, recipient, actIndex, leaseId, phase, routeKind, attemptN) {
115
+ return transitionNotificationLease(square, recipient, actIndex, leaseId, phase, NOTIFY_LEASE_MS, routeKind, attemptN);
123
116
  }
124
- function releaseNotifyLease(squarePath, recipient, actIndex, leaseId) {
125
- return execute(squarePath, {
126
- type: 'release-notify',
127
- key: notifyLeaseKey(recipient, actIndex),
128
- leaseId,
129
- });
117
+ async function releaseNotifyLease(square, recipient, actIndex, leaseId) {
118
+ await releaseNotificationLease(square, recipient, actIndex, leaseId);
130
119
  }
131
120
  async function processNotification(squarePath, notification, opts) {
132
121
  const env = opts.env ?? process.env;
@@ -137,23 +126,27 @@ async function processNotification(squarePath, notification, opts) {
137
126
  recipient: notification.recipient,
138
127
  };
139
128
  const initialAt = now();
140
- if (!wakeIsEligible(wakeEvidence(squarePath, notification.recipient, notification.item.index, initialAt, env)))
129
+ if (!wakeIsEligible(await wakeEvidence(squarePath, notification.recipient, notification.item.index, initialAt, env)))
141
130
  return;
142
- const claim = await claimNotifyLease(squarePath, notification.recipient, notification.item.index);
143
- if (claim.type === 'busy')
131
+ const square = await openSquare(squarePath, { clock: now });
132
+ const claim = await claimNotifyLease(square, notification.recipient, notification.item.index);
133
+ if (claim.type === 'busy' || claim.type === 'delivered') {
134
+ await closeOpenSquare(square);
144
135
  return;
136
+ }
145
137
  if (claim.type === 'ambiguous') {
146
138
  const recovered = recordRecoveredUnknown(attention, claim.lease, env);
147
139
  if (recovered !== undefined) {
148
- await releaseNotifyLease(squarePath, notification.recipient, notification.item.index, claim.lease.leaseId);
140
+ await releaseNotifyLease(square, notification.recipient, notification.item.index, claim.lease.leaseId);
149
141
  }
142
+ await closeOpenSquare(square);
150
143
  return;
151
144
  }
152
145
  const { leaseId } = claim;
153
146
  let releaseLease = true;
154
147
  try {
155
148
  const dispatchAt = now();
156
- const evidence = wakeEvidence(squarePath, notification.recipient, notification.item.index, dispatchAt, env);
149
+ const evidence = await wakeEvidence(squarePath, notification.recipient, notification.item.index, dispatchAt, env);
157
150
  if (!wakeIsEligible(evidence))
158
151
  return;
159
152
  const port = new WakePort(opts.adapters ?? [new PaseoAdapter()]);
@@ -170,22 +163,21 @@ async function processNotification(squarePath, notification, opts) {
170
163
  if (await waitForCatch(route, request, notification.item.body))
171
164
  return false;
172
165
  const currentAt = now();
173
- const latest = loadSquare(squarePath);
174
- if (!isCurrentlyJoined(latest.acts, notification.recipient))
166
+ if (!(await entryPresentation(square, notification.recipient)).joined)
175
167
  return false;
176
- const current = wakeEvidence(squarePath, notification.recipient, notification.item.index, currentAt, env);
168
+ const current = await wakeEvidence(squarePath, notification.recipient, notification.item.index, currentAt, env);
177
169
  if (!wakeIsEligible(current))
178
170
  return false;
179
171
  if (!current.attemptableRoutes.some((candidate) => candidate.ownerId === route.ownerId && candidate.kind === route.kind && candidate.sessionId === route.sessionId))
180
172
  return false;
181
- const dispatching = await transitionNotifyLease(squarePath, notification.recipient, notification.item.index, leaseId, 'dispatching', route.kind, attemptN);
173
+ const dispatching = await transitionNotifyLease(square, notification.recipient, notification.item.index, leaseId, 'dispatching', route.kind, attemptN);
182
174
  if (dispatching)
183
175
  releaseLease = false;
184
176
  return dispatching;
185
177
  },
186
178
  record: async (route, attemptN, outcome) => {
187
179
  if (outcome.outcome === 'failed') {
188
- await transitionNotifyLease(squarePath, notification.recipient, notification.item.index, leaseId, 'claimed');
180
+ await transitionNotifyLease(square, notification.recipient, notification.item.index, leaseId, 'claimed');
189
181
  releaseLease = true;
190
182
  }
191
183
  recordWakeAttempt({
@@ -205,47 +197,47 @@ async function processNotification(squarePath, notification, opts) {
205
197
  }
206
198
  finally {
207
199
  if (releaseLease) {
208
- await releaseNotifyLease(squarePath, notification.recipient, notification.item.index, leaseId);
200
+ await releaseNotifyLease(square, notification.recipient, notification.item.index, leaseId);
209
201
  }
202
+ await closeOpenSquare(square);
210
203
  }
211
204
  }
212
205
  export async function processActNotificationsOnce(squarePath, actIndex, opts = {}) {
213
- const doc = loadSquare(squarePath);
214
- const item = doc.acts.find((candidate) => candidate.index === actIndex);
215
- if (item === undefined)
216
- return;
217
- const notifications = planActNotifications(doc, item).filter(isPendingNotification);
206
+ const square = await openSquare(squarePath);
207
+ const notifications = await notificationForAct(square, actIndex).finally(() => closeOpenSquare(square));
218
208
  await Promise.all(notifications.map((notification) => processNotification(squarePath, notification, opts)));
219
209
  }
220
210
  function launchWorker(workerPath, args) {
221
211
  const child = spawn(process.execPath, [workerPath, ...args], { detached: true, stdio: 'ignore', env: process.env });
222
212
  child.unref();
223
213
  }
224
- /** Start one detached worker only when this act contains directed attention. */
225
- export async function dispatchActNotifications(squarePath, item, opts = {}) {
226
- const env = opts.env ?? process.env;
227
- if (env.SQUARE_DISABLE_PASEO_WAKE === '1')
228
- return;
229
- const doc = loadSquare(squarePath);
230
- if (!planActNotifications(doc, item).some(isPendingNotification))
231
- return;
232
- (opts.launchWorker ?? launchWorker)(fileURLToPath(new URL('./cmd/notify-once.js', import.meta.url)), ['--location', squarePath, '--act-index', String(item.index)]);
214
+ export function wakeNotifierForSquare(squarePath, env = process.env) {
215
+ return {
216
+ wake(recipients, activity) {
217
+ if (env.SQUARE_DISABLE_PASEO_WAKE === '1' || recipients.length === 0)
218
+ return;
219
+ const actIndex = parseActivityId(activity.id);
220
+ if (actIndex === undefined)
221
+ return;
222
+ launchWorker(fileURLToPath(new URL('./cmd/notify-once.js', import.meta.url)), ['--location', squarePath, '--act-index', String(actIndex)]);
223
+ },
224
+ };
233
225
  }
234
226
  /** Reconsider old pending attention at a bounded action boundary using the existing worker. */
235
- export function sweepPendingNotifications(squarePath, opts = {}) {
227
+ export async function sweepPendingNotifications(squarePath, opts = {}) {
236
228
  const env = opts.env ?? process.env;
237
229
  if (env.SQUARE_DISABLE_PASEO_WAKE === '1')
238
230
  return [];
239
231
  const now = opts.now ?? Date.now();
240
232
  const limit = opts.limit ?? 8;
241
- const doc = loadSquare(squarePath);
242
- const model = deriveDeliveryModel(doc);
233
+ const square = await openSquare(squarePath, { clock: () => now });
234
+ const pending = await pendingDeliveries(square).finally(() => closeOpenSquare(square));
243
235
  const indexes = new Set();
244
- for (const recipient of joinedRecipients(doc)) {
245
- for (const note of model.pendingFor(recipient)) {
236
+ for (const delivery of pending) {
237
+ for (const note of delivery.notifications) {
246
238
  if (now - note.item.at <= wakeGraceMs(env))
247
239
  continue;
248
- if (!wakeIsEligible(wakeEvidence(squarePath, recipient, note.item.index, now, env)))
240
+ if (!wakeIsEligible(await wakeEvidence(squarePath, delivery.recipient, note.item.index, now, env)))
249
241
  continue;
250
242
  indexes.add(note.item.index);
251
243
  }
@@ -0,0 +1,11 @@
1
+ import type { StateCell } from './state-cell.js';
2
+ import type { WakeNotifier } from './square-facade.js';
3
+ /** Private binding assembled by storage and consumed by the four concerns. */
4
+ export interface OpenSquare {
5
+ readonly cell: StateCell;
6
+ readonly clock: () => number;
7
+ readonly notifier?: WakeNotifier;
8
+ readonly location: string;
9
+ }
10
+ /** Package-private lifecycle boundary for bound squares. */
11
+ export declare function closeOpenSquare(square: OpenSquare): Promise<void>;
@@ -0,0 +1,4 @@
1
+ /** Package-private lifecycle boundary for bound squares. */
2
+ export function closeOpenSquare(square) {
3
+ return square.cell.close();
4
+ }
@@ -0,0 +1 @@
1
+ export declare function participantIdentity(name: string): string;
@@ -0,0 +1,3 @@
1
+ export function participantIdentity(name) {
2
+ return `@${name}`;
3
+ }
@@ -0,0 +1,15 @@
1
+ import { DaemonClient } from '@getpaseo/client/internal/daemon-client';
2
+ export type PaseoDaemonTarget = {
3
+ type: 'tcp';
4
+ url: string;
5
+ password?: string;
6
+ } | {
7
+ type: 'ipc';
8
+ url: string;
9
+ socketPath: string;
10
+ password?: string;
11
+ };
12
+ /** Match the host precedence used by the Paseo CLI for local daemon connections. */
13
+ export declare function paseoDaemonHosts(env?: NodeJS.ProcessEnv): string[];
14
+ export declare function resolvePaseoDaemonTarget(host: string, env?: NodeJS.ProcessEnv): PaseoDaemonTarget;
15
+ export declare function connectPaseoDaemon(env?: NodeJS.ProcessEnv, connectTimeoutMs?: number): Promise<DaemonClient>;
@@ -0,0 +1,14 @@
1
+ import { type WakeAdapter, type WakeDispatchResult } from './delivery.js';
2
+ import { discoverPaseoAgents, waitForPaseoWakeBoundary } from './paseo-state.js';
3
+ import { sendPaseoWake } from './wake-sink.js';
4
+ export interface PaseoAdapterOptions {
5
+ discover?: typeof discoverPaseoAgents;
6
+ waitForBoundary?: typeof waitForPaseoWakeBoundary;
7
+ sendWake?: typeof sendPaseoWake;
8
+ }
9
+ export declare class PaseoAdapter implements WakeAdapter {
10
+ private readonly opts;
11
+ readonly kind: "paseo";
12
+ constructor(opts?: PaseoAdapterOptions);
13
+ dispatch(address: Readonly<Record<string, string>>, payload: string, beforeSend: () => Promise<boolean>): Promise<WakeDispatchResult>;
14
+ }
@@ -0,0 +1,11 @@
1
+ export interface PaseoAgent {
2
+ id: string;
3
+ name: string;
4
+ status: string;
5
+ cwd?: string;
6
+ }
7
+ export declare function discoverPaseoAgents(timeoutMs?: number): {
8
+ agents: PaseoAgent[];
9
+ error?: string;
10
+ };
11
+ export declare function waitForPaseoWakeBoundary(agent: Pick<PaseoAgent, 'id' | 'status'>): Promise<boolean>;
@@ -0,0 +1,16 @@
1
+ export type PaseoToolStatus = 'running' | 'completed' | 'failed';
2
+ export interface PaseoToolCallSnapshot {
3
+ callId: string;
4
+ status: PaseoToolStatus;
5
+ }
6
+ export interface PaseoTimelineSnapshot {
7
+ agentStatus: string;
8
+ toolCalls: PaseoToolCallSnapshot[];
9
+ }
10
+ export interface WaitForPaseoToolBoundaryOptions {
11
+ pollIntervalMs?: number;
12
+ timeoutMs?: number;
13
+ readSnapshot?: (agentId: string) => Promise<PaseoTimelineSnapshot>;
14
+ delay?: (ms: number) => Promise<void>;
15
+ }
16
+ export declare function waitForPaseoToolBoundary(agentId: string, opts?: WaitForPaseoToolBoundaryOptions): Promise<boolean>;
@@ -0,0 +1,3 @@
1
+ import type { OpenSquare } from './open-square.js';
2
+ import type { CatchOptions, CatchResult } from './square-facade.js';
3
+ export declare function catchUp(square: OpenSquare, name: string, options?: CatchOptions): Promise<CatchResult>;
@@ -0,0 +1,42 @@
1
+ import { extractMentions, formatActivityId, perceive } from './square-core.js';
2
+ import { ackPeerDelta, deliveryDelta, filteredRoomChanges, matchesFeedFilter, peerPublicActs } from './activity-feed.js';
3
+ import { markDeliveredNotifications } from './delivery.js';
4
+ import { SquareError } from './model.js';
5
+ import { resolveKnownName } from './decisions.js';
6
+ import { readCursor } from './runtime.js';
7
+ function expose(activity, viewer) {
8
+ if (activity.kind === 'read' || activity.actor === undefined)
9
+ throw new Error(`Cannot expose stored activity ${formatActivityId(activity.index)}`);
10
+ const perception = perceive(activity, viewer);
11
+ const result = { id: formatActivityId(activity.index), at: activity.at, kind: activity.kind, actor: activity.actor, mentions: activity.kind === 'say' ? extractMentions(activity.body) : [], ...('body' in activity && activity.body !== undefined ? { body: activity.body } : {}), ...(activity.kind === 'say' && activity.reply !== undefined ? { reply: formatActivityId(activity.reply) } : {}) };
12
+ if (perception === 'full' || !('body' in result))
13
+ return { ...result, perception };
14
+ const { body: _body, ...withoutBody } = result;
15
+ return { ...withoutBody, perception };
16
+ }
17
+ export async function catchUp(square, name, options = {}) {
18
+ const idle = options.idle ?? 0;
19
+ if (!Number.isFinite(idle) || idle < 0)
20
+ throw new SquareError('invalid_args', 'Catch idle duration must be a non-negative number');
21
+ const deadline = Date.now() + idle;
22
+ while (true) {
23
+ const attempt = await square.cell.transact((state, version) => {
24
+ const at = square.clock();
25
+ const viewer = resolveKnownName(state, name);
26
+ const delta = deliveryDelta(state, viewer);
27
+ const filter = { ...(options.from === undefined ? {} : { participants: [...options.from] }), ...(options.mention === true ? { mention: viewer } : {}) };
28
+ const delivered = [...peerPublicActs(delta, viewer).filter((activity) => matchesFeedFilter(activity, filter)), ...filteredRoomChanges(delta, viewer, filter)]
29
+ .filter((activity, index, activities) => activities.findIndex((candidate) => candidate.index === activity.index) === index)
30
+ .sort((left, right) => left.index - right.index);
31
+ const cursorChanged = ackPeerDelta(state, viewer, delta, at);
32
+ const receiptsChanged = markDeliveredNotifications(state, viewer, delivered, at);
33
+ const cursor = readCursor(state, viewer);
34
+ return { ...(cursorChanged || receiptsChanged ? { state } : {}), result: { version, caught: { activities: delivered.map((activity) => expose(activity, viewer)), consumedThrough: cursor < 0 ? null : formatActivityId(cursor), idleExpired: false } } };
35
+ });
36
+ if (attempt.caught.activities.length > 0 || idle === 0)
37
+ return attempt.caught;
38
+ const remaining = deadline - Date.now();
39
+ if (remaining <= 0 || !await square.cell.changed(attempt.version, remaining))
40
+ return { ...attempt.caught, idleExpired: true };
41
+ }
42
+ }
@@ -0,0 +1,91 @@
1
+ import { type StoredAct, type SquareState, type PublicAct, type RoomChangeAct } from './model.js';
2
+ export { participantIdentity } from './participant-identity.js';
3
+ import type { UnreadActivitySummary, ParticipantStatus } from './decisions.js';
4
+ export type WatchStatus = 'stale' | 'empty-now' | 'quorum' | 'capped';
5
+ interface HeaderOptions {
6
+ participantCount?: number;
7
+ held?: boolean;
8
+ }
9
+ interface ParticipantOutputOptions {
10
+ squarePath: string;
11
+ name: string;
12
+ participantCount?: number;
13
+ held?: boolean;
14
+ }
15
+ interface ActivityLimitOptions extends ParticipantOutputOptions {
16
+ count?: number;
17
+ hardCap?: number;
18
+ draftPath?: string;
19
+ }
20
+ interface ActivityBlockedOptions extends ParticipantOutputOptions {
21
+ forceCommand: string;
22
+ activitySummaries: UnreadActivitySummary[];
23
+ unreadRoomChanges: RoomChangeAct[];
24
+ draftPath?: string;
25
+ }
26
+ interface ExpressWaitingOptions {
27
+ reason: 'throttled' | 'held';
28
+ delayMs?: number;
29
+ }
30
+ interface ExpressNoWaitOptions extends ParticipantOutputOptions {
31
+ reason: 'throttled' | 'held';
32
+ delayMs?: number;
33
+ holdReason?: string;
34
+ draftPath?: string;
35
+ }
36
+ interface WatchStatusOptions extends ParticipantOutputOptions {
37
+ status: WatchStatus;
38
+ idleMs?: number;
39
+ presence?: {
40
+ participants: ParticipantStatus[];
41
+ now: number;
42
+ };
43
+ showCatchHint?: boolean;
44
+ }
45
+ export declare function displayPath(squarePath: string, cwd?: string): string;
46
+ export declare function withPathOutput(squarePath: string, body?: string, opts?: HeaderOptions): string;
47
+ export declare function quoteShell(value: string): string;
48
+ export declare function commandPrefix(squarePath: string): string;
49
+ export declare function participantCommandPrefix(squarePath: string, name: string): string;
50
+ export declare function renderPresenceLines(participants: ParticipantStatus[], now: number, limit?: number): string[];
51
+ export declare function expressHintLine(ownActivityCount: number): string | undefined;
52
+ export declare function truncateChars(body: string, maxChars: number): {
53
+ text: string;
54
+ remaining: number;
55
+ };
56
+ export declare function previewActivityBody(body: string): string;
57
+ export declare function renderRoomChangeText(event: RoomChangeAct): string;
58
+ export declare function renderEventCli(event: StoredAct, opts?: {
59
+ now?: number;
60
+ preview?: number;
61
+ actNumber?: number;
62
+ mention?: string;
63
+ }): string;
64
+ export declare function renderAmbientEvent(event: StoredAct, viewer: string, opts?: {
65
+ now?: number;
66
+ preview?: number;
67
+ actNumber?: number;
68
+ mention?: string;
69
+ }): string;
70
+ export declare function renderPendingFeed(history: StoredAct[], publicItems: PublicAct[], roomChanges: RoomChangeAct[], viewer?: string): string;
71
+ export declare function renderActivityBlocked(opts: ActivityBlockedOptions): string;
72
+ export declare function renderExpressWaiting(opts: ExpressWaitingOptions): string;
73
+ export declare function renderExpressNoWait(opts: ExpressNoWaitOptions): string;
74
+ export declare function renderPublicTail(events: StoredAct[], lastN: number | null | undefined, now?: number, viewer?: string): string;
75
+ export declare function renderActivitiesView(squareState: SquareState, visible: StoredAct[], lastN: number | null | undefined, full: boolean | undefined, squarePath: string, viewer?: string, mode?: 'ambient' | 'archive'): string;
76
+ export declare function renderGrepActivitiesView(visible: StoredAct[], totalMatches: number, full: boolean | undefined, squarePath: string, pattern: string, fixed?: boolean): string;
77
+ export declare function renderActivityLimit(opts: ActivityLimitOptions): string;
78
+ export declare function renderWatchAlreadyActive(opts: ParticipantOutputOptions): string;
79
+ export declare function renderWatchForceTakeover(_opts: ParticipantOutputOptions): string;
80
+ export declare function renderWatchReplaced(_opts: ParticipantOutputOptions): string;
81
+ export declare function renderWatchStatus(opts: WatchStatusOptions): string;
82
+ export declare function renderDoctorClean(): string;
83
+ export declare function renderDoctorUnfixable(reason: string): string;
84
+ export declare function renderWatchOutput(history: StoredAct[], publicItems: PublicAct[], roomChanges: RoomChangeAct[], opts: {
85
+ squarePath: string;
86
+ stalePartial?: boolean;
87
+ idleMs?: number;
88
+ mention?: string;
89
+ viewer: string;
90
+ showCatchHint?: boolean;
91
+ }): string;