@astrosheep/square 0.3.69 → 0.3.71
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 +4 -5
- package/dist/activity-feed.js +14 -10
- package/dist/artifact.d.ts +26 -33
- package/dist/artifact.js +346 -317
- package/dist/attention-presentation.js +2 -9
- package/dist/automatic-session.js +6 -6
- package/dist/boundary-presentation.js +3 -3
- package/dist/catch-decisions.d.ts +19 -12
- package/dist/catch-decisions.js +32 -68
- package/dist/claude-delivery.js +7 -7
- package/dist/claude-mod.js +18 -7
- package/dist/cli/catch-presentation.d.ts +7 -0
- package/dist/cli/catch-presentation.js +55 -0
- package/dist/cli/context.d.ts +1 -1
- package/dist/cli/context.js +5 -23
- package/dist/cli/express-presentation.d.ts +10 -0
- package/dist/cli/express-presentation.js +196 -0
- package/dist/cli/maintenance-commands.d.ts +4 -0
- package/dist/cli/maintenance-commands.js +29 -6
- package/dist/cli/observation-commands.d.ts +7 -5
- package/dist/cli/observation-commands.js +275 -262
- package/dist/cli/program.d.ts +1 -1
- package/dist/cli/program.js +43 -56
- package/dist/cli/registry.js +2 -1
- package/dist/cli/square-commands.d.ts +3 -9
- package/dist/cli/square-commands.js +134 -255
- package/dist/codex-queue.js +4 -1
- package/dist/decisions.d.ts +26 -74
- package/dist/decisions.js +190 -335
- package/dist/delivery-health.js +13 -22
- package/dist/delivery-operations.d.ts +0 -11
- package/dist/delivery-operations.js +44 -33
- package/dist/delivery.d.ts +33 -32
- package/dist/delivery.js +70 -81
- package/dist/harness-claude.js +1 -1
- package/dist/harness-codex.js +1 -1
- package/dist/harness-pi.js +1 -1
- package/dist/help.js +6 -1
- package/dist/inbox.d.ts +27 -0
- package/dist/inbox.js +55 -18
- package/dist/index.d.ts +2 -4
- package/dist/index.js +1 -1
- package/dist/list.d.ts +7 -1
- package/dist/list.js +49 -122
- package/dist/mcp.d.ts +1 -1
- package/dist/mcp.js +7 -37
- package/dist/model.d.ts +4 -44
- package/dist/model.js +1 -3
- package/dist/notifications.d.ts +1 -1
- package/dist/notifications.js +13 -7
- package/dist/open-square.d.ts +16 -2
- package/dist/open-square.js +40 -1
- package/dist/perception-projection.d.ts +6 -15
- package/dist/perception-projection.js +6 -26
- package/dist/{opencode-delivery.d.ts → plugins/opencode/delivery.d.ts} +1 -1
- package/dist/{opencode-delivery.js → plugins/opencode/delivery.js} +18 -18
- package/dist/{opencode.d.ts → plugins/opencode/index.d.ts} +2 -2
- package/dist/{opencode.js → plugins/opencode/index.js} +9 -9
- package/dist/ports.d.ts +156 -11
- package/dist/presentation-operations.d.ts +1 -1
- package/dist/presentation-operations.js +35 -44
- package/dist/presentation.d.ts +12 -19
- package/dist/presentation.js +33 -54
- package/dist/routes.d.ts +7 -14
- package/dist/routes.js +33 -62
- package/dist/runtime.d.ts +12 -39
- package/dist/runtime.js +33 -164
- package/dist/square-actions.d.ts +11 -21
- package/dist/square-actions.js +171 -271
- package/dist/square-application.d.ts +31 -55
- package/dist/square-application.js +637 -141
- package/dist/square-core.d.ts +3 -94
- package/dist/square-core.js +8 -353
- package/dist/square-domain.d.ts +24 -0
- package/dist/square-domain.js +77 -0
- package/dist/square-facade.d.ts +360 -9
- package/dist/square-migration.d.ts +24 -0
- package/dist/square-migration.js +211 -0
- package/dist/square-projections.d.ts +2 -42
- package/dist/square-projections.js +1 -37
- package/dist/square-sqlite.d.ts +59 -0
- package/dist/square-sqlite.js +702 -0
- package/dist/stream.d.ts +3 -10
- package/dist/stream.js +81 -52
- package/dist/views.d.ts +27 -95
- package/dist/views.js +217 -87
- package/dist/wake-eligibility.d.ts +15 -5
- package/dist/wake-eligibility.js +32 -16
- package/dist/wakes.d.ts +3 -3
- package/dist/wakes.js +31 -27
- package/guides/application-facade-delivery-evidence.md +200 -0
- package/guides/application-facade-design.md +95 -0
- package/guides/change-waits.md +4 -4
- package/guides/migration.md +77 -0
- package/guides/pi-native-delivery.md +1 -1
- package/guides/primitive-catch-consolidation.md +85 -0
- package/guides/primitive-history-consolidation.md +76 -0
- package/guides/primitive-status-consolidation.md +87 -0
- package/guides/primitive-storage-consolidation.md +128 -0
- package/guides/row-runtime-delivery-evidence.md +160 -0
- package/guides/row-storage-design.md +567 -0
- package/package.json +5 -7
- package/{claude-plugin → plugins/claude}/.claude-plugin/plugin.json +1 -1
- package/{codex-plugin → plugins/codex}/.codex-plugin/plugin.json +1 -1
- package/plugins/opencode/delivery.ts +149 -0
- package/plugins/opencode/index.ts +136 -0
- package/plugins/paseo/OVERVIEW.md +14 -0
- package/plugins/paseo/README.md +54 -0
- package/plugins/paseo/client/square-message.tsx +106 -0
- package/plugins/paseo/client/transform.ts +24 -0
- package/plugins/paseo/index.client.tsx +19 -0
- package/plugins/paseo/package.json +19 -0
- package/plugins/paseo/paseo-plugin.json +7 -0
- package/plugins/paseo/shared/message.ts +29 -0
- package/{extensions → plugins/pi}/square-pi.js +8 -5
- package/dist/activity.d.ts +0 -14
- package/dist/activity.js +0 -248
- package/dist/square-file-adapter.d.ts +0 -26
- package/dist/square-file-adapter.js +0 -85
- package/dist/square-state.d.ts +0 -6
- package/dist/square-state.js +0 -138
- package/dist/square-storage.d.ts +0 -14
- package/dist/square-storage.js +0 -188
- package/dist/square-wiring.d.ts +0 -33
- package/dist/square-wiring.js +0 -109
- package/dist/watch.d.ts +0 -8
- package/dist/watch.js +0 -252
- /package/{claude-plugin → plugins/claude}/hooks/hooks.json +0 -0
- /package/{claude-plugin → plugins/claude}/hooks/register.js +0 -0
- /package/{claude-plugin → plugins/claude}/skills/square/SKILL.md +0 -0
- /package/{claude-plugin → plugins/claude}/types.d.ts +0 -0
- /package/{codex-plugin → plugins/codex}/hooks/hooks.json +0 -0
package/dist/square-storage.js
DELETED
|
@@ -1,188 +0,0 @@
|
|
|
1
|
-
import { isDeepStrictEqual } from 'node:util';
|
|
2
|
-
import { createSquareFile, createSquareState, diagnoseSquareFile as diagnoseArtifactFile, probeSquare, observeSquareRevision, readSquareSnapshot, transactSquareSnapshot, writeSquareFile, } from './artifact.js';
|
|
3
|
-
import { canonicalPath } from './canonical-path.js';
|
|
4
|
-
export { createSquareState };
|
|
5
|
-
export async function probeSquareFile(squarePath) {
|
|
6
|
-
if (!squarePath.endsWith('.square'))
|
|
7
|
-
return undefined;
|
|
8
|
-
return probeSquare(await canonicalPath(squarePath));
|
|
9
|
-
}
|
|
10
|
-
export async function diagnoseSquareFile(squarePath) {
|
|
11
|
-
return diagnoseArtifactFile(await canonicalPath(squarePath));
|
|
12
|
-
}
|
|
13
|
-
/** Test-helper snapshot replacement backed by one SQLite artifact. */
|
|
14
|
-
export async function writeSquareSnapshot(squarePath, squareState) {
|
|
15
|
-
await writeSquareFile(await canonicalPath(squarePath), squareState);
|
|
16
|
-
}
|
|
17
|
-
/** Race-safe non-force creation for the file adapter. */
|
|
18
|
-
export async function createSquareSnapshot(squarePath, squareState) {
|
|
19
|
-
return createSquareFile(await canonicalPath(squarePath), squareState);
|
|
20
|
-
}
|
|
21
|
-
function cloneState(squareState) {
|
|
22
|
-
return structuredClone(squareState);
|
|
23
|
-
}
|
|
24
|
-
function assertCellOpen(closed) {
|
|
25
|
-
if (closed)
|
|
26
|
-
throw new Error('Square artifact is closed');
|
|
27
|
-
}
|
|
28
|
-
function isThenable(value) {
|
|
29
|
-
return (typeof value === 'object' || typeof value === 'function') && value !== null
|
|
30
|
-
&& typeof value.then === 'function';
|
|
31
|
-
}
|
|
32
|
-
function discardThenable(value) {
|
|
33
|
-
void Promise.resolve(value).catch(() => undefined);
|
|
34
|
-
}
|
|
35
|
-
/** In-process artifact for fast behavior tests and embedded consumers. */
|
|
36
|
-
export function createMemoryCell(initial) {
|
|
37
|
-
let state = cloneState(initial);
|
|
38
|
-
let version = 0;
|
|
39
|
-
let closed = false;
|
|
40
|
-
let tail = Promise.resolve();
|
|
41
|
-
const waiters = new Set();
|
|
42
|
-
function publish() {
|
|
43
|
-
for (const waiter of [...waiters]) {
|
|
44
|
-
if (version <= waiter.since)
|
|
45
|
-
continue;
|
|
46
|
-
clearTimeout(waiter.timer);
|
|
47
|
-
waiters.delete(waiter);
|
|
48
|
-
waiter.signal?.removeEventListener("abort", waiter.onAbort);
|
|
49
|
-
waiter.resolve(true);
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
return {
|
|
53
|
-
transact(fn, signal) {
|
|
54
|
-
assertCellOpen(closed);
|
|
55
|
-
if (signal?.aborted)
|
|
56
|
-
throw signal.reason ?? new Error('Square artifact operation aborted');
|
|
57
|
-
const operation = tail.then(() => {
|
|
58
|
-
assertCellOpen(closed);
|
|
59
|
-
if (signal?.aborted)
|
|
60
|
-
throw signal.reason ?? new Error('Square artifact operation aborted');
|
|
61
|
-
const current = cloneState(state);
|
|
62
|
-
const outcome = fn(current, version);
|
|
63
|
-
if (isThenable(outcome)) {
|
|
64
|
-
discardThenable(outcome);
|
|
65
|
-
throw new TypeError('Square artifact transitions must be synchronous.');
|
|
66
|
-
}
|
|
67
|
-
if (typeof outcome !== 'object' || outcome === null || !Object.hasOwn(outcome, 'result')) {
|
|
68
|
-
throw new TypeError('Square artifact transition must return { state?, result }.');
|
|
69
|
-
}
|
|
70
|
-
if (outcome.state !== undefined && !isDeepStrictEqual(outcome.state, state)) {
|
|
71
|
-
state = cloneState(outcome.state);
|
|
72
|
-
version += 1;
|
|
73
|
-
publish();
|
|
74
|
-
}
|
|
75
|
-
return outcome.result;
|
|
76
|
-
});
|
|
77
|
-
tail = operation.then(() => undefined, () => undefined);
|
|
78
|
-
return operation;
|
|
79
|
-
},
|
|
80
|
-
async read(signal) {
|
|
81
|
-
assertCellOpen(closed);
|
|
82
|
-
if (signal?.aborted)
|
|
83
|
-
throw signal.reason ?? new Error('Square artifact operation aborted');
|
|
84
|
-
await tail;
|
|
85
|
-
assertCellOpen(closed);
|
|
86
|
-
if (signal?.aborted)
|
|
87
|
-
throw signal.reason ?? new Error('Square artifact operation aborted');
|
|
88
|
-
return { state: cloneState(state), version };
|
|
89
|
-
},
|
|
90
|
-
changed(sinceVersion, timeoutMs, signal) {
|
|
91
|
-
assertCellOpen(closed);
|
|
92
|
-
if (signal?.aborted)
|
|
93
|
-
return Promise.reject(signal.reason ?? new Error("Square artifact operation aborted"));
|
|
94
|
-
if (version > sinceVersion)
|
|
95
|
-
return Promise.resolve(true);
|
|
96
|
-
if (timeoutMs <= 0)
|
|
97
|
-
return Promise.resolve(false);
|
|
98
|
-
return new Promise((resolve, reject) => {
|
|
99
|
-
if (signal?.aborted) {
|
|
100
|
-
reject(signal.reason ?? new Error("Square artifact operation aborted"));
|
|
101
|
-
return;
|
|
102
|
-
}
|
|
103
|
-
const abort = () => { waiters.delete(waiter); clearTimeout(waiter.timer); signal?.removeEventListener("abort", abort); reject(signal?.reason ?? new Error("Square artifact operation aborted")); };
|
|
104
|
-
const waiter = {
|
|
105
|
-
since: sinceVersion,
|
|
106
|
-
resolve,
|
|
107
|
-
timer: setTimeout(() => { waiters.delete(waiter); signal?.removeEventListener("abort", abort); resolve(false); }, timeoutMs),
|
|
108
|
-
onAbort: abort,
|
|
109
|
-
signal,
|
|
110
|
-
};
|
|
111
|
-
waiters.add(waiter);
|
|
112
|
-
signal?.addEventListener("abort", abort, { once: true });
|
|
113
|
-
});
|
|
114
|
-
},
|
|
115
|
-
async close() {
|
|
116
|
-
if (closed)
|
|
117
|
-
return;
|
|
118
|
-
closed = true;
|
|
119
|
-
await tail;
|
|
120
|
-
for (const waiter of [...waiters]) {
|
|
121
|
-
clearTimeout(waiter.timer);
|
|
122
|
-
waiters.delete(waiter);
|
|
123
|
-
waiter.signal?.removeEventListener("abort", waiter.onAbort);
|
|
124
|
-
waiter.resolve(false);
|
|
125
|
-
}
|
|
126
|
-
},
|
|
127
|
-
};
|
|
128
|
-
}
|
|
129
|
-
/** SQLite-backed artifact. Revisions are read from the authoritative database, not file metadata. */
|
|
130
|
-
export function createFileCell(squarePath, externalSignal) {
|
|
131
|
-
let closed = false;
|
|
132
|
-
let storage;
|
|
133
|
-
let tail = Promise.resolve();
|
|
134
|
-
const cancel = new AbortController();
|
|
135
|
-
function storagePath() {
|
|
136
|
-
storage ??= canonicalPath(squarePath);
|
|
137
|
-
return storage;
|
|
138
|
-
}
|
|
139
|
-
/** Close wins over every operation; a per-call deadline bounds busy retries alongside it. */
|
|
140
|
-
function operationSignal(signal) {
|
|
141
|
-
if (signal === undefined && externalSignal === undefined)
|
|
142
|
-
return cancel.signal;
|
|
143
|
-
return AbortSignal.any([cancel.signal, ...(externalSignal === undefined ? [] : [externalSignal]), ...(signal === undefined ? [] : [signal])]);
|
|
144
|
-
}
|
|
145
|
-
return {
|
|
146
|
-
transact(fn, signal) {
|
|
147
|
-
assertCellOpen(closed);
|
|
148
|
-
const opSignal = operationSignal(signal);
|
|
149
|
-
const operation = tail.then(async () => {
|
|
150
|
-
assertCellOpen(closed);
|
|
151
|
-
const result = await transactSquareSnapshot(await storagePath(), fn, opSignal);
|
|
152
|
-
return result.result;
|
|
153
|
-
});
|
|
154
|
-
tail = operation.then(() => undefined, () => undefined);
|
|
155
|
-
return operation;
|
|
156
|
-
},
|
|
157
|
-
async read(signal) {
|
|
158
|
-
assertCellOpen(closed);
|
|
159
|
-
await tail;
|
|
160
|
-
assertCellOpen(closed);
|
|
161
|
-
const snapshot = await readSquareSnapshot(await storagePath(), operationSignal(signal));
|
|
162
|
-
return { state: cloneState(snapshot.state), version: snapshot.revision };
|
|
163
|
-
},
|
|
164
|
-
async changed(sinceVersion, timeoutMs, signal) {
|
|
165
|
-
assertCellOpen(closed);
|
|
166
|
-
const deadline = Date.now() + Math.max(0, timeoutMs);
|
|
167
|
-
const observer = await observeSquareRevision(await storagePath());
|
|
168
|
-
try {
|
|
169
|
-
return await observer.changed(sinceVersion, Math.max(0, deadline - Date.now()), operationSignal(signal));
|
|
170
|
-
}
|
|
171
|
-
catch (error) {
|
|
172
|
-
if (closed || cancel.signal.aborted)
|
|
173
|
-
return false;
|
|
174
|
-
throw error;
|
|
175
|
-
}
|
|
176
|
-
finally {
|
|
177
|
-
observer.close();
|
|
178
|
-
}
|
|
179
|
-
},
|
|
180
|
-
async close() {
|
|
181
|
-
if (closed)
|
|
182
|
-
return;
|
|
183
|
-
closed = true;
|
|
184
|
-
cancel.abort(new Error('Square artifact is closed'));
|
|
185
|
-
await tail;
|
|
186
|
-
},
|
|
187
|
-
};
|
|
188
|
-
}
|
package/dist/square-wiring.d.ts
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import type { Activity, ExpressResult, HistoryQuery, ParticipantStatus, SquareSnapshot } from './square-facade.js';
|
|
2
|
-
import type { Participant, OperationControl, SquareAtInput, SquareBuildInput } from './square-facade.js';
|
|
3
|
-
export declare class Square {
|
|
4
|
-
readonly location: string;
|
|
5
|
-
private readonly square;
|
|
6
|
-
private readonly context;
|
|
7
|
-
private constructor();
|
|
8
|
-
static at(input: SquareAtInput, control?: OperationControl): Promise<Square>;
|
|
9
|
-
static build(input: SquareBuildInput): Promise<Square>;
|
|
10
|
-
static inMemory(input: Omit<SquareBuildInput, 'path'>): Square;
|
|
11
|
-
join(name: string, control?: OperationControl): Promise<Participant>;
|
|
12
|
-
joinWithActivity(name: string, control?: OperationControl): Promise<{
|
|
13
|
-
readonly participant: Participant;
|
|
14
|
-
readonly activity: Activity | null;
|
|
15
|
-
}>;
|
|
16
|
-
takeoverWithActivity(name: string, control?: OperationControl): Promise<{
|
|
17
|
-
readonly participant: Participant;
|
|
18
|
-
readonly activities: readonly Activity[];
|
|
19
|
-
}>;
|
|
20
|
-
takeover(name: string, control?: OperationControl): Promise<Participant>;
|
|
21
|
-
doneOwnedSession(name: string, body: string, expectedEpoch: number, control?: OperationControl): Promise<ExpressResult>;
|
|
22
|
-
implicitJoin(name: string, control?: OperationControl): Promise<{
|
|
23
|
-
readonly state: 'joined' | 'active' | 'done';
|
|
24
|
-
readonly participant?: Participant;
|
|
25
|
-
}>;
|
|
26
|
-
participants(): Promise<ParticipantStatus[]>;
|
|
27
|
-
snapshot(control?: OperationControl): Promise<SquareSnapshot>;
|
|
28
|
-
history(query?: HistoryQuery, control?: OperationControl): Promise<Activity[]>;
|
|
29
|
-
recognize(env: NodeJS.ProcessEnv): Promise<Participant | null>;
|
|
30
|
-
close(): Promise<void>;
|
|
31
|
-
endOwnedSession(name: string, sessionId: string, expectedEpoch?: number): Promise<ExpressResult | null>;
|
|
32
|
-
retireEndedSessionRoutes(sessionId: string): Promise<void>;
|
|
33
|
-
}
|
package/dist/square-wiring.js
DELETED
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
import { closeOpenSquare } from './open-square.js';
|
|
2
|
-
import { buildMemorySquare, buildSquare, openSquare } from './square-file-adapter.js';
|
|
3
|
-
import { catchUp, done, endOwnedSession, express, hold, ignore, implicitJoin, join, takeover, listen, listening, resume, retireEndedSessionRoutes, } from './square-actions.js';
|
|
4
|
-
import { history, participantHistory, participants, snapshot } from './views.js';
|
|
5
|
-
import { currentParticipant } from './views.js';
|
|
6
|
-
import { projectSessionBindings } from './square-projections.js';
|
|
7
|
-
import { sessionIdsFromEnvironment } from './participant-identity.js';
|
|
8
|
-
class ParticipantHandle {
|
|
9
|
-
name;
|
|
10
|
-
square;
|
|
11
|
-
context;
|
|
12
|
-
constructor(name, square, context) {
|
|
13
|
-
this.name = name;
|
|
14
|
-
this.square = square;
|
|
15
|
-
this.context = context;
|
|
16
|
-
}
|
|
17
|
-
express(body, options, control) {
|
|
18
|
-
return express(this.context, this.name, body, options, control);
|
|
19
|
-
}
|
|
20
|
-
listen(target, control) {
|
|
21
|
-
return listen(this.context, this.name, target, control);
|
|
22
|
-
}
|
|
23
|
-
ignore(target, control) {
|
|
24
|
-
return ignore(this.context, this.name, target, control);
|
|
25
|
-
}
|
|
26
|
-
listening(control) {
|
|
27
|
-
return listening(this.context, this.name, control);
|
|
28
|
-
}
|
|
29
|
-
catch(options, control) {
|
|
30
|
-
return catchUp(this.context, this.name, options, undefined, control);
|
|
31
|
-
}
|
|
32
|
-
history(query, control) {
|
|
33
|
-
return participantHistory(this.square, this.name, query, control);
|
|
34
|
-
}
|
|
35
|
-
hold(reason, control) {
|
|
36
|
-
return hold(this.context, this.name, reason, control);
|
|
37
|
-
}
|
|
38
|
-
resume(control) {
|
|
39
|
-
return resume(this.context, this.name, control);
|
|
40
|
-
}
|
|
41
|
-
done(body, control) {
|
|
42
|
-
return done(this.context, this.name, body, {}, control);
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
export class Square {
|
|
46
|
-
location;
|
|
47
|
-
square;
|
|
48
|
-
context;
|
|
49
|
-
constructor(location, square) {
|
|
50
|
-
this.location = location;
|
|
51
|
-
this.square = square;
|
|
52
|
-
this.context = { ...square, location };
|
|
53
|
-
}
|
|
54
|
-
static async at(input, control) {
|
|
55
|
-
return new Square(input.path, await openSquare(input.path, input, control));
|
|
56
|
-
}
|
|
57
|
-
static async build(input) {
|
|
58
|
-
return new Square(input.path, await buildSquare(input.path, input));
|
|
59
|
-
}
|
|
60
|
-
static inMemory(input) {
|
|
61
|
-
return new Square('memory', buildMemorySquare(input));
|
|
62
|
-
}
|
|
63
|
-
async join(name, control) {
|
|
64
|
-
const joined = await join(this.context, name, control);
|
|
65
|
-
return new ParticipantHandle(joined.name, this.square, this.context);
|
|
66
|
-
}
|
|
67
|
-
async joinWithActivity(name, control) {
|
|
68
|
-
const joined = await join(this.context, name, control);
|
|
69
|
-
return { participant: new ParticipantHandle(joined.name, this.square, this.context), activity: joined.activity };
|
|
70
|
-
}
|
|
71
|
-
async takeoverWithActivity(name, control) {
|
|
72
|
-
const result = await takeover(this.context, name, [], control);
|
|
73
|
-
return { participant: new ParticipantHandle(result.name, this.square, this.context), activities: result.activities };
|
|
74
|
-
}
|
|
75
|
-
async takeover(name, control) {
|
|
76
|
-
return (await this.takeoverWithActivity(name, control)).participant;
|
|
77
|
-
}
|
|
78
|
-
doneOwnedSession(name, body, expectedEpoch, control) {
|
|
79
|
-
return done(this.context, name, body, { expectedEpoch }, control);
|
|
80
|
-
}
|
|
81
|
-
async implicitJoin(name, control) {
|
|
82
|
-
const joined = await implicitJoin(this.context, name, control);
|
|
83
|
-
return joined.state === 'done'
|
|
84
|
-
? { state: joined.state }
|
|
85
|
-
: { state: joined.state, participant: new ParticipantHandle(joined.name, this.square, this.context) };
|
|
86
|
-
}
|
|
87
|
-
participants() { return participants(this.square); }
|
|
88
|
-
snapshot(control) { return snapshot(this.square, control); }
|
|
89
|
-
history(query, control) { return history(this.square, query, control); }
|
|
90
|
-
async recognize(env) {
|
|
91
|
-
if (this.square.hostLedger === undefined)
|
|
92
|
-
return null;
|
|
93
|
-
const sessions = sessionIdsFromEnvironment(env);
|
|
94
|
-
if (sessions.length === 0)
|
|
95
|
-
return null;
|
|
96
|
-
const candidates = (await Promise.all(sessions.map((sessionId) => projectSessionBindings({
|
|
97
|
-
hostLedger: this.square.hostLedger,
|
|
98
|
-
location: this.square.location,
|
|
99
|
-
sessionId,
|
|
100
|
-
})))).flat();
|
|
101
|
-
if (candidates.length !== 1)
|
|
102
|
-
return null;
|
|
103
|
-
const canonicalName = await currentParticipant(this.square, candidates[0].participant);
|
|
104
|
-
return canonicalName === undefined ? null : new ParticipantHandle(canonicalName, this.square, this.context);
|
|
105
|
-
}
|
|
106
|
-
close() { return closeOpenSquare(this.square); }
|
|
107
|
-
endOwnedSession(name, sessionId, expectedEpoch) { return endOwnedSession(this.context, name, sessionId, expectedEpoch); }
|
|
108
|
-
retireEndedSessionRoutes(sessionId) { return retireEndedSessionRoutes(this.context, sessionId); }
|
|
109
|
-
}
|
package/dist/watch.d.ts
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import { type WatchOptions } from './model.js';
|
|
2
|
-
interface WatchCallerContext {
|
|
3
|
-
readonly cwd: string;
|
|
4
|
-
readonly env: NodeJS.ProcessEnv;
|
|
5
|
-
}
|
|
6
|
-
/** `false` is reserved for a quiet --now; idle completion preserves its existing sweep boundary. */
|
|
7
|
-
export declare function cmdWatch(squarePath: string, name: string, opts: WatchOptions, caller?: WatchCallerContext): Promise<boolean | undefined>;
|
|
8
|
-
export {};
|
package/dist/watch.js
DELETED
|
@@ -1,252 +0,0 @@
|
|
|
1
|
-
import { isSquareError, } from './model.js';
|
|
2
|
-
import { STALE_MS, WATCH_HEARTBEAT_MS, countSays, inSquareCount, nowMs, } from './runtime.js';
|
|
3
|
-
import { openSquare } from './square-file-adapter.js';
|
|
4
|
-
import { closeOpenSquare } from './open-square.js';
|
|
5
|
-
import { createSquareApplication } from './square-application.js';
|
|
6
|
-
import { resolveParticipant, watchPresentation } from './views.js';
|
|
7
|
-
import { acquireWatchLease, ownsWatchLease, pulseWatchLease, releaseWatchLease } from './wakes.js';
|
|
8
|
-
import { renderWatchForceTakeover, renderWatchAlreadyActive, renderWatchReplaceMissing, renderWatchOutput, renderWatchReplaced, renderWatchStatus, formatRefusal, participantCommandPrefix, joinRecoveryCommand, participantsRecoveryCommand, withPathOutput, } from './presentation.js';
|
|
9
|
-
import { hasAutomaticDeliveryIdentity } from './registry.js';
|
|
10
|
-
import { parseActivityId } from './square-core.js';
|
|
11
|
-
function watchStatusExitCode(status) {
|
|
12
|
-
return status === 'capped' ? 1 : 0;
|
|
13
|
-
}
|
|
14
|
-
function leaseId() {
|
|
15
|
-
return `watch_${process.pid}_${Date.now()}_${Math.random().toString(36).slice(2)}`;
|
|
16
|
-
}
|
|
17
|
-
function watchOutputResult(squarePath, presentation, name, caught, opts = {}) {
|
|
18
|
-
const delivered = caught.activities.flatMap((activity) => {
|
|
19
|
-
const index = parseActivityId(activity.id);
|
|
20
|
-
const stored = index === undefined ? undefined : presentation.activities.find((item) => item.index === index);
|
|
21
|
-
return stored === undefined ? [] : [{ activity: stored, perception: activity.perception }];
|
|
22
|
-
});
|
|
23
|
-
// Catch delivers only directed say activities, so there is no lifecycle list to split off.
|
|
24
|
-
const publicItems = delivered.map(({ activity }) => activity).filter((item) => item.kind === 'say' || item.kind === 'done');
|
|
25
|
-
const perceptions = new Map(delivered.map(({ activity, perception }) => [activity.index, perception]));
|
|
26
|
-
return {
|
|
27
|
-
type: 'output',
|
|
28
|
-
stdout: renderWatchOutput([...presentation.activities], publicItems, {
|
|
29
|
-
...opts,
|
|
30
|
-
viewer: name,
|
|
31
|
-
perceptions,
|
|
32
|
-
}) + (caught.remaining > 0
|
|
33
|
-
? `\n○ ${caught.remaining} matching ${caught.remaining === 1 ? 'activity remains' : 'activities remain'}\n${catchContinuationCommand(squarePath, name, opts)}`
|
|
34
|
-
: ''),
|
|
35
|
-
remaining: caught.remaining,
|
|
36
|
-
...(opts.status ? { status: opts.status } : {}),
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
function catchContinuationCommand(squarePath, name, opts) {
|
|
40
|
-
const args = ['--now'];
|
|
41
|
-
if (opts.participants !== undefined && opts.participants.length > 0)
|
|
42
|
-
args.push('--from', opts.participants.join(','));
|
|
43
|
-
if (opts.mention !== undefined)
|
|
44
|
-
args.push('--mention');
|
|
45
|
-
if (opts.limit !== undefined)
|
|
46
|
-
args.push('--limit', String(opts.limit));
|
|
47
|
-
return `${participantCommandPrefix(squarePath, name)} catch ${args.join(' ')}`;
|
|
48
|
-
}
|
|
49
|
-
function writeWatchOutput(squarePath, name, presentation, stdout, remaining, status, idleMs) {
|
|
50
|
-
const headerOpts = { participantCount: presentation.participantCount };
|
|
51
|
-
const showCatchHint = !hasAutomaticDeliveryIdentity();
|
|
52
|
-
if (status) {
|
|
53
|
-
process.stdout.write(withPathOutput(squarePath, [renderWatchStatus({ status, squarePath, name, idleMs, presence: presentation.presence, showCatchHint }), stdout.trimEnd()].filter(Boolean).join('\n\n').trimEnd(), headerOpts));
|
|
54
|
-
return;
|
|
55
|
-
}
|
|
56
|
-
const fallback = showCatchHint && remaining === 0
|
|
57
|
-
? `${participantCommandPrefix(squarePath, name)} catch --idle 30m\n stay available for new activity`
|
|
58
|
-
: '';
|
|
59
|
-
process.stdout.write(withPathOutput(squarePath, [stdout.trimEnd(), fallback].filter(Boolean).join('\n\n').trimEnd(), headerOpts));
|
|
60
|
-
}
|
|
61
|
-
function writeWatchTerminal(squarePath, name, presentation, status, idleMs) {
|
|
62
|
-
process.stdout.write(withPathOutput(squarePath, renderWatchStatus({
|
|
63
|
-
status,
|
|
64
|
-
squarePath,
|
|
65
|
-
name,
|
|
66
|
-
...(idleMs === undefined ? {} : { idleMs }),
|
|
67
|
-
presence: presentation.presence,
|
|
68
|
-
showCatchHint: !hasAutomaticDeliveryIdentity(),
|
|
69
|
-
ownActivityCount: countSays(presentation.state.acts, name),
|
|
70
|
-
hardCap: presentation.state.hardCap,
|
|
71
|
-
}), { participantCount: presentation.participantCount }));
|
|
72
|
-
}
|
|
73
|
-
function writeWatchReplaced(squarePath, name, presentation) {
|
|
74
|
-
process.stdout.write(withPathOutput(squarePath, renderWatchReplaced({ squarePath, name }), { participantCount: presentation.participantCount }));
|
|
75
|
-
}
|
|
76
|
-
async function finishWatchResult(square, squarePath, name, result, leaseId, idleMs) {
|
|
77
|
-
if (result.type === 'output') {
|
|
78
|
-
await endWatch(square, name, leaseId);
|
|
79
|
-
writeWatchOutput(squarePath, name, await watchPresentation(square, name), result.stdout, result.remaining, result.status);
|
|
80
|
-
process.exitCode = watchStatusExitCode(result.status);
|
|
81
|
-
return true;
|
|
82
|
-
}
|
|
83
|
-
if (result.type === 'terminal') {
|
|
84
|
-
await endWatch(square, name, leaseId);
|
|
85
|
-
writeWatchTerminal(squarePath, name, await watchPresentation(square, name), result.status, idleMs);
|
|
86
|
-
process.exitCode = watchStatusExitCode(result.status);
|
|
87
|
-
return true;
|
|
88
|
-
}
|
|
89
|
-
if (result.type === 'replaced') {
|
|
90
|
-
writeWatchReplaced(squarePath, name, await watchPresentation(square, name));
|
|
91
|
-
process.exitCode = 0;
|
|
92
|
-
return true;
|
|
93
|
-
}
|
|
94
|
-
return false;
|
|
95
|
-
}
|
|
96
|
-
async function beginWatch(square, squarePath, name, opts) {
|
|
97
|
-
const id = leaseId();
|
|
98
|
-
return acquireWatchLease(square, name, id, opts);
|
|
99
|
-
}
|
|
100
|
-
async function endWatch(square, name, id) {
|
|
101
|
-
await releaseWatchLease(square, name, id);
|
|
102
|
-
}
|
|
103
|
-
function installWatchInterruptHandler(square, squarePath, name, currentLeaseId) {
|
|
104
|
-
const onInterrupt = () => {
|
|
105
|
-
void (async () => {
|
|
106
|
-
await endWatch(square, name, currentLeaseId());
|
|
107
|
-
process.stdout.write(withPathOutput(squarePath, '○ you step back — catch stopped'));
|
|
108
|
-
process.exit(130);
|
|
109
|
-
})().catch((error) => {
|
|
110
|
-
process.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`);
|
|
111
|
-
process.exit(130);
|
|
112
|
-
});
|
|
113
|
-
};
|
|
114
|
-
process.once('SIGINT', onInterrupt);
|
|
115
|
-
return () => {
|
|
116
|
-
process.off('SIGINT', onInterrupt);
|
|
117
|
-
};
|
|
118
|
-
}
|
|
119
|
-
async function cmdWatchNow(squarePath, name, opts, caller) {
|
|
120
|
-
const square = await openSquare(squarePath, { clock: nowMs, env: caller.env });
|
|
121
|
-
const application = createSquareApplication({ cwd: caller.cwd, env: caller.env, squarePath, participant: name, clock: nowMs });
|
|
122
|
-
try {
|
|
123
|
-
const caught = await application.catch({
|
|
124
|
-
...(opts.id === undefined ? {} : { id: opts.id }),
|
|
125
|
-
...(opts.participants === undefined ? {} : { from: opts.participants }),
|
|
126
|
-
...(opts.mention === undefined ? {} : { mention: true }),
|
|
127
|
-
...(opts.limit === undefined ? {} : { limit: opts.limit }),
|
|
128
|
-
});
|
|
129
|
-
const presentation = await watchPresentation(square, name);
|
|
130
|
-
const status = presentation.terminalStatus;
|
|
131
|
-
const result = caught.activities.length > 0
|
|
132
|
-
? watchOutputResult(squarePath, presentation, name, caught, { mention: opts.mention, participants: opts.participants, limit: opts.limit, ...(status ? { status } : {}) })
|
|
133
|
-
: { type: 'terminal', status: status ?? 'empty-now' };
|
|
134
|
-
await finishWatchResult(square, squarePath, name, result, undefined);
|
|
135
|
-
return caught.activities.length > 0;
|
|
136
|
-
}
|
|
137
|
-
finally {
|
|
138
|
-
await closeOpenSquare(square);
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
/** `false` is reserved for a quiet --now; idle completion preserves its existing sweep boundary. */
|
|
142
|
-
export async function cmdWatch(squarePath, name, opts, caller = { cwd: process.cwd(), env: { ...process.env } }) {
|
|
143
|
-
let square;
|
|
144
|
-
let participantCount;
|
|
145
|
-
try {
|
|
146
|
-
square = await openSquare(squarePath, { clock: nowMs, env: caller.env });
|
|
147
|
-
participantCount = inSquareCount((await square.artifact.read()).state);
|
|
148
|
-
name = (await resolveParticipant(square, name)).name;
|
|
149
|
-
}
|
|
150
|
-
catch (err) {
|
|
151
|
-
if (isSquareError(err)) {
|
|
152
|
-
const bodyLines = [err.message];
|
|
153
|
-
// The caller's own name has never joined; only a join admits it.
|
|
154
|
-
if (err.facts?.reason === 'never_joined')
|
|
155
|
-
bodyLines.push(joinRecoveryCommand(squarePath, name));
|
|
156
|
-
process.stderr.write(formatRefusal(squarePath, bodyLines, participantCount === undefined ? {} : { participantCount }));
|
|
157
|
-
process.exit(err.code === 'not_found' ? 1 : 2);
|
|
158
|
-
}
|
|
159
|
-
throw err;
|
|
160
|
-
}
|
|
161
|
-
try {
|
|
162
|
-
if (opts.mention !== undefined)
|
|
163
|
-
opts = { ...opts, mention: (await resolveParticipant(square, opts.mention)).name };
|
|
164
|
-
if (opts.participants !== undefined && opts.participants.length > 0) {
|
|
165
|
-
opts = { ...opts, participants: await Promise.all(opts.participants.map(async (participant) => (await resolveParticipant(square, participant)).name)) };
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
catch (err) {
|
|
169
|
-
let participantCount;
|
|
170
|
-
try {
|
|
171
|
-
participantCount = inSquareCount((await square.artifact.read()).state);
|
|
172
|
-
}
|
|
173
|
-
catch { /* the header count is best effort */ }
|
|
174
|
-
await closeOpenSquare(square).catch(() => undefined);
|
|
175
|
-
if (isSquareError(err)) {
|
|
176
|
-
const bodyLines = [err.message];
|
|
177
|
-
// A filter target is unknown, not the caller; the roster is the useful next read.
|
|
178
|
-
if (err.facts?.reason === 'never_joined' || err.facts?.reason === 'not_standing')
|
|
179
|
-
bodyLines.push(participantsRecoveryCommand(squarePath));
|
|
180
|
-
process.stderr.write(formatRefusal(squarePath, bodyLines, participantCount === undefined ? {} : { participantCount }));
|
|
181
|
-
process.exit(err.code === 'not_found' ? 1 : 2);
|
|
182
|
-
}
|
|
183
|
-
throw err;
|
|
184
|
-
}
|
|
185
|
-
if (opts.now) {
|
|
186
|
-
await closeOpenSquare(square);
|
|
187
|
-
return cmdWatchNow(squarePath, name, opts, caller);
|
|
188
|
-
}
|
|
189
|
-
const start = await beginWatch(square, squarePath, name, opts);
|
|
190
|
-
if (start.type === 'active') {
|
|
191
|
-
const presentation = await watchPresentation(square, name);
|
|
192
|
-
process.stdout.write(withPathOutput(squarePath, renderWatchAlreadyActive({ squarePath, name }), { participantCount: presentation.participantCount }));
|
|
193
|
-
await closeOpenSquare(square);
|
|
194
|
-
process.exit(1);
|
|
195
|
-
}
|
|
196
|
-
let staleSince = nowMs();
|
|
197
|
-
let wasHeld = false;
|
|
198
|
-
let currentLeaseId = start.leaseId;
|
|
199
|
-
let nextHeartbeatAt = start.heartbeatAt + WATCH_HEARTBEAT_MS;
|
|
200
|
-
if (opts.replace) {
|
|
201
|
-
const presentation = await watchPresentation(square, name);
|
|
202
|
-
process.stdout.write(withPathOutput(squarePath, start.replaced
|
|
203
|
-
? renderWatchForceTakeover({ squarePath, name })
|
|
204
|
-
: renderWatchReplaceMissing({ squarePath, name }), { participantCount: presentation.participantCount }));
|
|
205
|
-
}
|
|
206
|
-
const idleMs = opts.idleMs ?? STALE_MS;
|
|
207
|
-
const removeInterruptHandler = installWatchInterruptHandler(square, squarePath, name, () => currentLeaseId);
|
|
208
|
-
const application = createSquareApplication({ cwd: caller.cwd, env: caller.env, squarePath, participant: name, clock: nowMs });
|
|
209
|
-
try {
|
|
210
|
-
while (true) {
|
|
211
|
-
// Capture before evaluation: changes during catch/lease checks must not be lost.
|
|
212
|
-
const baseline = (await square.artifact.read()).version;
|
|
213
|
-
const leaseState = await pulseWatchLease(square, name, currentLeaseId, opts, nowMs() >= nextHeartbeatAt);
|
|
214
|
-
if ((leaseState.type === 'sleep' || leaseState.type === 'held') && leaseState.heartbeatAt !== undefined) {
|
|
215
|
-
nextHeartbeatAt = leaseState.heartbeatAt + WATCH_HEARTBEAT_MS;
|
|
216
|
-
}
|
|
217
|
-
let result = leaseState;
|
|
218
|
-
if (result.type === 'sleep') {
|
|
219
|
-
const caught = await application.catch({
|
|
220
|
-
...(opts.participants === undefined ? {} : { from: opts.participants }),
|
|
221
|
-
...(opts.mention === undefined ? {} : { mention: true }),
|
|
222
|
-
...(opts.limit === undefined ? {} : { limit: opts.limit }),
|
|
223
|
-
});
|
|
224
|
-
if (caught.activities.length > 0) {
|
|
225
|
-
result = watchOutputResult(squarePath, await watchPresentation(square, name), name, caught, { mention: opts.mention, participants: opts.participants, limit: opts.limit });
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
if (await finishWatchResult(square, squarePath, name, result, currentLeaseId)) {
|
|
229
|
-
currentLeaseId = undefined;
|
|
230
|
-
return;
|
|
231
|
-
}
|
|
232
|
-
if (result.type === 'held' || wasHeld)
|
|
233
|
-
staleSince = nowMs();
|
|
234
|
-
wasHeld = result.type === 'held';
|
|
235
|
-
if (!wasHeld && nowMs() - staleSince >= idleMs) {
|
|
236
|
-
const result = !await ownsWatchLease(square, name, currentLeaseId)
|
|
237
|
-
? { type: 'replaced' }
|
|
238
|
-
: { type: 'terminal', status: 'stale' };
|
|
239
|
-
if (await finishWatchResult(square, squarePath, name, result, currentLeaseId, idleMs)) {
|
|
240
|
-
currentLeaseId = undefined;
|
|
241
|
-
return;
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
const nextDeadline = Math.min(nextHeartbeatAt, wasHeld ? Infinity : staleSince + idleMs);
|
|
245
|
-
await square.artifact.changed(baseline, Math.max(0, nextDeadline - nowMs()));
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
finally {
|
|
249
|
-
await closeOpenSquare(square);
|
|
250
|
-
removeInterruptHandler();
|
|
251
|
-
}
|
|
252
|
-
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|