@astrosheep/square 0.4.6 → 0.4.8

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 (101) hide show
  1. package/dist/card-format.d.ts +2 -0
  2. package/dist/card-format.js +2 -0
  3. package/dist/claude-mcp-context.d.ts +0 -1
  4. package/dist/claude-mcp-context.js +0 -10
  5. package/dist/claude-mod.d.ts +2 -0
  6. package/dist/claude-mod.js +211 -0
  7. package/dist/cli/context.d.ts +2 -2
  8. package/dist/cli/context.js +14 -16
  9. package/dist/cli/express-presentation.js +12 -53
  10. package/dist/cli/json.js +2 -2
  11. package/dist/cli/observation-commands.d.ts +2 -7
  12. package/dist/cli/observation-commands.js +31 -97
  13. package/dist/cli/registry.js +3 -6
  14. package/dist/cli/square-commands.d.ts +2 -3
  15. package/dist/cli/square-commands.js +12 -22
  16. package/dist/decisions.js +5 -4
  17. package/dist/harness-claude.js +3 -3
  18. package/dist/help.js +9 -16
  19. package/dist/index.d.ts +1 -1
  20. package/dist/index.js +1 -1
  21. package/dist/mcp.d.ts +1 -0
  22. package/dist/mcp.js +7 -18
  23. package/dist/model.d.ts +1 -1
  24. package/dist/neutral.d.ts +15 -3
  25. package/dist/notifications.d.ts +1 -3
  26. package/dist/notifications.js +21 -23
  27. package/dist/operation-control.d.ts +0 -1
  28. package/dist/operation-control.js +0 -11
  29. package/dist/operation-presentation.d.ts +28 -21
  30. package/dist/operation-presentation.js +90 -87
  31. package/dist/packages/agent-delivery/src/index.d.ts +4 -9
  32. package/dist/packages/agent-delivery/src/index.js +0 -9
  33. package/dist/packages/agent-delivery/src/local-endpoint.d.ts +2 -12
  34. package/dist/packages/agent-delivery/src/local-endpoint.js +4 -48
  35. package/dist/packages/agent-delivery/src/pi-client.js +0 -2
  36. package/dist/packages/agent-delivery/src/types.d.ts +3 -37
  37. package/dist/participant-identity.d.ts +0 -2
  38. package/dist/participant-identity.js +0 -13
  39. package/dist/plugins/paseo/shared/card-format.d.ts +6 -0
  40. package/dist/plugins/paseo/shared/card-format.js +38 -0
  41. package/dist/plugins/paseo/shared/card-presentation.d.ts +3 -1
  42. package/dist/plugins/paseo/shared/card-presentation.js +3 -1
  43. package/dist/presentation.d.ts +5 -22
  44. package/dist/presentation.js +25 -58
  45. package/dist/runtime.d.ts +6 -6
  46. package/dist/runtime.js +5 -15
  47. package/dist/sqlite-square.d.ts +4 -5
  48. package/dist/sqlite-square.js +29 -32
  49. package/dist/square-api.d.ts +1 -1
  50. package/dist/square-api.js +1 -1
  51. package/dist/square-facade.d.ts +5 -14
  52. package/dist/square-location.d.ts +0 -1
  53. package/dist/square-posting.d.ts +4 -4
  54. package/dist/square-posting.js +14 -16
  55. package/dist/square-tools.d.ts +4 -17
  56. package/dist/square-tools.js +52 -119
  57. package/dist/square-values.d.ts +1 -1
  58. package/dist/square-values.js +1 -1
  59. package/dist/time.d.ts +1 -0
  60. package/dist/time.js +10 -0
  61. package/dist/views.d.ts +1 -1
  62. package/dist/views.js +2 -2
  63. package/dist/wake-transports.d.ts +2 -2
  64. package/dist/wake-transports.js +7 -9
  65. package/dist/wakes.js +1 -1
  66. package/examples/symmetric-domains.mjs +1 -2
  67. package/guides/catch-cold-path-optimization.md +1 -1
  68. package/guides/claude-native.md +37 -7
  69. package/guides/delivery-primitives.md +2 -1
  70. package/guides/mcp.md +3 -3
  71. package/guides/pi-native-delivery.md +10 -2
  72. package/guides/pi-tools.md +1 -3
  73. package/guides/row-storage-design.md +1 -1
  74. package/package.json +1 -1
  75. package/plugins/claude/.claude-plugin/plugin.json +3 -2
  76. package/plugins/claude/README.md +9 -0
  77. package/plugins/claude/hooks/hooks.json +1 -9
  78. package/plugins/claude/hooks/register.js +178 -0
  79. package/plugins/claude/skills/square/SKILL.md +2 -2
  80. package/plugins/codex/.codex-plugin/plugin.json +1 -1
  81. package/plugins/paseo/OVERVIEW.md +1 -1
  82. package/plugins/paseo/README.md +20 -23
  83. package/plugins/paseo/client/markdown.tsx +88 -95
  84. package/plugins/paseo/client/palette.ts +37 -12
  85. package/plugins/paseo/client/square-message.tsx +52 -76
  86. package/plugins/paseo/client/transform.ts +4 -6
  87. package/plugins/paseo/shared/card-format.ts +37 -0
  88. package/plugins/paseo/shared/card-presentation.ts +6 -2
  89. package/plugins/paseo/shared/message.ts +1 -6
  90. package/plugins/pi/square-pi.js +76 -60
  91. package/skills/square/SKILL.md +2 -2
  92. package/dist/claude-boundary-state.d.ts +0 -20
  93. package/dist/claude-boundary-state.js +0 -84
  94. package/dist/claude-hook.d.ts +0 -2
  95. package/dist/claude-hook.js +0 -232
  96. package/dist/packages/agent-delivery/src/claude-auth.d.ts +0 -13
  97. package/dist/packages/agent-delivery/src/claude-auth.js +0 -75
  98. package/dist/packages/agent-delivery/src/claude-native.d.ts +0 -30
  99. package/dist/packages/agent-delivery/src/claude-native.js +0 -75
  100. package/dist/packages/agent-delivery/src/claude.d.ts +0 -5
  101. package/dist/packages/agent-delivery/src/claude.js +0 -66
