@astrosheep/square 0.4.7 → 0.4.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/card-format.d.ts +2 -0
- package/dist/card-format.js +2 -0
- package/dist/claude-mcp-context.d.ts +0 -1
- package/dist/claude-mcp-context.js +0 -10
- package/dist/claude-mod.d.ts +2 -0
- package/dist/claude-mod.js +211 -0
- package/dist/cli/context.d.ts +1 -1
- package/dist/cli/context.js +1 -12
- package/dist/cli/express-presentation.js +6 -33
- package/dist/cli/json.js +1 -1
- package/dist/cli/observation-commands.d.ts +2 -3
- package/dist/cli/observation-commands.js +21 -59
- package/dist/cli/registry.js +3 -5
- package/dist/cli/square-commands.d.ts +1 -2
- package/dist/cli/square-commands.js +7 -17
- package/dist/decisions.js +5 -4
- package/dist/harness-claude.js +3 -3
- package/dist/help.js +6 -8
- package/dist/mcp.js +1 -1
- package/dist/neutral.d.ts +15 -1
- package/dist/notifications.js +1 -1
- package/dist/operation-presentation.d.ts +17 -15
- package/dist/operation-presentation.js +58 -32
- package/dist/packages/agent-delivery/src/index.d.ts +4 -9
- package/dist/packages/agent-delivery/src/index.js +0 -9
- package/dist/packages/agent-delivery/src/local-endpoint.d.ts +2 -12
- package/dist/packages/agent-delivery/src/local-endpoint.js +4 -48
- package/dist/packages/agent-delivery/src/pi-client.js +0 -2
- package/dist/packages/agent-delivery/src/types.d.ts +3 -37
- package/dist/plugins/paseo/shared/card-format.d.ts +6 -0
- package/dist/plugins/paseo/shared/card-format.js +38 -0
- package/dist/plugins/paseo/shared/card-presentation.d.ts +3 -1
- package/dist/plugins/paseo/shared/card-presentation.js +3 -1
- package/dist/presentation.d.ts +2 -20
- package/dist/presentation.js +11 -46
- package/dist/sqlite-square.js +5 -6
- package/dist/square-facade.d.ts +3 -12
- package/dist/square-posting.js +1 -1
- package/dist/square-tools.d.ts +0 -11
- package/dist/square-tools.js +33 -119
- package/dist/square-values.d.ts +1 -1
- package/dist/square-values.js +1 -1
- package/dist/time.d.ts +1 -0
- package/dist/time.js +10 -0
- package/dist/views.d.ts +1 -1
- package/dist/views.js +2 -2
- package/dist/wake-transports.d.ts +1 -1
- package/dist/wake-transports.js +1 -1
- package/guides/catch-cold-path-optimization.md +1 -1
- package/guides/claude-native.md +37 -7
- package/guides/delivery-primitives.md +2 -1
- package/guides/mcp.md +3 -3
- package/guides/pi-native-delivery.md +10 -2
- package/guides/pi-tools.md +1 -3
- package/guides/row-storage-design.md +1 -1
- package/package.json +1 -1
- package/plugins/claude/.claude-plugin/plugin.json +3 -2
- package/plugins/claude/README.md +9 -0
- package/plugins/claude/hooks/hooks.json +1 -9
- package/plugins/claude/hooks/register.js +178 -0
- package/plugins/claude/skills/square/SKILL.md +2 -2
- package/plugins/codex/.codex-plugin/plugin.json +1 -1
- package/plugins/paseo/OVERVIEW.md +1 -1
- package/plugins/paseo/README.md +20 -23
- package/plugins/paseo/client/markdown.tsx +88 -95
- package/plugins/paseo/client/palette.ts +37 -12
- package/plugins/paseo/client/square-message.tsx +52 -76
- package/plugins/paseo/client/transform.ts +4 -6
- package/plugins/paseo/shared/card-format.ts +37 -0
- package/plugins/paseo/shared/card-presentation.ts +6 -2
- package/plugins/paseo/shared/message.ts +1 -6
- package/plugins/pi/square-pi.js +69 -50
- package/skills/square/SKILL.md +2 -2
- package/dist/claude-boundary-state.d.ts +0 -20
- package/dist/claude-boundary-state.js +0 -84
- package/dist/claude-hook.d.ts +0 -2
- package/dist/claude-hook.js +0 -232
- package/dist/packages/agent-delivery/src/claude-auth.d.ts +0 -13
- package/dist/packages/agent-delivery/src/claude-auth.js +0 -75
- package/dist/packages/agent-delivery/src/claude-native.d.ts +0 -30
- package/dist/packages/agent-delivery/src/claude-native.js +0 -75
- package/dist/packages/agent-delivery/src/claude.d.ts +0 -5
- package/dist/packages/agent-delivery/src/claude.js +0 -66
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export function reachLabel(reach) {
|
|
2
|
+
return reach === "mention" ? "@you" : reach === "attention" ? undefined : reach;
|
|
3
|
+
}
|
|
4
|
+
/** Calendar days, rather than elapsed hours, keep yesterday correct across DST. */
|
|
5
|
+
export function timeLabel(at, now = Date.now(), compact = false) {
|
|
6
|
+
const date = new Date(at), today = new Date(now);
|
|
7
|
+
const day = (value) => `${value.getFullYear()}-${value.getMonth()}-${value.getDate()}`;
|
|
8
|
+
const clock = `${String(date.getHours()).padStart(2, "0")}:${String(date.getMinutes()).padStart(2, "0")}`;
|
|
9
|
+
if (day(date) === day(today))
|
|
10
|
+
return clock;
|
|
11
|
+
const yesterday = new Date(today);
|
|
12
|
+
yesterday.setDate(today.getDate() - 1);
|
|
13
|
+
if (day(date) === day(yesterday))
|
|
14
|
+
return `${compact ? "yest" : "yesterday"} ${clock}`;
|
|
15
|
+
const shortDate = compact
|
|
16
|
+
? `${String(date.getMonth() + 1).padStart(2, "0")}/${String(date.getDate()).padStart(2, "0")}`
|
|
17
|
+
: date.toLocaleDateString("en-US", { month: "short", day: "numeric" });
|
|
18
|
+
return `${shortDate} ${clock}`;
|
|
19
|
+
}
|
|
20
|
+
/** Only adjacent references from the same origin can form a range. */
|
|
21
|
+
export function cardReferences(items, originLabel = origin => origin) {
|
|
22
|
+
const multipleOrigins = new Set(items.map(item => item.origin)).size > 1;
|
|
23
|
+
const runs = [];
|
|
24
|
+
for (const item of items) {
|
|
25
|
+
if (item.ref === undefined)
|
|
26
|
+
continue;
|
|
27
|
+
const match = /^act\/(\d+)$/.exec(item.ref);
|
|
28
|
+
const index = match ? Number(match[1]) : undefined;
|
|
29
|
+
const previous = runs.at(-1);
|
|
30
|
+
if (index !== undefined && previous?.origin === item.origin && previous.last !== undefined && previous.last + 1 === index) {
|
|
31
|
+
previous.last = index;
|
|
32
|
+
}
|
|
33
|
+
else
|
|
34
|
+
runs.push({ origin: item.origin, ref: item.ref, first: index, last: index });
|
|
35
|
+
}
|
|
36
|
+
return runs.map(run => `${multipleOrigins ? `${originLabel(run.origin)} ` : ""}${run.first !== run.last
|
|
37
|
+
? `act/${run.first}–${run.last}` : run.ref}`).join(", ");
|
|
38
|
+
}
|
|
@@ -4,7 +4,9 @@ export type CardPresentation = {
|
|
|
4
4
|
readonly origin: string;
|
|
5
5
|
readonly author?: string;
|
|
6
6
|
readonly ref?: string;
|
|
7
|
-
|
|
7
|
+
/** Absent on cards produced before landing time and reach were recorded. */
|
|
8
|
+
readonly at?: number;
|
|
9
|
+
readonly reach?: 'mention' | 'reply' | 'attention' | 'bell';
|
|
8
10
|
readonly body: string;
|
|
9
11
|
};
|
|
10
12
|
export declare function isCardPresentation(value: unknown): value is CardPresentation;
|
|
@@ -3,5 +3,7 @@ export function isCardPresentation(value) {
|
|
|
3
3
|
return false;
|
|
4
4
|
const item = value;
|
|
5
5
|
return item.kind === 'presentation' && typeof item.origin === 'string' && typeof item.body === 'string'
|
|
6
|
-
&&
|
|
6
|
+
&& (item.at === undefined || (typeof item.at === 'number' && Number.isFinite(item.at)))
|
|
7
|
+
&& (item.reach === undefined || ['mention', 'reply', 'attention', 'bell'].includes(item.reach))
|
|
8
|
+
&& ['author', 'ref'].every(key => item[key] === undefined || typeof item[key] === 'string');
|
|
7
9
|
}
|
package/dist/presentation.d.ts
CHANGED
|
@@ -17,26 +17,10 @@ interface ParticipantOutputOptions {
|
|
|
17
17
|
name: string;
|
|
18
18
|
participantCount?: number;
|
|
19
19
|
}
|
|
20
|
-
interface ActivityLimitOptions extends ParticipantOutputOptions {
|
|
21
|
-
count?: number;
|
|
22
|
-
hardCap?: number;
|
|
23
|
-
draftPath?: string;
|
|
24
|
-
}
|
|
25
|
-
interface ActivityBlockedOptions extends ParticipantOutputOptions {
|
|
26
|
-
retryCommand: string;
|
|
27
|
-
activitySummaries: readonly UnreadActivitySummary[];
|
|
28
|
-
draftPath?: string;
|
|
29
|
-
}
|
|
30
20
|
interface ExpressWaitingOptions {
|
|
31
21
|
reason: 'throttled';
|
|
32
22
|
delayMs?: number;
|
|
33
23
|
}
|
|
34
|
-
interface ExpressNoWaitOptions extends ParticipantOutputOptions {
|
|
35
|
-
reason: 'throttled';
|
|
36
|
-
retryCommand: string;
|
|
37
|
-
delayMs?: number;
|
|
38
|
-
draftPath?: string;
|
|
39
|
-
}
|
|
40
24
|
interface WatchStatusOptions extends ParticipantOutputOptions {
|
|
41
25
|
status: WatchStatus;
|
|
42
26
|
idleMs?: number;
|
|
@@ -92,7 +76,7 @@ export declare function renderAmbientEvent(event: HydratedAct | Activity, viewer
|
|
|
92
76
|
mention?: string;
|
|
93
77
|
perception?: Perception;
|
|
94
78
|
}): string;
|
|
95
|
-
export declare function
|
|
79
|
+
export declare function renderUnreadSummary(activitySummaries: readonly UnreadActivitySummary[]): string[];
|
|
96
80
|
/** An indeterminate or already-committed send only points to inspection, never resend. */
|
|
97
81
|
export declare function renderActivityUncertain(opts: ParticipantOutputOptions & {
|
|
98
82
|
draftPath: string;
|
|
@@ -100,10 +84,8 @@ export declare function renderActivityUncertain(opts: ParticipantOutputOptions &
|
|
|
100
84
|
detail?: string;
|
|
101
85
|
}): string;
|
|
102
86
|
export declare function renderExpressWaiting(opts: ExpressWaitingOptions): string;
|
|
103
|
-
export declare function renderExpressNoWait(opts: ExpressNoWaitOptions): string;
|
|
104
87
|
export declare function renderPresenceAnchor(names: readonly string[]): string;
|
|
105
|
-
export declare function renderGrepActivitiesView(visible: readonly HydratedAct[], totalMatches: number,
|
|
106
|
-
export declare function renderActivityLimit(opts: ActivityLimitOptions): string;
|
|
88
|
+
export declare function renderGrepActivitiesView(visible: readonly HydratedAct[], totalMatches: number, full: boolean | undefined, squarePath: string, pattern: string, fixed?: boolean, perception?: (act: HydratedAct) => Perception, surface?: PresentationSurface): string;
|
|
107
89
|
export declare function renderWatchAlreadyActive(opts: ParticipantOutputOptions): string;
|
|
108
90
|
export declare function renderWatchForceTakeover(_opts: ParticipantOutputOptions): string;
|
|
109
91
|
export declare function renderWatchReplaceMissing(_opts: ParticipantOutputOptions): string;
|
package/dist/presentation.js
CHANGED
|
@@ -214,17 +214,14 @@ export function renderAmbientEvent(event, viewer, opts = {}) {
|
|
|
214
214
|
function draftSavedLines(draftPath) {
|
|
215
215
|
return draftPath === undefined ? [] : [style('dim', `· draft kept: ${draftPath}`)];
|
|
216
216
|
}
|
|
217
|
-
function
|
|
218
|
-
return draftPath === undefined ? command : `${command} < ${quoteShell(draftPath)}`;
|
|
219
|
-
}
|
|
220
|
-
function renderUnreadSummary(activitySummaries) {
|
|
217
|
+
export function renderUnreadSummary(activitySummaries) {
|
|
221
218
|
const visibleSummaries = activitySummaries.slice(0, MAX_IDENTITY_SET_SIZE);
|
|
222
219
|
const remainingSummaries = activitySummaries.length - visibleSummaries.length;
|
|
223
220
|
return [
|
|
224
221
|
...visibleSummaries.map((item) => {
|
|
225
222
|
const compact = (item.preview.body ?? '').replace(/\s+/g, ' ').trim();
|
|
226
223
|
const bodyPreview = compact === ''
|
|
227
|
-
? { text: item.preview.
|
|
224
|
+
? { text: item.preview.structured ? '(structured activity)' : '(empty)', remaining: 0 }
|
|
228
225
|
: truncateChars(compact, UNREAD_PREVIEW_CHARS);
|
|
229
226
|
const bodyText = bodyPreview.remaining === 0 ? bodyPreview.text : `${bodyPreview.text}${style('dim', `… (+${bodyPreview.remaining} chars)`)}`;
|
|
230
227
|
return style('dim', ` · ${participantIdentity(item.name)} spoke — ${formatAge(item.latestActivityAgeMs)} ago · "${bodyText}"`);
|
|
@@ -232,17 +229,6 @@ function renderUnreadSummary(activitySummaries) {
|
|
|
232
229
|
...(remainingSummaries === 0 ? [] : [style('dim', ` · ${remainingSummaries} more participants have unread activity`)]),
|
|
233
230
|
];
|
|
234
231
|
}
|
|
235
|
-
export function renderActivityBlocked(opts) {
|
|
236
|
-
const readNowCommand = `${participantCommandPrefix(opts.squarePath, opts.name, opts.owner)} perceive`;
|
|
237
|
-
return withPathOutput(opts.squarePath, [
|
|
238
|
-
`${style('blocked', '✕')} your activity hasn't landed — someone spoke while you were away`,
|
|
239
|
-
...renderUnreadSummary(opts.activitySummaries),
|
|
240
|
-
...draftSavedLines(opts.draftPath),
|
|
241
|
-
`${readNowCommand}`,
|
|
242
|
-
' · take it in, then retry:',
|
|
243
|
-
withDraftInput(opts.retryCommand, opts.draftPath),
|
|
244
|
-
].join('\n'), { participantCount: opts.participantCount });
|
|
245
|
-
}
|
|
246
232
|
/** An indeterminate or already-committed send only points to inspection, never resend. */
|
|
247
233
|
export function renderActivityUncertain(opts) {
|
|
248
234
|
return formatRefusal(opts.squarePath, [
|
|
@@ -252,7 +238,7 @@ export function renderActivityUncertain(opts) {
|
|
|
252
238
|
...(opts.detail === undefined ? [] : [` · ${truncateExternalDiagnostic(opts.detail)}`]),
|
|
253
239
|
...draftSavedLines(opts.draftPath),
|
|
254
240
|
' · the draft is a saved copy; sending it again could repeat your activity',
|
|
255
|
-
`${commandPrefix(opts.squarePath)} history${opts.landedId === undefined ? ' --limit 10' : ` --at ${opts.landedId}`} --
|
|
241
|
+
`${commandPrefix(opts.squarePath)} history${opts.landedId === undefined ? ' --limit 10' : ` --at ${opts.landedId}`} --full`,
|
|
256
242
|
], opts);
|
|
257
243
|
}
|
|
258
244
|
export function renderExpressWaiting(opts) {
|
|
@@ -262,16 +248,6 @@ export function renderExpressWaiting(opts) {
|
|
|
262
248
|
' · --no-wait saves a draft and returns now',
|
|
263
249
|
].join('\n');
|
|
264
250
|
}
|
|
265
|
-
export function renderExpressNoWait(opts) {
|
|
266
|
-
const retryCommand = opts.retryCommand;
|
|
267
|
-
const lines = [
|
|
268
|
-
`${style('blocked', '✕')} the square is packed — shoulder to shoulder`,
|
|
269
|
-
` · a lull opens in ${formatDuration(opts.delayMs)}`,
|
|
270
|
-
...draftSavedLines(opts.draftPath),
|
|
271
|
-
`${withDraftInput(retryCommand, opts.draftPath)}`,
|
|
272
|
-
];
|
|
273
|
-
return withPathOutput(opts.squarePath, lines.join('\n'), { participantCount: opts.participantCount });
|
|
274
|
-
}
|
|
275
251
|
export function renderPresenceAnchor(names) {
|
|
276
252
|
const visibleNames = names.slice(0, MAX_IDENTITY_SET_SIZE);
|
|
277
253
|
const participants = visibleNames.map((name) => participantIdentity(name)).join(', ');
|
|
@@ -280,7 +256,7 @@ export function renderPresenceAnchor(names) {
|
|
|
280
256
|
return style('dim', names.length === 1 ? `→ ${participants} was here` : `→ ${participants}${suffix} were here`);
|
|
281
257
|
}
|
|
282
258
|
const GREP_PREVIEW_CHARS = 160;
|
|
283
|
-
export function renderGrepActivitiesView(visible, totalMatches,
|
|
259
|
+
export function renderGrepActivitiesView(visible, totalMatches, full, squarePath, pattern, fixed = false, perception, surface = 'cli') {
|
|
284
260
|
const publicVisible = visible.filter((act) => act.kind === 'say' || act.kind === 'done');
|
|
285
261
|
if (totalMatches === 0)
|
|
286
262
|
return `○ no activity matched ${quoteShell(pattern)}`;
|
|
@@ -294,7 +270,7 @@ export function renderGrepActivitiesView(visible, totalMatches, noTruncate, squa
|
|
|
294
270
|
chunks.push(header);
|
|
295
271
|
continue;
|
|
296
272
|
}
|
|
297
|
-
if (
|
|
273
|
+
if (full === true) {
|
|
298
274
|
const body = rawBody.split('\n').map((line) => ` ${line}`).join('\n');
|
|
299
275
|
chunks.push(`${header}\n${body}`);
|
|
300
276
|
continue;
|
|
@@ -316,34 +292,23 @@ export function renderGrepActivitiesView(visible, totalMatches, noTruncate, squa
|
|
|
316
292
|
}
|
|
317
293
|
if (publicVisible.length === 1) {
|
|
318
294
|
chunks.push(surface === 'tool'
|
|
319
|
-
? formatToolAction('history', { location: displayPath(squarePath), at: [formatActivityId(publicVisible[0].index)], context: 2, ...(truncated ? {
|
|
320
|
-
: `${commandPrefix(squarePath)} history --at ${formatActivityId(publicVisible[0].index)} -C 2${truncated ? ' --
|
|
295
|
+
? formatToolAction('history', { location: displayPath(squarePath), at: [formatActivityId(publicVisible[0].index)], context: 2, ...(truncated ? { full: true } : {}) })
|
|
296
|
+
: `${commandPrefix(squarePath)} history --at ${formatActivityId(publicVisible[0].index)} -C 2${truncated ? ' --full' : ''}`);
|
|
321
297
|
}
|
|
322
298
|
else if (truncated && publicVisible.length > 1) {
|
|
323
299
|
chunks.push(surface === 'tool'
|
|
324
|
-
? formatToolAction('history', { location: displayPath(squarePath), at: [formatActivityId(publicVisible[0].index)], context: 2,
|
|
325
|
-
: `${commandPrefix(squarePath)} history --at ${formatActivityId(publicVisible[0].index)} -C 2 --
|
|
300
|
+
? formatToolAction('history', { location: displayPath(squarePath), at: [formatActivityId(publicVisible[0].index)], context: 2, full: true })
|
|
301
|
+
: `${commandPrefix(squarePath)} history --at ${formatActivityId(publicVisible[0].index)} -C 2 --full`);
|
|
326
302
|
}
|
|
327
303
|
return chunks.join('\n\n');
|
|
328
304
|
}
|
|
329
|
-
export function renderActivityLimit(opts) {
|
|
330
|
-
// The cap wording lives inside the count: the speaker is simply spent.
|
|
331
|
-
const spoken = opts.count !== undefined && opts.hardCap !== undefined ? ` — ${opts.count}/${opts.hardCap} spoken` : '';
|
|
332
|
-
const doneCommand = `${participantCommandPrefix(opts.squarePath, opts.name, opts.owner)} done`;
|
|
333
|
-
return withPathOutput(opts.squarePath, [
|
|
334
|
-
`${style('blocked', '✕')} you’ve reached your speaking cap${spoken}`,
|
|
335
|
-
...draftSavedLines(opts.draftPath),
|
|
336
|
-
' · your draft stays unsent; done only steps out',
|
|
337
|
-
doneCommand,
|
|
338
|
-
].join('\n'), { participantCount: opts.participantCount });
|
|
339
|
-
}
|
|
340
305
|
export function renderWatchAlreadyActive(opts) {
|
|
341
306
|
return [
|
|
342
307
|
`${style('blocked', '✕')} you are already perceiving`,
|
|
343
308
|
` · an active perceive is already running for ${participantIdentity(opts.name)}`,
|
|
344
309
|
` · ${opts.surface === 'tool' ? 'takeover' : '--takeover'} lets a new perceive take over`,
|
|
345
310
|
opts.surface === 'tool'
|
|
346
|
-
? formatToolAction('perceive', { location: displayPath(opts.squarePath), as: opts.name, idle:
|
|
311
|
+
? formatToolAction('perceive', { location: displayPath(opts.squarePath), as: opts.name, idle: '30m', takeover: true })
|
|
347
312
|
: `${participantCommandPrefix(opts.squarePath, opts.name, opts.owner)} perceive --idle 30m --takeover`,
|
|
348
313
|
].join('\n');
|
|
349
314
|
}
|
|
@@ -375,7 +340,7 @@ export function renderWatchStatus(opts) {
|
|
|
375
340
|
? style('dim', `○ dust settles on the flagstones — ${formatDuration(idleMs)} of quiet`)
|
|
376
341
|
: style('dim', '○ only footsteps in the square — nothing new for you');
|
|
377
342
|
// The quiet report never repeats the perceive just run.
|
|
378
|
-
const hints = [opts.surface === 'tool' ? formatToolAction('perceive', { location: displayPath(opts.squarePath), as: opts.name, idle:
|
|
343
|
+
const hints = [opts.surface === 'tool' ? formatToolAction('perceive', { location: displayPath(opts.squarePath), as: opts.name, idle: '30m' }) : `${prefix} perceive --idle 30m`];
|
|
379
344
|
return [
|
|
380
345
|
quiet,
|
|
381
346
|
...(opts.showPerceiveHint === false ? [] : hints),
|
package/dist/sqlite-square.js
CHANGED
|
@@ -215,9 +215,9 @@ export class SqliteSquare {
|
|
|
215
215
|
...(options.reach === undefined ? {} : { reach: options.reach }), ...(options.noMention === undefined ? {} : { noMention: options.noMention }), ...(reply === undefined ? {} : { reply }) });
|
|
216
216
|
const decision = rejectUnsentActivity(() => {
|
|
217
217
|
if (proposed.type === 'blocked')
|
|
218
|
-
throw new SquareError('behind', `${participantIdentity(name)} has pending activity`, {
|
|
218
|
+
throw new SquareError('behind', `${participantIdentity(name)} has pending activity`, { activitySummaries: proposed.activitySummaries });
|
|
219
219
|
if (proposed.type === 'capped')
|
|
220
|
-
throw new SquareError('capped', `${participantIdentity(name)} reached the activity cap
|
|
220
|
+
throw new SquareError('capped', `${participantIdentity(name)} reached the activity cap`, { spoken: facts.participant(name).sayCount, ...(facts.header().hardCap == null ? {} : { hardCap: facts.header().hardCap }) });
|
|
221
221
|
if (proposed.type === 'throttled')
|
|
222
222
|
throw new SquareError('throttled', `${name} is throttled`, { retryAfterMs: proposed.delayMs });
|
|
223
223
|
if (proposed.type === 'bell_quota')
|
|
@@ -515,11 +515,10 @@ export class SqliteSquare {
|
|
|
515
515
|
throw new SquareError('invalid_args', 'History order must be asc or desc.');
|
|
516
516
|
if (query.since !== undefined && !Number.isFinite(query.since))
|
|
517
517
|
throw new SquareError('invalid_args', 'History timestamp must be finite');
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
throw new SquareError('invalid_args', 'History context must be a non-negative safe integer');
|
|
518
|
+
if (query.context !== undefined && (!Number.isSafeInteger(query.context) || query.context < 0 || query.context > HISTORY_MAX_LIMIT))
|
|
519
|
+
throw new SquareError('invalid_args', `History context must be a non-negative integer no greater than ${HISTORY_MAX_LIMIT}`);
|
|
521
520
|
const limit = query.limit === undefined ? (query.at?.length ? null : HISTORY_DEFAULT_LIMIT) : query.limit;
|
|
522
|
-
const contextual = !!query.at?.length || query.
|
|
521
|
+
const contextual = !!query.at?.length || query.context !== undefined;
|
|
523
522
|
const kinds = contextual || query.since !== undefined ? [...NON_READ, 'read'] : NON_READ;
|
|
524
523
|
return (await this.artifact.read(facts => {
|
|
525
524
|
const selected = selectHistory(facts, query, limit, kinds, query.observe === true);
|
package/dist/square-facade.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import type { MetadataMatch } from './delivery-deferral.js';
|
|
|
2
2
|
export type { MetadataMatch, MetadataScalar } from './delivery-deferral.js';
|
|
3
3
|
import type { ActivityId, Perception, Reach } from './square-core.js';
|
|
4
4
|
import type { Owner, HydratedAct, WakeAddress, ActivityMetadata, DirectedNotificationRoute } from './model.js';
|
|
5
|
-
import type { OperationControl } from './neutral.js';
|
|
5
|
+
import type { OperationControl, UnreadActivitySummary } from './neutral.js';
|
|
6
6
|
export interface ActivitySearch {
|
|
7
7
|
readonly text: string;
|
|
8
8
|
readonly mode: 'literal' | 'regex';
|
|
@@ -16,7 +16,7 @@ export interface HeldSeat {
|
|
|
16
16
|
readonly name: string;
|
|
17
17
|
readonly generation: string;
|
|
18
18
|
}
|
|
19
|
-
export type { PerceiveWaitStart, OperationProgress, OperationControl, OperationFailureDetail, OperationError } from './neutral.js';
|
|
19
|
+
export type { PerceiveWaitStart, OperationProgress, OperationControl, OperationFailureDetail, OperationError, UnreadActivitySummary, SquareErrorFacts } from './neutral.js';
|
|
20
20
|
export type { ActivityId, Perception, Reach } from './square-core.js';
|
|
21
21
|
export type { Owner, WakeAddress, ActivityMetadata, JsonValue, DirectedNotificationRoute } from './model.js';
|
|
22
22
|
/** Indexed archive event, including read bookkeeping and a say's linked content. */
|
|
@@ -119,8 +119,7 @@ export interface HistoryQuery extends ActivityQuery, ObservationOptions {
|
|
|
119
119
|
readonly order?: 'asc' | 'desc';
|
|
120
120
|
readonly mention?: string;
|
|
121
121
|
readonly since?: number;
|
|
122
|
-
readonly
|
|
123
|
-
readonly contextAfter?: number;
|
|
122
|
+
readonly context?: number;
|
|
124
123
|
}
|
|
125
124
|
export interface HistoryResult {
|
|
126
125
|
readonly activities: readonly Activity[];
|
|
@@ -255,14 +254,6 @@ export interface StreamOptions {
|
|
|
255
254
|
readonly start?: StreamStart;
|
|
256
255
|
}
|
|
257
256
|
export type StreamRecord = Activity | PerceivedActivity;
|
|
258
|
-
export interface UnreadActivitySummary {
|
|
259
|
-
readonly name: string;
|
|
260
|
-
readonly count: number;
|
|
261
|
-
readonly latestActivityAgeMs: number;
|
|
262
|
-
readonly preview: Extract<ArchiveRecord, {
|
|
263
|
-
kind: 'say';
|
|
264
|
-
}>;
|
|
265
|
-
}
|
|
266
257
|
export interface EntryPresentation {
|
|
267
258
|
readonly joinedBefore: boolean;
|
|
268
259
|
readonly scene: string;
|
package/dist/square-posting.js
CHANGED
|
@@ -134,7 +134,7 @@ export async function flushSquarePosts(artifact, location, clock, signal, ledger
|
|
|
134
134
|
const result = await ledger.post({ owner: post.owner, key: squarePostKey(location, post), text: rendered.text,
|
|
135
135
|
...(post.kind === 'activity' ? { details: { kind: 'presentation', origin: displayAttentionPath(location),
|
|
136
136
|
ref: formatActivityId(post.index), author: post.from, body: post.body ?? '',
|
|
137
|
-
|
|
137
|
+
at: post.at, reach: post.route } } : {}),
|
|
138
138
|
}, signal);
|
|
139
139
|
posted = ['posted', 'duplicate', 'suppressed'].includes(result.status);
|
|
140
140
|
knownUnsent = !posted;
|
package/dist/square-tools.d.ts
CHANGED
|
@@ -6,16 +6,6 @@ export interface ToolIdentity {
|
|
|
6
6
|
readonly wakeAddress?: WakeAddress;
|
|
7
7
|
}
|
|
8
8
|
type JsonObject = Record<string, unknown>;
|
|
9
|
-
export declare class SquareExpressDrafts {
|
|
10
|
-
private readonly drafts;
|
|
11
|
-
private purgeExpired;
|
|
12
|
-
resolve(args: JsonObject, owner?: Owner): {
|
|
13
|
-
args: JsonObject;
|
|
14
|
-
token?: string;
|
|
15
|
-
};
|
|
16
|
-
consume(token?: string): void;
|
|
17
|
-
retain(args: JsonObject, owner: Owner | undefined, token: string | undefined, failure: JsonObject, expressAttempted: boolean): string | undefined;
|
|
18
|
-
}
|
|
19
9
|
interface ToolBinding {
|
|
20
10
|
identity: ToolIdentity;
|
|
21
11
|
readonly now?: () => number;
|
|
@@ -48,6 +38,5 @@ export declare function squareToolFailure(error: unknown, signal?: AbortSignal):
|
|
|
48
38
|
export declare function squareToolFailureText(failure: JsonObject, context?: {
|
|
49
39
|
location?: string;
|
|
50
40
|
participant?: string;
|
|
51
|
-
draft?: string;
|
|
52
41
|
}): string;
|
|
53
42
|
export {};
|
package/dist/square-tools.js
CHANGED
|
@@ -1,95 +1,32 @@
|
|
|
1
|
-
import crypto from 'node:crypto';
|
|
2
1
|
import { z } from 'zod/v4';
|
|
3
2
|
import { isSquareError, SquareError } from './model.js';
|
|
4
|
-
import { requireOwner, requireJoinName, selectOwnSeat, HISTORY_MAX_LIMIT, PERCEIVE_DEFAULT_LIMIT, DEFAULT_LIST_DEPTH, DEFAULT_LIST_LIMIT, MAX_LIST_DEPTH, MAX_LIST_LIMIT } from './square-api.js';
|
|
5
|
-
import { parseTimeOrRelative } from './time.js';
|
|
3
|
+
import { requireOwner, requireJoinName, selectOwnSeat, HISTORY_MAX_LIMIT, PERCEIVE_MAX_LIMIT, PERCEIVE_DEFAULT_LIMIT, DEFAULT_LIST_DEPTH, DEFAULT_LIST_LIMIT, MAX_LIST_DEPTH, MAX_LIST_LIMIT } from './square-api.js';
|
|
4
|
+
import { parseDurationMs, parseTimeOrRelative } from './time.js';
|
|
6
5
|
import { renderPerceiveOutcome, renderExpression, renderFailureLines, renderHistoryResult, renderJoinResult, renderLifecycleResult, renderListenerChange, renderStatusResult, renderSquareList, } from './operation-presentation.js';
|
|
7
|
-
/** Process-local recovery: FIFO 64, fixed two-hour TTL, consumed only by a successful express. */
|
|
8
|
-
const EXPRESS_DRAFT_TTL_MS = 2 * 60 * 60 * 1000;
|
|
9
|
-
const EXPRESS_DRAFT_LIMIT = 64;
|
|
10
|
-
export class SquareExpressDrafts {
|
|
11
|
-
drafts = new Map();
|
|
12
|
-
purgeExpired() {
|
|
13
|
-
const now = Date.now();
|
|
14
|
-
for (const [token, draft] of this.drafts)
|
|
15
|
-
if (draft.expiresAt <= now)
|
|
16
|
-
this.drafts.delete(token);
|
|
17
|
-
}
|
|
18
|
-
resolve(args, owner) {
|
|
19
|
-
if (args.draft === undefined)
|
|
20
|
-
return { args };
|
|
21
|
-
this.purgeExpired();
|
|
22
|
-
if (typeof args.draft !== 'string' || Object.keys(args).length !== 1)
|
|
23
|
-
throw new SquareError('invalid_args', 'An express draft token cannot be combined with other arguments.');
|
|
24
|
-
const draft = this.drafts.get(args.draft);
|
|
25
|
-
if (draft === undefined || draft.owner !== owner)
|
|
26
|
-
throw new SquareError('invalid_args', 'Unknown, expired, or inaccessible express draft.');
|
|
27
|
-
return { args: draft.args, token: args.draft };
|
|
28
|
-
}
|
|
29
|
-
consume(token) {
|
|
30
|
-
if (token !== undefined)
|
|
31
|
-
this.drafts.delete(token);
|
|
32
|
-
}
|
|
33
|
-
retain(args, owner, token, failure, expressAttempted) {
|
|
34
|
-
const effect = failure.operation?.expressEffect;
|
|
35
|
-
// After an attempt, only an admission or argument refusal proves that retrying cannot duplicate an activity.
|
|
36
|
-
const unsent = !expressAttempted || effect === 'unsent' || (effect === undefined && failure.code === 'invalid_args');
|
|
37
|
-
if (!unsent || effect === 'landed' || effect === 'unknown' || typeof args.body !== 'string' || args.draft !== undefined
|
|
38
|
-
|| typeof args.location !== 'string' || !args.location.trim())
|
|
39
|
-
return undefined;
|
|
40
|
-
this.purgeExpired();
|
|
41
|
-
if (token !== undefined && this.drafts.has(token))
|
|
42
|
-
return token;
|
|
43
|
-
const created = `dr_${crypto.randomBytes(16).toString('base64url')}`;
|
|
44
|
-
this.drafts.set(created, { owner, args, expiresAt: Date.now() + EXPRESS_DRAFT_TTL_MS });
|
|
45
|
-
if (this.drafts.size > EXPRESS_DRAFT_LIMIT)
|
|
46
|
-
this.drafts.delete(this.drafts.keys().next().value);
|
|
47
|
-
return created;
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
6
|
export function createSquareToolRunner() {
|
|
51
|
-
const drafts = new SquareExpressDrafts();
|
|
52
7
|
return async (tool, args, control, bind) => {
|
|
53
|
-
let toolArgs = args;
|
|
54
|
-
let owner;
|
|
55
|
-
let token;
|
|
56
|
-
let attempted = false;
|
|
57
8
|
let square;
|
|
58
9
|
try {
|
|
59
10
|
const binding = await bind();
|
|
60
|
-
owner = binding.identity.owner;
|
|
61
11
|
if ('runDiscovery' in tool)
|
|
62
|
-
return { text: await tool.runDiscovery(
|
|
63
|
-
|
|
64
|
-
const resolved = drafts.resolve(toolArgs, owner);
|
|
65
|
-
toolArgs = resolved.args;
|
|
66
|
-
token = resolved.token;
|
|
67
|
-
}
|
|
68
|
-
square = await binding.open(toolArgs.location, control);
|
|
69
|
-
let text;
|
|
12
|
+
return { text: await tool.runDiscovery(args, control, binding) };
|
|
13
|
+
square = await binding.open(args.location, control);
|
|
70
14
|
try {
|
|
71
|
-
|
|
72
|
-
text = await tool.run(square, toolArgs, control, binding.identity, binding.now);
|
|
73
|
-
drafts.consume(token);
|
|
15
|
+
return { text: await tool.run(square, args, control, binding.identity, binding.now) };
|
|
74
16
|
}
|
|
75
17
|
finally {
|
|
76
18
|
await square.close();
|
|
77
19
|
}
|
|
78
|
-
return { text };
|
|
79
20
|
}
|
|
80
21
|
catch (error) {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
location: square?.location ?? toolArgs.location,
|
|
85
|
-
participant: typeof toolArgs.as === 'string' ? toolArgs.as : undefined,
|
|
86
|
-
draft,
|
|
22
|
+
return { isError: true, text: squareToolFailureText(squareToolFailure(error, control.signal), {
|
|
23
|
+
location: square?.location ?? args.location,
|
|
24
|
+
participant: typeof args.as === 'string' ? args.as : undefined,
|
|
87
25
|
}) };
|
|
88
26
|
}
|
|
89
27
|
};
|
|
90
28
|
}
|
|
91
|
-
const location = z.string().describe('
|
|
92
|
-
const expressLocation = z.string().optional().describe('Which square: a .square file path. Relative paths start from the working directory. Required unless retrying with a draft token.');
|
|
29
|
+
const location = z.string().describe('Path to the .square file, relative to the working directory.');
|
|
93
30
|
const participant = z.string().optional().describe('Your name in the square. Leave it out if you hold exactly one name here.');
|
|
94
31
|
const activityId = z.string().regex(/^act\/(0|[1-9][0-9]*)$/);
|
|
95
32
|
const stringArray = z.array(z.string());
|
|
@@ -98,7 +35,7 @@ function rendering(render) {
|
|
|
98
35
|
return (result, args) => render(result, args);
|
|
99
36
|
}
|
|
100
37
|
function tool(name, description, shape, run, render) {
|
|
101
|
-
const inputSchema = z.object({ ...shape, location
|
|
38
|
+
const inputSchema = z.object({ ...shape, location }).strict();
|
|
102
39
|
return { name, description, inputSchema,
|
|
103
40
|
run: async (square, args, control, identity, now) => {
|
|
104
41
|
const { location: _location, ...operationArgs } = inputSchema.parse(args);
|
|
@@ -115,21 +52,15 @@ export function squareToolsEnabled(env = process.env) {
|
|
|
115
52
|
throw new SquareError('invalid_args', 'Invalid SQUARE_TOOLS: expected 0, 1, true, false, or none.');
|
|
116
53
|
}
|
|
117
54
|
export const SQUARE_TOOL_INSTRUCTIONS = 'List nearby squares and your joined names with list. Pass location for a single square. Join once. Then express to speak, and perceive to take in what reached you. History looks back without taking anything in.';
|
|
118
|
-
function historyToolQuery({
|
|
119
|
-
if (grep !== undefined && fixed !== undefined)
|
|
120
|
-
throw new SquareError('invalid_args', 'Use grep or fixed, not both.');
|
|
55
|
+
function historyToolQuery({ search, regex, before, after, since, full: _full, ...query }, now = Date.now()) {
|
|
121
56
|
if (before !== undefined && after !== undefined)
|
|
122
57
|
throw new SquareError('invalid_args', 'Use before or after, not both.');
|
|
123
58
|
const sinceMs = since === undefined ? undefined : parseTimeOrRelative(since, now);
|
|
124
59
|
if (sinceMs !== undefined && !Number.isFinite(sinceMs))
|
|
125
60
|
throw new SquareError('invalid_args', `Invalid since timestamp: ${since}`);
|
|
126
|
-
const resolvedBefore = contextBefore ?? context;
|
|
127
|
-
const resolvedAfter = contextAfter ?? context;
|
|
128
61
|
return { ...query,
|
|
129
62
|
...(sinceMs === undefined ? {} : { since: sinceMs }),
|
|
130
|
-
|
|
131
|
-
...(resolvedAfter === undefined ? {} : { contextAfter: resolvedAfter }),
|
|
132
|
-
search: grep !== undefined ? { text: grep, mode: 'regex' } : fixed === undefined ? undefined : { text: fixed, mode: 'literal' },
|
|
63
|
+
search: search === undefined ? undefined : { text: search, mode: regex ? 'regex' : 'literal' },
|
|
133
64
|
cursor: after !== undefined ? { id: after, direction: 'after' } : before === undefined ? undefined : { id: before, direction: 'before' },
|
|
134
65
|
};
|
|
135
66
|
}
|
|
@@ -150,66 +81,57 @@ export const SQUARE_TOOLS = [
|
|
|
150
81
|
},
|
|
151
82
|
},
|
|
152
83
|
tool('join', 'Step into the square under your name. Do this once before you speak or perceive. You arrive seeing what was said most recently.', {
|
|
153
|
-
as: z.string().
|
|
84
|
+
as: z.string().describe('Your name in the square.'),
|
|
154
85
|
takeover: z.boolean().optional().describe('Claim this name even though another session holds it now. That session loses it.'),
|
|
155
|
-
last: z.number().int().min(1).max(HISTORY_MAX_LIMIT).optional().describe('How many recent public activities to show on arrival (default 10
|
|
86
|
+
last: z.number().int().min(1).max(HISTORY_MAX_LIMIT).optional().describe('How many recent public activities to show on arrival (default 10).'),
|
|
156
87
|
}, (square, { as, takeover, last }, control, identity) => square.join(requireJoinName(as), { ...identity, owner: requireOwner(identity.owner), takeover, last, observe: true }, control), rendering((result) => renderJoinResult(result, undefined, 'tool'))),
|
|
157
88
|
tool('express', 'Speak or act in the square. Plain words, half-formed ideas and *actions* all belong here. Mention or reply to someone to be heard by them; ring the bell to be heard by everyone. Said to no one in particular, your words reach those who listen to you.', {
|
|
158
89
|
as: participant,
|
|
159
|
-
body: z.string().
|
|
160
|
-
draft: z.string().optional().describe('Retry a failed express kept in this process. Pass only the token; the original body and options are restored.'),
|
|
90
|
+
body: z.string().describe('What you say or do. Markdown works; *asterisks* mark an action.'),
|
|
161
91
|
mentions: stringArray.optional().describe('Who you are speaking to. An @name in the body that matches someone here counts too.'),
|
|
162
|
-
|
|
92
|
+
bell: z.boolean().optional().describe('Call everyone in the square. Not with mentions.'),
|
|
163
93
|
reply: activityId.optional().describe('The activity you are answering, like act/12. Its author hears you if still here.'),
|
|
164
94
|
noMention: z.boolean().optional().describe('Leave @names in the body as plain text. Mentions and reply still reach people.'),
|
|
165
95
|
force: z.boolean().optional().describe('Speak now, even if something reached you that you have not perceived yet.'),
|
|
166
96
|
noWait: z.boolean().optional().describe('If you are speaking too fast, return at once instead of waiting.'),
|
|
167
|
-
}, async (square, { body,
|
|
168
|
-
if (draft !== undefined)
|
|
169
|
-
throw new SquareError('invalid_args', 'Unknown or expired express draft.');
|
|
170
|
-
if (body === undefined)
|
|
171
|
-
throw new SquareError('invalid_args', 'Express needs a body or a draft token.');
|
|
172
|
-
return (await selectOwnSeat(square, identity.owner, as)).express(body, { ...options, observe: true }, control);
|
|
173
|
-
}, rendering((result) => renderExpression(result.observation?.location ?? '', result, undefined, 'tool'))),
|
|
97
|
+
}, async (square, { body, bell, as, ...options }, control, identity) => (await selectOwnSeat(square, identity.owner, as)).express(body, { ...options, ...(bell ? { reach: 'bell' } : {}), observe: true }, control), rendering((result) => renderExpression(result.observation?.location ?? '', result, undefined, 'tool'))),
|
|
174
98
|
tool('perceive', 'Take in what reached you since you last looked: mentions, replies, bells, and words from those you listen to. What you perceive no longer waits for you; history lets you look back.', {
|
|
175
99
|
as: participant,
|
|
176
|
-
id: activityId.optional().describe('
|
|
177
|
-
idle: z.
|
|
100
|
+
id: activityId.optional().describe('Open this one activity in full, like act/12. Use it alone.'),
|
|
101
|
+
idle: z.string().optional().describe('When nothing is waiting, wait for activity or this much quiet, like "30s". Leave it out to return at once.'),
|
|
178
102
|
from: stringArray.optional().describe('Only what these participants said.'),
|
|
179
103
|
mention: z.boolean().optional().describe('Only what was addressed to you, and bells.'),
|
|
180
|
-
limit: z.number().int().min(1).optional().describe('At most this many at once (default 10
|
|
104
|
+
limit: z.number().int().min(1).max(PERCEIVE_MAX_LIMIT).optional().describe('At most this many at once (default 10). The rest keeps waiting.'),
|
|
181
105
|
takeover: z.boolean().optional().describe('Take over from another active idle perceive for this participant.'),
|
|
182
|
-
}, async (square, { as,
|
|
106
|
+
}, async (square, { as, idle, ...args }, control, identity) => {
|
|
107
|
+
const options = { ...args, ...(idle === undefined ? {} : { idle: parseDurationMs(idle, 'idle') }) };
|
|
108
|
+
return { ...(await (await selectOwnSeat(square, identity.owner, as)).perceive({ ...options, observe: true }, control)), options };
|
|
109
|
+
}, rendering((result) => {
|
|
183
110
|
// The CLI always spells the default cap in its continuation, so the tool does too.
|
|
184
|
-
const options =
|
|
111
|
+
const options = result.options;
|
|
185
112
|
const renderOptions = options.id === undefined ? { ...options, limit: options.limit ?? PERCEIVE_DEFAULT_LIMIT } : options;
|
|
186
113
|
return renderPerceiveOutcome(result.observation?.location ?? '', result, renderOptions, undefined, 'tool').stdout;
|
|
187
114
|
})),
|
|
188
115
|
tool('history', 'Look back at what was said. Reading here takes nothing in: whatever waits for perceive keeps waiting. Page with before or after.', {
|
|
189
|
-
limit: z.number().int().min(1).optional().describe('How many per page (default 10
|
|
116
|
+
limit: z.number().int().min(1).max(HISTORY_MAX_LIMIT).optional().describe('How many per page (default 10).'),
|
|
190
117
|
order: z.enum(['asc', 'desc']).optional().describe('"asc" for oldest first (default), "desc" for newest first.'),
|
|
191
118
|
before: activityId.optional().describe('The page just before this activity, like act/12.'),
|
|
192
119
|
after: activityId.optional().describe('The page just after this activity, like act/12.'),
|
|
193
120
|
at: z.array(activityId).min(1).optional().describe('Center on these activity ids, like ["act/12"].'),
|
|
194
|
-
context: z.number().int().min(0).optional().describe('Activities of context before and after each "at" activity.'),
|
|
195
|
-
contextBefore: z.number().int().min(0).optional().describe('Activities of context before each "at" activity.'),
|
|
196
|
-
contextAfter: z.number().int().min(0).optional().describe('Activities of context after each "at" activity.'),
|
|
121
|
+
context: z.number().int().min(0).max(HISTORY_MAX_LIMIT).optional().describe('Activities of context before and after each "at" activity.'),
|
|
197
122
|
since: z.string().optional().describe('Only activities after this ISO timestamp or relative duration (like "10m").'),
|
|
198
|
-
|
|
199
|
-
|
|
123
|
+
search: z.string().optional().describe('Only activities containing this text in their names, ids or words.'),
|
|
124
|
+
regex: z.boolean().optional().describe('Treat search as a regular expression.'),
|
|
200
125
|
from: stringArray.optional().describe('Only what these participants said.'),
|
|
201
126
|
mention: z.string().optional().describe('Only what was addressed to this participant.'),
|
|
202
|
-
|
|
127
|
+
full: z.boolean().optional().describe('Show full activity bodies even when multiple activities are returned.'),
|
|
203
128
|
}, async (square, args, control, _identity, now) => {
|
|
204
129
|
const query = historyToolQuery(args, now?.());
|
|
205
130
|
return { ...(await square.history({ ...query, observe: true }, control)), query };
|
|
206
|
-
}, rendering((result, args) => renderHistoryResult(result.observation?.location ?? '', result, { query: result.query,
|
|
131
|
+
}, rendering((result, args) => renderHistoryResult(result.observation?.location ?? '', result, { query: result.query, full: args.full === true, surface: 'tool' }))),
|
|
207
132
|
tool('attention', 'Turn toward someone or away from them, from now on. Listen: hear everything they say, even to others. Unlisten: stop listening without clearing an ignore; mentions and replies still reach you unless ignored. Ignore: hear nothing from them but bells. What was already said stays as it was.', {
|
|
208
133
|
as: participant, action: z.enum(['listen', 'unlisten', 'ignore']).describe('"listen", "unlisten" or "ignore". Listening again ends an ignore.'), target,
|
|
209
|
-
}, async (square, { as, action, target }, control, identity) => {
|
|
210
|
-
const self = await selectOwnSeat(square, identity.owner, as);
|
|
211
|
-
return self[action](target, { observe: true }, control);
|
|
212
|
-
}, rendering((result, args) => renderListenerChange(result.observation?.location ?? '', args.action, result))),
|
|
134
|
+
}, async (square, { as, action, target }, control, identity) => (await selectOwnSeat(square, identity.owner, as))[action](target, { observe: true }, control), rendering((result, args) => renderListenerChange(result.observation?.location ?? '', args.action, result))),
|
|
213
135
|
tool('done', 'Step out of the square. Everyone sees you leave, and you stop listening to anyone. Leaving carries no words, so say goodbye with express first. Stay instead if someone may still need you; you can join again later.', { as: participant }, async (square, { as }, control, identity) => (await selectOwnSeat(square, identity.owner, as)).done(undefined, { observe: true }, control), rendering((result) => renderLifecycleResult(result.observation?.location ?? '', result))),
|
|
214
136
|
tool('status', 'Look around the square: who is here, the latest activity, and who you listen to.', {
|
|
215
137
|
as: z.string().optional().describe('Whose listening to show. Leave it out if you hold exactly one name here.'),
|
|
@@ -231,13 +153,5 @@ export function squareToolFailure(error, signal) {
|
|
|
231
153
|
}
|
|
232
154
|
/** Readable failure text with tool-native recovery actions, never raw JSON. */
|
|
233
155
|
export function squareToolFailureText(failure, context = {}) {
|
|
234
|
-
|
|
235
|
-
const lines = renderFailureLines(report, { squarePath: context.location, name: context.participant, surface: 'tool' });
|
|
236
|
-
if (context.draft !== undefined) {
|
|
237
|
-
lines.push(`· draft kept in memory: ${context.draft}`);
|
|
238
|
-
lines.push(report.code === 'behind'
|
|
239
|
-
? '· perceive the pending activity, then retry express with only:'
|
|
240
|
-
: '· correct the problem above, then retry express with only:', `{ "draft": "${context.draft}" }`);
|
|
241
|
-
}
|
|
242
|
-
return lines.join('\n');
|
|
156
|
+
return renderFailureLines(failure, { squarePath: context.location, name: context.participant, surface: 'tool' }).join('\n');
|
|
243
157
|
}
|
package/dist/square-values.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare const WAKE_ROUTE_KINDS: readonly ["opencode-server", "codex-queue", "
|
|
1
|
+
export declare const WAKE_ROUTE_KINDS: readonly ["opencode-server", "codex-queue", "paseo", "http"];
|
|
2
2
|
export type WakeRouteKind = typeof WAKE_ROUTE_KINDS[number];
|
|
3
3
|
export type JsonValue = null | boolean | number | string | readonly JsonValue[] | {
|
|
4
4
|
readonly [key: string]: JsonValue;
|
package/dist/square-values.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { SquareError, nameKey } from './neutral.js';
|
|
2
|
-
export const WAKE_ROUTE_KINDS = ['opencode-server', 'codex-queue', '
|
|
2
|
+
export const WAKE_ROUTE_KINDS = ['opencode-server', 'codex-queue', 'paseo', 'http'];
|
|
3
3
|
export const MESSAGE_METADATA_MAX_BYTES = 16 * 1024;
|
|
4
4
|
export const MESSAGE_METADATA_MAX_DEPTH = 256;
|
|
5
5
|
/** Validate the bounded, lossless JSON object carried by a message. */
|
package/dist/time.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export declare function parseDurationMs(value: string, label: string): number;
|
|
1
2
|
export declare function formatTimestamp(at: number): string;
|
|
2
3
|
export declare function formatDuration(ms: number | undefined): string;
|
|
3
4
|
export declare function formatRelativeTime(at: number, now?: number): string;
|