@astrosheep/square 0.3.70 → 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.
Files changed (115) hide show
  1. package/dist/activity-feed.d.ts +4 -5
  2. package/dist/activity-feed.js +14 -10
  3. package/dist/artifact.d.ts +26 -33
  4. package/dist/artifact.js +346 -317
  5. package/dist/attention-presentation.js +2 -9
  6. package/dist/automatic-session.js +6 -6
  7. package/dist/boundary-presentation.js +3 -3
  8. package/dist/catch-decisions.d.ts +19 -12
  9. package/dist/catch-decisions.js +32 -68
  10. package/dist/claude-delivery.js +7 -7
  11. package/dist/claude-mod.js +18 -7
  12. package/dist/cli/catch-presentation.d.ts +7 -0
  13. package/dist/cli/catch-presentation.js +55 -0
  14. package/dist/cli/context.d.ts +1 -1
  15. package/dist/cli/context.js +5 -23
  16. package/dist/cli/express-presentation.d.ts +10 -0
  17. package/dist/cli/express-presentation.js +196 -0
  18. package/dist/cli/maintenance-commands.d.ts +4 -0
  19. package/dist/cli/maintenance-commands.js +29 -6
  20. package/dist/cli/observation-commands.d.ts +7 -5
  21. package/dist/cli/observation-commands.js +275 -262
  22. package/dist/cli/program.d.ts +1 -1
  23. package/dist/cli/program.js +43 -56
  24. package/dist/cli/registry.js +2 -1
  25. package/dist/cli/square-commands.d.ts +3 -9
  26. package/dist/cli/square-commands.js +134 -255
  27. package/dist/codex-queue.js +4 -1
  28. package/dist/decisions.d.ts +26 -74
  29. package/dist/decisions.js +190 -335
  30. package/dist/delivery-health.js +13 -22
  31. package/dist/delivery-operations.d.ts +0 -11
  32. package/dist/delivery-operations.js +44 -33
  33. package/dist/delivery.d.ts +33 -32
  34. package/dist/delivery.js +70 -81
  35. package/dist/help.js +6 -1
  36. package/dist/inbox.d.ts +27 -0
  37. package/dist/inbox.js +55 -18
  38. package/dist/index.d.ts +2 -4
  39. package/dist/index.js +1 -1
  40. package/dist/list.d.ts +7 -1
  41. package/dist/list.js +49 -122
  42. package/dist/mcp.d.ts +1 -1
  43. package/dist/mcp.js +7 -37
  44. package/dist/model.d.ts +4 -44
  45. package/dist/model.js +1 -3
  46. package/dist/notifications.d.ts +1 -1
  47. package/dist/notifications.js +13 -7
  48. package/dist/open-square.d.ts +16 -2
  49. package/dist/open-square.js +40 -1
  50. package/dist/perception-projection.d.ts +6 -15
  51. package/dist/perception-projection.js +6 -26
  52. package/dist/plugins/opencode/delivery.js +9 -9
  53. package/dist/plugins/opencode/index.js +3 -3
  54. package/dist/ports.d.ts +156 -11
  55. package/dist/presentation-operations.d.ts +1 -1
  56. package/dist/presentation-operations.js +35 -44
  57. package/dist/presentation.d.ts +12 -19
  58. package/dist/presentation.js +33 -54
  59. package/dist/routes.d.ts +7 -14
  60. package/dist/routes.js +33 -62
  61. package/dist/runtime.d.ts +12 -39
  62. package/dist/runtime.js +33 -164
  63. package/dist/square-actions.d.ts +11 -21
  64. package/dist/square-actions.js +171 -271
  65. package/dist/square-application.d.ts +31 -55
  66. package/dist/square-application.js +637 -141
  67. package/dist/square-core.d.ts +3 -94
  68. package/dist/square-core.js +8 -353
  69. package/dist/square-domain.d.ts +24 -0
  70. package/dist/square-domain.js +77 -0
  71. package/dist/square-facade.d.ts +360 -9
  72. package/dist/square-migration.d.ts +24 -0
  73. package/dist/square-migration.js +211 -0
  74. package/dist/square-projections.d.ts +2 -42
  75. package/dist/square-projections.js +1 -37
  76. package/dist/square-sqlite.d.ts +59 -0
  77. package/dist/square-sqlite.js +702 -0
  78. package/dist/stream.d.ts +3 -10
  79. package/dist/stream.js +81 -52
  80. package/dist/views.d.ts +27 -95
  81. package/dist/views.js +217 -87
  82. package/dist/wake-eligibility.d.ts +15 -5
  83. package/dist/wake-eligibility.js +32 -16
  84. package/dist/wakes.d.ts +3 -3
  85. package/dist/wakes.js +31 -27
  86. package/guides/application-facade-delivery-evidence.md +200 -0
  87. package/guides/application-facade-design.md +95 -0
  88. package/guides/change-waits.md +4 -4
  89. package/guides/migration.md +77 -0
  90. package/guides/primitive-catch-consolidation.md +85 -0
  91. package/guides/primitive-history-consolidation.md +76 -0
  92. package/guides/primitive-status-consolidation.md +87 -0
  93. package/guides/primitive-storage-consolidation.md +128 -0
  94. package/guides/row-runtime-delivery-evidence.md +160 -0
  95. package/guides/row-storage-design.md +567 -0
  96. package/package.json +1 -1
  97. package/plugins/claude/.claude-plugin/plugin.json +1 -1
  98. package/plugins/codex/.codex-plugin/plugin.json +1 -1
  99. package/plugins/opencode/delivery.ts +11 -11
  100. package/plugins/opencode/index.ts +3 -3
  101. package/plugins/paseo/client/square-message.tsx +70 -52
  102. package/plugins/paseo/shared/message.ts +15 -0
  103. package/plugins/pi/square-pi.js +3 -0
  104. package/dist/activity.d.ts +0 -14
  105. package/dist/activity.js +0 -248
  106. package/dist/square-file-adapter.d.ts +0 -26
  107. package/dist/square-file-adapter.js +0 -85
  108. package/dist/square-state.d.ts +0 -6
  109. package/dist/square-state.js +0 -138
  110. package/dist/square-storage.d.ts +0 -14
  111. package/dist/square-storage.js +0 -188
  112. package/dist/square-wiring.d.ts +0 -33
  113. package/dist/square-wiring.js +0 -109
  114. package/dist/watch.d.ts +0 -8
  115. package/dist/watch.js +0 -252