@@ -5,7 +5,7 @@ import { squareLocation } from './square-location.js';
5
5
  import crypto from 'node:crypto';
6
6
  import { setTimeout as sleep } from 'node:timers/promises';
7
7
  import { InternalSquareError, SquareError, isSquareError, nameKey, validateName } from './model.js';
8
- import { checkControl, failure, squareClock } from './operation-control.js';
8
+ import { checkControl, failure } from './operation-control.js';
9
9
  import { validateMetadataMatch } from './delivery-deferral.js';
10
10
  import { flushSquarePosts, reconcileSquareDelivery, readSquareSessions, ensureInitialDeliverySession } from './square-posting.js';
11
11
  import { attentionChange, coreDone, coreListening, decideAct, decideJoin, resolveKnownName, validateDoneBody } from './decisions.js';
@@ -17,13 +17,11 @@ import { asSeatRef, participantAuthority, requireJoinName, requireOwner } from '
17
17
  import { recoveryObservation, entryPresentation, queryStatus, queryParticipants, perceivePresence, parseRequiredActivityId, toPublicActivity, toPerceivedActivity, publicActivities, selectHistory, NON_READ, HISTORY_MAX_LIMIT, HISTORY_DEFAULT_LIMIT } from './views.js';
18
18
  import { sessionInboxCounts } from './inbox.js';
19
19
  import { participantIdentity } from './participant-identity.js';
20
- import { joinRecoveryCommand } from './presentation.js';
21
20
  import { acquireWatchLease, ownsWatchLease, pulseWatchLease, releaseWatchLease } from './wakes.js';
22
21
  import { createArtifactPort, createSquare, diagnoseSquareFile, prepareSquareBuild } from './artifact.js';
23
22
  import { activityQueryFilter } from './activity-query.js';
24
23
  import { discoverSquares } from './list.js';
25
24
  import { streamSquare } from './stream.js';
26
- export { squareClock } from './operation-control.js';
27
25
  export { formatActivityId, parseActivityId, MAX_IDENTITY_SET_SIZE } from './square-core.js';
28
26
  export { PERCEIVE_DEFAULT_LIMIT, PERCEIVE_MAX_LIMIT } from './perceive-decisions.js';
29
27
  export { HISTORY_DEFAULT_LIMIT, HISTORY_MAX_LIMIT } from './views.js';
