@astrosheep/square 0.4.0 → 0.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 (187) hide show
  1. package/dist/artifact.d.ts +1 -3
  2. package/dist/artifact.js +12 -36
  3. package/dist/attention-presentation.d.ts +2 -22
  4. package/dist/attention-presentation.js +9 -12
  5. package/dist/boundary-presentation.d.ts +3 -14
  6. package/dist/boundary-presentation.js +29 -104
  7. package/dist/card-presentation.d.ts +1 -0
  8. package/dist/card-presentation.js +2 -0
  9. package/dist/catch-decisions.js +1 -7
  10. package/dist/claude-delivery.d.ts +13 -8
  11. package/dist/claude-delivery.js +40 -93
  12. package/dist/claude-mcp-context.js +2 -2
  13. package/dist/claude-mod.js +28 -140
  14. package/dist/claude-transport.d.ts +3 -3
  15. package/dist/claude-transport.js +20 -44
  16. package/dist/cli/context.js +7 -9
  17. package/dist/cli/observation-commands.d.ts +2 -0
  18. package/dist/cli/observation-commands.js +12 -2
  19. package/dist/cli/registry.js +3 -1
  20. package/dist/codex-address.d.ts +2 -2
  21. package/dist/codex-boundary-state.d.ts +1 -5
  22. package/dist/codex-boundary-state.js +0 -4
  23. package/dist/codex-hook.d.ts +7 -10
  24. package/dist/codex-hook.js +69 -33
  25. package/dist/codex-queue.d.ts +10 -11
  26. package/dist/codex-queue.js +32 -32
  27. package/dist/codex-watch.d.ts +2 -0
  28. package/dist/codex-watch.js +100 -0
  29. package/dist/decisions.js +2 -2
  30. package/dist/delivery-deferral.d.ts +8 -17
  31. package/dist/delivery-deferral.js +0 -28
  32. package/dist/delivery-frame.d.ts +7 -0
  33. package/dist/delivery-frame.js +11 -0
  34. package/dist/delivery-ledger-sqlite.d.ts +97 -0
  35. package/dist/delivery-ledger-sqlite.js +496 -0
  36. package/dist/delivery-ledger.d.ts +196 -0
  37. package/dist/delivery-ledger.js +268 -0
  38. package/dist/delivery-lifetime.d.ts +6 -0
  39. package/dist/delivery-lifetime.js +45 -0
  40. package/dist/harness-links.js +61 -7
  41. package/dist/harness.js +12 -17
  42. package/dist/help.js +2 -0
  43. package/dist/http-delivery.d.ts +5 -9
  44. package/dist/http-delivery.js +20 -77
  45. package/dist/inbox.d.ts +6 -49
  46. package/dist/inbox.js +24 -371
  47. package/dist/index.d.ts +6 -3
  48. package/dist/index.js +4 -1
  49. package/dist/mcp.js +1 -1
  50. package/dist/model.d.ts +7 -47
  51. package/dist/model.js +1 -7
  52. package/dist/notifications.d.ts +24 -20
  53. package/dist/notifications.js +39 -108
  54. package/dist/operation-control.d.ts +4 -0
  55. package/dist/operation-control.js +20 -0
  56. package/dist/packages/agent-delivery/src/claude-native.d.ts +2 -0
  57. package/dist/packages/agent-delivery/src/claude-native.js +5 -0
  58. package/dist/packages/agent-delivery/src/codex-boundary.d.ts +11 -6
  59. package/dist/packages/agent-delivery/src/codex-boundary.js +31 -40
  60. package/dist/packages/agent-delivery/src/codex-hook.d.ts +17 -12
  61. package/dist/packages/agent-delivery/src/codex-hook.js +26 -39
  62. package/dist/packages/agent-delivery/src/codex.d.ts +3 -0
  63. package/dist/packages/agent-delivery/src/codex.js +41 -4
  64. package/dist/packages/agent-delivery/src/index.d.ts +3 -1
  65. package/dist/packages/agent-delivery/src/index.js +1 -1
  66. package/dist/packages/agent-delivery/src/paseo.js +11 -2
  67. package/dist/packages/agent-delivery/src/types.d.ts +1 -0
  68. package/dist/paseo-delivery.d.ts +5 -5
  69. package/dist/paseo-delivery.js +19 -97
  70. package/dist/paseo.d.ts +1 -1
  71. package/dist/paseo.js +1 -1
  72. package/dist/plugins/opencode/index.d.ts +5 -3
  73. package/dist/plugins/opencode/index.js +99 -21
  74. package/dist/plugins/opencode-shared/delivery.d.ts +23 -0
  75. package/dist/plugins/opencode-shared/delivery.js +109 -0
  76. package/dist/plugins/opencode-v1/index.d.ts +28 -0
  77. package/dist/plugins/opencode-v1/index.js +41 -0
  78. package/dist/plugins/opencode-v1/runtime.d.ts +56 -0
  79. package/dist/plugins/opencode-v1/runtime.js +152 -0
  80. package/dist/plugins/opencode-v1/transport.d.ts +13 -0
  81. package/dist/plugins/opencode-v1/transport.js +50 -0
  82. package/dist/plugins/paseo/shared/card-presentation.d.ts +10 -0
  83. package/dist/plugins/paseo/shared/card-presentation.js +7 -0
  84. package/dist/ports.d.ts +31 -90
  85. package/dist/session-lifecycle.d.ts +8 -7
  86. package/dist/session-lifecycle.js +40 -42
  87. package/dist/sqlite-square.d.ts +14 -23
  88. package/dist/sqlite-square.js +132 -139
  89. package/dist/square-api.js +4 -7
  90. package/dist/square-core.d.ts +0 -1
  91. package/dist/square-domain.d.ts +5 -17
  92. package/dist/square-domain.js +104 -221
  93. package/dist/square-facade.d.ts +18 -15
  94. package/dist/square-post.d.ts +53 -0
  95. package/dist/square-post.js +4 -0
  96. package/dist/square-posting.d.ts +13 -0
  97. package/dist/square-posting.js +174 -0
  98. package/dist/square-producer-sqlite.d.ts +11 -0
  99. package/dist/square-producer-sqlite.js +210 -0
  100. package/dist/square-sqlite.d.ts +15 -25
  101. package/dist/square-sqlite.js +150 -226
  102. package/dist/views.d.ts +2 -2
  103. package/dist/views.js +0 -1
  104. package/dist/wake-sink.d.ts +4 -11
  105. package/dist/wake-sink.js +8 -32
  106. package/dist/wake-transports.d.ts +4 -7
  107. package/dist/wake-transports.js +8 -39
  108. package/examples/symmetric-domains.mjs +29 -249
  109. package/guides/change-waits.md +13 -53
  110. package/guides/claude-native.md +19 -175
  111. package/guides/codex-delivery.md +55 -80
  112. package/guides/delivery-primitives.md +48 -207
  113. package/guides/operation-cancellation.md +2 -5
  114. package/guides/participant-ownership.md +25 -89
  115. package/guides/pi-native-delivery.md +19 -56
  116. package/guides/pi-tools.md +6 -8
  117. package/guides/square-api.md +113 -615
  118. package/package.json +8 -8
  119. package/plugins/claude/.claude-plugin/plugin.json +1 -1
  120. package/plugins/claude/hooks/hooks.json +1 -1
  121. package/plugins/claude/{hooks/register.js → mods/square.js} +4 -7
  122. package/plugins/codex/.codex-plugin/plugin.json +1 -1
  123. package/plugins/codex/hooks/hooks.json +11 -23
  124. package/plugins/opencode/index.ts +91 -23
  125. package/plugins/opencode-shared/delivery.ts +91 -0
  126. package/plugins/opencode-v1/index.ts +36 -0
  127. package/plugins/opencode-v1/runtime.ts +134 -0
  128. package/plugins/opencode-v1/transport.ts +41 -0
  129. package/plugins/paseo/OVERVIEW.md +5 -5
  130. package/plugins/paseo/README.md +7 -6
  131. package/plugins/paseo/client/markdown.tsx +5 -5
  132. package/plugins/paseo/client/square-message.tsx +28 -24
  133. package/plugins/paseo/client/transform.ts +8 -5
  134. package/plugins/paseo/shared/card-presentation.ts +16 -0
  135. package/plugins/paseo/shared/message.ts +6 -11
  136. package/plugins/pi/square-pi.js +156 -417
  137. package/dist/channel-artifact.d.ts +0 -10
  138. package/dist/channel-artifact.js +0 -55
  139. package/dist/channel-delivery.d.ts +0 -11
  140. package/dist/channel-delivery.js +0 -51
  141. package/dist/channel-domain.d.ts +0 -3
  142. package/dist/channel-domain.js +0 -83
  143. package/dist/channel-facade.d.ts +0 -76
  144. package/dist/channel-facade.js +0 -1
  145. package/dist/channel-internal.d.ts +0 -126
  146. package/dist/channel-internal.js +0 -440
  147. package/dist/channel-metadata.d.ts +0 -11
  148. package/dist/channel-metadata.js +0 -1
  149. package/dist/channel-ports.d.ts +0 -241
  150. package/dist/channel-ports.js +0 -1
  151. package/dist/channel-presentation.d.ts +0 -17
  152. package/dist/channel-presentation.js +0 -22
  153. package/dist/channel-sqlite-schema.d.ts +0 -13
  154. package/dist/channel-sqlite-schema.js +0 -81
  155. package/dist/channel-transport.d.ts +0 -62
  156. package/dist/channel-transport.js +0 -1
  157. package/dist/channel.d.ts +0 -84
  158. package/dist/channel.js +0 -60
  159. package/dist/claude-delivery-status.d.ts +0 -13
  160. package/dist/claude-delivery-status.js +0 -46
  161. package/dist/cmd/notify-once.d.ts +0 -2
  162. package/dist/cmd/notify-once.js +0 -29
  163. package/dist/delivery-attempts.d.ts +0 -52
  164. package/dist/delivery-attempts.js +0 -73
  165. package/dist/delivery-effects.d.ts +0 -139
  166. package/dist/delivery-effects.js +0 -163
  167. package/dist/delivery-health.d.ts +0 -51
  168. package/dist/delivery-health.js +0 -173
  169. package/dist/delivery-operations.d.ts +0 -22
  170. package/dist/delivery-operations.js +0 -198
  171. package/dist/delivery-primitives.d.ts +0 -5
  172. package/dist/delivery-primitives.js +0 -3
  173. package/dist/delivery.d.ts +0 -56
  174. package/dist/delivery.js +0 -80
  175. package/dist/plugins/opencode/delivery.d.ts +0 -19
  176. package/dist/plugins/opencode/delivery.js +0 -223
  177. package/dist/presentation-operations.d.ts +0 -5
  178. package/dist/presentation-operations.js +0 -86
  179. package/dist/sqlite-channel.d.ts +0 -15
  180. package/dist/sqlite-channel.js +0 -600
  181. package/dist/square-index.d.ts +0 -16
  182. package/dist/square-index.js +0 -106
  183. package/dist/wake-preview.d.ts +0 -7
  184. package/dist/wake-preview.js +0 -15
  185. package/plugins/opencode/delivery.ts +0 -198
  186. /package/dist/{channel-values.d.ts → square-values.d.ts} +0 -0
  187. /package/dist/{channel-values.js → square-values.js} +0 -0
