@astrosheep/square 0.3.61 → 0.3.62
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 +1 -1
- package/claude-plugin/skills/square/SKILL.md +5 -7
- package/codex-plugin/.codex-plugin/plugin.json +1 -1
- package/dist/activity.d.ts +6 -2
- package/dist/activity.js +168 -133
- package/dist/artifact.d.ts +4 -0
- package/dist/artifact.js +43 -14
- package/dist/attention-presentation.d.ts +1 -0
- package/dist/attention-presentation.js +8 -6
- package/dist/automatic-session.js +14 -24
- package/dist/boundary-presentation.d.ts +1 -2
- package/dist/boundary-presentation.js +4 -19
- package/dist/cli/context.d.ts +2 -0
- package/dist/cli/context.js +2 -18
- package/dist/cli/harness-command.js +1 -1
- package/dist/cli/mcp-server-command.d.ts +2 -0
- package/dist/cli/mcp-server-command.js +13 -0
- package/dist/cli/observation-commands.js +47 -19
- package/dist/cli/program.js +5 -2
- package/dist/cli/registry.js +2 -0
- package/dist/cli/square-commands.d.ts +1 -1
- package/dist/cli/square-commands.js +93 -125
- package/dist/decisions.d.ts +2 -0
- package/dist/decisions.js +44 -3
- package/dist/delivery-operations.d.ts +1 -2
- package/dist/delivery-operations.js +1 -4
- package/dist/file-changes.d.ts +12 -0
- package/dist/file-changes.js +235 -0
- package/dist/help.js +4 -8
- package/dist/host-ledger-file-adapter.d.ts +15 -13
- package/dist/host-ledger-file-adapter.js +131 -79
- package/dist/host-ledger-root.d.ts +2 -0
- package/dist/host-ledger-root.js +9 -0
- package/dist/host-ledger.d.ts +4 -24
- package/dist/inbox.d.ts +10 -5
- package/dist/inbox.js +152 -67
- package/dist/index.d.ts +3 -1
- package/dist/index.js +1 -0
- package/dist/mcp.d.ts +7 -0
- package/dist/mcp.js +122 -0
- package/dist/mention-parse.d.ts +8 -0
- package/dist/mention-parse.js +107 -0
- package/dist/model.d.ts +5 -0
- package/dist/model.js +4 -1
- package/dist/notifications.d.ts +1 -0
- package/dist/notifications.js +25 -20
- package/dist/participant-host.js +2 -2
- package/dist/ports.d.ts +2 -9
- package/dist/presentation.d.ts +12 -1
- package/dist/presentation.js +42 -12
- package/dist/presented.js +2 -1
- package/dist/registry.d.ts +8 -4
- package/dist/registry.js +41 -74
- package/dist/routes.d.ts +19 -2
- package/dist/routes.js +48 -5
- package/dist/runtime.d.ts +2 -0
- package/dist/runtime.js +2 -0
- package/dist/square-actions.d.ts +26 -13
- package/dist/square-actions.js +200 -84
- package/dist/square-application.d.ts +58 -0
- package/dist/square-application.js +183 -0
- package/dist/square-facade.d.ts +24 -9
- package/dist/square-file-adapter.d.ts +5 -12
- package/dist/square-file-adapter.js +12 -64
- package/dist/square-projections.d.ts +3 -2
- package/dist/square-projections.js +12 -3
- package/dist/square-storage.js +27 -34
- package/dist/square-wiring.d.ts +12 -7
- package/dist/square-wiring.js +36 -32
- package/dist/state-cell.d.ts +1 -1
- package/dist/stream.js +30 -26
- package/dist/views.d.ts +3 -3
- package/dist/views.js +4 -4
- package/dist/wake-attempts.js +2 -1
- package/dist/wake-evidence.js +2 -8
- package/dist/wakes.d.ts +1 -0
- package/dist/wakes.js +5 -5
- package/dist/watch.d.ts +6 -1
- package/dist/watch.js +20 -18
- package/extensions/square-pi.js +100 -112
- package/guides/application-boundary.md +32 -0
- package/guides/change-waits.md +28 -0
- package/guides/host-ledger.md +9 -0
- package/guides/mcp.md +9 -0
- package/guides/operation-cancellation.md +17 -0
- package/package.json +8 -2
- package/skills/square/SKILL.md +5 -7
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import type { InboxMembership } from './model.js';
|
|
2
|
-
|
|
3
|
-
export declare function pendingAtBoundary(inbox: InboxMembership[]): InboxMembership[];
|
|
2
|
+
export { pendingAtBoundary } from './square-projections.js';
|
|
4
3
|
export declare function renderPendingAtBoundary(inbox: InboxMembership[]): string;
|
|
5
4
|
/** Serialize a boundary across hook processes so one stale inbox cannot render twice. */
|
|
6
5
|
export declare function presentPendingAtBoundary<T>(sessionId: string, present: (context: string) => T | Promise<T>, lookup?: (sessionId: string, env?: NodeJS.ProcessEnv, signal?: AbortSignal) => Promise<InboxMembership[]> | InboxMembership[], env?: NodeJS.ProcessEnv, signal?: AbortSignal): Promise<T | undefined>;
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
+
import { hostLedgerRoot } from './host-ledger-root.js';
|
|
1
2
|
import { createHash } from 'node:crypto';
|
|
2
|
-
import os from 'node:os';
|
|
3
3
|
import path from 'node:path';
|
|
4
|
-
import { leaseOwnsNotification } from './delivery.js';
|
|
5
4
|
import { withFileLock } from './file-lock.js';
|
|
6
5
|
import { openSquare } from './square-file-adapter.js';
|
|
7
6
|
import { closeOpenSquare } from './open-square.js';
|
|
8
7
|
import { presentPending } from './presentation-operations.js';
|
|
9
8
|
import { hostLedgerForEnv, sessionInbox } from './inbox.js';
|
|
10
9
|
import { attentionBodyIsClipped, renderAttentionPreview } from './attention-presentation.js';
|
|
11
|
-
import { presentationSuppressesWake, projectPresentationEvidence } from './square-projections.js';
|
|
10
|
+
import { pendingAtBoundary, presentationSuppressesWake, projectPresentationEvidence } from './square-projections.js';
|
|
11
|
+
export { pendingAtBoundary } from './square-projections.js';
|
|
12
12
|
import { formatActivityId } from './square-core.js';
|
|
13
13
|
const CONTEXT_MAX = 1200;
|
|
14
14
|
const presentationLocks = new Map();
|
|
@@ -38,20 +38,6 @@ async function awaitWithSignal(promise, signal) {
|
|
|
38
38
|
function pendingCount(inbox) {
|
|
39
39
|
return inbox.reduce((total, membership) => total + membership.notifications.length, 0);
|
|
40
40
|
}
|
|
41
|
-
/** A fresh blocking catch owns only the notifications admitted by its filter. */
|
|
42
|
-
export function pendingAtBoundary(inbox) {
|
|
43
|
-
return inbox
|
|
44
|
-
.map((membership) => {
|
|
45
|
-
const lease = membership.catchLease;
|
|
46
|
-
if (lease === undefined)
|
|
47
|
-
return membership;
|
|
48
|
-
return {
|
|
49
|
-
...membership,
|
|
50
|
-
notifications: membership.notifications.filter((notification) => !leaseOwnsNotification(lease, { ...notification, recipient: membership.name })),
|
|
51
|
-
};
|
|
52
|
-
})
|
|
53
|
-
.filter((membership) => membership.notifications.length > 0);
|
|
54
|
-
}
|
|
55
41
|
export function renderPendingAtBoundary(inbox) {
|
|
56
42
|
return renderBoundary(inbox).context;
|
|
57
43
|
}
|
|
@@ -165,8 +151,7 @@ async function presentPendingAtBoundaryUnlocked(sessionId, present, lookup = ses
|
|
|
165
151
|
}
|
|
166
152
|
/** Serialize a boundary across hook processes so one stale inbox cannot render twice. */
|
|
167
153
|
export async function presentPendingAtBoundary(sessionId, present, lookup = sessionInbox, env = process.env, signal) {
|
|
168
|
-
const ledgerRoot = env
|
|
169
|
-
?? (env.SQUARE_REGISTRY === undefined ? path.join(os.homedir(), '.square', 'host-ledger') : path.dirname(env.SQUARE_REGISTRY));
|
|
154
|
+
const ledgerRoot = hostLedgerRoot(env);
|
|
170
155
|
const ownerKey = createHash('sha256').update(sessionId).digest('hex');
|
|
171
156
|
return withFileLock(path.join(ledgerRoot, `presentation-boundary-${ownerKey}.lock`), { retryMs: 10, signal }, () => presentPendingAtBoundaryUnlocked(sessionId, present, lookup, env, signal));
|
|
172
157
|
}
|
package/dist/cli/context.d.ts
CHANGED
package/dist/cli/context.js
CHANGED
|
@@ -113,6 +113,7 @@ const LOCATION_REQUIRED_COMMANDS = new Set([
|
|
|
113
113
|
'history',
|
|
114
114
|
'status',
|
|
115
115
|
'participants',
|
|
116
|
+
'mcp-server',
|
|
116
117
|
'doctor',
|
|
117
118
|
]);
|
|
118
119
|
function configuredLocation() {
|
|
@@ -126,22 +127,10 @@ function configuredName() {
|
|
|
126
127
|
validateName(value);
|
|
127
128
|
return value;
|
|
128
129
|
}
|
|
129
|
-
function withoutAsCommand(rawArgs) {
|
|
130
|
-
const args = [];
|
|
131
|
-
for (let index = 0; index < rawArgs.length; index++) {
|
|
132
|
-
if (rawArgs[index] === '--as') {
|
|
133
|
-
index += 1;
|
|
134
|
-
continue;
|
|
135
|
-
}
|
|
136
|
-
args.push(rawArgs[index]);
|
|
137
|
-
}
|
|
138
|
-
return `square ${args.map((arg) => /^[A-Za-z0-9_./:=@+,-]+$/.test(arg) ? arg : `'${arg.replace(/'/g, "'\\''")}'`).join(' ')}`;
|
|
139
|
-
}
|
|
140
130
|
export async function parseGlobalArgs(rawArgs) {
|
|
141
131
|
const args = [...rawArgs];
|
|
142
132
|
let requestedPath;
|
|
143
133
|
let name;
|
|
144
|
-
let hasExplicitName = false;
|
|
145
134
|
for (let index = 0; index < args.length; index++) {
|
|
146
135
|
if (args[index] === '--location') {
|
|
147
136
|
requestedPath = requireValue(args, index, args[index]);
|
|
@@ -150,15 +139,11 @@ export async function parseGlobalArgs(rawArgs) {
|
|
|
150
139
|
}
|
|
151
140
|
else if (args[index] === '--as') {
|
|
152
141
|
name = requireValue(args, index, args[index]);
|
|
153
|
-
hasExplicitName = true;
|
|
154
142
|
args.splice(index, 2);
|
|
155
143
|
index -= 1;
|
|
156
144
|
}
|
|
157
145
|
}
|
|
158
146
|
const command = args[0];
|
|
159
|
-
if (command === 'history' && hasExplicitName) {
|
|
160
|
-
fail(`✕ history is an archive and does not use --as\n${withoutAsCommand(rawArgs)}`);
|
|
161
|
-
}
|
|
162
147
|
if (name === undefined)
|
|
163
148
|
name = configuredName();
|
|
164
149
|
if (name !== undefined)
|
|
@@ -174,7 +159,6 @@ export async function parseGlobalArgs(rawArgs) {
|
|
|
174
159
|
hostLedger: createHostLedgerPort(),
|
|
175
160
|
location: squarePath,
|
|
176
161
|
sessionId,
|
|
177
|
-
scopes: ['user', 'local'],
|
|
178
162
|
})))).flat();
|
|
179
163
|
const names = new Set(bindings.map((binding) => binding.participant));
|
|
180
164
|
name = names.size === 1 ? [...names][0] : undefined;
|
|
@@ -185,7 +169,7 @@ export function locationIsRequired(command) {
|
|
|
185
169
|
return LOCATION_REQUIRED_COMMANDS.has(command);
|
|
186
170
|
}
|
|
187
171
|
export function defaultContext(command, squarePath, name) {
|
|
188
|
-
return { command, squarePath, name, homeDir: os.homedir() };
|
|
172
|
+
return { command, cwd: process.cwd(), env: { ...process.env }, squarePath, name, homeDir: os.homedir() };
|
|
189
173
|
}
|
|
190
174
|
export function requireSquarePath(context) {
|
|
191
175
|
if (context.squarePath === undefined)
|
|
@@ -102,7 +102,7 @@ export function formatHarnessResult(result) {
|
|
|
102
102
|
return `${[...result.notes, ...result.lines, ...result.failures].join('\n')}\n`;
|
|
103
103
|
}
|
|
104
104
|
export function runHarnessCommand(argv, squarePath) {
|
|
105
|
-
const context = { homeDir: os.homedir(), ...(squarePath === undefined ? {} : { squarePath }), command: 'harness' };
|
|
105
|
+
const context = { cwd: process.cwd(), env: { ...process.env }, homeDir: os.homedir(), ...(squarePath === undefined ? {} : { squarePath }), command: 'harness' };
|
|
106
106
|
const intent = harnessCommand.parse(argv, context);
|
|
107
107
|
return Promise.resolve(harnessCommand.execute(intent, context)).then(formatHarnessResult);
|
|
108
108
|
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { fail } from './context.js';
|
|
2
|
+
export const mcpServerCommand = {
|
|
3
|
+
parse(argv) {
|
|
4
|
+
if (argv.length > 0)
|
|
5
|
+
fail('Usage: square [--location <square>] [--as <name>] mcp-server');
|
|
6
|
+
return undefined;
|
|
7
|
+
},
|
|
8
|
+
async execute(_intent, context) {
|
|
9
|
+
const { runSquareMcpStdio } = await import('../mcp.js');
|
|
10
|
+
await runSquareMcpStdio({ cwd: context.cwd, env: context.env, squarePath: context.squarePath, participant: context.name });
|
|
11
|
+
},
|
|
12
|
+
present() { },
|
|
13
|
+
};
|
|
@@ -12,7 +12,9 @@ import { formatRelativeTime, formatTimestamp, parseTimeOrRelative } from '../tim
|
|
|
12
12
|
import { cmdWatch } from '../watch.js';
|
|
13
13
|
import { openSquare } from '../square-file-adapter.js';
|
|
14
14
|
import { closeOpenSquare } from '../open-square.js';
|
|
15
|
-
import {
|
|
15
|
+
import { createSquareApplication } from '../square-application.js';
|
|
16
|
+
import { historyPresentation } from '../views.js';
|
|
17
|
+
import { hostLedgerForEnv } from '../registry.js';
|
|
16
18
|
import { fail, parseBoundedLimit, parseDurationMs, parseNameList, parseNonNegativeInteger, readStdin, requireParticipant, requireSquarePath, requireValue, usage, } from './context.js';
|
|
17
19
|
import { CATCH_DEFAULT_LIMIT, CATCH_MAX_LIMIT } from '../catch-decisions.js';
|
|
18
20
|
const STATUS_PARTICIPANT_PREVIEW_LIMIT = 10;
|
|
@@ -147,7 +149,7 @@ export const catchCommand = {
|
|
|
147
149
|
},
|
|
148
150
|
async execute(intent, context) {
|
|
149
151
|
const squarePath = requireSquarePath(context);
|
|
150
|
-
const caught = await cmdWatch(squarePath, requireParticipant(context.name), intent);
|
|
152
|
+
const caught = await cmdWatch(squarePath, requireParticipant(context.name), intent, { cwd: context.cwd, env: context.env });
|
|
151
153
|
if (caught !== false)
|
|
152
154
|
await sweepPendingNotifications(squarePath);
|
|
153
155
|
},
|
|
@@ -303,6 +305,30 @@ function parseHistory(argv, context) {
|
|
|
303
305
|
continuationArgs: historyContinuationArgs(argv),
|
|
304
306
|
};
|
|
305
307
|
}
|
|
308
|
+
function applicationHistoryQuery(options) {
|
|
309
|
+
return {
|
|
310
|
+
...(options.participants === undefined || options.participants.length === 0 ? {} : { from: options.participants }),
|
|
311
|
+
...(options.mention === undefined ? {} : { mention: options.mention }),
|
|
312
|
+
...(options.afterIndex === undefined ? {} : { after: actId(options.afterIndex) }),
|
|
313
|
+
...(options.beforeIndex === undefined ? {} : { before: actId(options.beforeIndex) }),
|
|
314
|
+
...(options.grep === undefined ? {} : { grep: options.grep }), ...(options.fixed === undefined ? {} : { fixed: options.fixed }),
|
|
315
|
+
order: 'asc',
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
function activityAsStored(activity) {
|
|
319
|
+
const index = parseActivityId(activity.id);
|
|
320
|
+
if (index === undefined)
|
|
321
|
+
throw new Error('Application returned a non-canonical activity id');
|
|
322
|
+
switch (activity.kind) {
|
|
323
|
+
case 'say': return { index, kind: 'say', actor: activity.actor, at: activity.at, body: activity.body ?? '', mentions: activity.mentions, ...(activity.reach === undefined ? {} : { reach: activity.reach }), ...(activity.reply === undefined ? {} : { reply: parseActivityId(activity.reply) ?? undefined }) };
|
|
324
|
+
case 'done': return { index, kind: 'done', actor: activity.actor, at: activity.at, body: activity.body ?? '' };
|
|
325
|
+
case 'hold': return { index, kind: 'hold', actor: activity.actor, at: activity.at, ...(activity.body === undefined ? {} : { body: activity.body }) };
|
|
326
|
+
case 'resume': return { index, kind: 'resume', actor: activity.actor, at: activity.at };
|
|
327
|
+
case 'join': return { index, kind: 'join', actor: activity.actor, at: activity.at };
|
|
328
|
+
case 'listen': return { index, kind: 'listen', actor: activity.actor, target: activity.target ?? '', at: activity.at };
|
|
329
|
+
case 'ignore': return { index, kind: 'ignore', actor: activity.actor, target: activity.target ?? '', at: activity.at };
|
|
330
|
+
}
|
|
331
|
+
}
|
|
306
332
|
function historyContinuationCommand(options, squarePath, direction, index) {
|
|
307
333
|
const args = [...(options.continuationArgs ?? []), direction, actId(index), '--limit', String(options.lastN ?? HISTORY_DEFAULT_LIMIT)];
|
|
308
334
|
return `${commandPrefix(squarePath)} history ${args.map((arg) => arg.startsWith('-') || /^act\/\d+$/.test(arg) || /^\d+$/.test(arg) ? arg : quoteShell(arg)).join(' ')}`;
|
|
@@ -311,6 +337,10 @@ function boundedHistoryCommand(options, squarePath) {
|
|
|
311
337
|
const args = [...(options.continuationArgs ?? []), '--limit', String(HISTORY_MAX_LIMIT)];
|
|
312
338
|
return `${commandPrefix(squarePath)} history ${args.map((arg) => arg.startsWith('-') || /^act\/\d+$/.test(arg) || /^\d+$/.test(arg) ? arg : quoteShell(arg)).join(' ')}`;
|
|
313
339
|
}
|
|
340
|
+
/** The archive-visible activity model: content plus the lifecycle moves that keep its story honest — a raised hand pairs with its lowering, and a departure pairs with the return. */
|
|
341
|
+
function isArchiveActivity(item) {
|
|
342
|
+
return item.kind === 'say' || item.kind === 'done' || item.kind === 'hold' || item.kind === 'resume' || item.kind === 'join';
|
|
343
|
+
}
|
|
314
344
|
function renderFields(sayNumbers, item, fields) {
|
|
315
345
|
return fields.map((field) => {
|
|
316
346
|
switch (field) {
|
|
@@ -344,7 +374,7 @@ function jsonLine(sayNumbers, item) {
|
|
|
344
374
|
});
|
|
345
375
|
}
|
|
346
376
|
function renderHistoryProjection(projection, visible, noTruncate, squarePath) {
|
|
347
|
-
const shown = visible.filter(
|
|
377
|
+
const shown = visible.filter(isArchiveActivity);
|
|
348
378
|
const preview = noTruncate || shown.length <= 1 ? undefined : 200;
|
|
349
379
|
const chunks = [];
|
|
350
380
|
for (const activity of shown) {
|
|
@@ -370,12 +400,16 @@ export const historyCommand = {
|
|
|
370
400
|
parse(argv, context) { return parseHistory(argv, context); },
|
|
371
401
|
async execute(options, context) {
|
|
372
402
|
const squarePath = requireSquarePath(context);
|
|
373
|
-
const square = await openSquare(squarePath, { clock: nowMs });
|
|
403
|
+
const square = await openSquare(squarePath, { clock: nowMs, env: context.env, hostLedger: hostLedgerForEnv(context.env) });
|
|
374
404
|
try {
|
|
375
405
|
// Keep the projection chronological; pagination chooses a stable edge,
|
|
376
406
|
// then --order only changes how the selected page is displayed.
|
|
377
407
|
const projection = await historyPresentation(square, { ...options, order: 'asc' });
|
|
378
|
-
|
|
408
|
+
const useApplicationHistory = options.atIndexes === undefined && options.beforeContext === undefined && options.afterContext === undefined && options.after === undefined;
|
|
409
|
+
const applicationHistory = useApplicationHistory
|
|
410
|
+
? await createSquareApplication({ cwd: context.cwd, env: { ...context.env, SQUARE_PARTICIPANT_NAME: undefined }, squarePath, clock: nowMs }).history(applicationHistoryQuery(options))
|
|
411
|
+
: undefined;
|
|
412
|
+
let events = applicationHistory === undefined ? [...projection.activities] : applicationHistory.map(activityAsStored);
|
|
379
413
|
if (options.lastN === null && events.length > HISTORY_MAX_LIMIT) {
|
|
380
414
|
fail(`✕ history is capped at ${HISTORY_MAX_LIMIT} activities\n${boundedHistoryCommand(options, squarePath)}`);
|
|
381
415
|
}
|
|
@@ -397,8 +431,8 @@ export const historyCommand = {
|
|
|
397
431
|
const output = pattern === undefined || pattern === ''
|
|
398
432
|
? renderHistoryProjection(projection, events, options.noTruncate === true, squarePath)
|
|
399
433
|
: renderGrepActivitiesView(events, totalMatches, options.noTruncate, squarePath, pattern, options.fixed !== undefined, () => 'full');
|
|
400
|
-
const publicEvents = events.filter(
|
|
401
|
-
const allPublic = projection.activities.filter(
|
|
434
|
+
const publicEvents = events.filter(isArchiveActivity);
|
|
435
|
+
const allPublic = projection.activities.filter(isArchiveActivity);
|
|
402
436
|
const pageMin = publicEvents.length === 0 ? undefined : Math.min(...publicEvents.map((item) => item.index));
|
|
403
437
|
const pageMax = publicEvents.length === 0 ? undefined : Math.max(...publicEvents.map((item) => item.index));
|
|
404
438
|
const hasMore = options.lastN != null && publicEvents.length > 0 && (options.afterIndex !== undefined
|
|
@@ -432,10 +466,10 @@ export const participantsCommand = {
|
|
|
432
466
|
parse(argv, context) { return parseParticipants(argv, context); },
|
|
433
467
|
async execute(intent, context) {
|
|
434
468
|
const squarePath = requireSquarePath(context);
|
|
435
|
-
const
|
|
436
|
-
|
|
469
|
+
const application = createSquareApplication({ cwd: context.cwd, env: context.env, squarePath, clock: nowMs });
|
|
470
|
+
{
|
|
437
471
|
const now = nowMs();
|
|
438
|
-
const participants = await
|
|
472
|
+
const participants = await application.participants();
|
|
439
473
|
const lines = participants.slice(0, intent.limit).map((participant) => {
|
|
440
474
|
const recent = participant.lastActiveAt !== undefined && now - participant.lastActiveAt <= STATUS_HERE_WINDOW_MS;
|
|
441
475
|
const glyph = participant.state === 'done' ? '○' : participant.presence === 'watching' ? '◎' : participant.activityCount > 0 && recent ? '●' : '○';
|
|
@@ -456,9 +490,6 @@ export const participantsCommand = {
|
|
|
456
490
|
participantCount,
|
|
457
491
|
});
|
|
458
492
|
}
|
|
459
|
-
finally {
|
|
460
|
-
await closeOpenSquare(square);
|
|
461
|
-
}
|
|
462
493
|
},
|
|
463
494
|
present: (result) => process.stdout.write(result),
|
|
464
495
|
};
|
|
@@ -467,9 +498,9 @@ export const statusCommand = {
|
|
|
467
498
|
usage(context.command); return undefined; },
|
|
468
499
|
async execute(_intent, context) {
|
|
469
500
|
const squarePath = requireSquarePath(context);
|
|
470
|
-
const
|
|
471
|
-
|
|
472
|
-
const presentation = await
|
|
501
|
+
const application = createSquareApplication({ cwd: context.cwd, env: context.env, squarePath, clock: nowMs });
|
|
502
|
+
{
|
|
503
|
+
const presentation = await application.status();
|
|
473
504
|
const result = presentation.status;
|
|
474
505
|
const active = result.participants.filter((participant) => participant.state === 'active');
|
|
475
506
|
const here = active.filter((participant) => participant.presence === 'watching'
|
|
@@ -561,9 +592,6 @@ export const statusCommand = {
|
|
|
561
592
|
].join('\n');
|
|
562
593
|
return withPathOutput(squarePath, output, { participantCount: result.activeCount, held: result.holdActive });
|
|
563
594
|
}
|
|
564
|
-
finally {
|
|
565
|
-
await closeOpenSquare(square);
|
|
566
|
-
}
|
|
567
595
|
},
|
|
568
596
|
present: (result) => process.stdout.write(result),
|
|
569
597
|
};
|
package/dist/cli/program.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { helpRequest } from '../help.js';
|
|
2
2
|
import { isSquareError } from '../model.js';
|
|
3
|
-
import { formatRefusal, joinRecoveryCommand, participantsRecoveryCommand } from '../presentation.js';
|
|
3
|
+
import { formatRefusal, joinRecoveryCommand, participantsRecoveryCommand, takeoverRecoveryLines } from '../presentation.js';
|
|
4
4
|
import { inSquareCount, nowMs } from '../runtime.js';
|
|
5
5
|
import { openSquare } from '../square-file-adapter.js';
|
|
6
6
|
import { closeOpenSquare } from '../open-square.js';
|
|
@@ -23,7 +23,10 @@ async function participantCountFor(squarePath) {
|
|
|
23
23
|
async function handleSquareError(error, squarePath, name) {
|
|
24
24
|
if (isSquareError(error)) {
|
|
25
25
|
const existing = [error.message];
|
|
26
|
-
if (squarePath !== undefined &&
|
|
26
|
+
if (squarePath !== undefined && name !== undefined && error.code === 'already_joined') {
|
|
27
|
+
existing.push(...takeoverRecoveryLines(squarePath, name));
|
|
28
|
+
}
|
|
29
|
+
else if (squarePath !== undefined && /^✕ .* has never stepped into/.test(error.message)) {
|
|
27
30
|
// The caller's name has never joined this square; only a join admits it.
|
|
28
31
|
if (name !== undefined)
|
|
29
32
|
existing.push(joinRecoveryCommand(squarePath, name));
|
package/dist/cli/registry.js
CHANGED
|
@@ -2,6 +2,7 @@ import { buildCommand, doneCommand, expressCommand, holdCommand, ignoreCommand,
|
|
|
2
2
|
import { doctorCommand } from './maintenance-commands.js';
|
|
3
3
|
import { harnessCommand, installCommand, uninstallCommand } from './harness-command.js';
|
|
4
4
|
import { helpCommand, versionCommand } from './meta-commands.js';
|
|
5
|
+
import { mcpServerCommand } from './mcp-server-command.js';
|
|
5
6
|
import { catchCommand, claudeHookCommand, codexHookCommand, historyCommand, inboxCommand, listCommand, participantsCommand, statusCommand, streamCommand, } from './observation-commands.js';
|
|
6
7
|
/** Every public command is an executable adapter, including aliases and utility commands. */
|
|
7
8
|
export const commandRegistry = [
|
|
@@ -29,6 +30,7 @@ export const commandRegistry = [
|
|
|
29
30
|
{ names: ['participants'], spec: participantsCommand },
|
|
30
31
|
{ names: ['help'], spec: helpCommand },
|
|
31
32
|
{ names: ['version', '--version', '-v'], spec: versionCommand },
|
|
33
|
+
{ names: ['mcp-server'], spec: mcpServerCommand },
|
|
32
34
|
];
|
|
33
35
|
export function findCommand(name) {
|
|
34
36
|
return commandRegistry.find((command) => command.names.includes(name));
|