@@ -43,25 +41,25 @@ export class SqliteSquare {
43
41
  location;
44
42
  artifact;
45
43
  clock;
46
- env;
47
- deliveryLocation;
48
- constructor(location, artifact, clock, env, deliveryLocation = location) {
44
+ canonicalLocation;
45
+ ledgerLocation;
46
+ constructor(location, artifact, clock, canonicalLocation = location, ledgerLocation) {
49
47
  this.location = location;
50
48
  this.artifact = artifact;
51
49
  this.clock = clock;
52
- this.env = env;
53
- this.deliveryLocation = deliveryLocation;
50
+ this.canonicalLocation = canonicalLocation;
51
+ this.ledgerLocation = ledgerLocation;
54
52
  }
55
- reconcile(signal) { return reconcileSquareDelivery(this.artifact, this.deliveryLocation, this.env, this.clock, signal); }
53
+ reconcile(signal) { return reconcileSquareDelivery(this.artifact, this.canonicalLocation, this.clock, signal, this.ledgerLocation); }
56
54
  // Posting is retryable after commit; a delivery failure cannot make a landed write unsent.
57
- async flush(signal) { await flushSquarePosts(this.artifact, this.deliveryLocation, this.env, this.clock, signal).catch(() => undefined); }
55
+ async flush(signal) { await flushSquarePosts(this.artifact, this.canonicalLocation, this.clock, signal, this.ledgerLocation).catch(() => undefined); }
58
56
  static async at(input, control) {
59
- const env = { ...(input.env ?? process.env) }, location = squareLocation({ ...input, env });
60
- const clock = squareClock(env, input.clock);
57
+ const location = squareLocation(input);
58
+ const clock = input.clock ?? Date.now;
61
59
  const artifact = createArtifactPort(location, undefined, control?.signal);
62
60
  try {
63
61
  await artifact.read(facts => facts.header(), control?.signal);
64
- return new SqliteSquare(location, artifact, clock, env, await canonicalPath(location));
62
+ return new SqliteSquare(location, artifact, clock, await canonicalPath(location), input.ledgerLocation);
65
63
  }
66
64
  catch (error) {
67
65
  await artifact.close();
@@ -72,15 +70,15 @@ export class SqliteSquare {
72
70
  }
73
71
  static async build(input, control) {
74
72
  checkControl(control);
75
- const env = { ...(input.env ?? process.env) }, location = squareLocation({ ...input, env });
73
+ const location = squareLocation(input);
76
74
  await createSquare(location, { hardCap: input.hardCap, throttlePerMinute: input.throttlePerMinute,
77
75
  template: input.template, force: input.force ?? false }, input.markdown, control?.signal);
78
76
  // Publication already committed; cancellation cannot erase the completed build.
79
- return SqliteSquare.at({ ...input, path: location, env });
77
+ return SqliteSquare.at({ ...input, path: location });
80
78
  }
81
79
  static inMemory(input) {
82
- const env = { ...(input.env ?? process.env) };
83
- return new SqliteSquare(`memory://${crypto.randomUUID()}`, createArtifactPort(':memory:', prepareSquareBuild(input, input.markdown)), squareClock(env, input.clock), env);
80
+ const clock = input.clock ?? Date.now;
81
+ return new SqliteSquare(`memory://${crypto.randomUUID()}`, createArtifactPort(':memory:', prepareSquareBuild(input, input.markdown)), clock, undefined, input.ledgerLocation);
84
82
  }
85
83
  /** Join establishes membership and local producer custody in one transaction. */
86
84
  async joinSeat(name, options, control) {
@@ -133,7 +131,7 @@ export class SqliteSquare {
133
131
  : seat?.attachment === 'detached' ? 'is away; resume the host session first'
134
132
  : 'needs a current participant seat; join first';
135
133
  throw new SquareError('already_joined', `${participantIdentity(participant?.name ?? name)} ${reason}`, {
136
- reason: 'needs_seat', join: joinRecoveryCommand(this.location, participant?.name ?? name),
134
+ reason: 'needs_seat',
137
135
  });
138
136
  }
139
137
  return seat;
@@ -150,7 +148,7 @@ export class SqliteSquare {
150
148
  async withHostPresence(select, control) {
151
149
  const seats = (await this.artifact.read(facts => facts.roster().filter(person => person.joined)
152
150
  .flatMap(person => { const seat = facts.seat(person.name); return seat === undefined ? [] : [seat]; }), control?.signal)).value;
153
- const sessions = await readSquareSessions(seats, this.env, control?.signal);
151
+ const sessions = await readSquareSessions(seats, control?.signal, this.ledgerLocation);
154
152
  const captured = new Map(seats.map(seat => [nameKey(seat.participant), seat]));
155
153
  return (await this.artifact.read(facts => {
156
154
  const seat = (name) => {
@@ -217,9 +215,9 @@ export class SqliteSquare {
217
215
  ...(options.reach === undefined ? {} : { reach: options.reach }), ...(options.noMention === undefined ? {} : { noMention: options.noMention }), ...(reply === undefined ? {} : { reply }) });
218
216
  const decision = rejectUnsentActivity(() => {
219
217
  if (proposed.type === 'blocked')
220
- throw new SquareError('behind', `${participantIdentity(name)} has pending activity`, { pending: proposed.activitySummaries.reduce((count, summary) => count + summary.count, 0) });
218
+ throw new SquareError('behind', `${participantIdentity(name)} has pending activity`, { activitySummaries: proposed.activitySummaries });
221
219
  if (proposed.type === 'capped')
222
- throw new SquareError('capped', `${participantIdentity(name)} reached the activity cap`);
220
+ throw new SquareError('capped', `${participantIdentity(name)} reached the activity cap`, { spoken: facts.participant(name).sayCount, ...(facts.header().hardCap == null ? {} : { hardCap: facts.header().hardCap }) });
223
221
  if (proposed.type === 'throttled')
224
222
  throw new SquareError('throttled', `${name} is throttled`, { retryAfterMs: proposed.delayMs });
225
223
  if (proposed.type === 'bell_quota')
@@ -338,10 +336,10 @@ export class SqliteSquare {
338
336
  validateName(name);
339
337
  if (!Number.isFinite(idle) || idle < 0)
340
338
  throw new SquareError('invalid_args', 'Perceive idle duration must be a non-negative number');
341
- if (options.id !== undefined && ['idle', 'from', 'mention', 'limit', 'replace'].some(key => Object.hasOwn(options, key)))
342
- throw new SquareError('invalid_args', 'Perceive id cannot be combined with idle, from, mention, limit or replace');
343
- if (Object.hasOwn(options, 'replace') && idle === 0)
344
- throw new SquareError('invalid_args', 'Perceive replacement requires a positive idle duration');
339
+ if (options.id !== undefined && ['idle', 'from', 'mention', 'limit', 'takeover'].some(key => Object.hasOwn(options, key)))
340
+ throw new SquareError('invalid_args', 'Perceive id cannot be combined with idle, from, mention, limit or takeover');
341
+ if (Object.hasOwn(options, 'takeover') && idle === 0)
342
+ throw new SquareError('invalid_args', 'Perceive takeover requires a positive idle duration');
345
343
  perceiveLimit(options.limit);
346
344
  const probe = (await square.artifact.read(facts => {
347
345
  name = resolveKnownName(facts, this.name);
@@ -362,13 +360,13 @@ export class SqliteSquare {
362
360
  }
363
361
  const watch = {
364
362
  ...(selection.from === undefined ? {} : { participants: [...selection.from] }), ...(options.mention ? { mention: name } : {}),
365
- ...(options.replace === undefined ? {} : { replace: options.replace }),
363
+ ...(options.takeover === undefined ? {} : { takeover: options.takeover }),
366
364
  };
367
365
  const start = await acquireWatchLease(square.artifact, seat, square.clock(), crypto.randomUUID(), watch, control?.signal);
368
366
  if (start.type === 'active')
369
367
  return await complete(undefined, 'already-active');
370
368
  leaseId = start.leaseId;
371
- control?.onProgress?.({ kind: 'perceive-started', participant: name, idleMs: idle, replacementRequested: options.replace ?? false, replaced: start.replaced });
369
+ control?.onProgress?.({ kind: 'perceive-started', participant: name, idleMs: idle, replacementRequested: options.takeover ?? false, replaced: start.replaced });
372
370
  const quietSince = square.clock();
373
371
  let nextHeartbeat = start.heartbeatAt + WATCH_HEARTBEAT_MS;
374
372
  while (true) {
@@ -483,7 +481,7 @@ export class SqliteSquare {
483
481
  const last = options.last ?? HISTORY_DEFAULT_LIMIT;
484
482
  if (!Number.isSafeInteger(last) || last < 1 || last > HISTORY_MAX_LIMIT)
485
483
  throw new SquareError('invalid_args', 'Join history limit must be between 1 and 100');
486
- if (!await ensureInitialDeliverySession(requireOwner(options.owner), this.env, options.wakeAddress, control?.signal))
484
+ if (!await ensureInitialDeliverySession(requireOwner(options.owner), options.wakeAddress, control?.signal, this.ledgerLocation))
487
485
  throw new SquareError('already_joined', `${participantIdentity(name)} is away; resume the host session first`, { reason: 'needs_seat' });
488
486
  await this.reconcile(control?.signal);
489
487
  const committed = await this.joinSeat(name, options, control);
@@ -517,11 +515,10 @@ export class SqliteSquare {
517
515
  throw new SquareError('invalid_args', 'History order must be asc or desc.');
518
516
  if (query.since !== undefined && !Number.isFinite(query.since))
519
517
  throw new SquareError('invalid_args', 'History timestamp must be finite');
520
- for (const count of [query.contextBefore, query.contextAfter])
521
- if (count !== undefined && (!Number.isSafeInteger(count) || count < 0))
522
- throw new SquareError('invalid_args', 'History context must be a non-negative safe integer');
518
+ if (query.context !== undefined && (!Number.isSafeInteger(query.context) || query.context < 0 || query.context > HISTORY_MAX_LIMIT))
519
+ throw new SquareError('invalid_args', `History context must be a non-negative integer no greater than ${HISTORY_MAX_LIMIT}`);
523
520
  const limit = query.limit === undefined ? (query.at?.length ? null : HISTORY_DEFAULT_LIMIT) : query.limit;
524
- const contextual = !!query.at?.length || query.contextBefore !== undefined || query.contextAfter !== undefined;
521
+ const contextual = !!query.at?.length || query.context !== undefined;
525
522
  const kinds = contextual || query.since !== undefined ? [...NON_READ, 'read'] : NON_READ;
526
523
  return (await this.artifact.read(facts => {
527
524
  const selected = selectHistory(facts, query, limit, kinds, query.observe === true);
@@ -16,4 +16,4 @@ export declare function selectOwnSeat(square: Pick<SqliteSquare, 'participant' |
16
16
  }): Promise<Participant | undefined>;
17
17
  export { ACTIVITY_METADATA_MAX_BYTES } from './model.js';
18
18
  export { localUserOwner, harnessOwner, decodeHarnessOwner } from './owner.js';
19
- export { squareClock, formatActivityId, parseActivityId, MAX_IDENTITY_SET_SIZE, PERCEIVE_DEFAULT_LIMIT, PERCEIVE_MAX_LIMIT, HISTORY_DEFAULT_LIMIT, HISTORY_MAX_LIMIT, DEFAULT_LIST_DEPTH, MAX_LIST_DEPTH, DEFAULT_LIST_LIMIT, MAX_LIST_LIMIT, diagnoseSquare, discover, inbox } from './sqlite-square.js';
19
+ export { formatActivityId, parseActivityId, MAX_IDENTITY_SET_SIZE, PERCEIVE_DEFAULT_LIMIT, PERCEIVE_MAX_LIMIT, HISTORY_DEFAULT_LIMIT, HISTORY_MAX_LIMIT, DEFAULT_LIST_DEPTH, MAX_LIST_DEPTH, DEFAULT_LIST_LIMIT, MAX_LIST_LIMIT, diagnoseSquare, discover, inbox } from './sqlite-square.js';
@@ -24,4 +24,4 @@ export async function selectOwnSeat(square, owner, name, options) {
24
24
  }
25
25
  export { ACTIVITY_METADATA_MAX_BYTES } from './model.js';
26
26
  export { localUserOwner, harnessOwner, decodeHarnessOwner } from './owner.js';
27
- export { squareClock, formatActivityId, parseActivityId, MAX_IDENTITY_SET_SIZE, PERCEIVE_DEFAULT_LIMIT, PERCEIVE_MAX_LIMIT, HISTORY_DEFAULT_LIMIT, HISTORY_MAX_LIMIT, DEFAULT_LIST_DEPTH, MAX_LIST_DEPTH, DEFAULT_LIST_LIMIT, MAX_LIST_LIMIT, diagnoseSquare, discover, inbox } from './sqlite-square.js';
27
+ export { formatActivityId, parseActivityId, MAX_IDENTITY_SET_SIZE, PERCEIVE_DEFAULT_LIMIT, PERCEIVE_MAX_LIMIT, HISTORY_DEFAULT_LIMIT, HISTORY_MAX_LIMIT, DEFAULT_LIST_DEPTH, MAX_LIST_DEPTH, DEFAULT_LIST_LIMIT, MAX_LIST_LIMIT, diagnoseSquare, discover, inbox } from './sqlite-square.js';
@@ -2,7 +2,7 @@ import type { MetadataMatch } from './delivery-deferral.js';
2
2
  export type { MetadataMatch, MetadataScalar } from './delivery-deferral.js';
3
3
  import type { ActivityId, Perception, Reach } from './square-core.js';
4
4
  import type { Owner, HydratedAct, WakeAddress, ActivityMetadata, DirectedNotificationRoute } from './model.js';
5
- import type { OperationControl } from './neutral.js';
5
+ import type { OperationControl, UnreadActivitySummary } from './neutral.js';
6
6
  export interface ActivitySearch {
7
7
  readonly text: string;
8
8
  readonly mode: 'literal' | 'regex';
@@ -16,7 +16,7 @@ export interface HeldSeat {
16
16
  readonly name: string;
17
17
  readonly generation: string;
18
18
  }
19
- export type { PerceiveWaitStart, OperationProgress, OperationControl, OperationFailureDetail, OperationError } from './neutral.js';
19
+ export type { PerceiveWaitStart, OperationProgress, OperationControl, OperationFailureDetail, OperationError, UnreadActivitySummary, SquareErrorFacts } from './neutral.js';
20
20
  export type { ActivityId, Perception, Reach } from './square-core.js';
21
21
  export type { Owner, WakeAddress, ActivityMetadata, JsonValue, DirectedNotificationRoute } from './model.js';
22
22
  /** Indexed archive event, including read bookkeeping and a say's linked content. */
@@ -81,7 +81,7 @@ export interface PerceiveOptions extends ObservationOptions {
81
81
  readonly from?: readonly string[];
82
82
  readonly mention?: boolean;
83
83
  readonly limit?: number;
84
- readonly replace?: boolean;
84
+ readonly takeover?: boolean;
85
85
  }
86
86
  export interface ActivityCursor {
87
87
  readonly id: ActivityId;
@@ -119,8 +119,7 @@ export interface HistoryQuery extends ActivityQuery, ObservationOptions {
119
119
  readonly order?: 'asc' | 'desc';
120
120
  readonly mention?: string;
121
121
  readonly since?: number;
122
- readonly contextBefore?: number;
123
- readonly contextAfter?: number;
122
+ readonly context?: number;
124
123
  }
125
124
  export interface HistoryResult {
126
125
  readonly activities: readonly Activity[];
@@ -128,11 +127,11 @@ export interface HistoryResult {
128
127
  }
129
128
  export interface OpenOptions {
130
129
  readonly clock?: () => number;
130
+ readonly ledgerLocation?: string;
131
131
  }
132
132
  export interface SquareLocation {
133
133
  readonly path?: string;
134
134
  readonly cwd?: string;
135
- readonly env?: NodeJS.ProcessEnv;
136
135
  }
137
136
  export interface SquareAtInput extends SquareLocation, OpenOptions {
138
137
  }
@@ -255,14 +254,6 @@ export interface StreamOptions {
255
254
  readonly start?: StreamStart;
256
255
  }
257
256
  export type StreamRecord = Activity | PerceivedActivity;
258
- export interface UnreadActivitySummary {
259
- readonly name: string;
260
- readonly count: number;
261
- readonly latestActivityAgeMs: number;
262
- readonly preview: Extract<ArchiveRecord, {
263
- kind: 'say';
264
- }>;
265
- }
266
257
  export interface EntryPresentation {
267
258
  readonly joinedBefore: boolean;
268
259
  readonly scene: string;
@@ -1,7 +1,6 @@
1
1
  interface SquareLocation {
2
2
  readonly path?: string;
3
3
  readonly cwd?: string;
4
- readonly env?: NodeJS.ProcessEnv;
5
4
  }
6
5
  export declare function squareLocation(input: SquareLocation): string;
7
6
  export {};
@@ -4,10 +4,10 @@ import type { SquareArtifactPort } from './ports.js';
4
4
  /** Local producer custody and current host attachment are different observations. */
5
5
  export declare function deliverySessionsForSeats(ledger: DeliveryLedger, seats: readonly Seat[], signal?: AbortSignal): Promise<ReadonlyMap<string, DeliverySession | undefined>>;
6
6
  /** Read-only host observations for status; callers fence them against the captured World seats. */
7
- export declare function readSquareSessions(seats: readonly Seat[], env: NodeJS.ProcessEnv, signal?: AbortSignal): Promise<ReadonlyMap<string, DeliverySession | undefined>>;
7
+ export declare function readSquareSessions(seats: readonly Seat[], signal?: AbortSignal, ledgerLocation?: string): Promise<ReadonlyMap<string, DeliverySession | undefined>>;
8
8
  /** A first producer join may register an absent owner, never resume or revive one. */
9
- export declare function ensureInitialDeliverySession(owner: Seat['owner'], env: NodeJS.ProcessEnv, route?: DeliveryRoute, signal?: AbortSignal): Promise<boolean>;
9
+ export declare function ensureInitialDeliverySession(owner: Seat['owner'], route?: DeliveryRoute, signal?: AbortSignal, ledgerLocation?: string): Promise<boolean>;
10
10
  /** Called only by privileged mutations. Sandbox lease/ACK/selection never enters here. */
11
- export declare function reconcileSquareDelivery(artifact: SquareArtifactPort, location: string, env: NodeJS.ProcessEnv, clock: () => number, signal?: AbortSignal): Promise<void>;
11
+ export declare function reconcileSquareDelivery(artifact: SquareArtifactPort, location: string, clock: () => number, signal?: AbortSignal, ledgerLocation?: string): Promise<void>;
12
12
  /** One export path for Square activities and Square-owned notices. No transaction spans I/O. */
13
- export declare function flushSquarePosts(artifact: SquareArtifactPort, location: string, env: NodeJS.ProcessEnv, clock: () => number, signal?: AbortSignal): Promise<void>;
13
+ export declare function flushSquarePosts(artifact: SquareArtifactPort, location: string, clock: () => number, signal?: AbortSignal, ledgerLocation?: string): Promise<void>;
@@ -1,5 +1,5 @@
1
1
  import { randomUUID } from 'node:crypto';
2
- import { DeliveryLedger, deliveryLedgerLocation } from './delivery-ledger.js';
2
+ import { DeliveryLedger } from './delivery-ledger.js';
3
3
  import { dispatchPostedCard } from './notifications.js';
4
4
  import { retainDeliveryLedger } from './delivery-lifetime.js';
5
5
  import { projectNotification, displayAttentionPath } from './attention-presentation.js';
@@ -7,9 +7,7 @@ import { coreDone } from './decisions.js';
7
7
  import { activityMetadataHasContent } from './model.js';
8
8
  import { formatActivityId } from './square-core.js';
9
9
  import { squarePostKey } from './square-post.js';
10
- const openLedger = (env, signal) => DeliveryLedger.open({
11
- location: deliveryLedgerLocation(env), signal,
12
- });
10
+ const openLedger = (ledgerLocation, signal) => DeliveryLedger.open({ location: ledgerLocation, signal });
13
11
  function renderPost(location, post) {
14
12
  if (post.kind === 'notice')
15
13
  return { text: post.body ?? '', full: true };
@@ -24,10 +22,10 @@ export async function deliverySessionsForSeats(ledger, seats, signal) {
24
22
  return new Map(await Promise.all(owners.map(async (owner) => [owner, await ledger.session(owner, signal)])));
25
23
  }
26
24
  /** Read-only host observations for status; callers fence them against the captured World seats. */
27
- export async function readSquareSessions(seats, env, signal) {
25
+ export async function readSquareSessions(seats, signal, ledgerLocation) {
28
26
  if (!seats.length)
29
27
  return new Map();
30
- const ledger = await openLedger(env, signal);
28
+ const ledger = await openLedger(ledgerLocation, signal);
31
29
  try {
32
30
  return await deliverySessionsForSeats(ledger, seats, signal);
33
31
  }
@@ -36,8 +34,8 @@ export async function readSquareSessions(seats, env, signal) {
36
34
  }
37
35
  }
38
36
  /** A first producer join may register an absent owner, never resume or revive one. */
39
- export async function ensureInitialDeliverySession(owner, env, route, signal) {
40
- const ledger = await openLedger(env, signal);
37
+ export async function ensureInitialDeliverySession(owner, route, signal, ledgerLocation) {
38
+ const ledger = await openLedger(ledgerLocation, signal);
41
39
  try {
42
40
  const current = await ledger.session(owner, signal);
43
41
  if (!current) {
@@ -55,12 +53,12 @@ export async function ensureInitialDeliverySession(owner, env, route, signal) {
55
53
  }
56
54
  }
57
55
  /** Called only by privileged mutations. Sandbox lease/ACK/selection never enters here. */
58
- export async function reconcileSquareDelivery(artifact, location, env, clock, signal) {
56
+ export async function reconcileSquareDelivery(artifact, location, clock, signal, ledgerLocation) {
59
57
  const snapshot = (await artifact.read(facts => ({ seats: facts.roster().filter(person => person.joined)
60
58
  .flatMap(person => { const seat = facts.seat(person.name); return seat ? [seat] : []; }), posts: facts.postedPosts() }), signal)).value;
61
59
  if (!snapshot.seats.length && !snapshot.posts.length)
62
60
  return;
63
- const ledger = await openLedger(env, signal);
61
+ const ledger = await openLedger(ledgerLocation, signal);
64
62
  try {
65
63
  const sessions = await deliverySessionsForSeats(ledger, snapshot.seats, signal);
66
64
  for (const seat of snapshot.seats) {
@@ -107,7 +105,7 @@ async function suppressWithdrawn(artifact, ledger, location, signal) {
107
105
  await ledger.suppress({ owner: post.owner, key: squarePostKey(location, post), scope: 'exact' }, signal);
108
106
  }
109
107
  /** One export path for Square activities and Square-owned notices. No transaction spans I/O. */
110
- export async function flushSquarePosts(artifact, location, env, clock, signal) {
108
+ export async function flushSquarePosts(artifact, location, clock, signal, ledgerLocation) {
111
109
  signal ??= AbortSignal.timeout(5000);
112
110
  // Delivery enrichment cannot turn a committed producer mutation into a retry of that mutation.
113
111
  let lifetime;
@@ -115,14 +113,14 @@ export async function flushSquarePosts(artifact, location, env, clock, signal) {
115
113
  const snapshot = (await artifact.read(facts => ({ pending: facts.pendingPosts(), posted: facts.postedPosts() }), signal)).value;
116
114
  if (!snapshot.pending.length && !snapshot.posted.length)
117
115
  return;
118
- const ledger = await openLedger(env, signal);
116
+ const ledger = await openLedger(ledgerLocation, signal);
119
117
  lifetime = retainDeliveryLedger(ledger);
120
118
  for (const post of snapshot.pending) {
121
119
  const session = await ledger.session(post.owner, signal);
122
120
  if (session?.state !== 'attached')
123
121
  continue;
124
122
  const rendered = renderPost(location, post), token = randomUUID();
125
- const owned = (await artifact.transactAs({ kind: 'producer' }, facts => facts.acquirePost({ ...post, full: rendered.full }, token, process.pid, clock(), Date.now()), signal)).value;
123
+ const owned = (await artifact.transactAs({ kind: 'producer' }, facts => facts.acquirePost({ ...post, full: rendered.full }, token, process.pid, clock()), signal)).value;
126
124
  if (!owned)
127
125
  continue;
128
126
  let posted = false, knownUnsent = true;
@@ -130,13 +128,13 @@ export async function flushSquarePosts(artifact, location, env, clock, signal) {
130
128
  // This check is not custody across the await; the ledger independently fences delivery.
131
129
  const current = await ledger.session(post.owner, signal);
132
130
  if (current?.state !== 'attached' || current.generation !== session.generation
133
- || !(await artifact.read(facts => facts.ownsPost(token, Date.now()), signal)).value)
131
+ || !(await artifact.read(facts => facts.ownsPost(token), signal)).value)
134
132
  continue;
135
133
  knownUnsent = false;
136
134
  const result = await ledger.post({ owner: post.owner, key: squarePostKey(location, post), text: rendered.text,
137
135
  ...(post.kind === 'activity' ? { details: { kind: 'presentation', origin: displayAttentionPath(location),
138
136
  ref: formatActivityId(post.index), author: post.from, body: post.body ?? '',
139
- ...(post.route === 'bell' ? { badge: '🔔' } : {}) } } : {}),
137
+ at: post.at, reach: post.route } } : {}),
140
138
  }, signal);
141
139
  posted = ['posted', 'duplicate', 'suppressed'].includes(result.status);
142
140
  knownUnsent = !posted;
@@ -161,7 +159,7 @@ export async function flushSquarePosts(artifact, location, env, clock, signal) {
161
159
  for (const post of posts.filter(post => post.owner === owner)) {
162
160
  const key = squarePostKey(location, post);
163
161
  if (pendingKeys.has(key))
164
- await dispatchPostedCard(ledger, owner, key, lifetime.track, env, signal);
162
+ await dispatchPostedCard(ledger, post.owner, key, result => lifetime?.track(result), signal);
165
163
  }
166
164
  }
167
165
  }
@@ -6,23 +6,11 @@ export interface ToolIdentity {
6
6
  readonly wakeAddress?: WakeAddress;
7
7
  }
8
8
  type JsonObject = Record<string, unknown>;
9
- export declare class SquareExpressDrafts {
10
- private readonly drafts;
11
- private purgeExpired;
12
- resolve(args: JsonObject, owner?: Owner): {
13
- args: JsonObject;
14
- token?: string;
15
- };
16
- consume(token?: string): void;
17
- retain(args: JsonObject, owner: Owner | undefined, token: string | undefined, failure: JsonObject, expressAttempted: boolean): string | undefined;
18
- }
19
9
  interface ToolBinding {
20
10
  identity: ToolIdentity;
11
+ readonly now?: () => number;
21
12
  open(location: string | undefined, control: OperationControl): Promise<Square>;
22
- discover(options: DiscoveryOptions, control: OperationControl): Promise<{
23
- result: DiscoveryResult;
24
- now: number;
25
- }>;
13
+ discover(options: DiscoveryOptions, control: OperationControl): Promise<DiscoveryResult>;
26
14
  }
27
15
  export declare function createSquareToolRunner(): (tool: ToolDefinition, args: JsonObject, control: OperationControl, bind: () => Promise<ToolBinding> | ToolBinding) => Promise<{
28
16
  text: string;
@@ -33,7 +21,7 @@ interface SingleSquareToolDefinition {
33
21
  description: string;
34
22
  inputSchema: z.ZodObject<z.ZodRawShape>;
35
23
  /** Human text identical to what the CLI prints; domain receipts stay inside the adapter. */
36
- run(square: Square, args: JsonObject, control: OperationControl, identity: ToolIdentity): Promise<string>;
24
+ run(square: Square, args: JsonObject, control: OperationControl, identity: ToolIdentity, now?: () => number): Promise<string>;
37
25
  }
38
26
  interface DiscoveryToolDefinition {
39
27
  name: 'list';
@@ -46,10 +34,9 @@ export declare function squareToolsEnabled(env?: NodeJS.ProcessEnv): boolean;
46
34
  export declare const SQUARE_TOOL_INSTRUCTIONS = "List nearby squares and your joined names with list. Pass location for a single square. Join once. Then express to speak, and perceive to take in what reached you. History looks back without taking anything in.";
47
35
  export declare const SQUARE_TOOLS: readonly ToolDefinition[];
48
36
  export declare function squareToolFailure(error: unknown, signal?: AbortSignal): JsonObject;
49
- /** Readable failure text with the same recovery commands the CLI offers, never raw JSON. */
37
+ /** Readable failure text with tool-native recovery actions, never raw JSON. */
50
38
  export declare function squareToolFailureText(failure: JsonObject, context?: {
51
39
  location?: string;
52
40
  participant?: string;
53
- draft?: string;
54
41
  }): string;
55
42
  export {};