@astrosheep/square 0.3.93 → 0.3.95
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/activity-feed.d.ts +3 -5
- package/dist/activity-feed.js +16 -14
- package/dist/artifact.js +3 -3
- package/dist/attention.d.ts +19 -0
- package/dist/attention.js +30 -0
- package/dist/boundary-presentation.d.ts +2 -2
- package/dist/boundary-presentation.js +33 -40
- package/dist/catch-decisions.d.ts +5 -8
- package/dist/catch-decisions.js +45 -25
- package/dist/claude-delivery-status.js +10 -4
- package/dist/claude-delivery.js +19 -11
- package/dist/claude-mod.js +24 -53
- package/dist/cli/context.d.ts +9 -4
- package/dist/cli/context.js +30 -27
- package/dist/cli/express-presentation.d.ts +3 -1
- package/dist/cli/express-presentation.js +28 -16
- package/dist/cli/json.d.ts +3 -0
- package/dist/cli/json.js +14 -0
- package/dist/cli/mcp-server-command.js +2 -2
- package/dist/cli/observation-commands.d.ts +1 -3
- package/dist/cli/observation-commands.js +43 -56
- package/dist/cli/program.js +3 -3
- package/dist/cli/registry.js +7 -6
- package/dist/cli/square-commands.d.ts +0 -2
- package/dist/cli/square-commands.js +30 -44
- package/dist/codex-hook.d.ts +3 -2
- package/dist/codex-hook.js +13 -4
- package/dist/codex-queue.js +4 -4
- package/dist/decisions.d.ts +5 -16
- package/dist/decisions.js +9 -33
- package/dist/delivery-attempts.d.ts +52 -0
- package/dist/delivery-attempts.js +73 -0
- package/dist/delivery-deferral.js +2 -2
- package/dist/delivery-effects.d.ts +139 -0
- package/dist/delivery-effects.js +163 -0
- package/dist/delivery-health.d.ts +0 -1
- package/dist/delivery-health.js +1 -3
- package/dist/delivery-operations.d.ts +2 -2
- package/dist/delivery-operations.js +76 -101
- package/dist/delivery-primitives.d.ts +5 -0
- package/dist/delivery-primitives.js +3 -0
- package/dist/delivery.d.ts +1 -1
- package/dist/delivery.js +7 -6
- package/dist/help.js +14 -14
- package/dist/http-delivery.d.ts +16 -0
- package/dist/http-delivery.js +101 -0
- package/dist/inbox.d.ts +9 -22
- package/dist/inbox.js +23 -27
- package/dist/index.d.ts +1 -3
- package/dist/index.js +1 -1
- package/dist/mcp.d.ts +3 -0
- package/dist/mcp.js +23 -24
- package/dist/model.d.ts +12 -21
- package/dist/model.js +5 -8
- package/dist/notifications.d.ts +1 -1
- package/dist/notifications.js +8 -5
- package/dist/operation-presentation.d.ts +6 -6
- package/dist/operation-presentation.js +55 -58
- package/dist/owner.d.ts +11 -0
- package/dist/owner.js +32 -0
- package/dist/paseo-delivery.d.ts +4 -1
- package/dist/paseo-delivery.js +7 -12
- package/dist/paseo-state.d.ts +2 -2
- package/dist/paseo-state.js +6 -4
- package/dist/plugins/opencode/delivery.js +27 -15
- package/dist/ports.d.ts +18 -47
- package/dist/presentation-operations.d.ts +14 -19
- package/dist/presentation-operations.js +51 -61
- package/dist/presentation.d.ts +7 -17
- package/dist/presentation.js +46 -91
- package/dist/receive.d.ts +66 -0
- package/dist/receive.js +54 -0
- package/dist/runtime.d.ts +1 -8
- package/dist/runtime.js +2 -17
- package/dist/seats.d.ts +2 -3
- package/dist/seats.js +7 -15
- package/dist/session-lifecycle.d.ts +6 -2
- package/dist/session-lifecycle.js +39 -11
- package/dist/sqlite-square.d.ts +36 -23
- package/dist/sqlite-square.js +162 -211
- package/dist/square-api.d.ts +16 -11
- package/dist/square-api.js +27 -23
- package/dist/square-core.d.ts +0 -14
- package/dist/square-core.js +0 -9
- package/dist/square-domain.d.ts +4 -2
- package/dist/square-domain.js +65 -52
- package/dist/square-facade.d.ts +47 -105
- package/dist/square-index.d.ts +5 -13
- package/dist/square-index.js +13 -38
- package/dist/square-legacy-framing.d.ts +2 -0
- package/dist/square-legacy-framing.js +8 -0
- package/dist/square-location.d.ts +1 -14
- package/dist/square-location.js +4 -70
- package/dist/square-migration-host-ledger.d.ts +2 -2
- package/dist/square-migration-host-ledger.js +6 -5
- package/dist/square-migration.d.ts +4 -1
- package/dist/square-migration.js +93 -38
- package/dist/square-receive.d.ts +6 -0
- package/dist/square-receive.js +18 -0
- package/dist/square-sqlite.d.ts +9 -3
- package/dist/square-sqlite.js +139 -114
- package/dist/square-tools.d.ts +7 -10
- package/dist/square-tools.js +21 -61
- package/dist/stream.js +4 -5
- package/dist/views.d.ts +23 -13
- package/dist/views.js +47 -53
- package/dist/wakes.d.ts +1 -5
- package/dist/wakes.js +4 -6
- package/examples/symmetric-domains.mjs +250 -0
- package/guides/application-facade-delivery-evidence.md +6 -6
- package/guides/attention-primitive.md +32 -0
- package/guides/change-waits.md +2 -2
- package/guides/claude-native.md +18 -9
- package/guides/codex-delivery.md +17 -6
- package/guides/delivery-primitives.md +180 -0
- package/guides/mcp-connection-lifetime.md +1 -1
- package/guides/mcp.md +3 -3
- package/guides/migration.md +148 -151
- package/guides/operation-cancellation.md +1 -1
- package/guides/participant-ownership.md +78 -47
- package/guides/pi-tools.md +34 -5
- package/guides/primitive-catch-consolidation.md +5 -5
- package/guides/primitive-history-consolidation.md +2 -2
- package/guides/primitive-status-consolidation.md +3 -3
- package/guides/primitive-storage-consolidation.md +1 -1
- package/guides/receive-primitive.md +90 -0
- package/guides/row-runtime-delivery-evidence.md +1 -1
- package/guides/row-storage-design.md +22 -28
- package/guides/square-api.md +314 -91
- package/guides/symmetric-domains.md +92 -0
- package/package.json +14 -1
- package/plugins/claude/.claude-plugin/plugin.json +1 -1
- package/plugins/claude/skills/square/SKILL.md +2 -6
- package/plugins/codex/.codex-plugin/plugin.json +1 -1
- package/plugins/opencode/delivery.ts +27 -17
- package/plugins/paseo/client/palette.ts +18 -18
- package/plugins/paseo/client/square-message.tsx +17 -23
- package/plugins/pi/square-pi.js +17 -17
- package/skills/square/SKILL.md +2 -6
- package/dist/square-backend.d.ts +0 -13
- package/dist/square-backend.js +0 -1
- package/dist/square-stdio.d.ts +0 -22
- package/dist/square-stdio.js +0 -235
- package/dist/stdio-server.d.ts +0 -3
- package/dist/stdio-server.js +0 -212
- package/guides/backends.md +0 -193
package/dist/sqlite-square.js
CHANGED
|
@@ -1,21 +1,23 @@
|
|
|
1
1
|
import { formatActivityId } from './square-core.js';
|
|
2
|
+
import { assertCurrentSeat } from './square-domain.js';
|
|
3
|
+
import { canonicalPath } from './canonical-path.js';
|
|
2
4
|
import { validateMetadataMatch, validateDeferralDuration, validateDeferralId } from './delivery-deferral.js';
|
|
3
|
-
import { squareLocation
|
|
5
|
+
import { squareLocation } from './square-location.js';
|
|
4
6
|
import crypto from 'node:crypto';
|
|
5
7
|
import { setTimeout as sleep } from 'node:timers/promises';
|
|
6
|
-
import { InternalSquareError, SquareError, isSquareError, nameKey,
|
|
7
|
-
import { coreDone,
|
|
8
|
-
import {
|
|
8
|
+
import { InternalSquareError, SquareError, isSquareError, nameKey, validateName } from './model.js';
|
|
9
|
+
import { coreDone, coreIgnore, coreListen, coreListening, coreUnlisten, decideAct, decideJoin, resolveKnownName, validateDoneBody } from './decisions.js';
|
|
10
|
+
import { WATCH_HEARTBEAT_MS, inSquareCount, presenceAnchor } from './runtime.js';
|
|
9
11
|
import { catchLimit, decideCatch, observeCatchSelection, selectCatchPage } from './catch-decisions.js';
|
|
10
|
-
import {
|
|
12
|
+
import { expressionContext } from './activity-feed.js';
|
|
11
13
|
import { expressHint } from './hints.js';
|
|
12
|
-
import { asSeatRef, participantAuthority,
|
|
14
|
+
import { asSeatRef, participantAuthority, requireOwner, requireJoinName } from './seats.js';
|
|
13
15
|
import { recoveryObservation, entryPresentation, snapshot, queryStatus, queryParticipants, catchPresence, parseRequiredActivityId, toPublicActivity, publicActivities, selectHistory, NON_READ, HISTORY_DEFAULT_LIMIT, HISTORY_MAX_LIMIT } from './views.js';
|
|
14
16
|
import { sessionInboxCounts } from './inbox.js';
|
|
15
17
|
import { rememberSquarePath, squareIndexPath } from './square-index.js';
|
|
16
|
-
import { createDefaultWakeTransport } from './notifications.js';
|
|
17
18
|
import { deliverPending } from './delivery-operations.js';
|
|
18
19
|
import { participantIdentity } from './participant-identity.js';
|
|
20
|
+
import { joinRecoveryCommand } from './presentation.js';
|
|
19
21
|
import { acquireWatchLease, ownsWatchLease, pulseWatchLease, releaseWatchLease } from './wakes.js';
|
|
20
22
|
import { createArtifactPort, createSquare, diagnoseSquareFile, prepareSquareBuild } from './artifact.js';
|
|
21
23
|
import { migrateSquareFile } from './square-migration.js';
|
|
@@ -24,7 +26,6 @@ import { streamSquare } from './stream.js';
|
|
|
24
26
|
export { createSquareResourceOwner } from './artifact.js';
|
|
25
27
|
export { formatActivityId, parseActivityId, MAX_IDENTITY_SET_SIZE } from './square-core.js';
|
|
26
28
|
export { CATCH_DEFAULT_LIMIT, CATCH_MAX_LIMIT } from './catch-decisions.js';
|
|
27
|
-
export { HELD_WAIT_BUDGET_MS } from './runtime.js';
|
|
28
29
|
export { HISTORY_DEFAULT_LIMIT, HISTORY_MAX_LIMIT } from './views.js';
|
|
29
30
|
export { DEFAULT_LIST_DEPTH, MAX_LIST_DEPTH, DEFAULT_LIST_LIMIT, MAX_LIST_LIMIT } from './list.js';
|
|
30
31
|
function checkControl(control) {
|
|
@@ -65,38 +66,28 @@ export class SqliteSquare {
|
|
|
65
66
|
location;
|
|
66
67
|
artifact;
|
|
67
68
|
clock;
|
|
68
|
-
body;
|
|
69
|
-
wakeAddress;
|
|
70
69
|
wakeTransport;
|
|
71
70
|
indexPath;
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
constructor(location, artifact, clock, body, wakeAddress, wakeTransport, indexPath, automaticDelivery = true, ownsArtifact = true, defaultParticipant) {
|
|
71
|
+
closesArtifact;
|
|
72
|
+
deliveryLocation;
|
|
73
|
+
constructor(location, artifact, clock, wakeTransport, indexPath, closesArtifact = true, deliveryLocation = location) {
|
|
76
74
|
this.location = location;
|
|
77
75
|
this.artifact = artifact;
|
|
78
76
|
this.clock = clock;
|
|
79
|
-
this.body = body;
|
|
80
|
-
this.wakeAddress = wakeAddress;
|
|
81
77
|
this.wakeTransport = wakeTransport;
|
|
82
78
|
this.indexPath = indexPath;
|
|
83
|
-
this.
|
|
84
|
-
this.
|
|
85
|
-
this.defaultParticipant = defaultParticipant;
|
|
79
|
+
this.closesArtifact = closesArtifact;
|
|
80
|
+
this.deliveryLocation = deliveryLocation;
|
|
86
81
|
}
|
|
87
|
-
static async at(input, control
|
|
82
|
+
static async at(input, control) {
|
|
88
83
|
const env = { ...(input.env ?? process.env) }, location = squareLocation({ ...input, env });
|
|
89
84
|
const clock = squareClock(env, input.clock);
|
|
90
|
-
const wakeTransport = input.wakeTransport ?? (automaticDelivery
|
|
91
|
-
? await createDefaultWakeTransport(env).catch(() => undefined) : undefined);
|
|
92
85
|
// A request can abort its own borrowed reads, never the owner's connection lifetime.
|
|
93
86
|
const borrowed = input.resources?.artifact(location);
|
|
94
87
|
const artifact = borrowed ?? createArtifactPort(location, undefined, control?.signal);
|
|
95
88
|
try {
|
|
96
89
|
await artifact.read(facts => facts.header(), control?.signal);
|
|
97
|
-
|
|
98
|
-
await resource.publishIdentity();
|
|
99
|
-
return resource;
|
|
90
|
+
return new SqliteSquare(location, artifact, clock, input.wakeTransport || undefined, squareIndexPath(env), borrowed === undefined, await canonicalPath(location));
|
|
100
91
|
}
|
|
101
92
|
catch (error) {
|
|
102
93
|
if (borrowed === undefined)
|
|
@@ -106,33 +97,33 @@ export class SqliteSquare {
|
|
|
106
97
|
throw error;
|
|
107
98
|
}
|
|
108
99
|
}
|
|
109
|
-
static async build(input, control
|
|
100
|
+
static async build(input, control) {
|
|
110
101
|
checkControl(control);
|
|
111
102
|
const env = { ...(input.env ?? process.env) }, location = squareLocation({ ...input, env });
|
|
112
103
|
await createSquare(location, { hardCap: input.hardCap, throttlePerMinute: input.throttlePerMinute,
|
|
113
104
|
template: input.template, force: input.force ?? false }, input.markdown, control?.signal);
|
|
114
105
|
// Publication already committed; cancellation cannot erase the completed build.
|
|
115
|
-
return SqliteSquare.at({ ...input, path: location, env }
|
|
106
|
+
return SqliteSquare.at({ ...input, path: location, env });
|
|
116
107
|
}
|
|
117
108
|
static inMemory(input) {
|
|
118
109
|
const env = { ...(input.env ?? process.env) };
|
|
119
|
-
return new SqliteSquare(
|
|
110
|
+
return new SqliteSquare(`memory://${crypto.randomUUID()}`, createArtifactPort(':memory:', prepareSquareBuild(input, input.markdown)), squareClock(env, input.clock), input.wakeTransport || undefined);
|
|
120
111
|
}
|
|
121
|
-
/** Discovery is best effort and never grants write authority.
|
|
122
|
-
async
|
|
123
|
-
if (this.
|
|
124
|
-
await rememberSquarePath(this.location,
|
|
112
|
+
/** Discovery is best effort and never grants write authority. */
|
|
113
|
+
async publishSeat(owner) {
|
|
114
|
+
if (this.indexPath !== undefined)
|
|
115
|
+
await rememberSquarePath(this.location, owner, this.indexPath).catch(() => undefined);
|
|
125
116
|
}
|
|
126
|
-
observation(standingCount,
|
|
127
|
-
return { location: this.location, standingCount,
|
|
128
|
-
...(participant === undefined ? {} : { participant })
|
|
117
|
+
observation(standingCount, participant, now = this.clock()) {
|
|
118
|
+
return { location: this.location, standingCount, now,
|
|
119
|
+
...(participant === undefined ? {} : { participant }) };
|
|
129
120
|
}
|
|
130
121
|
async contextObservation(participant, control) {
|
|
131
|
-
return (await this.artifact.read(facts => this.observation(inSquareCount(facts),
|
|
122
|
+
return (await this.artifact.read(facts => this.observation(inSquareCount(facts), participant), control?.signal)).value;
|
|
132
123
|
}
|
|
133
|
-
handle(
|
|
134
|
-
// The nested handle
|
|
135
|
-
//
|
|
124
|
+
handle(seat) { return new SqliteSquare.ParticipantHandle(seat.participant, this, seat); }
|
|
125
|
+
// The nested handle uses its resource's private dependencies without copying
|
|
126
|
+
// them into a second context.
|
|
136
127
|
static ParticipantHandle = class {
|
|
137
128
|
name;
|
|
138
129
|
owner;
|
|
@@ -150,16 +141,11 @@ export class SqliteSquare {
|
|
|
150
141
|
const control = input === undefined ? operationControl : optionsOrControl;
|
|
151
142
|
let name = this.name, effect = 'unsent';
|
|
152
143
|
let landedId;
|
|
153
|
-
let waited = false, heldWaitedMs = 0;
|
|
154
144
|
try {
|
|
155
145
|
checkControl(control);
|
|
156
146
|
name = (await square.artifact.read(facts => resolveKnownName(facts, this.name), control?.signal)).value;
|
|
157
|
-
const seat =
|
|
158
|
-
const
|
|
159
|
-
const pendingPublic = directedSuffix(facts, name);
|
|
160
|
-
return { pendingPublic, sayNumbers: facts.sayOrdinals(pendingPublic.map(item => item.index)),
|
|
161
|
-
perceptions: Object.fromEntries(pendingPublic.map(item => [item.index, 'full'])) };
|
|
162
|
-
}, control?.signal)).value;
|
|
147
|
+
const seat = this.seat;
|
|
148
|
+
const context = !options.observe ? undefined : (await square.artifact.read(facts => expressionContext(facts, name), control?.signal)).value;
|
|
163
149
|
while (true) {
|
|
164
150
|
checkControl(control);
|
|
165
151
|
try {
|
|
@@ -179,12 +165,9 @@ export class SqliteSquare {
|
|
|
179
165
|
// Decoding selected rows is storage work, not proof of safe admission refusal.
|
|
180
166
|
const proposed = decideAct(facts, { name, body, force: options.force ?? false, metadata: options.metadata, now, mentions: options.mentions,
|
|
181
167
|
...(options.reach === undefined ? {} : { reach: options.reach }), ...(options.noMention === undefined ? {} : { noMention: options.noMention }), ...(reply === undefined ? {} : { reply }) });
|
|
182
|
-
const holder = proposed.type === 'held' ? facts.hold().actor : undefined;
|
|
183
168
|
const decision = rejectUnsentActivity(() => {
|
|
184
169
|
if (proposed.type === 'blocked')
|
|
185
170
|
throw new SquareError('behind', `${participantIdentity(name)} has pending activity`, { pending: proposed.activitySummaries.reduce((count, summary) => count + summary.count, 0) });
|
|
186
|
-
if (proposed.type === 'held')
|
|
187
|
-
throw new SquareError('held', 'The square is held', { ...(holder === undefined ? {} : { holder }), ...(proposed.reason === undefined ? {} : { holdReason: proposed.reason }) });
|
|
188
171
|
if (proposed.type === 'capped')
|
|
189
172
|
throw new SquareError('capped', `${participantIdentity(name)} reached the activity cap`);
|
|
190
173
|
if (proposed.type === 'throttled')
|
|
@@ -193,46 +176,29 @@ export class SqliteSquare {
|
|
|
193
176
|
throw new SquareError('bell_quota', `${participantIdentity(name)} cannot ring the bell yet`, { retryAfterMs: Math.max(1, proposed.nextAt - now) });
|
|
194
177
|
return proposed;
|
|
195
178
|
});
|
|
196
|
-
return { stored: facts.land(decision.act), standingCount: inSquareCount(facts),
|
|
179
|
+
return { stored: facts.land(decision.act), standingCount: inSquareCount(facts),
|
|
197
180
|
ownActivityCount: facts.participant(name).sayCount, hardCap: facts.header().hardCap,
|
|
198
181
|
...(decision.unmatchedMentions === undefined ? {} : { unmatchedMentions: decision.unmatchedMentions }),
|
|
199
182
|
...(decision.replyAuthorNotHere === undefined ? {} : { replyAuthorNotHere: decision.replyAuthorNotHere }) };
|
|
200
183
|
}, control?.signal)).value;
|
|
201
184
|
landedId = formatActivityId(committed.stored.index);
|
|
202
185
|
effect = 'landed';
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
.catch(() => ({ attempted: 0, accepted: 0, failed: 0, unknown: 0, notCapable: 1 }))
|
|
207
|
-
: { attempted: 0, accepted: 0, failed: 0, unknown: 0, notCapable: 1 };
|
|
208
|
-
const { stored, standingCount, held, ownActivityCount, hardCap, ...metadata } = committed;
|
|
186
|
+
if (square.wakeTransport !== undefined)
|
|
187
|
+
await deliverPending({ artifact: square.artifact, transport: square.wakeTransport, location: square.deliveryLocation, activity: committed.stored.index, now }).catch(() => undefined);
|
|
188
|
+
const { stored, standingCount, ownActivityCount, hardCap, ...metadata } = committed;
|
|
209
189
|
const hint = expressHint(ownActivityCount);
|
|
210
|
-
return { activity: toPublicActivity(stored),
|
|
211
|
-
...(hint === undefined ? {} : { hint }), ...(
|
|
212
|
-
...square.observation(standingCount,
|
|
190
|
+
return { activity: toPublicActivity(stored), ...metadata,
|
|
191
|
+
...(hint === undefined ? {} : { hint }), ...(context === undefined ? {} : { observation: {
|
|
192
|
+
...square.observation(standingCount, name, now), ownActivityCount, hardCap, context, participant: name,
|
|
213
193
|
} }) };
|
|
214
194
|
}
|
|
215
195
|
catch (error) {
|
|
216
196
|
if (effect !== 'landed' && isSquareError(error) && error.facts?.activityUnsent === true)
|
|
217
197
|
effect = 'unsent';
|
|
218
|
-
if (effect === 'landed' || !isSquareError(error) || options.noWait ||
|
|
219
|
-
throw error;
|
|
220
|
-
if (error.code === 'held' && heldWaitedMs >= HELD_WAIT_BUDGET_MS)
|
|
198
|
+
if (effect === 'landed' || !isSquareError(error) || options.noWait || error.code !== 'throttled')
|
|
221
199
|
throw error;
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
...(error.code === 'throttled' ? { delayMs: error.facts?.retryAfterMs ?? 1 } : {}),
|
|
225
|
-
...(error.facts?.holder === undefined ? {} : { holder: error.facts.holder }),
|
|
226
|
-
...(error.facts?.holdReason === undefined ? {} : { holdReason: error.facts.holdReason }) });
|
|
227
|
-
if (error.code === 'throttled')
|
|
228
|
-
await sleep(error.facts?.retryAfterMs ?? 1, undefined, { signal: control?.signal });
|
|
229
|
-
else {
|
|
230
|
-
const started = Date.now();
|
|
231
|
-
const observation = await square.artifact.read(facts => facts.hold().active, control?.signal);
|
|
232
|
-
if (observation.value)
|
|
233
|
-
await square.artifact.changed(observation.version, Math.max(1, HELD_WAIT_BUDGET_MS - heldWaitedMs), control?.signal);
|
|
234
|
-
heldWaitedMs += Date.now() - started;
|
|
235
|
-
}
|
|
200
|
+
control?.onProgress?.({ kind: 'waiting', reason: 'throttled', delayMs: error.facts?.retryAfterMs ?? 1 });
|
|
201
|
+
await sleep(error.facts?.retryAfterMs ?? 1, undefined, { signal: control?.signal });
|
|
236
202
|
}
|
|
237
203
|
}
|
|
238
204
|
}
|
|
@@ -246,13 +212,13 @@ export class SqliteSquare {
|
|
|
246
212
|
const square = this.owner;
|
|
247
213
|
const name = (await square.artifact.read(facts => resolveKnownName(facts, this.name), control?.signal)).value;
|
|
248
214
|
checkControl(control);
|
|
249
|
-
const seat =
|
|
215
|
+
const seat = this.seat, now = square.clock();
|
|
250
216
|
return (await square.artifact.transactAs(participantAuthority(seat), facts => {
|
|
251
217
|
const act = verb === 'listen' ? coreListen(facts, name, target, now) : verb === 'ignore' ? coreIgnore(facts, name, target, now) : coreUnlisten(facts, name, target, now);
|
|
252
218
|
const activity = act === undefined ? null : toPublicActivity(facts.land(act));
|
|
253
219
|
return { activity, ...(!options.observe ? {} : { observation: {
|
|
254
|
-
...square.observation(inSquareCount(facts),
|
|
255
|
-
|
|
220
|
+
...square.observation(inSquareCount(facts), name, now), participant: name,
|
|
221
|
+
target: activity?.target ?? target,
|
|
256
222
|
} }) };
|
|
257
223
|
}, control?.signal)).value;
|
|
258
224
|
}
|
|
@@ -263,7 +229,7 @@ export class SqliteSquare {
|
|
|
263
229
|
const square = this.owner;
|
|
264
230
|
return (await square.artifact.read(facts => {
|
|
265
231
|
const name = resolveKnownName(facts, this.name);
|
|
266
|
-
return { listening: coreListening(facts, name), ...(!options.observe ? {} : { observation: square.observation(inSquareCount(facts),
|
|
232
|
+
return { listening: coreListening(facts, name), ...(!options.observe ? {} : { observation: square.observation(inSquareCount(facts), name) }) };
|
|
267
233
|
}, control?.signal)).value;
|
|
268
234
|
}
|
|
269
235
|
/** Receipt selection rechecks the lease inside the writer, not at its last heartbeat. */
|
|
@@ -278,15 +244,14 @@ export class SqliteSquare {
|
|
|
278
244
|
const square = this.owner;
|
|
279
245
|
let name = this.name, subject = 'caller';
|
|
280
246
|
let leaseId, seat;
|
|
281
|
-
let waitStarted = false, replaced = false;
|
|
282
247
|
let selection = options;
|
|
283
248
|
const idle = options.idle ?? 0;
|
|
284
|
-
const complete = async (caught,
|
|
249
|
+
const complete = async (caught, reason = 'drained') => {
|
|
285
250
|
const view = caught ?? (await square.artifact.read(facts => observeCatchSelection(facts, name, [], {
|
|
286
251
|
unseenOnly: true, senders: selection.from, ...(selection.mention === true ? { attentionOnly: true } : {}),
|
|
287
252
|
}, square.clock()))).value;
|
|
288
|
-
if (
|
|
289
|
-
|
|
253
|
+
if (reason === 'drained')
|
|
254
|
+
reason = view.terminalStatus ?? reason;
|
|
290
255
|
if (leaseId !== undefined) {
|
|
291
256
|
await releaseWatchLease(square.artifact, seat, leaseId).catch(() => undefined);
|
|
292
257
|
leaseId = undefined;
|
|
@@ -298,13 +263,12 @@ export class SqliteSquare {
|
|
|
298
263
|
}
|
|
299
264
|
catch { /* Optional presence cannot erase the completed selection or receipts. */ }
|
|
300
265
|
}
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
...(presence === undefined ? { enrichmentUnavailable: true } : { presence }), waitStarted, replaced,
|
|
266
|
+
return { activities: view.activities, remaining: view.remaining, reason,
|
|
267
|
+
...(view.hint === undefined ? {} : { hint: view.hint }), ...(!options.observe ? {} : { observation: {
|
|
268
|
+
...square.observation(view.standingCount, view.participant, view.now), participant: view.participant,
|
|
269
|
+
deliveryAvailable: view.deliveryAvailable,
|
|
270
|
+
ownActivityCount: view.ownActivityCount, hardCap: view.hardCap,
|
|
271
|
+
...(presence === undefined ? { enrichmentUnavailable: true } : { presence }),
|
|
308
272
|
} }) };
|
|
309
273
|
};
|
|
310
274
|
try {
|
|
@@ -319,7 +283,8 @@ export class SqliteSquare {
|
|
|
319
283
|
catchLimit(options.limit);
|
|
320
284
|
const probe = (await square.artifact.read(facts => {
|
|
321
285
|
name = resolveKnownName(facts, this.name);
|
|
322
|
-
seat =
|
|
286
|
+
seat = this.seat;
|
|
287
|
+
assertCurrentSeat(facts, asSeatRef(seat));
|
|
323
288
|
subject = 'filter';
|
|
324
289
|
const from = options.from?.map(target => resolveKnownName(facts, target));
|
|
325
290
|
selection = { ...options, ...(from === undefined ? {} : { from }) };
|
|
@@ -331,7 +296,7 @@ export class SqliteSquare {
|
|
|
331
296
|
}, control?.signal)).value;
|
|
332
297
|
if (idle === 0) {
|
|
333
298
|
const data = probe ?? (await this.catchPage(name, seat, selection, control));
|
|
334
|
-
return await complete(data
|
|
299
|
+
return await complete(data);
|
|
335
300
|
}
|
|
336
301
|
const watch = {
|
|
337
302
|
...(selection.from === undefined ? {} : { participants: [...selection.from] }), ...(options.mention ? { mention: name } : {}),
|
|
@@ -341,10 +306,9 @@ export class SqliteSquare {
|
|
|
341
306
|
if (start.type === 'active')
|
|
342
307
|
return await complete(undefined, 'already-active');
|
|
343
308
|
leaseId = start.leaseId;
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
let quietSince = square.clock(), wasHeld = false, nextHeartbeat = start.heartbeatAt + WATCH_HEARTBEAT_MS;
|
|
309
|
+
control?.onProgress?.({ kind: 'catch-started', participant: name, idleMs: idle, replacementRequested: options.replace ?? false, replaced: start.replaced });
|
|
310
|
+
const quietSince = square.clock();
|
|
311
|
+
let nextHeartbeat = start.heartbeatAt + WATCH_HEARTBEAT_MS;
|
|
348
312
|
while (true) {
|
|
349
313
|
checkControl(control);
|
|
350
314
|
// Arm before selecting: a commit during selection must not be missed.
|
|
@@ -356,21 +320,16 @@ export class SqliteSquare {
|
|
|
356
320
|
return await complete(undefined, pulse.status);
|
|
357
321
|
if (pulse.heartbeatAt !== undefined)
|
|
358
322
|
nextHeartbeat = pulse.heartbeatAt + WATCH_HEARTBEAT_MS;
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
}
|
|
366
|
-
if (pulse.type === 'held' || wasHeld)
|
|
367
|
-
quietSince = square.clock();
|
|
368
|
-
wasHeld = pulse.type === 'held';
|
|
369
|
-
if (!wasHeld && square.clock() - quietSince >= idle) {
|
|
323
|
+
const caught = await this.catchPage(name, seat, selection, control, leaseId);
|
|
324
|
+
if (caught === null)
|
|
325
|
+
return await complete(undefined, 'replaced');
|
|
326
|
+
if (caught.activities.length > 0)
|
|
327
|
+
return await complete(caught);
|
|
328
|
+
if (square.clock() - quietSince >= idle) {
|
|
370
329
|
const owns = await ownsWatchLease(square.artifact, seat, square.clock(), leaseId, control?.signal);
|
|
371
|
-
return await complete(undefined, owns ? '
|
|
330
|
+
return await complete(undefined, owns ? 'idle' : 'replaced');
|
|
372
331
|
}
|
|
373
|
-
const deadline = Math.min(nextHeartbeat,
|
|
332
|
+
const deadline = Math.min(nextHeartbeat, quietSince + idle);
|
|
374
333
|
await square.artifact.changed(baseline, Math.max(0, deadline - square.clock()), control?.signal);
|
|
375
334
|
}
|
|
376
335
|
}
|
|
@@ -386,7 +345,7 @@ export class SqliteSquare {
|
|
|
386
345
|
async deferDelivery(input, control) {
|
|
387
346
|
checkControl(control);
|
|
388
347
|
const match = validateMetadataMatch(input?.match), duration = validateDeferralDuration(input?.durationMs);
|
|
389
|
-
const square = this.owner, seat =
|
|
348
|
+
const square = this.owner, seat = this.seat;
|
|
390
349
|
return (await square.artifact.transactAs(participantAuthority(seat), facts => {
|
|
391
350
|
const now = square.clock(), expiresAt = now + duration, id = crypto.randomUUID();
|
|
392
351
|
const result = { id, expiresAt: new Date(expiresAt).toISOString() };
|
|
@@ -398,7 +357,7 @@ export class SqliteSquare {
|
|
|
398
357
|
checkControl(control);
|
|
399
358
|
validateDeferralId(id);
|
|
400
359
|
const duration = validateDeferralDuration(durationMs), square = this.owner;
|
|
401
|
-
const seat =
|
|
360
|
+
const seat = this.seat;
|
|
402
361
|
return (await square.artifact.transactAs(participantAuthority(seat), facts => {
|
|
403
362
|
const now = square.clock(), expiresAt = now + duration;
|
|
404
363
|
const result = { id, expiresAt: new Date(expiresAt).toISOString() };
|
|
@@ -408,55 +367,51 @@ export class SqliteSquare {
|
|
|
408
367
|
async releaseDeliveryDeferral(id, control) {
|
|
409
368
|
checkControl(control);
|
|
410
369
|
validateDeferralId(id);
|
|
411
|
-
const square = this.owner, seat =
|
|
370
|
+
const square = this.owner, seat = this.seat;
|
|
412
371
|
return (await square.artifact.transactAs(participantAuthority(seat), facts => facts.releaseDeliveryDeferral(asSeatRef(seat), id, square.clock()), control?.signal)).value;
|
|
413
372
|
}
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
if (verb === 'done')
|
|
417
|
-
validateDoneBody(body);
|
|
373
|
+
async done(body, options = {}, control) {
|
|
374
|
+
validateDoneBody(body);
|
|
418
375
|
const square = this.owner;
|
|
419
376
|
const name = (await square.artifact.read(facts => resolveKnownName(facts, this.name), control?.signal)).value;
|
|
420
|
-
const seat =
|
|
377
|
+
const seat = this.seat, now = square.clock();
|
|
421
378
|
return (await square.artifact.transactAs(participantAuthority(seat), facts => {
|
|
422
|
-
const stored = facts.land(
|
|
423
|
-
return { activity: toPublicActivity(stored), ...(!options.observe ? {} : { observation:
|
|
424
|
-
|
|
425
|
-
} }) };
|
|
379
|
+
const stored = facts.land(coreDone(facts, name, body ?? '', now));
|
|
380
|
+
return { activity: toPublicActivity(stored), ...(!options.observe ? {} : { observation: square.observation(inSquareCount(facts), name, now),
|
|
381
|
+
}) };
|
|
426
382
|
}, control?.signal)).value;
|
|
427
383
|
}
|
|
428
|
-
hold(reason, options = {}, control) { return this.lifecycle('hold', reason, options, control); }
|
|
429
|
-
resume(options = {}, control) { return this.lifecycle('resume', undefined, options, control); }
|
|
430
|
-
done(body, options = {}, control) { return this.lifecycle('done', body, options, control); }
|
|
431
384
|
};
|
|
432
|
-
async participant(
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
const
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
385
|
+
async participant(name, { owner }) {
|
|
386
|
+
validateName(name);
|
|
387
|
+
requireOwner(owner);
|
|
388
|
+
return (await this.artifact.read(facts => {
|
|
389
|
+
const participant = facts.participant(name), seat = facts.seat(name);
|
|
390
|
+
if (!participant?.joined || seat === undefined || seat.owner !== owner || seat.attachment !== 'attached') {
|
|
391
|
+
const reason = participant === undefined ? 'has never stepped into this square'
|
|
392
|
+
: !participant.joined ? 'needs a current attached seat; join first'
|
|
393
|
+
: seat !== undefined && seat.owner !== owner ? 'is not held by this owner; join before writing'
|
|
394
|
+
: seat?.attachment === 'detached' ? 'is away — join again before writing'
|
|
395
|
+
: 'needs a current attached seat; join first';
|
|
396
|
+
throw new SquareError('already_joined', `${participantIdentity(participant?.name ?? name)} ${reason}`, {
|
|
397
|
+
reason: 'needs_seat', join: joinRecoveryCommand(this.location, participant?.name ?? name),
|
|
398
|
+
});
|
|
399
|
+
}
|
|
400
|
+
return this.handle(seat);
|
|
401
|
+
})).value;
|
|
447
402
|
}
|
|
448
|
-
async join(requested, options
|
|
403
|
+
async join(requested, options, control) {
|
|
449
404
|
let name = requested;
|
|
450
405
|
try {
|
|
451
406
|
checkControl(control);
|
|
452
407
|
name = requireJoinName(requested);
|
|
453
|
-
const last = options
|
|
408
|
+
const last = options?.last ?? HISTORY_DEFAULT_LIMIT;
|
|
454
409
|
if (!Number.isSafeInteger(last) || last < 1 || last > HISTORY_MAX_LIMIT)
|
|
455
410
|
throw new SquareError('invalid_args', 'Join history limit must be between 1 and 100');
|
|
456
|
-
const
|
|
411
|
+
const owner = requireOwner(options?.owner), wakeAddress = options.wakeAddress, now = this.clock();
|
|
457
412
|
const initial = !options.takeover ? undefined : (await this.artifact.read(facts => facts.participant(name)?.joined ? facts.seat(name) : undefined, control?.signal)).value;
|
|
458
|
-
const authority = initial === undefined ? { kind: 'join', participant: name,
|
|
459
|
-
: { kind: 'takeover', participant: initial.participant,
|
|
413
|
+
const authority = initial === undefined ? { kind: 'join', participant: name, owner, wakeAddress }
|
|
414
|
+
: { kind: 'takeover', participant: initial.participant, owner, expectedGeneration: initial.generation, wakeAddress };
|
|
460
415
|
const committed = (await this.artifact.transactAs(authority, facts => {
|
|
461
416
|
const participant = facts.participant(name)?.name ?? name;
|
|
462
417
|
const current = facts.participant(participant), currentSeat = facts.seat(participant);
|
|
@@ -468,10 +423,12 @@ export class SqliteSquare {
|
|
|
468
423
|
kind = 'taken-over';
|
|
469
424
|
}
|
|
470
425
|
else if (current?.joined) {
|
|
471
|
-
if (currentSeat === undefined ||
|
|
472
|
-
throw new SquareError('already_joined', `${participantIdentity(participant)} is held by another
|
|
473
|
-
if (
|
|
474
|
-
facts.
|
|
426
|
+
if (currentSeat === undefined || currentSeat.owner !== owner)
|
|
427
|
+
throw new SquareError('already_joined', `${participantIdentity(participant)} is held by another owner; take it over explicitly`);
|
|
428
|
+
if (currentSeat.attachment === 'detached')
|
|
429
|
+
facts.reattachSeat(asSeatRef(currentSeat), wakeAddress);
|
|
430
|
+
else if (wakeAddress !== undefined && canRefreshWakeAddress(currentSeat.wakeAddress, wakeAddress))
|
|
431
|
+
facts.updateWakeAddress(asSeatRef(currentSeat), wakeAddress);
|
|
475
432
|
kind = 'reconnected';
|
|
476
433
|
}
|
|
477
434
|
if (kind !== 'reconnected') {
|
|
@@ -483,11 +440,11 @@ export class SqliteSquare {
|
|
|
483
440
|
const seat = facts.seat(participant);
|
|
484
441
|
if (seat === undefined)
|
|
485
442
|
throw new SquareError('invalid_args', 'The join activity did not establish its artifact seat.');
|
|
486
|
-
return { participant: this.handle(seat
|
|
487
|
-
|
|
488
|
-
|
|
443
|
+
return { participant: this.handle(seat), activity, kind,
|
|
444
|
+
...(!options.observe ? {} : { observation: { ...this.observation(inSquareCount(facts), seat.participant, now),
|
|
445
|
+
deliveryAvailable: seat.wakeAddress !== undefined } }) };
|
|
489
446
|
}, control?.signal)).value;
|
|
490
|
-
await this.
|
|
447
|
+
await this.publishSeat(owner);
|
|
491
448
|
if (!options.observe)
|
|
492
449
|
return committed;
|
|
493
450
|
let entry;
|
|
@@ -501,30 +458,27 @@ export class SqliteSquare {
|
|
|
501
458
|
throw failure(error, { operation: 'join', subject: 'caller', participant: name });
|
|
502
459
|
}
|
|
503
460
|
}
|
|
504
|
-
|
|
461
|
+
/** Restore only a standing seat; a concurrent departure or takeover cannot be revived. */
|
|
462
|
+
async reattach(name, { owner, wakeAddress }, control) {
|
|
505
463
|
checkControl(control);
|
|
506
464
|
validateName(name);
|
|
507
|
-
|
|
508
|
-
const
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
else
|
|
518
|
-
facts.
|
|
519
|
-
|
|
520
|
-
if (seat === undefined)
|
|
521
|
-
throw new SquareError('invalid_args', 'The implicit join did not establish its artifact seat.');
|
|
522
|
-
}
|
|
523
|
-
return { state: decision.state, ...(decision.state === 'done' ? {} : { participant: this.handle(decision.joinedName, seat) }) };
|
|
465
|
+
requireOwner(owner);
|
|
466
|
+
const captured = (await this.artifact.read(facts => facts.seat(name), control?.signal)).value;
|
|
467
|
+
if (captured === undefined || captured.owner !== owner)
|
|
468
|
+
return null;
|
|
469
|
+
const seat = (await this.artifact.transactAs({ kind: 'join', participant: name, owner, wakeAddress }, facts => {
|
|
470
|
+
const current = facts.seat(name);
|
|
471
|
+
if (!facts.participant(name)?.joined || current === undefined || current.generation !== captured.generation || current.owner !== owner)
|
|
472
|
+
return null;
|
|
473
|
+
if (current.attachment === 'detached')
|
|
474
|
+
facts.reattachSeat(asSeatRef(current), wakeAddress);
|
|
475
|
+
else if (wakeAddress !== undefined && canRefreshWakeAddress(current.wakeAddress, wakeAddress))
|
|
476
|
+
facts.updateWakeAddress(asSeatRef(current), wakeAddress);
|
|
477
|
+
return facts.seat(name);
|
|
524
478
|
}, control?.signal)).value;
|
|
525
|
-
if (
|
|
526
|
-
await this.
|
|
527
|
-
return
|
|
479
|
+
if (seat !== null)
|
|
480
|
+
await this.publishSeat(owner);
|
|
481
|
+
return seat === null ? null : this.handle(seat);
|
|
528
482
|
}
|
|
529
483
|
async snapshot(control) { return (await this.artifact.read(facts => snapshot(facts, this.clock()), control?.signal)).value; }
|
|
530
484
|
async history(query = {}, control) {
|
|
@@ -555,78 +509,75 @@ export class SqliteSquare {
|
|
|
555
509
|
if (indexes.includes(anchor))
|
|
556
510
|
(presenceAnchors[anchor] ??= []).push(participant.name);
|
|
557
511
|
}
|
|
558
|
-
return { activities, observation: { ...this.observation(inSquareCount(facts)
|
|
512
|
+
return { activities, observation: { ...this.observation(inSquareCount(facts)), ...selected,
|
|
559
513
|
sayNumbers: facts.sayOrdinals(indexes), presenceAnchors } };
|
|
560
514
|
}, control?.signal)).value;
|
|
561
515
|
}
|
|
562
516
|
async status(options = {}, control) {
|
|
563
|
-
return (await this.artifact.read(facts => {
|
|
564
|
-
const seats = this.body === undefined ? [] : facts.seatsForBody(this.body);
|
|
565
|
-
const viewer = options.viewer ?? this.defaultParticipant ?? (seats.length === 1 ? seats[0].participant : '');
|
|
566
|
-
return queryStatus(facts, {
|
|
567
|
-
location: this.location, now: this.clock(), automaticDeliveryAvailable: this.automaticDelivery && this.body !== undefined,
|
|
568
|
-
}, viewer, options.observe === true);
|
|
569
|
-
}, control?.signal)).value;
|
|
517
|
+
return (await this.artifact.read(facts => queryStatus(facts, { location: this.location, now: this.clock() }, options.viewer, options.observe === true), control?.signal)).value;
|
|
570
518
|
}
|
|
571
519
|
async participants(options = {}, control) {
|
|
572
520
|
return (await this.artifact.read(facts => queryParticipants(facts, {
|
|
573
|
-
location: this.location, now: this.clock(),
|
|
521
|
+
location: this.location, now: this.clock(),
|
|
574
522
|
}, options.observe === true), control?.signal)).value;
|
|
575
523
|
}
|
|
576
524
|
async recovery(requested, control) {
|
|
577
|
-
const
|
|
578
|
-
|
|
579
|
-
return facts ?? await this.contextObservation(name, control);
|
|
525
|
+
const facts = requested === undefined ? undefined : (await this.artifact.read(facts => recoveryObservation(facts, requested, this.clock()), control?.signal).catch(() => undefined))?.value;
|
|
526
|
+
return facts ?? await this.contextObservation(requested, control);
|
|
580
527
|
}
|
|
581
528
|
stream(options, control) {
|
|
582
529
|
// A path stream follows replacements independently of this connection's inode
|
|
583
530
|
// and lifetime. Only explicit artifact readers borrow an existing port.
|
|
584
531
|
return streamSquare(this.location, options, control);
|
|
585
532
|
}
|
|
586
|
-
async
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
const candidates = (await this.artifact.read(facts => facts.seatsForBody(this.body))).value;
|
|
590
|
-
return candidates.map(seat => this.handle(seat.participant, seat));
|
|
533
|
+
async seatsOf(owner) {
|
|
534
|
+
requireOwner(owner);
|
|
535
|
+
return (await this.artifact.read(facts => facts.seatsForOwner(owner).map(({ participant: name, generation, attachment }) => ({ name, generation, attachment })))).value;
|
|
591
536
|
}
|
|
592
|
-
close() { return this.
|
|
593
|
-
async
|
|
594
|
-
|
|
595
|
-
if (body === undefined)
|
|
596
|
-
return false;
|
|
537
|
+
close() { return this.closesArtifact ? this.artifact.close() : Promise.resolve(); }
|
|
538
|
+
async heldSeat(name, { owner, generation }) {
|
|
539
|
+
requireOwner(owner);
|
|
597
540
|
const seat = (await this.artifact.read(facts => facts.seat(name))).value;
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
541
|
+
return seat?.generation === generation && seat.owner === owner ? seat : undefined;
|
|
542
|
+
}
|
|
543
|
+
async cancelDeliveries(name, identity) {
|
|
544
|
+
const seat = await this.heldSeat(name, identity);
|
|
545
|
+
return seat === undefined ? false : this.artifact.cancelDeliveries(asSeatRef(seat));
|
|
546
|
+
}
|
|
547
|
+
async detach(name, identity) {
|
|
548
|
+
const captured = await this.heldSeat(name, identity);
|
|
549
|
+
if (captured === undefined)
|
|
550
|
+
return null;
|
|
551
|
+
const seat = asSeatRef(captured);
|
|
552
|
+
return (await this.artifact.transactAs({ kind: 'host-cleanup', seat }, facts => facts.detachSeat(seat) ? true : null)).value;
|
|
601
553
|
}
|
|
602
|
-
async
|
|
603
|
-
const captured =
|
|
604
|
-
if (captured === undefined
|
|
605
|
-
|| (expectedGeneration !== undefined && captured.generation !== expectedGeneration))
|
|
554
|
+
async endHeld(name, identity) {
|
|
555
|
+
const captured = await this.heldSeat(name, identity);
|
|
556
|
+
if (captured === undefined)
|
|
606
557
|
return null;
|
|
607
|
-
return (await this.artifact.transactAs(
|
|
558
|
+
return (await this.artifact.transactAs({ kind: 'host-cleanup', seat: asSeatRef(captured) }, facts => {
|
|
608
559
|
const current = facts.seat(name);
|
|
609
|
-
if (current === undefined || current.generation !== captured.generation ||
|
|
560
|
+
if (current === undefined || current.generation !== captured.generation || current.owner !== captured.owner)
|
|
610
561
|
return null;
|
|
611
562
|
return { activity: toPublicActivity(facts.land(coreDone(facts, current.participant, '', this.clock()))) };
|
|
612
563
|
})).value;
|
|
613
564
|
}
|
|
614
565
|
}
|
|
615
|
-
export function diagnoseSquare(input, control) { checkControl(control); return diagnoseSquareFile(
|
|
616
|
-
export function migrateSquare(input, control) { checkControl(control); const env = input.env ?? process.env; return migrateSquareFile(
|
|
566
|
+
export function diagnoseSquare(input, control) { checkControl(control); return diagnoseSquareFile(squareLocation(input)); }
|
|
567
|
+
export function migrateSquare(input, control) { checkControl(control); const env = input.env ?? process.env; return migrateSquareFile(squareLocation(input), control?.signal, env); }
|
|
617
568
|
export function discover(input, options = {}, control) {
|
|
618
569
|
if (input.path !== undefined || (input.env ?? process.env).SQUARE_LOCATION)
|
|
619
|
-
|
|
570
|
+
squareLocation(input);
|
|
620
571
|
const env = { ...(input.env ?? process.env) };
|
|
621
572
|
return discoverSquares(input.cwd ?? process.cwd(), options, control, { clock: squareClock(env, input.clock) });
|
|
622
573
|
}
|
|
623
|
-
export async function inbox(input,
|
|
574
|
+
export async function inbox(input, owner, options = {}, control) {
|
|
624
575
|
checkControl(control);
|
|
576
|
+
requireOwner(owner);
|
|
625
577
|
const env = { ...(input.env ?? process.env) }, limit = options.limit ?? 20;
|
|
626
578
|
if (!Number.isSafeInteger(limit) || limit < 1 || limit > 100)
|
|
627
579
|
throw new SquareError('invalid_args', 'Inbox limit must be between 1 and 100');
|
|
628
|
-
const
|
|
629
|
-
const rows = await sessionInboxCounts(query, control?.signal);
|
|
580
|
+
const rows = await sessionInboxCounts({ owner, env }, control?.signal);
|
|
630
581
|
checkControl(control);
|
|
631
582
|
const compare = (left, right) => left < right ? -1 : left > right ? 1 : 0;
|
|
632
583
|
rows.sort((a, b) => compare(a.squarePath, b.squarePath) || compare(nameKey(a.name), nameKey(b.name)) || compare(a.name, b.name));
|