@@ -1,85 +0,0 @@
1
- export { observeSquareRevision as observeSquareChanges } from './artifact.js';
2
- import { hostLedgerRoot } from './host-ledger-root.js';
3
- import { createSquareState, createSquareSnapshot, probeSquareFile, writeSquareSnapshot, createFileCell, createMemoryCell, } from './square-storage.js';
4
- import { InternalSquareError, SquareError, } from './model.js';
5
- import { createHostLedgerPort } from './host-ledger-file-adapter.js';
6
- /** File-owned artifact creation for the CLI and path-backed public facade. */
7
- export async function createSquare(squarePath, options, snippet) {
8
- const state = createSquareState(options, snippet);
9
- if (options.force) {
10
- await writeSquareSnapshot(squarePath, state);
11
- return;
12
- }
13
- if (!await createSquareSnapshot(squarePath, state)) {
14
- throw new InternalSquareError('conflict', `Refusing to overwrite existing square: ${squarePath}\nPass -f to overwrite.`);
15
- }
16
- }
17
- function validateBuildOptions(options) {
18
- if (options.hardCap !== undefined && options.hardCap !== null
19
- && (!Number.isSafeInteger(options.hardCap) || options.hardCap < 1)) {
20
- throw new SquareError('invalid_args', 'hardCap must be a positive integer or null');
21
- }
22
- if (options.throttlePerMinute !== undefined
23
- && (!Number.isSafeInteger(options.throttlePerMinute) || options.throttlePerMinute < 1)) {
24
- throw new SquareError('invalid_args', 'throttlePerMinute must be a positive integer');
25
- }
26
- }
27
- export async function openSquare(squarePath, options = {}, control) {
28
- const env = options.env ?? process.env;
29
- const ledgerRoot = hostLedgerRoot(env);
30
- const artifact = openSquareArtifact(squarePath, options.signal);
31
- try {
32
- await artifact.read(control?.signal);
33
- return {
34
- artifact,
35
- clock: options.clock ?? Date.now,
36
- location: squarePath,
37
- env,
38
- hostLedger: options.hostLedger ?? createHostLedgerPort({
39
- rootPath: ledgerRoot,
40
- }),
41
- wakeTransport: options.wakeTransport,
42
- };
43
- }
44
- catch (error) {
45
- await artifact.close();
46
- if (error instanceof InternalSquareError && error.code === 'not_found') {
47
- throw new SquareError('unavailable', `Square is unavailable at ${squarePath}`);
48
- }
49
- throw error;
50
- }
51
- }
52
- export async function probeSquare(squarePath) {
53
- const state = await probeSquareFile(squarePath);
54
- return state === undefined ? undefined : { artifact: createMemoryCell(state), clock: Date.now, location: squarePath, hostLedger: createHostLedgerPort({ rootPath: hostLedgerRoot(process.env) }) };
55
- }
56
- export async function buildSquare(squarePath, options) {
57
- validateBuildOptions(options);
58
- try {
59
- await createSquare(squarePath, {
60
- force: false,
61
- hardCap: options.hardCap ?? null,
62
- ...(options.throttlePerMinute === undefined ? {} : { throttlePerMinute: options.throttlePerMinute }),
63
- }, options.markdown);
64
- }
65
- catch (error) {
66
- if (error instanceof InternalSquareError && error.code === 'conflict') {
67
- throw new SquareError('io', `Cannot build over an existing square at ${squarePath}`);
68
- }
69
- throw error;
70
- }
71
- return openSquare(squarePath, options);
72
- }
73
- export function buildMemorySquare(options) {
74
- validateBuildOptions(options);
75
- const squareState = createSquareState({
76
- force: false,
77
- hardCap: options.hardCap ?? null,
78
- ...(options.throttlePerMinute === undefined ? {} : { throttlePerMinute: options.throttlePerMinute }),
79
- }, options.markdown);
80
- return { artifact: createMemoryCell(squareState), clock: options.clock ?? Date.now, location: 'memory', hostLedger: options.hostLedger, wakeTransport: options.wakeTransport };
81
- }
82
- /** A projection reads and validates its snapshot once; no preliminary duplicate read. */
83
- export function openSquareArtifact(squarePath, signal) {
84
- return createFileCell(squarePath, signal);
85
- }
@@ -1,6 +0,0 @@
1
- import { type BuildOptions, type HardCap, type SquareRuntimeState, type SquareState } from './model.js';
2
- export declare function validateSquareState(value: unknown): SquareState;
3
- export declare function emptyRuntimeState(nextActIndex?: number): SquareRuntimeState;
4
- export declare function createSquareState(options: BuildOptions & {
5
- hardCap: HardCap;
6
- }, snippet: string): SquareState;
@@ -1,138 +0,0 @@
1
- import fs from 'node:fs';
2
- import { isWakeRouteKind, SquareError, } from './model.js';
3
- import { parseActivityId } from './square-core.js';
4
- const guideNames = ['participant', 'architect', 'brainstorm'];
5
- const guideContents = new Map(await Promise.all(guideNames.map(async (name) => [name, (await fs.promises.readFile(new URL(`../guides/${name}.md`, import.meta.url), 'utf8')).trim()])));
6
- function invalidArtifact(detail) {
7
- return new SquareError('invalid_args', `Invalid square artifact: ${detail}`);
8
- }
9
- function isObject(value) {
10
- return typeof value === 'object' && value !== null && !Array.isArray(value);
11
- }
12
- function hasExactKeys(value, required, optional = []) {
13
- const allowed = new Set([...required, ...optional]);
14
- return required.every((key) => Object.hasOwn(value, key)) && Object.keys(value).every((key) => allowed.has(key));
15
- }
16
- function isFiniteNumber(value) {
17
- return typeof value === 'number' && Number.isFinite(value);
18
- }
19
- function isNonNegativeInteger(value) {
20
- return typeof value === 'number' && Number.isSafeInteger(value) && value >= 0;
21
- }
22
- function isNonblankString(value) {
23
- return typeof value === 'string' && value.length > 0;
24
- }
25
- function isStringArray(value) {
26
- return Array.isArray(value) && value.every((item) => typeof item === 'string');
27
- }
28
- function validateWatchLease(value) {
29
- if (!isObject(value) || !hasExactKeys(value, ['leaseId', 'heartbeatAt', 'expiresAt'], ['filter'])
30
- || !isNonblankString(value.leaseId) || !isFiniteNumber(value.heartbeatAt)
31
- || !isFiniteNumber(value.expiresAt) || value.expiresAt < value.heartbeatAt)
32
- return false;
33
- if (value.filter === undefined)
34
- return true;
35
- return isObject(value.filter) && hasExactKeys(value.filter, [], ['participants', 'mention'])
36
- && (value.filter.participants === undefined || isStringArray(value.filter.participants))
37
- && (value.filter.mention === undefined || typeof value.filter.mention === 'string');
38
- }
39
- function validateRecord(value, item) {
40
- return isObject(value) && Object.entries(value).every(([key, candidate]) => key.length > 0 && item(candidate));
41
- }
42
- function validateRuntime(value) {
43
- return isObject(value) && hasExactKeys(value, ['nextActIndex', 'observations', 'leases'])
44
- && isNonNegativeInteger(value.nextActIndex)
45
- && validateRecord(value.observations, (candidate) => isObject(candidate)
46
- && Object.entries(candidate).every(([id, observation]) => parseActivityId(id) !== undefined && isObject(observation) && hasExactKeys(observation, ['state', 'at']) && observation.state === 'seen' && isFiniteNumber(observation.at)))
47
- && validateRecord(value.leases, validateWatchLease);
48
- }
49
- function validateAssignedRuntimeReferences(runtime) {
50
- for (const observations of Object.values(runtime.observations)) {
51
- for (const id of Object.keys(observations)) {
52
- const index = parseActivityId(id);
53
- if (index === undefined)
54
- return 'malformed';
55
- if (index >= runtime.nextActIndex)
56
- return 'future';
57
- }
58
- }
59
- return 'ok';
60
- }
61
- function validateActor(value, required) {
62
- return required ? isNonblankString(value) : value === undefined || isNonblankString(value);
63
- }
64
- function validateStoredAct(value) {
65
- if (!isObject(value) || typeof value.kind !== 'string' || !isNonNegativeInteger(value.index) || !isFiniteNumber(value.at))
66
- return false;
67
- switch (value.kind) {
68
- case 'join': return hasExactKeys(value, ['kind', 'actor', 'at', 'index']) && validateActor(value.actor, true);
69
- case 'done': return hasExactKeys(value, ['kind', 'actor', 'at', 'index'], ['body']) && validateActor(value.actor, true) && (value.body === undefined || typeof value.body === 'string');
70
- case 'say': return hasExactKeys(value, ['kind', 'actor', 'at', 'body', 'index'], ['mentions', 'reach', 'reply'])
71
- && validateActor(value.actor, true) && typeof value.body === 'string'
72
- && (value.mentions === undefined || isStringArray(value.mentions)) && (value.reach === undefined || value.reach === 'bell')
73
- && (value.reply === undefined || isNonNegativeInteger(value.reply));
74
- case 'hold': return hasExactKeys(value, ['kind', 'at', 'index'], ['actor', 'body']) && validateActor(value.actor, false) && (value.body === undefined || typeof value.body === 'string');
75
- case 'resume': return hasExactKeys(value, ['kind', 'at', 'index'], ['actor']) && validateActor(value.actor, false);
76
- case 'read': return hasExactKeys(value, ['kind', 'actor', 'at', 'through', 'index']) && validateActor(value.actor, true) && isNonNegativeInteger(value.through);
77
- case 'listen':
78
- case 'ignore': return hasExactKeys(value, ['kind', 'actor', 'target', 'at', 'index']) && validateActor(value.actor, true) && validateActor(value.target, true);
79
- default: return false;
80
- }
81
- }
82
- function validateActs(value) {
83
- if (!Array.isArray(value) || !value.every(validateStoredAct))
84
- return false;
85
- let previous = -1;
86
- for (const act of value) {
87
- if (act.index <= previous || (act.kind === 'say' && act.reply !== undefined && act.reply >= act.index))
88
- return false;
89
- previous = act.index;
90
- }
91
- return true;
92
- }
93
- export function validateSquareState(value) {
94
- if (!isObject(value) || !hasExactKeys(value, ['hardCap', 'preamble', 'warmup', 'acts', 'runtime'], ['throttlePerMinute', 'routes'])
95
- || !(value.hardCap === null || (Number.isSafeInteger(value.hardCap) && value.hardCap > 0))
96
- || (value.throttlePerMinute !== undefined && (!Number.isSafeInteger(value.throttlePerMinute) || value.throttlePerMinute <= 0))
97
- || !isStringArray(value.preamble) || !isStringArray(value.warmup) || !validateActs(value.acts)
98
- || (value.routes !== undefined && (!Array.isArray(value.routes) || !value.routes.every((route) => isObject(route) && isWakeRouteKind(route.kind)
99
- && typeof route.location === 'string' && typeof route.participant === 'string' && typeof route.sessionId === 'string'
100
- && typeof route.channel === 'string' && isObject(route.address) && Object.values(route.address).every((item) => typeof item === 'string')
101
- && typeof route.updatedAt === 'number')))
102
- || !validateRuntime(value.runtime))
103
- throw invalidArtifact('snapshot schema is malformed.');
104
- const historyBoundary = value.acts.at(-1)?.index ?? -1;
105
- if (value.runtime.nextActIndex <= historyBoundary)
106
- throw invalidArtifact('nextActIndex is behind the activity history.');
107
- const references = validateAssignedRuntimeReferences(value.runtime);
108
- if (references === 'malformed')
109
- throw invalidArtifact('snapshot schema is malformed.');
110
- if (references === 'future')
111
- throw invalidArtifact('runtime references an unassigned activity index.');
112
- return value;
113
- }
114
- export function emptyRuntimeState(nextActIndex = 0) {
115
- return { nextActIndex, observations: {}, leases: {} };
116
- }
117
- function normalizedLines(value) {
118
- const normalized = value.replace(/\r\n/g, '\n').trim();
119
- return normalized === '' ? [] : normalized.split('\n');
120
- }
121
- function readGuide(name) {
122
- const guide = guideContents.get(name);
123
- if (guide === undefined)
124
- throw new SquareError('invalid_args', `Unknown square guide: ${name}`);
125
- return guide;
126
- }
127
- export function createSquareState(options, snippet) {
128
- const guides = [readGuide('participant')];
129
- if (options.template !== undefined)
130
- guides.push(readGuide(options.template));
131
- return {
132
- hardCap: options.hardCap,
133
- ...(options.throttlePerMinute === undefined ? {} : { throttlePerMinute: options.throttlePerMinute }),
134
- preamble: normalizedLines(snippet),
135
- warmup: normalizedLines(guides.join('\n\n')),
136
- acts: [], routes: [], runtime: emptyRuntimeState(),
137
- };
138
- }
@@ -1,14 +0,0 @@
1
- import { createSquareState, diagnoseSquareFile as diagnoseArtifactFile } from './artifact.js';
2
- import type { SquareState } from './model.js';
3
- import type { SquareArtifactPort } from './ports.js';
4
- export { createSquareState };
5
- export declare function probeSquareFile(squarePath: string): Promise<SquareState | undefined>;
6
- export declare function diagnoseSquareFile(squarePath: string): ReturnType<typeof diagnoseArtifactFile>;
7
- /** Test-helper snapshot replacement backed by one SQLite artifact. */
8
- export declare function writeSquareSnapshot(squarePath: string, squareState: SquareState): Promise<void>;
9
- /** Race-safe non-force creation for the file adapter. */
10
- export declare function createSquareSnapshot(squarePath: string, squareState: SquareState): Promise<boolean>;
11
- /** In-process artifact for fast behavior tests and embedded consumers. */
12
- export declare function createMemoryCell(initial: SquareState): SquareArtifactPort;
13
- /** SQLite-backed artifact. Revisions are read from the authoritative database, not file metadata. */
14
- export declare function createFileCell(squarePath: string, externalSignal?: AbortSignal): SquareArtifactPort;
@@ -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
- }
@@ -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
- }
@@ -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 {};