@astrosheep/square 0.3.63 → 0.3.65
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/claude-plugin/.claude-plugin/plugin.json +3 -2
- package/claude-plugin/hooks/hooks.json +1 -22
- package/claude-plugin/hooks/register.js +119 -0
- package/claude-plugin/types.d.ts +7 -0
- package/codex-plugin/.codex-plugin/plugin.json +1 -1
- package/dist/activity-feed.d.ts +1 -10
- package/dist/activity-feed.js +1 -27
- package/dist/activity.js +57 -25
- package/dist/artifact.d.ts +1 -1
- package/dist/artifact.js +24 -25
- package/dist/attention-presentation.js +1 -0
- package/dist/automatic-session.d.ts +3 -1
- package/dist/automatic-session.js +21 -34
- package/dist/boundary-presentation.js +4 -13
- package/dist/canonical-path.d.ts +11 -0
- package/dist/canonical-path.js +47 -0
- package/dist/catch-decisions.js +14 -10
- package/dist/catch-selection.d.ts +6 -0
- package/dist/catch-selection.js +14 -0
- package/dist/claude-delivery.d.ts +11 -0
- package/dist/claude-delivery.js +145 -0
- package/dist/claude-mod.d.ts +8 -0
- package/dist/claude-mod.js +164 -0
- package/dist/cli/context.d.ts +0 -1
- package/dist/cli/context.js +9 -21
- package/dist/cli/harness-command.d.ts +0 -1
- package/dist/cli/harness-command.js +0 -6
- package/dist/cli/observation-commands.d.ts +1 -1
- package/dist/cli/observation-commands.js +31 -58
- package/dist/cli/program.js +20 -18
- package/dist/cli/registry.js +2 -2
- package/dist/cli/square-commands.js +10 -6
- package/dist/codex-boundary-state.d.ts +2 -2
- package/dist/codex-boundary-state.js +4 -4
- package/dist/codex-hook.js +12 -15
- package/dist/codex-queue.d.ts +2 -2
- package/dist/codex-queue.js +7 -5
- package/dist/decisions.d.ts +2 -6
- package/dist/decisions.js +16 -17
- package/dist/delivery-health.d.ts +1 -2
- package/dist/delivery-health.js +4 -5
- package/dist/delivery-operations.d.ts +2 -5
- package/dist/delivery-operations.js +77 -214
- package/dist/delivery.d.ts +25 -47
- package/dist/delivery.js +14 -46
- package/dist/diagnostic-redaction.js +7 -9
- package/dist/file-changes.d.ts +0 -1
- package/dist/file-changes.js +2 -19
- package/dist/harness-claude.js +8 -6
- package/dist/harness-codex.d.ts +0 -2
- package/dist/harness-codex.js +0 -2
- package/dist/harness-links.js +13 -17
- package/dist/harness.js +3 -7
- package/dist/help.js +4 -3
- package/dist/host-ledger-file-adapter.d.ts +17 -8
- package/dist/host-ledger-file-adapter.js +164 -80
- package/dist/host-ledger.d.ts +55 -50
- package/dist/inbox.d.ts +0 -3
- package/dist/inbox.js +88 -50
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/list.js +1 -4
- package/dist/mcp.js +24 -41
- package/dist/mention-parse.js +3 -9
- package/dist/model.d.ts +11 -2
- package/dist/model.js +1 -1
- package/dist/notifications.d.ts +3 -16
- package/dist/notifications.js +41 -122
- package/dist/opencode-delivery.d.ts +14 -0
- package/dist/opencode-delivery.js +171 -0
- package/dist/opencode.d.ts +39 -18
- package/dist/opencode.js +145 -40
- package/dist/packages/agent-delivery/src/claude-auth.d.ts +13 -0
- package/dist/packages/agent-delivery/src/claude-auth.js +75 -0
- package/dist/packages/agent-delivery/src/claude-native.d.ts +28 -0
- package/dist/packages/agent-delivery/src/claude-native.js +68 -0
- package/dist/packages/agent-delivery/src/claude.d.ts +14 -0
- package/dist/packages/agent-delivery/src/claude.js +66 -0
- package/dist/packages/agent-delivery/src/deadline.d.ts +11 -0
- package/dist/packages/agent-delivery/src/deadline.js +41 -0
- package/dist/packages/agent-delivery/src/errors.d.ts +16 -0
- package/dist/packages/agent-delivery/src/errors.js +41 -0
- package/dist/packages/agent-delivery/src/guards.d.ts +6 -0
- package/dist/packages/agent-delivery/src/guards.js +6 -0
- package/dist/packages/agent-delivery/src/index.d.ts +83 -0
- package/dist/packages/agent-delivery/src/index.js +110 -0
- package/dist/packages/agent-delivery/src/local-endpoint.d.ts +26 -0
- package/dist/packages/agent-delivery/src/local-endpoint.js +114 -0
- package/dist/packages/agent-delivery/src/opencode-native.d.ts +33 -0
- package/dist/packages/agent-delivery/src/opencode-native.js +75 -0
- package/dist/packages/agent-delivery/src/opencode.d.ts +14 -0
- package/dist/packages/agent-delivery/src/opencode.js +127 -0
- package/dist/packages/agent-delivery/src/paseo-native.d.ts +58 -0
- package/dist/packages/agent-delivery/src/paseo-native.js +122 -0
- package/dist/packages/agent-delivery/src/paseo.d.ts +19 -0
- package/dist/packages/agent-delivery/src/paseo.js +106 -0
- package/dist/packages/agent-delivery/src/pi-client.d.ts +10 -0
- package/dist/packages/agent-delivery/src/pi-client.js +106 -0
- package/dist/packages/agent-delivery/src/pi-protocol.d.ts +15 -0
- package/dist/packages/agent-delivery/src/pi-protocol.js +50 -0
- package/dist/packages/agent-delivery/src/pi-send.d.ts +23 -0
- package/dist/packages/agent-delivery/src/pi-send.js +4 -0
- package/dist/packages/agent-delivery/src/pi.d.ts +25 -0
- package/dist/packages/agent-delivery/src/pi.js +209 -0
- package/dist/packages/agent-delivery/src/types.d.ts +120 -0
- package/dist/participant-host.js +12 -13
- package/dist/participant-identity.d.ts +21 -0
- package/dist/participant-identity.js +32 -11
- package/dist/paseo-delivery.d.ts +2 -2
- package/dist/paseo-delivery.js +35 -27
- package/dist/paseo-timeline.js +25 -21
- package/dist/paseo.d.ts +2 -2
- package/dist/paseo.js +1 -2
- package/dist/ports.d.ts +7 -20
- package/dist/presentation-operations.js +16 -4
- package/dist/presentation.d.ts +19 -10
- package/dist/presentation.js +99 -177
- package/dist/registry.d.ts +15 -66
- package/dist/registry.js +45 -123
- package/dist/routes.d.ts +1 -28
- package/dist/routes.js +22 -104
- package/dist/runtime.d.ts +3 -9
- package/dist/runtime.js +14 -67
- package/dist/search.d.ts +0 -2
- package/dist/search.js +3 -10
- package/dist/square-actions.js +48 -72
- package/dist/square-application.js +32 -30
- package/dist/square-core.d.ts +3 -0
- package/dist/square-core.js +22 -5
- package/dist/square-facade.d.ts +2 -0
- package/dist/square-file-adapter.d.ts +2 -1
- package/dist/square-file-adapter.js +6 -9
- package/dist/square-projections.d.ts +40 -45
- package/dist/square-projections.js +60 -74
- package/dist/square-state.js +1 -4
- package/dist/square-storage.d.ts +5 -8
- package/dist/square-storage.js +13 -36
- package/dist/square-wiring.d.ts +2 -7
- package/dist/square-wiring.js +6 -24
- package/dist/stream.js +4 -6
- package/dist/time.js +2 -7
- package/dist/views.d.ts +6 -18
- package/dist/views.js +14 -21
- package/dist/wake-attempts.d.ts +2 -56
- package/dist/wake-attempts.js +15 -110
- package/dist/wake-eligibility.d.ts +43 -0
- package/dist/wake-eligibility.js +106 -0
- package/dist/wake-evidence.d.ts +32 -9
- package/dist/wake-evidence.js +29 -24
- package/dist/wake-sink.d.ts +13 -9
- package/dist/wake-sink.js +35 -54
- package/dist/watch.js +13 -21
- package/extensions/square-pi.js +27 -13
- package/guides/change-waits.md +1 -1
- package/guides/claude-native.md +101 -0
- package/guides/host-ledger.md +3 -1
- package/guides/participant.md +14 -7
- package/guides/pi-native-delivery.md +49 -0
- package/package.json +4 -3
- package/dist/claude-hook.d.ts +0 -10
- package/dist/claude-hook.js +0 -60
- package/dist/paseo-connection.d.ts +0 -15
- package/dist/paseo-connection.js +0 -141
- package/dist/presence.d.ts +0 -2
- package/dist/presence.js +0 -24
- package/dist/presented.d.ts +0 -2
- package/dist/presented.js +0 -10
- package/dist/state-cell.d.ts +0 -14
- package/dist/wake-port.d.ts +0 -23
- package/dist/wake-port.js +0 -27
- /package/dist/{state-cell.js → packages/agent-delivery/src/types.js} +0 -0
package/dist/inbox.js
CHANGED
|
@@ -1,39 +1,42 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { nameKey } from './model.js';
|
|
2
2
|
import { openSquareArtifact, observeSquareChanges } from './square-file-adapter.js';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { formatActivityId } from './square-core.js';
|
|
3
|
+
import { hostLedgerForEnv } from './registry.js';
|
|
4
|
+
import { canonicalPath } from './canonical-path.js';
|
|
5
|
+
import { projectBoundaryEligibility, projectPresentation, projectSessionBindings } from './square-projections.js';
|
|
7
6
|
import { WATCH_STALE_MS } from './runtime.js';
|
|
8
|
-
export function hostLedgerForEnv(env) {
|
|
9
|
-
return createHostLedgerPort({ rootPath: hostLedgerRoot(env) });
|
|
10
|
-
}
|
|
11
7
|
function notificationKey(membership, actIndex) {
|
|
12
8
|
return membership.squarePath + '\0' + membership.name.toLocaleLowerCase() + '\0' + actIndex;
|
|
13
9
|
}
|
|
10
|
+
async function readInboxMembership(binding, signal) {
|
|
11
|
+
const artifact = openSquareArtifact(binding.location, signal);
|
|
12
|
+
try {
|
|
13
|
+
const projection = await projectPresentation({ artifact, binding, now: Date.now() });
|
|
14
|
+
if (!projection.joined)
|
|
15
|
+
return undefined;
|
|
16
|
+
return { name: projection.binding.participant, squarePath: projection.binding.location,
|
|
17
|
+
notifications: [...projection.notifications],
|
|
18
|
+
...(projection.catchLease === undefined ? {} : { catchLease: projection.catchLease }) };
|
|
19
|
+
}
|
|
20
|
+
finally {
|
|
21
|
+
await artifact.close();
|
|
22
|
+
}
|
|
23
|
+
}
|
|
14
24
|
export async function sessionInbox(sessionId, env = process.env, signal) {
|
|
15
25
|
const inbox = [];
|
|
16
26
|
const hostLedger = hostLedgerForEnv(env);
|
|
17
27
|
for (const binding of await projectSessionBindings({ hostLedger, sessionId })) {
|
|
18
28
|
if (signal?.aborted)
|
|
19
29
|
throw signal.reason;
|
|
20
|
-
const artifact = openSquareArtifact(binding.location, signal);
|
|
21
30
|
try {
|
|
22
|
-
const
|
|
23
|
-
if (
|
|
24
|
-
|
|
25
|
-
inbox.push({ name: projection.binding.participant, squarePath: projection.binding.location,
|
|
26
|
-
notifications: [...projection.notifications],
|
|
27
|
-
...(projection.catchLease === undefined ? {} : { catchLease: projection.catchLease }) });
|
|
31
|
+
const membership = await readInboxMembership(binding, signal);
|
|
32
|
+
if (membership !== undefined)
|
|
33
|
+
inbox.push(membership);
|
|
28
34
|
}
|
|
29
35
|
catch (error) {
|
|
30
36
|
if (signal?.aborted)
|
|
31
37
|
throw signal.reason ?? error;
|
|
32
38
|
// A stale or unreadable membership cannot disable delivery for other memberships.
|
|
33
39
|
}
|
|
34
|
-
finally {
|
|
35
|
-
await artifact.close();
|
|
36
|
-
}
|
|
37
40
|
}
|
|
38
41
|
return inbox;
|
|
39
42
|
}
|
|
@@ -41,13 +44,28 @@ async function capture(observer, kind, signal) {
|
|
|
41
44
|
const generation = observer.generation;
|
|
42
45
|
try {
|
|
43
46
|
const value = await observer.read(signal);
|
|
44
|
-
return { kind, wait: (timeout, abort) => observer.changed(value, timeout, abort) };
|
|
47
|
+
return { kind, value, wait: (timeout, abort) => observer.changed(value, timeout, abort) };
|
|
45
48
|
}
|
|
46
49
|
catch (error) {
|
|
47
50
|
if (signal.aborted)
|
|
48
51
|
throw signal.reason ?? error;
|
|
49
|
-
//
|
|
50
|
-
return { kind, wait: (timeout, abort) =>
|
|
52
|
+
// Failed revision reads are not changes; only a successful retry wakes projection.
|
|
53
|
+
return { kind, wait: async (timeout, abort) => {
|
|
54
|
+
const deadline = Date.now() + Math.max(0, timeout);
|
|
55
|
+
let since = generation;
|
|
56
|
+
while (await observer.hinted(since, Math.max(0, deadline - Date.now()), abort)) {
|
|
57
|
+
since = observer.generation;
|
|
58
|
+
try {
|
|
59
|
+
await observer.read(abort);
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
if (abort.aborted)
|
|
64
|
+
throw abort.reason ?? error;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return false;
|
|
68
|
+
} };
|
|
51
69
|
}
|
|
52
70
|
}
|
|
53
71
|
/** Session-scoped projection over process-shared storage change detectors. */
|
|
@@ -71,11 +89,11 @@ export async function observeSessionPending(sessionId, suppliedEnv = process.env
|
|
|
71
89
|
while (!signal.aborted) {
|
|
72
90
|
// Subscribe/capture the ledger BEFORE discovering bindings; a concurrent join cannot fall in a gap.
|
|
73
91
|
const sources = await Promise.all([capture(ledger.presence, 'presence', signal), capture(ledger.evidence, 'evidence', signal)]);
|
|
74
|
-
const bindings = await projectSessionBindings({ hostLedger, sessionId });
|
|
75
|
-
const paths = new Set(
|
|
76
|
-
for (const [file,
|
|
92
|
+
const bindings = await Promise.all((await projectSessionBindings({ hostLedger, sessionId })).map(async (binding) => ({ ...binding, location: await canonicalPath(binding.location) })));
|
|
93
|
+
const paths = new Set(bindings.map((binding) => binding.location));
|
|
94
|
+
for (const [file, entry] of artifacts) {
|
|
77
95
|
if (!paths.has(file)) {
|
|
78
|
-
observer.close();
|
|
96
|
+
entry.observer.close();
|
|
79
97
|
artifacts.delete(file);
|
|
80
98
|
}
|
|
81
99
|
}
|
|
@@ -87,22 +105,52 @@ export async function observeSessionPending(sessionId, suppliedEnv = process.env
|
|
|
87
105
|
observer.close();
|
|
88
106
|
return [];
|
|
89
107
|
}
|
|
90
|
-
artifacts.set(file, observer);
|
|
108
|
+
artifacts.set(file, { observer, inbox: new Map() });
|
|
91
109
|
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
110
|
+
for (const [file, entry] of artifacts) {
|
|
111
|
+
const source = await capture(entry.observer, 'artifact', signal);
|
|
112
|
+
sources.push(source);
|
|
113
|
+
if (source.value === undefined || source.value !== entry.revision)
|
|
114
|
+
entry.inbox.clear();
|
|
115
|
+
entry.revision = source.value;
|
|
116
|
+
const names = new Set(bindings.filter((binding) => binding.location === file).map((binding) => nameKey(binding.participant)));
|
|
117
|
+
for (const name of entry.inbox.keys())
|
|
118
|
+
if (!names.has(name))
|
|
119
|
+
entry.inbox.delete(name);
|
|
101
120
|
}
|
|
102
|
-
const
|
|
103
|
-
|
|
121
|
+
const inbox = [];
|
|
122
|
+
for (const binding of bindings) {
|
|
123
|
+
if (signal.aborted)
|
|
124
|
+
return [];
|
|
125
|
+
const entry = artifacts.get(binding.location);
|
|
126
|
+
const name = nameKey(binding.participant);
|
|
127
|
+
try {
|
|
128
|
+
if (!entry.inbox.has(name))
|
|
129
|
+
entry.inbox.set(name, await readInboxMembership(binding, signal));
|
|
130
|
+
const membership = entry.inbox.get(name);
|
|
131
|
+
if (membership === undefined)
|
|
132
|
+
continue;
|
|
133
|
+
const { catchLease, ...rest } = membership;
|
|
134
|
+
const now = Date.now();
|
|
135
|
+
inbox.push(catchLease !== undefined && catchLease.expiresAt > now && now - catchLease.heartbeatAt <= WATCH_STALE_MS
|
|
136
|
+
? membership : rest);
|
|
137
|
+
}
|
|
138
|
+
catch (error) {
|
|
139
|
+
if (signal.aborted)
|
|
140
|
+
throw signal.reason ?? error;
|
|
141
|
+
// Unreadable projections are retried, never cached as current.
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
const eligible = await projectBoundaryEligibility({ hostLedger, sessionId, inbox });
|
|
145
|
+
const excludeKeys = options.excludeKeys;
|
|
146
|
+
const pending = excludeKeys === undefined ? eligible : eligible.flatMap((membership) => {
|
|
147
|
+
const notifications = membership.notifications.filter((notification) => !excludeKeys.has(notificationKey(membership, notification.actIndex)));
|
|
148
|
+
return notifications.length === 0 ? [] : [{ ...membership, notifications }];
|
|
149
|
+
});
|
|
150
|
+
const eligibleKeys = JSON.stringify(pending.flatMap((membership) => membership.notifications.map((note) => notificationKey(membership, note.actIndex))).sort());
|
|
151
|
+
if (previousEligible !== undefined && previousEligible !== eligibleKeys)
|
|
104
152
|
canReturn = true;
|
|
105
|
-
previousEligible =
|
|
153
|
+
previousEligible = eligibleKeys;
|
|
106
154
|
if (signal.aborted)
|
|
107
155
|
return [];
|
|
108
156
|
if (canReturn && pending.length > 0)
|
|
@@ -161,19 +209,9 @@ export async function observeSessionPending(sessionId, suppliedEnv = process.env
|
|
|
161
209
|
lifetime.abort();
|
|
162
210
|
ledger.presence.close();
|
|
163
211
|
ledger.evidence.close();
|
|
164
|
-
for (const
|
|
165
|
-
observer.close();
|
|
212
|
+
for (const entry of artifacts.values())
|
|
213
|
+
entry.observer.close();
|
|
166
214
|
artifacts.clear();
|
|
167
215
|
},
|
|
168
216
|
};
|
|
169
217
|
}
|
|
170
|
-
/** Finite one-shot consumers retain their API; Pi owns a long-lived observer instead. */
|
|
171
|
-
export async function waitForSessionPending(sessionId, timeoutMs, options = {}, env = process.env) {
|
|
172
|
-
const observer = await observeSessionPending(sessionId, env);
|
|
173
|
-
try {
|
|
174
|
-
return await observer.wait(timeoutMs, options);
|
|
175
|
-
}
|
|
176
|
-
finally {
|
|
177
|
-
observer.close();
|
|
178
|
-
}
|
|
179
|
-
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { Square } from './square-wiring.js';
|
|
2
2
|
export { createSquareApplication } from './square-application.js';
|
|
3
3
|
export { SquareError } from './model.js';
|
|
4
|
-
export {
|
|
4
|
+
export { squareAssignedParticipantName } from './registry.js';
|
|
5
5
|
export { createDefaultWakeTransport } from './notifications.js';
|
|
6
6
|
export { createHostLedgerPort, FileHostLedgerPort } from './host-ledger-file-adapter.js';
|
|
7
7
|
export type { HostLedgerPort, PresenceRecord, EvidenceRecord } from './host-ledger.js';
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { Square } from './square-wiring.js';
|
|
2
2
|
export { createSquareApplication } from './square-application.js';
|
|
3
3
|
export { SquareError } from './model.js';
|
|
4
|
-
export {
|
|
4
|
+
export { squareAssignedParticipantName } from './registry.js';
|
|
5
5
|
export { createDefaultWakeTransport } from './notifications.js';
|
|
6
6
|
export { createHostLedgerPort, FileHostLedgerPort } from './host-ledger-file-adapter.js';
|
package/dist/list.js
CHANGED
|
@@ -15,9 +15,6 @@ const CONTEXT_PREVIEW_LINES = 2;
|
|
|
15
15
|
const PARTICIPANT_PREVIEW_COUNT = 3;
|
|
16
16
|
const DISPLAY_CHARACTER_LIMIT = 160;
|
|
17
17
|
const LIST_SKIP_DIRS = new Set(['.git', 'node_modules', 'dist']);
|
|
18
|
-
function contextLines(lines) {
|
|
19
|
-
return lines.map((line) => line.trim()).filter(Boolean);
|
|
20
|
-
}
|
|
21
18
|
async function readSquareListItem(filePath, root) {
|
|
22
19
|
let stat;
|
|
23
20
|
try {
|
|
@@ -34,7 +31,7 @@ async function readSquareListItem(filePath, root) {
|
|
|
34
31
|
return {
|
|
35
32
|
path: relative,
|
|
36
33
|
lastActiveAt: stat.mtimeMs,
|
|
37
|
-
context:
|
|
34
|
+
context: [...projection.context].map((line) => line.trim()).filter(Boolean),
|
|
38
35
|
participants: [...projection.participants],
|
|
39
36
|
activities: projection.activities,
|
|
40
37
|
};
|
package/dist/mcp.js
CHANGED
|
@@ -3,45 +3,23 @@ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'
|
|
|
3
3
|
import { z } from 'zod/v4';
|
|
4
4
|
import { SquareError, isSquareError } from './model.js';
|
|
5
5
|
import { createSquareApplication } from './square-application.js';
|
|
6
|
-
|
|
7
|
-
const
|
|
8
|
-
|
|
6
|
+
import { toPublicActivity } from './views.js';
|
|
7
|
+
const activityId = z.string().regex(/^act\/(0|[1-9][0-9]*)$/);
|
|
8
|
+
const stringArray = z.array(z.string());
|
|
9
9
|
const TOOL_DEFINITIONS = [
|
|
10
|
-
{ name: 'join', description: 'Join the square as the configured participant.', inputSchema:
|
|
11
|
-
{ name: 'express', description: 'Express a message or embodied action in the square.', inputSchema:
|
|
12
|
-
{ name: 'catch', description: 'Catch and consume activities perceptible to the configured participant.', inputSchema:
|
|
13
|
-
{ name: 'history', description: 'Read the activity stream using stable activity-id cursors.', inputSchema:
|
|
14
|
-
{ name: 'listen', description: 'Listen for future activity from a participant.', inputSchema:
|
|
15
|
-
{ name: 'ignore', description: 'Stop listening for future activity from a participant.', inputSchema:
|
|
16
|
-
{ name: 'listening', description: 'List participants this participant is listening to.', inputSchema:
|
|
17
|
-
{ name: 'hold', description: 'Raise a hand to hold the square.', inputSchema:
|
|
18
|
-
{ name: 'resume', description: 'Release the current hold.', inputSchema:
|
|
19
|
-
{ name: 'done', description: 'Leave the square without adding a message.', inputSchema:
|
|
20
|
-
{ name: 'status', description: 'Read the public status of the square.', inputSchema:
|
|
21
|
-
{ name: 'participants', description: 'List participants standing in or done with the square.', inputSchema:
|
|
10
|
+
{ name: 'join', description: 'Join the square as the configured participant.', inputSchema: z.object({ takeover: z.boolean().optional() }).strict() },
|
|
11
|
+
{ name: 'express', description: 'Express a message or embodied action in the square.', inputSchema: z.object({ body: z.string(), mentions: stringArray.optional(), reach: z.enum(['bell']).optional(), reply: activityId.optional(), force: z.boolean().optional(), noWait: z.boolean().optional() }).strict() },
|
|
12
|
+
{ name: 'catch', description: 'Catch and consume activities perceptible to the configured participant.', inputSchema: z.object({ id: activityId.optional(), idle: z.number().finite().min(0).optional(), from: stringArray.optional(), mention: z.boolean().optional(), limit: z.number().int().min(1).optional() }).strict() },
|
|
13
|
+
{ name: 'history', description: 'Read the activity stream using stable activity-id cursors.', inputSchema: z.object({ limit: z.number().int().min(1).optional(), order: z.enum(['asc', 'desc']).optional(), before: activityId.optional(), after: activityId.optional(), grep: z.string().optional(), fixed: z.string().optional(), from: stringArray.optional(), mention: z.string().optional() }).strict() },
|
|
14
|
+
{ name: 'listen', description: 'Listen for future activity from a participant.', inputSchema: z.object({ target: z.string() }).strict() },
|
|
15
|
+
{ name: 'ignore', description: 'Stop listening for future activity from a participant.', inputSchema: z.object({ target: z.string() }).strict() },
|
|
16
|
+
{ name: 'listening', description: 'List participants this participant is listening to.', inputSchema: z.object({}).strict() },
|
|
17
|
+
{ name: 'hold', description: 'Raise a hand to hold the square.', inputSchema: z.object({ reason: z.string().optional() }).strict() },
|
|
18
|
+
{ name: 'resume', description: 'Release the current hold.', inputSchema: z.object({}).strict() },
|
|
19
|
+
{ name: 'done', description: 'Leave the square without adding a message.', inputSchema: z.object({}).strict() },
|
|
20
|
+
{ name: 'status', description: 'Read the public status of the square.', inputSchema: z.object({}).strict() },
|
|
21
|
+
{ name: 'participants', description: 'List participants standing in or done with the square.', inputSchema: z.object({}).strict() },
|
|
22
22
|
];
|
|
23
|
-
function zodInputSchema(schema) {
|
|
24
|
-
const shape = {};
|
|
25
|
-
for (const [key, property] of Object.entries(schema.properties)) {
|
|
26
|
-
let field;
|
|
27
|
-
if (property.type === 'string' && property.enum !== undefined)
|
|
28
|
-
field = z.enum(property.enum);
|
|
29
|
-
else if (property.type === 'string')
|
|
30
|
-
field = property.pattern === undefined ? z.string() : z.string().regex(new RegExp(property.pattern));
|
|
31
|
-
else if (property.type === 'boolean')
|
|
32
|
-
field = z.boolean();
|
|
33
|
-
else if (property.type === 'number')
|
|
34
|
-
field = z.number().finite().min(property.minimum ?? -Infinity);
|
|
35
|
-
else if (property.type === 'integer')
|
|
36
|
-
field = z.number().int().min(property.minimum ?? -Infinity);
|
|
37
|
-
else if (property.type === 'array')
|
|
38
|
-
field = z.array(z.string());
|
|
39
|
-
else
|
|
40
|
-
throw new Error(`Unsupported input schema type: ${property.type}`);
|
|
41
|
-
shape[key] = schema.required.includes(key) ? field : field.optional();
|
|
42
|
-
}
|
|
43
|
-
return z.object(shape).strict();
|
|
44
|
-
}
|
|
45
23
|
function isObject(value) { return value !== null && typeof value === 'object' && !Array.isArray(value); }
|
|
46
24
|
function publicActivity(activity) { return { ...activity }; }
|
|
47
25
|
function publicResult(name, value) {
|
|
@@ -56,13 +34,13 @@ function publicResult(name, value) {
|
|
|
56
34
|
doneCount: rest.doneCount,
|
|
57
35
|
hold: rest.holdActive ? { by: rest.holdActor, ...(rest.holdReason === undefined ? {} : { reason: rest.holdReason }), ...(rest.holdAt === undefined ? {} : { at: rest.holdAt }) } : null,
|
|
58
36
|
participants: participants.filter((participant) => participant.state !== 'not joined').map((participant) => ({ name: participant.name, state: participant.state, presence: participant.presence, activityCount: participant.activityCount, ...(participant.lastActiveAt === undefined ? {} : { lastActiveAt: participant.lastActiveAt }), unreadActivityCount: participant.unreadActivityCount, pendingMentionCount: participant.pendingMentionCount, listening: participant.listening })),
|
|
59
|
-
...(latestAct === undefined ? {} : { latestActivity: publicActivity(
|
|
37
|
+
...(latestAct === undefined ? {} : { latestActivity: publicActivity(toPublicActivity(latestAct)) }),
|
|
60
38
|
now: rest.now,
|
|
61
39
|
};
|
|
62
40
|
}
|
|
63
41
|
if (name === 'express' || name === 'hold' || name === 'resume' || name === 'done') {
|
|
64
42
|
const result = value;
|
|
65
|
-
return { ...(result.activity === undefined ? {} : { activity: result.activity === null ? null : publicActivity(result.activity) }), ...(result.waited === undefined ? {} : { waited: result.waited }) };
|
|
43
|
+
return { ...(result.activity === undefined ? {} : { activity: result.activity === null ? null : publicActivity(result.activity) }), ...(result.waited === undefined ? {} : { waited: result.waited }), ...(result.replyAuthorNotHere === undefined ? {} : { replyAuthorNotHere: result.replyAuthorNotHere }) };
|
|
66
44
|
}
|
|
67
45
|
if (name === 'history')
|
|
68
46
|
return { activities: value };
|
|
@@ -98,7 +76,7 @@ export function createSquareMcpServer(options) {
|
|
|
98
76
|
instructions: 'The catch tool consumes activities. Use history with act/<index> cursors for read-only archive access.',
|
|
99
77
|
});
|
|
100
78
|
for (const tool of TOOL_DEFINITIONS) {
|
|
101
|
-
server.registerTool(tool.name, { description: tool.description, inputSchema:
|
|
79
|
+
server.registerTool(tool.name, { description: tool.description, inputSchema: tool.inputSchema }, async (args, extra) => {
|
|
102
80
|
try {
|
|
103
81
|
const value = await operation(app, tool.name, args, { signal: extra.signal });
|
|
104
82
|
const projected = publicResult(tool.name, value);
|
|
@@ -118,5 +96,10 @@ export function createSquareMcpServer(options) {
|
|
|
118
96
|
return server;
|
|
119
97
|
}
|
|
120
98
|
export async function runSquareMcpStdio(options) {
|
|
121
|
-
|
|
99
|
+
const server = createSquareMcpServer(options);
|
|
100
|
+
const transport = new StdioServerTransport();
|
|
101
|
+
const close = () => { void server.close(); };
|
|
102
|
+
process.stdin.once('end', close);
|
|
103
|
+
process.stdin.once('close', close);
|
|
104
|
+
await server.connect(transport);
|
|
122
105
|
}
|
package/dist/mention-parse.js
CHANGED
|
@@ -54,14 +54,6 @@ function codeSpanRanges(body) {
|
|
|
54
54
|
}
|
|
55
55
|
return ranges;
|
|
56
56
|
}
|
|
57
|
-
function codePointBefore(body, index) {
|
|
58
|
-
if (index <= 0)
|
|
59
|
-
return undefined;
|
|
60
|
-
const unit = body.charCodeAt(index - 1);
|
|
61
|
-
if (unit >= 0xdc00 && unit <= 0xdfff && index >= 2)
|
|
62
|
-
return String.fromCodePoint(body.codePointAt(index - 2));
|
|
63
|
-
return String.fromCodePoint(unit);
|
|
64
|
-
}
|
|
65
57
|
export function scanMentionCandidates(body) {
|
|
66
58
|
const spans = codeSpanRanges(body);
|
|
67
59
|
const found = [];
|
|
@@ -70,7 +62,9 @@ export function scanMentionCandidates(body) {
|
|
|
70
62
|
const start = match.index;
|
|
71
63
|
if (spans.some(([from, to]) => start >= from && start < to))
|
|
72
64
|
continue;
|
|
73
|
-
const
|
|
65
|
+
const unit = start <= 0 ? undefined : body.charCodeAt(start - 1);
|
|
66
|
+
const previous = unit === undefined ? undefined
|
|
67
|
+
: unit >= 0xdc00 && unit <= 0xdfff && start >= 2 ? String.fromCodePoint(body.codePointAt(start - 2)) : String.fromCodePoint(unit);
|
|
74
68
|
if (previous !== undefined && BOUNDARY_BLOCKER.test(previous))
|
|
75
69
|
continue;
|
|
76
70
|
const token = match[1];
|
package/dist/model.d.ts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import type { Act, ActivityId } from './square-core.js';
|
|
2
2
|
export { formatActivityId, parseActivityId } from './square-core.js';
|
|
3
3
|
export type { Act, ActivityId, Audience, Reach } from './square-core.js';
|
|
4
|
-
export declare const WAKE_ROUTE_KINDS: readonly ["opencode-server", "codex-queue", "claude-native", "
|
|
4
|
+
export declare const WAKE_ROUTE_KINDS: readonly ["opencode-server", "codex-queue", "claude-native", "paseo"];
|
|
5
5
|
export type WakeRouteKind = typeof WAKE_ROUTE_KINDS[number];
|
|
6
6
|
export declare function isWakeRouteKind(value: unknown): value is WakeRouteKind;
|
|
7
7
|
export interface WakeRoute {
|
|
8
|
+
/** Ownership generation, when the receiver publishes a fenced route. */
|
|
9
|
+
epoch?: number;
|
|
8
10
|
location: string;
|
|
9
11
|
participant: string;
|
|
10
12
|
sessionId: string;
|
|
@@ -20,6 +22,13 @@ export type InternalSquareErrorCode = SquareErrorCode | 'not_found' | 'cap_reach
|
|
|
20
22
|
export interface SquareErrorFacts {
|
|
21
23
|
/** Express admission rejected before any activity was committed. */
|
|
22
24
|
activityUnsent?: true;
|
|
25
|
+
/** Why a name could not be resolved: never in the roster, no longer standing in it, a bell
|
|
26
|
+
* colliding with a mention, an @name that matches nobody, or an activity catch cannot address. */
|
|
27
|
+
reason?: 'never_joined' | 'not_standing' | 'bell_mention_conflict' | 'unmatched_mention' | 'not_addressed';
|
|
28
|
+
/** The activity id a `catch --id` refusal named. */
|
|
29
|
+
activityId?: string;
|
|
30
|
+
/** Whether the artifact holds that activity at all; an unknown id needs an ordinary page. */
|
|
31
|
+
activityExists?: boolean;
|
|
23
32
|
pending?: number;
|
|
24
33
|
holder?: string;
|
|
25
34
|
holdReason?: string;
|
|
@@ -62,7 +71,7 @@ export interface WatchLease {
|
|
|
62
71
|
expiresAt: number;
|
|
63
72
|
filter?: WatchLeaseFilter;
|
|
64
73
|
}
|
|
65
|
-
export type DirectedNotificationRoute = 'mention' | 'attention' | 'bell';
|
|
74
|
+
export type DirectedNotificationRoute = 'mention' | 'reply' | 'attention' | 'bell';
|
|
66
75
|
export interface InboxNotification {
|
|
67
76
|
actIndex: number;
|
|
68
77
|
actor: string;
|
package/dist/model.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Shared model and constants for Square.
|
|
2
2
|
export { formatActivityId, parseActivityId } from './square-core.js';
|
|
3
|
-
export const WAKE_ROUTE_KINDS = ['opencode-server', 'codex-queue', 'claude-native', '
|
|
3
|
+
export const WAKE_ROUTE_KINDS = ['opencode-server', 'codex-queue', 'claude-native', 'paseo'];
|
|
4
4
|
export function isWakeRouteKind(value) {
|
|
5
5
|
return typeof value === 'string' && WAKE_ROUTE_KINDS.includes(value);
|
|
6
6
|
}
|
package/dist/notifications.d.ts
CHANGED
|
@@ -1,27 +1,16 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { type SquareState } from './model.js';
|
|
3
|
-
import { matchesMentionTarget } from './runtime.js';
|
|
4
|
-
import { type ActivityId } from './square-core.js';
|
|
1
|
+
import { type WakeAdapter } from './delivery.js';
|
|
5
2
|
import type { WakeTransportPort } from './ports.js';
|
|
6
3
|
export type { PlannedNotification } from './delivery.js';
|
|
7
|
-
export { planActNotifications, matchesMentionTarget };
|
|
8
|
-
export { notificationMessageId } from './delivery.js';
|
|
9
4
|
export declare const PRIVILEGED_HOOK_BUDGET_MS = 3000;
|
|
10
5
|
export declare function wakeGraceMs(env?: NodeJS.ProcessEnv): number;
|
|
11
|
-
export declare function hasDeliveredNotification(squarePath: string, name: string, ref: number | ActivityId): Promise<boolean>;
|
|
12
|
-
export declare function hasAttentionNotification(squarePath: string, name: string, ref: number | ActivityId, env?: NodeJS.ProcessEnv): Promise<boolean>;
|
|
13
|
-
export declare function waitForDeliveredNotification(squarePath: string, name: string, ref: number | ActivityId, opts?: {
|
|
14
|
-
timeoutMs?: number;
|
|
15
|
-
signal?: AbortSignal;
|
|
16
|
-
}): Promise<boolean>;
|
|
17
6
|
interface ProcessNotificationOptions {
|
|
18
7
|
adapters?: WakeAdapter[];
|
|
19
8
|
env?: NodeJS.ProcessEnv;
|
|
20
9
|
now?: () => number;
|
|
21
10
|
}
|
|
22
11
|
export declare function defaultWakeAdapters(): Promise<WakeAdapter[]>;
|
|
23
|
-
export declare function createDefaultWakeTransport(hostLedger: import('./host-ledger.js').HostLedgerPort, clock: () => number, env?: NodeJS.ProcessEnv): Promise<WakeTransportPort>;
|
|
24
|
-
export declare function createWakeTransport(adapters: readonly WakeAdapter[], hostLedger: import('./host-ledger.js').HostLedgerPort, clock: () => number): WakeTransportPort;
|
|
12
|
+
export declare function createDefaultWakeTransport(hostLedger: import('./host-ledger.js').HostLedgerPort, clock: () => number, env?: NodeJS.ProcessEnv, suppliedAdapters?: readonly WakeAdapter[]): Promise<WakeTransportPort>;
|
|
13
|
+
export declare function createWakeTransport(adapters: readonly WakeAdapter[], hostLedger: import('./host-ledger.js').HostLedgerPort, clock: () => number, nativePorts?: Readonly<Partial<Record<import('./model.js').WakeRouteKind, WakeTransportPort>>>): WakeTransportPort;
|
|
25
14
|
export declare function processActNotificationsOnce(squarePath: string, actIndex: number, opts?: ProcessNotificationOptions): Promise<import("./ports.js").DeliveryResult>;
|
|
26
15
|
/** Privileged hook fallback: sweep indexed squares plus the current cwd's local squares within one boundary budget. */
|
|
27
16
|
export declare function sweepPrivilegedPending(cwd: string, env?: NodeJS.ProcessEnv, suppliedAdapters?: WakeAdapter[], deadline?: number, signal?: AbortSignal): Promise<void>;
|
|
@@ -31,7 +20,5 @@ export interface SweepPendingNotificationsOptions {
|
|
|
31
20
|
limit?: number;
|
|
32
21
|
dispatchCandidate?: (actIndex: number) => void | Promise<void>;
|
|
33
22
|
}
|
|
34
|
-
/** Select sweep candidates from one frozen snapshot and one delivery replay. */
|
|
35
|
-
export declare function pendingNotificationSweepFromState(squarePath: string, state: SquareState, now: number, env: NodeJS.ProcessEnv, limit: number, deriveDelivery?: (snapshot: import('./model.js').SquareState) => ReturnType<typeof import('./delivery.js').deriveDeliveryModel>): Promise<number[]>;
|
|
36
23
|
/** Select old pending attention at a bounded action boundary for an explicit executor. */
|
|
37
24
|
export declare function sweepPendingNotifications(squarePath: string, opts?: SweepPendingNotificationsOptions): Promise<number[]>;
|