@astrosheep/square 0.3.93 → 0.3.94
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 +2 -2
- package/dist/boundary-presentation.d.ts +2 -2
- package/dist/catch-decisions.d.ts +4 -6
- package/dist/catch-decisions.js +4 -4
- 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 -25
- package/dist/cli/express-presentation.d.ts +3 -1
- package/dist/cli/express-presentation.js +26 -14
- 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 +2 -2
- package/dist/cli/registry.js +6 -3
- package/dist/cli/square-commands.d.ts +1 -1
- package/dist/cli/square-commands.js +46 -54
- 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 -11
- package/dist/decisions.js +9 -20
- package/dist/delivery-deferral.js +2 -2
- 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 +38 -38
- package/dist/delivery.d.ts +1 -1
- package/dist/delivery.js +1 -1
- package/dist/help.js +12 -10
- 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 +8 -15
- package/dist/model.js +4 -7
- package/dist/notifications.d.ts +1 -1
- package/dist/notifications.js +6 -5
- package/dist/operation-presentation.d.ts +5 -4
- package/dist/operation-presentation.js +50 -45
- 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 +13 -33
- package/dist/presentation-operations.js +4 -4
- package/dist/presentation.d.ts +5 -8
- package/dist/presentation.js +33 -43
- package/dist/runtime.d.ts +1 -7
- package/dist/runtime.js +0 -14
- 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 -22
- package/dist/sqlite-square.js +138 -161
- package/dist/square-api.d.ts +15 -10
- package/dist/square-api.js +26 -22
- package/dist/square-core.d.ts +0 -5
- package/dist/square-core.js +0 -9
- package/dist/square-domain.d.ts +4 -2
- package/dist/square-domain.js +56 -21
- package/dist/square-facade.d.ts +45 -87
- package/dist/square-index.d.ts +5 -13
- package/dist/square-index.js +13 -38
- 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 +2 -1
- package/dist/square-migration.js +52 -30
- package/dist/square-sqlite.d.ts +6 -2
- package/dist/square-sqlite.js +54 -28
- package/dist/square-tools.d.ts +7 -10
- package/dist/square-tools.js +22 -54
- package/dist/stream.js +4 -5
- package/dist/views.d.ts +21 -10
- package/dist/views.js +38 -38
- package/dist/wakes.d.ts +1 -2
- package/dist/wakes.js +1 -1
- package/guides/application-facade-delivery-evidence.md +1 -1
- package/guides/claude-native.md +18 -9
- package/guides/codex-delivery.md +17 -6
- package/guides/mcp-connection-lifetime.md +1 -1
- package/guides/mcp.md +3 -3
- package/guides/migration.md +142 -151
- package/guides/operation-cancellation.md +1 -1
- package/guides/participant-ownership.md +78 -47
- package/guides/pi-tools.md +33 -4
- package/guides/primitive-history-consolidation.md +1 -1
- package/guides/row-storage-design.md +8 -8
- package/guides/square-api.md +244 -88
- package/package.json +1 -1
- package/plugins/claude/.claude-plugin/plugin.json +1 -1
- 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/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/inbox.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { sameBody } from './model.js';
|
|
2
1
|
import { createArtifactPort, observeSquareDeliveryRevision, observeSquareRevision } from './artifact.js';
|
|
3
2
|
import { indexedSquareEntries, observeSquareIndex } from './square-index.js';
|
|
4
3
|
import { canonicalPath } from './canonical-path.js';
|
|
@@ -20,8 +19,8 @@ export function pendingAtBoundary(inbox) {
|
|
|
20
19
|
}
|
|
21
20
|
function eligibleNotifications(facts, membership, now = Date.now()) {
|
|
22
21
|
const seat = facts.seat(membership.seat.participant);
|
|
23
|
-
if (seat === undefined || seat.generation !== membership.seat.generation
|
|
24
|
-
||
|
|
22
|
+
if (seat === undefined || seat.attachment !== 'attached' || seat.generation !== membership.seat.generation
|
|
23
|
+
|| seat.owner !== membership.seat.owner)
|
|
25
24
|
return { notifications: [] };
|
|
26
25
|
const cancelledThrough = facts.cancelledThrough(seat.participant, seat.generation);
|
|
27
26
|
let expiry = Infinity;
|
|
@@ -68,22 +67,22 @@ export async function projectBoundaryEligibility(inbox) {
|
|
|
68
67
|
/** HOME is a candidate path index; current seats and delivery evidence live in the artifact. */
|
|
69
68
|
export async function projectSessionCandidates(input) {
|
|
70
69
|
const location = input.location === undefined ? undefined : await canonicalPath(input.location);
|
|
71
|
-
const entries = await indexedSquareEntries({
|
|
70
|
+
const entries = await indexedSquareEntries({ owner: input.owner }, input.env ?? process.env);
|
|
72
71
|
const candidates = new Map();
|
|
73
72
|
for (const entry of entries) {
|
|
74
73
|
if (location !== undefined && location !== entry.location)
|
|
75
74
|
continue;
|
|
76
|
-
const key = JSON.stringify([entry.location, entry.
|
|
77
|
-
candidates.set(key, { location: entry.location,
|
|
75
|
+
const key = JSON.stringify([entry.location, entry.owner]);
|
|
76
|
+
candidates.set(key, { location: entry.location, owner: entry.owner });
|
|
78
77
|
}
|
|
79
78
|
return [...candidates.values()];
|
|
80
79
|
}
|
|
81
80
|
function groupCandidates(candidates) {
|
|
82
81
|
const grouped = new Map();
|
|
83
|
-
for (const { location,
|
|
84
|
-
const
|
|
85
|
-
|
|
86
|
-
grouped.set(location,
|
|
82
|
+
for (const { location, owner } of candidates) {
|
|
83
|
+
const owners = grouped.get(location) ?? [];
|
|
84
|
+
owners.push(owner);
|
|
85
|
+
grouped.set(location, owners);
|
|
87
86
|
}
|
|
88
87
|
return grouped;
|
|
89
88
|
}
|
|
@@ -97,11 +96,11 @@ function locatedSeats(facts, location, seats) {
|
|
|
97
96
|
/** Lifecycle reads resolve seats and join times, never pending activity bodies. */
|
|
98
97
|
export async function projectSessionSeats(input, signal) {
|
|
99
98
|
const seats = [];
|
|
100
|
-
for (const [location,
|
|
99
|
+
for (const [location, owners] of groupCandidates(await projectSessionCandidates(input))) {
|
|
101
100
|
signal?.throwIfAborted();
|
|
102
101
|
const artifact = createArtifactPort(location, undefined, signal);
|
|
103
102
|
try {
|
|
104
|
-
seats.push(...(await artifact.read(facts => locatedSeats(facts, location,
|
|
103
|
+
seats.push(...(await artifact.read(facts => locatedSeats(facts, location, owners.flatMap(owner => facts.seatsForOwner(owner))), signal)).value);
|
|
105
104
|
}
|
|
106
105
|
catch (error) {
|
|
107
106
|
if (signal?.aborted)
|
|
@@ -116,11 +115,11 @@ export async function projectSessionSeats(input, signal) {
|
|
|
116
115
|
/** Public count boundary: one coherent read per artifact, without pending body hydration. */
|
|
117
116
|
export async function sessionInboxCounts(input, signal) {
|
|
118
117
|
const rows = [];
|
|
119
|
-
for (const [location,
|
|
118
|
+
for (const [location, owners] of groupCandidates(await projectSessionCandidates(input))) {
|
|
120
119
|
signal?.throwIfAborted();
|
|
121
120
|
const artifact = createArtifactPort(location, undefined, signal);
|
|
122
121
|
try {
|
|
123
|
-
rows.push(...(await artifact.read(facts => locatedSeats(facts, location,
|
|
122
|
+
rows.push(...(await artifact.read(facts => locatedSeats(facts, location, owners.flatMap(owner => facts.seatsForOwner(owner).filter(seat => seat.attachment === 'attached'))).map(({ seat }) => ({
|
|
124
123
|
name: seat.participant, squarePath: location, pending: facts.directedCount(seat.participant, { unseenOnly: true }),
|
|
125
124
|
})), signal)).value);
|
|
126
125
|
}
|
|
@@ -137,13 +136,13 @@ export async function sessionInboxCounts(input, signal) {
|
|
|
137
136
|
/** One authoritative read per canonical artifact, even when discovery names several bodies. */
|
|
138
137
|
async function projectPending(candidates, cache, signal) {
|
|
139
138
|
const pending = [];
|
|
140
|
-
for (const [location,
|
|
139
|
+
for (const [location, owners] of groupCandidates(candidates)) {
|
|
141
140
|
signal?.throwIfAborted();
|
|
142
141
|
const artifact = createArtifactPort(location, undefined, signal);
|
|
143
142
|
try {
|
|
144
143
|
const { value: current } = await artifact.read(facts => {
|
|
145
|
-
const seats =
|
|
146
|
-
const coordinate = JSON.stringify([
|
|
144
|
+
const seats = owners.flatMap(owner => facts.seatsForOwner(owner).filter(seat => seat.attachment === 'attached'));
|
|
145
|
+
const coordinate = JSON.stringify([owners, seats.map(seat => [seat.participant, seat.owner, seat.generation])]);
|
|
147
146
|
const header = facts.header();
|
|
148
147
|
let cached = cache?.get(location);
|
|
149
148
|
if (cached?.coordinate !== coordinate || cached.version !== header.revision) {
|
|
@@ -177,14 +176,14 @@ async function projectPending(candidates, cache, signal) {
|
|
|
177
176
|
return pending;
|
|
178
177
|
}
|
|
179
178
|
function sameWakeAddress(address, kind, requested) {
|
|
180
|
-
if (address?.kind !== kind)
|
|
179
|
+
if (address?.kind !== kind || Object.keys(address.address).length !== Object.keys(requested).length)
|
|
181
180
|
return false;
|
|
182
181
|
return Object.entries(requested).every(([key, value]) => address.address[key] === value);
|
|
183
182
|
}
|
|
184
|
-
/**
|
|
183
|
+
/** Current-generation native attention, owned by its exact wake address and catch state. */
|
|
185
184
|
export function nativePendingPreview(facts, input) {
|
|
186
185
|
const seat = facts.seat(input.participant);
|
|
187
|
-
if (seat === undefined || seat.
|
|
186
|
+
if (seat === undefined || seat.attachment !== 'attached' || seat.generation !== input.generation
|
|
188
187
|
|| !sameWakeAddress(seat.wakeAddress, input.routeKind, input.address))
|
|
189
188
|
return undefined;
|
|
190
189
|
const cancelledThrough = facts.cancelledThrough(seat.participant, seat.generation);
|
|
@@ -200,10 +199,8 @@ export function nativePendingPreview(facts, input) {
|
|
|
200
199
|
return { payload: renderSquareReminder([renderAttentionPreview({ squarePath: input.location, recipient: input.participant, actIndex: item.index,
|
|
201
200
|
actor: item.actor, route: head.route, body: item.body ?? '(structured activity)' })]), clipped: attentionBodyIsClipped(item.body ?? '(structured activity)') };
|
|
202
201
|
}
|
|
203
|
-
export async function sessionInbox(
|
|
204
|
-
|
|
205
|
-
: { body: identity, env };
|
|
206
|
-
return projectPending(await projectSessionCandidates(query), undefined, signal);
|
|
202
|
+
export async function sessionInbox(owner, env = process.env, signal) {
|
|
203
|
+
return projectPending(await projectSessionCandidates({ owner, env }), undefined, signal);
|
|
207
204
|
}
|
|
208
205
|
async function capture(observer, kind, signal) {
|
|
209
206
|
const generation = observer.generation;
|
|
@@ -234,10 +231,9 @@ async function capture(observer, kind, signal) {
|
|
|
234
231
|
}
|
|
235
232
|
}
|
|
236
233
|
/** Session-scoped projection over process-shared storage change detectors. */
|
|
237
|
-
export async function observeSessionPending(
|
|
234
|
+
export async function observeSessionPending(owner, suppliedEnv = process.env) {
|
|
238
235
|
const env = { ...suppliedEnv };
|
|
239
|
-
const query =
|
|
240
|
-
: { body: identity, env };
|
|
236
|
+
const query = { owner, env };
|
|
241
237
|
const index = await observeSquareIndex(env);
|
|
242
238
|
const artifacts = new Map();
|
|
243
239
|
const cache = new Map();
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
export { Square, squareLocation, squareClock, createSquareResourceOwner, discover, inbox, diagnoseSquare, migrateSquare } from './square-api.js';
|
|
2
2
|
export { SquareError, ACTIVITY_METADATA_MAX_BYTES } from './model.js';
|
|
3
|
+
export { selectOwnSeat, requireOwner, localUserOwner, harnessOwner, decodeHarnessOwner } from './square-api.js';
|
|
3
4
|
export type { WakeTransportPort, WakeRequest, WakeOutcome } from './ports.js';
|
|
4
5
|
export type { WakeTransports } from './notifications.js';
|
|
5
|
-
export { createDefaultWakeTransport } from './notifications.js';
|
|
6
|
-
export type { PresentationSinkPort } from './ports.js';
|
|
7
|
-
export type * from './square-backend.js';
|
|
8
6
|
export type * from './square-facade.js';
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export { Square, squareLocation, squareClock, createSquareResourceOwner, discover, inbox, diagnoseSquare, migrateSquare } from './square-api.js';
|
|
2
2
|
export { SquareError, ACTIVITY_METADATA_MAX_BYTES } from './model.js';
|
|
3
|
-
export {
|
|
3
|
+
export { selectOwnSeat, requireOwner, localUserOwner, harnessOwner, decodeHarnessOwner } from './square-api.js';
|
package/dist/mcp.d.ts
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
import { type Owner } from './square-api.js';
|
|
2
3
|
import type { SquareAtInput } from './square-facade.js';
|
|
3
4
|
/** The server owns its artifact connection lifetime, so callers cannot lend one. */
|
|
4
5
|
export interface SquareMcpOptions extends Omit<SquareAtInput, 'resources'> {
|
|
6
|
+
readonly owner?: Owner;
|
|
7
|
+
readonly wakeAddress?: import('./model.js').WakeAddress;
|
|
5
8
|
}
|
|
6
9
|
export type SquareMcpServer = McpServer;
|
|
7
10
|
export declare function createSquareMcpServer(options: SquareMcpOptions): SquareMcpServer;
|
package/dist/mcp.js
CHANGED
|
@@ -6,8 +6,10 @@ import { codexWakeAddress } from './codex-address.js';
|
|
|
6
6
|
import { readClaudeMcpCall } from './claude-mcp-context.js';
|
|
7
7
|
import { SQUARE_IDENTITY } from './identity.js';
|
|
8
8
|
import { Square, createSquareResourceOwner } from './square-api.js';
|
|
9
|
+
import { harnessOwner } from './square-api.js';
|
|
9
10
|
export function createSquareMcpServer(options) {
|
|
10
|
-
const
|
|
11
|
+
const { owner: configuredOwner, wakeAddress, ...resourceOptions } = options;
|
|
12
|
+
const baseEnv = { ...(resourceOptions.env ?? process.env) };
|
|
11
13
|
const resources = createSquareResourceOwner();
|
|
12
14
|
// Calls to the configured square borrow one server-owned connection.
|
|
13
15
|
const inFlight = new Set();
|
|
@@ -19,21 +21,20 @@ export function createSquareMcpServer(options) {
|
|
|
19
21
|
const call = (async () => {
|
|
20
22
|
let square;
|
|
21
23
|
try {
|
|
22
|
-
const {
|
|
24
|
+
const { location } = args;
|
|
23
25
|
const threadId = extra._meta?.threadId;
|
|
24
26
|
const opencodeSessionId = extra._meta?.['ai.opencode/sessionID'];
|
|
25
27
|
// Claude's plugin endpoint requires the mod's call-local coordinate, never startup identity.
|
|
26
28
|
const claude = baseEnv.SQUARE_CLAUDE_MCP_CONTEXT === '1'
|
|
27
29
|
? await readClaudeMcpCall(extra._meta?.['claudecode/toolUseId'], baseEnv)
|
|
28
30
|
: undefined;
|
|
29
|
-
const
|
|
30
|
-
? { channel: 'claude-code', session: claude.sessionId,
|
|
31
|
-
...(claude.agentId === undefined ? {} : { agent: claude.agentId }) }
|
|
31
|
+
const owner = claude !== undefined
|
|
32
|
+
? harnessOwner({ channel: 'claude-code', session: claude.sessionId, ...(claude.agentId === undefined ? {} : { agent: claude.agentId }) })
|
|
32
33
|
: typeof threadId === 'string' && threadId.trim()
|
|
33
|
-
? { channel: 'codex', session: threadId }
|
|
34
|
+
? harnessOwner({ channel: 'codex', session: threadId })
|
|
34
35
|
: typeof opencodeSessionId === 'string' && opencodeSessionId.trim()
|
|
35
|
-
? { channel: 'opencode', session: opencodeSessionId }
|
|
36
|
-
:
|
|
36
|
+
? harnessOwner({ channel: 'opencode', session: opencodeSessionId })
|
|
37
|
+
: configuredOwner;
|
|
37
38
|
const env = claude !== undefined
|
|
38
39
|
? { ...operationEnv('claude', claude.sessionId, baseEnv),
|
|
39
40
|
// Preserve Claude's session + child flag semantics; an agent loop ID is not a session ID.
|
|
@@ -44,37 +45,35 @@ export function createSquareMcpServer(options) {
|
|
|
44
45
|
? operationEnv('opencode', opencodeSessionId, baseEnv)
|
|
45
46
|
: baseEnv;
|
|
46
47
|
square = await Square.at({
|
|
47
|
-
...
|
|
48
|
-
// A call-local Codex thread uses its native queue even when managed by Paseo.
|
|
49
|
-
wakeAddress: claude === undefined && typeof threadId === 'string' && threadId.trim()
|
|
50
|
-
? codexWakeAddress(threadId, env) : options.wakeAddress,
|
|
48
|
+
...resourceOptions, env, cwd: claude?.cwd ?? resourceOptions.cwd,
|
|
51
49
|
path: location ?? options.path,
|
|
52
|
-
participant: participant ?? options.participant,
|
|
53
50
|
// The server owner is bound to its configured square; overrides close after each call.
|
|
54
51
|
resources: location === undefined && claude === undefined ? resources : undefined,
|
|
55
52
|
}, { signal: extra.signal });
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
53
|
+
const callWake = wakeAddress !== undefined && (owner === configuredOwner
|
|
54
|
+
|| wakeAddress.kind === 'paseo' && wakeAddress.address.agentId === baseEnv.PASEO_AGENT_ID
|
|
55
|
+
|| wakeAddress.kind === 'claude-native' && wakeAddress.address.sessionId === claude?.sessionId
|
|
56
|
+
|| wakeAddress.kind === 'opencode-server' && wakeAddress.address.sessionId === opencodeSessionId)
|
|
57
|
+
? wakeAddress : undefined;
|
|
58
|
+
let text;
|
|
59
59
|
try {
|
|
60
|
-
|
|
60
|
+
text = await tool.run(square, args, { signal: extra.signal }, {
|
|
61
|
+
owner, wakeAddress: claude === undefined && typeof threadId === 'string' && threadId.trim()
|
|
62
|
+
? codexWakeAddress(threadId, env) : callWake,
|
|
63
|
+
});
|
|
61
64
|
}
|
|
62
65
|
finally {
|
|
63
66
|
await square.close();
|
|
64
67
|
}
|
|
65
|
-
|
|
66
|
-
const text = tool.render(receipt, args) ?? '';
|
|
67
|
-
// Observation facts are a rendering aid, not part of the receipt machines receive.
|
|
68
|
-
const { observation: _observation, ...structuredContent } = receipt;
|
|
69
|
-
return { content: [{ type: 'text', text }], structuredContent };
|
|
68
|
+
return { content: [{ type: 'text', text }] };
|
|
70
69
|
}
|
|
71
70
|
catch (error) {
|
|
72
71
|
const failure = squareToolFailure(error, extra.signal);
|
|
73
72
|
const participant = args.as;
|
|
74
73
|
return { isError: true, content: [{ type: 'text', text: squareToolFailureText(failure, {
|
|
75
74
|
location: square?.location ?? options.path,
|
|
76
|
-
participant: typeof participant === 'string' ? participant :
|
|
77
|
-
}) }]
|
|
75
|
+
participant: typeof participant === 'string' ? participant : undefined,
|
|
76
|
+
}) }] };
|
|
78
77
|
}
|
|
79
78
|
})();
|
|
80
79
|
inFlight.add(call);
|
package/dist/model.d.ts
CHANGED
|
@@ -12,11 +12,8 @@ export declare const ACTIVITY_METADATA_MAX_DEPTH = 256;
|
|
|
12
12
|
/** Validate the bounded, lossless JSON object carried by a say. */
|
|
13
13
|
export declare function validateActivityMetadata(value: unknown): ActivityMetadata | undefined;
|
|
14
14
|
export declare function activityMetadataHasContent(metadata: ActivityMetadata | undefined): boolean;
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
readonly session: string;
|
|
18
|
-
readonly agent?: string;
|
|
19
|
-
}
|
|
15
|
+
/** Opaque custody identity. Harness coordinates are adapter-owned. */
|
|
16
|
+
export type Owner = string;
|
|
20
17
|
export interface WakeAddress {
|
|
21
18
|
readonly kind: WakeRouteKind;
|
|
22
19
|
readonly address: Readonly<Record<string, string>>;
|
|
@@ -24,24 +21,22 @@ export interface WakeAddress {
|
|
|
24
21
|
/** Artifact-owned custody binding. Generation is the join activity that established it. */
|
|
25
22
|
export interface Seat {
|
|
26
23
|
readonly participant: string;
|
|
27
|
-
readonly
|
|
24
|
+
readonly owner: Owner;
|
|
28
25
|
readonly generation: ActivityId;
|
|
26
|
+
readonly attachment: 'attached' | 'detached';
|
|
29
27
|
readonly wakeAddress?: WakeAddress;
|
|
30
28
|
}
|
|
31
29
|
export interface SeatWatchLease {
|
|
32
30
|
readonly generation: ActivityId;
|
|
33
31
|
readonly lease: WatchLease;
|
|
34
32
|
}
|
|
35
|
-
export declare function
|
|
36
|
-
export declare function validateBody(body: Body): void;
|
|
33
|
+
export declare function validateOwner(owner: Owner): Owner;
|
|
37
34
|
export declare function isWakeRouteKind(value: unknown): value is WakeRouteKind;
|
|
38
35
|
export interface WakeRoute {
|
|
39
36
|
/** Ownership generation, when the receiver publishes a fenced route. */
|
|
40
37
|
epoch?: number;
|
|
41
38
|
location: string;
|
|
42
39
|
participant: string;
|
|
43
|
-
sessionId: string;
|
|
44
|
-
channel: string;
|
|
45
40
|
kind: WakeRouteKind;
|
|
46
41
|
address: Record<string, string>;
|
|
47
42
|
updatedAt: number;
|
|
@@ -49,10 +44,12 @@ export interface WakeRoute {
|
|
|
49
44
|
export type SquareErrorCode = 'invalid_name' | 'invalid_args' | 'unknown_participant' | 'not_joined' | 'already_joined' | 'already_done' | 'held' | 'capped' | 'throttled' | 'bell_quota' | 'behind' | 'io' | 'unavailable';
|
|
50
45
|
export type InternalSquareErrorCode = SquareErrorCode | 'not_found' | 'cap_reached' | 'conflict' | 'pending_peer';
|
|
51
46
|
export interface SquareErrorFacts {
|
|
47
|
+
/** Copyable recovery for a missing, detached or foreign seat. */
|
|
48
|
+
join?: string;
|
|
52
49
|
/** Express admission rejected before any activity was committed. */
|
|
53
50
|
activityUnsent?: true;
|
|
54
51
|
/** Refusal reason, including absent participants, conflicting reach, and inaccessible activities. */
|
|
55
|
-
reason?: 'never_joined' | 'not_standing' | 'bell_mention_conflict' | 'not_addressed' | 'migration_required' | 'invalid_reply' | 'invalid_done_body';
|
|
52
|
+
reason?: 'never_joined' | 'not_standing' | 'bell_mention_conflict' | 'not_addressed' | 'migration_required' | 'invalid_reply' | 'invalid_done_body' | 'needs_seat';
|
|
56
53
|
/** The activity id a `catch --id` refusal named. */
|
|
57
54
|
activityId?: string;
|
|
58
55
|
/** The host ledger requiring offline migration, rather than the selected artifact. */
|
|
@@ -122,13 +119,9 @@ export interface PendingMembership extends LocatedSeat {
|
|
|
122
119
|
readonly deliveryDeferralExpiry?: number;
|
|
123
120
|
}
|
|
124
121
|
export interface WatchOptions {
|
|
125
|
-
id?: ActivityId;
|
|
126
122
|
participants?: string[];
|
|
127
123
|
mention?: string;
|
|
128
|
-
limit?: number;
|
|
129
|
-
idleMs?: number;
|
|
130
124
|
replace?: boolean;
|
|
131
|
-
now?: boolean;
|
|
132
125
|
}
|
|
133
126
|
export type PublicAct = Extract<StoredAct, {
|
|
134
127
|
kind: 'say' | 'done';
|
package/dist/model.js
CHANGED
|
@@ -76,14 +76,11 @@ export function validateActivityMetadata(value) {
|
|
|
76
76
|
export function activityMetadataHasContent(metadata) {
|
|
77
77
|
return metadata !== undefined && Object.keys(metadata).length > 0;
|
|
78
78
|
}
|
|
79
|
-
export function
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
export function validateBody(body) {
|
|
83
|
-
if (!body || typeof body.channel !== 'string' || !body.channel || typeof body.session !== 'string' || !body.session
|
|
84
|
-
|| (body.agent !== undefined && (typeof body.agent !== 'string' || !body.agent))) {
|
|
85
|
-
throw new SquareError('invalid_args', 'A participant write requires an explicit channel and session body.');
|
|
79
|
+
export function validateOwner(owner) {
|
|
80
|
+
if (typeof owner !== 'string' || !owner || Buffer.byteLength(owner, 'utf8') > 512 || /[\u0000-\u001f\u007f-\u009f]/u.test(owner)) {
|
|
81
|
+
throw new SquareError('invalid_args', 'A participant write requires a non-empty owner without control characters (at most 512 UTF-8 bytes).');
|
|
86
82
|
}
|
|
83
|
+
return owner;
|
|
87
84
|
}
|
|
88
85
|
export function isWakeRouteKind(value) {
|
|
89
86
|
return typeof value === 'string' && WAKE_ROUTE_KINDS.includes(value);
|
package/dist/notifications.d.ts
CHANGED
|
@@ -13,7 +13,7 @@ interface ProcessNotificationOptions {
|
|
|
13
13
|
export declare function createDefaultWakeTransport(env?: NodeJS.ProcessEnv, suppliedTransports?: WakeTransports): Promise<WakeTransportPort>;
|
|
14
14
|
/** Route selection only: all implementations receive the same request and final gate. */
|
|
15
15
|
export declare function createWakeTransport(transports: WakeTransports): WakeTransportPort;
|
|
16
|
-
export declare function processActNotificationsOnce(squarePath: string, actIndex: number, opts?: ProcessNotificationOptions): Promise<
|
|
16
|
+
export declare function processActNotificationsOnce(squarePath: string, actIndex: number, opts?: ProcessNotificationOptions): Promise<void>;
|
|
17
17
|
/** Privileged hook fallback: sweep indexed squares plus the current cwd's local squares within one boundary budget. */
|
|
18
18
|
export declare function sweepPrivilegedPending(cwd: string, env?: NodeJS.ProcessEnv, suppliedTransports?: WakeTransports, deadline?: number, signal?: AbortSignal): Promise<void>;
|
|
19
19
|
export interface SweepPendingNotificationsOptions {
|
package/dist/notifications.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
|
+
import { canonicalPath } from './canonical-path.js';
|
|
2
3
|
import fs from 'node:fs';
|
|
3
4
|
import { indexedSquareEntries } from './square-index.js';
|
|
4
5
|
import { InternalSquareError, SquareError } from './model.js';
|
|
@@ -55,16 +56,15 @@ export function createWakeTransport(transports) {
|
|
|
55
56
|
export async function processActNotificationsOnce(squarePath, actIndex, opts = {}) {
|
|
56
57
|
const env = opts.env ?? process.env;
|
|
57
58
|
const now = opts.now ?? Date.now;
|
|
59
|
+
squarePath = await canonicalPath(squarePath);
|
|
58
60
|
const artifact = createArtifactPort(squarePath);
|
|
59
61
|
try {
|
|
60
62
|
await artifact.read(facts => facts.header());
|
|
61
63
|
const transport = await createDefaultWakeTransport(env, opts.transports);
|
|
62
64
|
try {
|
|
63
|
-
|
|
64
|
-
}
|
|
65
|
-
catch {
|
|
66
|
-
return { attempted: 0, accepted: 0, failed: 0, unknown: 0, notCapable: 1 };
|
|
65
|
+
await deliverPending({ artifact, transport, location: squarePath, activity: actIndex, timeoutMs: Number(env.SQUARE_NOTIFY_DELIVERY_WAIT_MS ?? 5000), now: now() });
|
|
67
66
|
}
|
|
67
|
+
catch { /* Delivery failure does not undo the activity. */ }
|
|
68
68
|
}
|
|
69
69
|
catch (error) {
|
|
70
70
|
if (error instanceof InternalSquareError && error.code === 'not_found')
|
|
@@ -92,10 +92,11 @@ export async function sweepPrivilegedPending(cwd, env = process.env, suppliedTra
|
|
|
92
92
|
if (remainingMs() === 0 || signal?.aborted)
|
|
93
93
|
return;
|
|
94
94
|
const transport = await createDefaultWakeTransport(env, suppliedTransports);
|
|
95
|
-
for (const
|
|
95
|
+
for (const candidate of paths) {
|
|
96
96
|
if (remainingMs() === 0 || signal?.aborted)
|
|
97
97
|
break;
|
|
98
98
|
try {
|
|
99
|
+
const squarePath = await canonicalPath(candidate);
|
|
99
100
|
const artifact = createArtifactPort(squarePath, undefined, signal);
|
|
100
101
|
try {
|
|
101
102
|
await artifact.read(facts => facts.header(), signal);
|
|
@@ -7,10 +7,10 @@ export type JoinPresentation = Omit<JoinResult, 'participant'> & {
|
|
|
7
7
|
readonly name: string;
|
|
8
8
|
} | string;
|
|
9
9
|
};
|
|
10
|
-
export declare function renderJoinResult(data: JoinPresentation): string | undefined;
|
|
11
|
-
export declare function renderExpression(squarePath: string, data: ExpressResult): string | undefined;
|
|
10
|
+
export declare function renderJoinResult(data: JoinPresentation, owner?: string): string | undefined;
|
|
11
|
+
export declare function renderExpression(squarePath: string, data: ExpressResult, owner?: string): string | undefined;
|
|
12
12
|
/** Render settled catch facts; no selection, terminal decisions, receipts or wait machinery. */
|
|
13
|
-
export declare function renderCatchOutcome(squarePath: string, data: CatchResult, options?: CatchOptions): {
|
|
13
|
+
export declare function renderCatchOutcome(squarePath: string, data: CatchResult, options?: CatchOptions, owner?: string): {
|
|
14
14
|
stdout: string;
|
|
15
15
|
exitCode: number;
|
|
16
16
|
};
|
|
@@ -31,7 +31,7 @@ export interface FailureReport {
|
|
|
31
31
|
readonly code: string;
|
|
32
32
|
readonly message: string;
|
|
33
33
|
readonly facts?: {
|
|
34
|
-
readonly reason?: 'never_joined' | 'not_standing' | 'bell_mention_conflict' | 'not_addressed' | 'migration_required' | 'invalid_reply' | 'invalid_done_body';
|
|
34
|
+
readonly reason?: 'never_joined' | 'not_standing' | 'bell_mention_conflict' | 'not_addressed' | 'migration_required' | 'invalid_reply' | 'invalid_done_body' | 'needs_seat';
|
|
35
35
|
readonly activityId?: string;
|
|
36
36
|
readonly ledgerRoot?: string;
|
|
37
37
|
readonly activityExists?: boolean;
|
|
@@ -42,4 +42,5 @@ export interface FailureReport {
|
|
|
42
42
|
export declare function renderFailureLines(failure: FailureReport, options?: {
|
|
43
43
|
squarePath?: string;
|
|
44
44
|
name?: string;
|
|
45
|
+
owner?: string;
|
|
45
46
|
}): string[];
|