@@ -1,223 +0,0 @@
1
- import { createHash } from 'node:crypto';
2
- import { squareWakeProjection } from '../../wake-preview.js';
3
- import { channelArtifact, createArtifactPort } from '../../artifact.js';
4
- import { deliverPending } from '../../delivery-operations.js';
5
- import { nativePendingSource, observeSessionPending, projectSessionSeats } from '../../inbox.js';
6
- import { automaticWakeEligible, nativePendingHead, presentationBlocksWake } from '../../delivery.js';
7
- import { harnessOwner, decodeHarnessOwner } from '../../owner.js';
8
- import { formatMessageId, parseMessageId } from '../../message.js';
9
- import { indexedSquareEntries } from '../../square-index.js';
10
- import { asSeatRef } from '../../seats.js';
11
- import { restoreSessionSeats } from '../../session-lifecycle.js';
12
- import { presentPending } from '../../presentation-operations.js';
13
- import { createNativeInputId, sendNativeText } from '../../packages/agent-delivery/src/opencode-native.js';
14
- const routeKind = 'opencode-server';
15
- const ownerFor = (sessionId) => harnessOwner({ channel: 'opencode', session: sessionId });
16
- const payloadHash = (payload) => createHash('sha256').update(payload).digest('hex');
17
- export async function indexedOpenCodeSessions(env) {
18
- return [...new Set((await indexedSquareEntries({}, env)).flatMap((entry) => {
19
- const coordinate = decodeHarnessOwner(entry.owner);
20
- return coordinate?.channel === 'opencode' ? [coordinate.session] : [];
21
- }))];
22
- }
23
- export async function discoverOpenCodeSeats(sessionId, env, signal) {
24
- return projectSessionSeats({ owner: ownerFor(sessionId), env }, signal);
25
- }
26
- function sameSeat(left, right) {
27
- return left !== undefined && left.attachment === 'attached' && left.generation === right.generation && left.owner === right.owner;
28
- }
29
- function createOpenCodeWakeTransport(target, lifetime) {
30
- return {
31
- probe: async (route) => !lifetime.aborted && route.kind === routeKind
32
- && route.address.sessionId === target.sessionId,
33
- async attempt(request, timeoutMs, beforeSend) {
34
- const presentation = request.presentation;
35
- if (request.claimToken === undefined || parseMessageId(request.message) === undefined || presentation === undefined
36
- || request.route.kind !== routeKind || request.route.address.sessionId !== target.sessionId) {
37
- return { outcome: 'not-capable', diagnostic: 'OpenCode attention has no matching artifact claim or session.' };
38
- }
39
- const signal = AbortSignal.any([lifetime, AbortSignal.timeout(timeoutMs)]);
40
- const started = Date.now();
41
- if (signal.aborted || !await beforeSend())
42
- return { outcome: 'not-capable', diagnostic: 'OpenCode attention changed before send.' };
43
- const inputId = createNativeInputId();
44
- const correlation = { harness: 'opencode', token: inputId, payloadHash: payloadHash(presentation.payload) };
45
- if (!await request.channel.prepare({ correlation,
46
- coverage: presentation.coverage, ...(presentation.description === undefined ? {} : { description: presentation.description }) }, signal))
47
- return { outcome: 'not-capable', diagnostic: 'OpenCode delivery claim is no longer current.' };
48
- if (signal.aborted || !await beforeSend())
49
- return { outcome: 'not-capable', diagnostic: 'OpenCode attention was consumed before send.' };
50
- const result = await sendNativeText(target, presentation.payload, {
51
- inputId, delivery: 'steer', timeoutMs: Math.max(1, timeoutMs - (Date.now() - started)), signal,
52
- });
53
- if (result.state === 'accepted')
54
- return { outcome: 'accepted' };
55
- if (result.state === 'unavailable')
56
- return { outcome: 'failed', signature: result.code };
57
- return { outcome: 'unknown', signature: result.code };
58
- },
59
- };
60
- }
61
- function textMessage(message) {
62
- if (message.role !== 'user' || message.id === undefined || !message.content.every((part) => part.type === 'text' && typeof part.text === 'string'))
63
- return undefined;
64
- return message.content.map((part) => part.text).join('');
65
- }
66
- /** The exact prepared native message can authorize artifact-backed presentation once. */
67
- export async function observeOpenCodeContext(sessionId, messages, env, signal) {
68
- const observed = new Map(messages.flatMap((message) => {
69
- const text = textMessage(message);
70
- return text === undefined ? [] : [[message.id, payloadHash(text)]];
71
- }));
72
- if (observed.size === 0 || signal.aborted)
73
- return;
74
- for (const { location, seat } of await discoverOpenCodeSeats(sessionId, env, signal)) {
75
- if (signal.aborted)
76
- return;
77
- const artifact = createArtifactPort(location, undefined, signal);
78
- try {
79
- const { value: matches } = await artifact.read((facts) => {
80
- if (!sameSeat(facts.seat(seat.participant), seat))
81
- return [];
82
- return facts.deliveryEvidence(seat.participant, seat.generation).flatMap((evidence) => {
83
- const token = evidence.correlation?.harness === 'opencode' ? evidence.correlation.token : undefined;
84
- const hash = token === undefined ? undefined : observed.get(token);
85
- const index = parseMessageId(evidence.message), now = Date.now();
86
- if (token === undefined || hash === undefined || evidence.claimToken === undefined || index === undefined
87
- || evidence.route === undefined || !['dispatching', 'unknown', 'accepted'].includes(evidence.outcome)
88
- || evidence.correlation?.payloadHash !== hash
89
- || evidence.route.kind !== routeKind
90
- || presentationBlocksWake(facts.deliveryEvidence(seat.participant, seat.generation, evidence.message), now))
91
- return [];
92
- const source = nativePendingSource(facts, { location, participant: seat.participant, generation: seat.generation,
93
- owner: seat.owner, index, route: evidence.route, now });
94
- if (source === undefined)
95
- return [];
96
- return [{ evidence, index, hash, clipped: evidence.coverage === 'clipped' }];
97
- });
98
- }, signal);
99
- for (const { evidence, index, hash, clipped } of matches) {
100
- if (signal.aborted || evidence.claimToken === undefined)
101
- return;
102
- await presentPending({ artifact, location, participant: seat.participant,
103
- message: formatMessageId(index), seat: asSeatRef(seat), observationOf: evidence.claimToken, sink: { present() { } }, markSeen: !clipped, signal,
104
- current: (facts) => {
105
- const correlation = facts.deliveryByToken(evidence.claimToken);
106
- return nativePendingHead(facts, { location, participant: seat.participant, generation: seat.generation,
107
- owner: seat.owner, index, route: evidence.route, now: Date.now() }) !== undefined
108
- && ['dispatching', 'unknown', 'accepted'].includes(correlation?.outcome ?? '')
109
- && correlation?.correlation?.harness === 'opencode'
110
- && correlation.correlation.token !== undefined
111
- && correlation.correlation.payloadHash === hash;
112
- },
113
- });
114
- }
115
- }
116
- finally {
117
- await artifact.close();
118
- }
119
- }
120
- }
121
- /** The native receiver owns no claims outside the artifact; HOME is used only for discovery. */
122
- export async function receiveOpenCodePending(target, env, signal) {
123
- const observer = await observeSessionPending(ownerFor(target.sessionId), env);
124
- const transport = createOpenCodeWakeTransport(target, signal);
125
- let waiting;
126
- try {
127
- while (!signal.aborted) {
128
- const armed = new Promise((resolve) => {
129
- waiting = observer.wait(Infinity, { signal, skipImmediate: true, onChangeArmed: resolve });
130
- void waiting.catch(() => resolve(false));
131
- });
132
- if (!await armed) {
133
- await waiting;
134
- break;
135
- }
136
- for (const membership of await observer.read({ signal })) {
137
- const { location, seat } = membership;
138
- if (signal.aborted)
139
- return;
140
- const artifact = createArtifactPort(location, undefined, signal);
141
- try {
142
- const { value: notifications } = await artifact.read((facts) => {
143
- if (!sameSeat(facts.seat(seat.participant), seat))
144
- return [];
145
- return membership.notifications.filter((note) => automaticWakeEligible(facts.deliveryEvidence(seat.participant, seat.generation, formatMessageId(note.messageIndex)), Date.now()));
146
- }, signal);
147
- for (const note of notifications) {
148
- if (signal.aborted)
149
- return;
150
- await deliverPending({ artifact: channelArtifact(artifact), preparePresentation: squareWakeProjection(artifact), transport, location, message: formatMessageId(note.messageIndex), now: Date.now() });
151
- }
152
- }
153
- catch (error) {
154
- if (signal.aborted)
155
- throw signal.reason ?? error;
156
- // A candidate that became unreadable cannot authorize sending; the shared observer
157
- // keeps its subscription and will reconsider the artifact after repair.
158
- }
159
- finally {
160
- await artifact.close();
161
- }
162
- }
163
- await waiting;
164
- waiting = undefined;
165
- }
166
- }
167
- catch (error) {
168
- if (!signal.aborted)
169
- throw error;
170
- }
171
- finally {
172
- observer.close();
173
- await waiting?.catch(() => { });
174
- }
175
- }
176
- /** Publish the native address into current artifact seats; the legacy route projection is not read. */
177
- export async function publishOpenCodeAddress(sessionId, env, signal) {
178
- await restoreSessionSeats(ownerFor(sessionId), env, { kind: routeKind, address: { sessionId } }, signal);
179
- const seats = (await discoverOpenCodeSeats(sessionId, env, signal)).filter(({ seat }) => seat.attachment === 'attached');
180
- for (const { location, seat } of seats) {
181
- if (signal.aborted)
182
- return false;
183
- const artifact = createArtifactPort(location, undefined, signal);
184
- try {
185
- await artifact.transactAs({ kind: 'participant', seat: asSeatRef(seat) }, (facts) => facts.updateWakeAddress(asSeatRef(seat), { kind: routeKind, address: { sessionId } }));
186
- }
187
- finally {
188
- await artifact.close();
189
- }
190
- }
191
- return seats.length > 0;
192
- }
193
- export async function cancelOpenCodeDeliveries(sessionId, env, signal) {
194
- for (const { location, seat } of await discoverOpenCodeSeats(sessionId, env, signal)) {
195
- if (signal.aborted)
196
- return;
197
- if (seat.attachment !== 'attached')
198
- continue;
199
- const artifact = createArtifactPort(location, undefined, signal);
200
- try {
201
- const { value: through } = await artifact.read((facts) => facts.channel.header().lastMessageIndex, signal);
202
- if (through >= 0)
203
- await artifact.cancelDeliveries(asSeatRef(seat), through, signal);
204
- }
205
- finally {
206
- await artifact.close();
207
- }
208
- }
209
- }
210
- export async function endOpenCodeSession(sessionId, env, signal) {
211
- for (const { location, seat } of await discoverOpenCodeSeats(sessionId, env, signal)) {
212
- if (signal.aborted)
213
- return;
214
- const { Square } = await import('../../square-api.js');
215
- const square = await Square.at({ path: location, env });
216
- try {
217
- await square.endHeld(seat.participant, { owner: seat.owner, generation: seat.generation });
218
- }
219
- finally {
220
- await square.close();
221
- }
222
- }
223
- }
@@ -1,5 +0,0 @@
1
- import type { PresentationResult, PresentPendingInput } from './ports.js';
2
- /** Prepare custody before any external effect. A batch prepares every included item first. */
3
- export declare function preparePendingPresentation(input: Omit<PresentPendingInput, 'sink'>): Promise<import("./delivery-effects.js").PreparedPresentation<import("./channel-ports.js").MessageFact> | undefined>;
4
- /** A sink error cannot prove that content was never injected. */
5
- export declare function presentPending(input: PresentPendingInput): Promise<PresentationResult>;
@@ -1,86 +0,0 @@
1
- import { randomUUID } from 'node:crypto';
2
- import { formatMessageId, parseMessageId } from './message.js';
3
- import { isSquareError } from './model.js';
4
- import { pendingHead, sameJoin } from './delivery.js';
5
- import { deliveryDeferralExpiry } from './delivery-deferral.js';
6
- import { asSeatRef } from './seats.js';
7
- import { preparePresentation, presentPrepared } from './delivery-effects.js';
8
- /** Prepare custody before any external effect. A batch prepares every included item first. */
9
- export async function preparePendingPresentation(input) {
10
- const named = input.message;
11
- const index = typeof named === 'number' ? named : parseMessageId(named);
12
- if (index === undefined)
13
- return undefined;
14
- const initial = await input.artifact.read((facts) => {
15
- const seat = facts.channel.endpoint(input.participant);
16
- if (seat === undefined || seat.attachment !== 'attached' || input.generation !== undefined && input.generation !== seat.generation
17
- || input.seat !== undefined && (input.seat.generation !== seat.generation || input.seat.owner !== seat.owner)
18
- || input.current?.(facts) === false || !pendingHead(facts, input.participant, index)
19
- || deliveryDeferralExpiry(facts.channel, seat, index, input.now ?? Date.now()) !== undefined)
20
- return undefined;
21
- const item = facts.channel.message(index);
22
- return item === undefined ? undefined : { participant: { name: input.participant, generation: seat.generation }, seat, item };
23
- }, input.signal).catch(() => undefined);
24
- if (initial?.value === undefined)
25
- return undefined;
26
- const { participant, seat, item } = initial.value;
27
- const ref = asSeatRef(seat);
28
- const owns = (facts) => {
29
- const current = facts.seat(seat.participant);
30
- return current !== undefined && current.attachment === 'attached' && current.owner === seat.owner && current.generation === seat.generation
31
- && sameJoin(facts, participant);
32
- };
33
- const claimToken = randomUUID();
34
- return preparePresentation({
35
- payload: item, coverage: input.markSeen === false ? 'clipped' : 'full',
36
- port: {
37
- async claim(signal) {
38
- const claimed = await input.artifact.claimDelivery({ seat: ref, message: formatMessageId(index), kind: 'presentation',
39
- observationOf: input.observationOf, at: input.now ?? Date.now(), leaseMs: input.timeoutMs ?? 5000, claimToken }, signal).catch(() => ({ status: 'stale' }));
40
- return claimed.status === 'acquired' ? { token: claimToken, ordinal: claimed.attemptN } : undefined;
41
- },
42
- async current(signal) {
43
- return (await input.artifact.read(facts => owns(facts) && input.current?.(facts) !== false
44
- && pendingHead(facts, participant.name, index) !== undefined
45
- && deliveryDeferralExpiry(facts.channel, seat, index, input.now ?? Date.now()) === undefined, signal ?? input.signal)).value;
46
- },
47
- async settle(claim, completion) {
48
- const success = completion.outcome === 'presented' || completion.outcome === 'clipped';
49
- const { value } = await input.artifact.settleAs({ kind: 'participant', seat: ref }, facts => {
50
- // Captured ownership fences truth; post-effect policy/cancellation cannot veto it.
51
- if (!owns(facts))
52
- return false;
53
- if (!facts.channel.completeDelivery({ seat: ref, message: formatMessageId(index), claimToken: claim.token,
54
- outcome: completion.outcome, at: success ? input.now ?? Date.now() : Date.now(),
55
- ...(completion.reason === 'threw' ? { messageText: completion.error instanceof Error ? completion.error.message : String(completion.error) } : {}),
56
- }))
57
- return false;
58
- if (completion.outcome === 'presented')
59
- facts.channel.markSeen(participant.name, [index], input.now ?? Date.now());
60
- return true;
61
- }).catch(error => {
62
- if (!success || isSquareError(error) && error.code === 'already_joined')
63
- return { value: false };
64
- throw error;
65
- });
66
- return value;
67
- },
68
- },
69
- }, { signal: input.signal });
70
- }
71
- /** A sink error cannot prove that content was never injected. */
72
- export async function presentPending(input) {
73
- const prepared = await preparePendingPresentation(input);
74
- if (prepared === undefined)
75
- return { presented: false };
76
- const report = await presentPrepared(prepared, message => input.sink.present(message), {
77
- signal: input.signal,
78
- });
79
- if (report.observation.kind === 'threw')
80
- throw report.observation.error;
81
- const result = report.settlements[0].result;
82
- if (result.persistence.status === 'error')
83
- throw result.persistence.error;
84
- return report.observation.kind === 'returned' && result.persistence.status === 'recorded'
85
- ? { presented: true, message: prepared.payload } : { presented: false };
86
- }
@@ -1,15 +0,0 @@
1
- import type { DatabaseSync } from 'node:sqlite';
2
- import type { ChannelWrite, MessageAddressFact, EndpointFact, ReceiveClaimFact, ChannelDeliveryEvidence } from './channel-ports.js';
3
- import { type DeliveryDeferralFact } from './delivery-deferral.js';
4
- import { type EndpointGeneration } from './message.js';
5
- import { type Row } from './sqlite-values.js';
6
- export declare function messageAddress(row: Row): MessageAddressFact;
7
- export declare function endpointGeneration(value: unknown): EndpointGeneration;
8
- export declare function endpoint(row: Row): EndpointFact;
9
- export declare function deliveryEvidence(row: Row, payload?: Record<string, unknown>): ChannelDeliveryEvidence;
10
- export declare function deliveryDeferral(row: Row): DeliveryDeferralFact;
11
- export declare function receiveClaim(row: Row): ReceiveClaimFact;
12
- export declare function createChannelSqlite(db: DatabaseSync): ChannelWrite & {
13
- readonly changed: boolean;
14
- readonly deliveryChanged: boolean;
15
- };