@astrosheep/square 0.3.14 → 0.3.16
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/codex-plugin/.codex-plugin/plugin.json +1 -1
- package/dist/activity-feed.d.ts +2 -3
- package/dist/activity-feed.js +6 -15
- package/dist/activity.js +1 -1
- package/dist/artifact.js +17 -26
- package/dist/attention-presentation.d.ts +13 -0
- package/dist/attention-presentation.js +22 -0
- package/dist/automatic-session.js +6 -8
- package/dist/boundary-presentation.js +35 -14
- package/dist/claude-hook.js +5 -3
- package/dist/cli/context.d.ts +4 -4
- package/dist/cli/context.js +25 -4
- package/dist/cli/harness-command.js +1 -1
- package/dist/cli/maintenance-commands.js +5 -4
- package/dist/cli/observation-commands.js +24 -16
- package/dist/cli/program.js +1 -1
- package/dist/cli/registry.js +4 -1
- package/dist/cli/square-commands.d.ts +7 -0
- package/dist/cli/square-commands.js +123 -27
- package/dist/codex-hook.js +5 -3
- package/dist/decisions.d.ts +19 -0
- package/dist/decisions.js +45 -12
- package/dist/delivery.d.ts +14 -21
- package/dist/delivery.js +40 -74
- package/dist/help.js +8 -5
- package/dist/inbox.js +1 -0
- package/dist/index.d.ts +1 -10
- package/dist/index.js +0 -32
- package/dist/landing.d.ts +12 -0
- package/dist/landing.js +35 -4
- package/dist/model.d.ts +8 -11
- package/dist/model.js +2 -2
- package/dist/notifications.js +35 -11
- package/dist/paseo-delivery.js +7 -4
- package/dist/paseo.d.ts +6 -0
- package/dist/paseo.js +5 -0
- package/dist/presence.d.ts +3 -0
- package/dist/presence.js +40 -10
- package/dist/presentation.d.ts +6 -2
- package/dist/presentation.js +22 -9
- package/dist/presented.d.ts +2 -0
- package/dist/presented.js +20 -0
- package/dist/registry.js +4 -1
- package/dist/routes.d.ts +5 -0
- package/dist/routes.js +17 -0
- package/dist/runtime.d.ts +4 -5
- package/dist/runtime.js +35 -18
- package/dist/square-core.d.ts +17 -0
- package/dist/square-core.js +51 -1
- package/dist/square-facade.d.ts +9 -1
- package/dist/square-wiring.d.ts +8 -0
- package/dist/square-wiring.js +32 -3
- package/dist/views.d.ts +9 -3
- package/dist/views.js +16 -14
- package/dist/wake-port.d.ts +4 -1
- package/dist/wake-port.js +5 -0
- package/dist/wakes.js +3 -5
- package/dist/watch.js +1 -0
- package/package.json +19 -3
- package/skills/brainstorm/SKILL.md +1 -1
- package/skills/square/.claude-plugin/plugin.json +1 -1
- package/skills/square/SKILL.md +1 -1
package/dist/views.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { type ActivityId } from './square-core.js';
|
|
2
2
|
import { coreParticipants, coreStatus } from './decisions.js';
|
|
3
3
|
import { type PlannedNotification } from './delivery.js';
|
|
4
|
-
import { type ActivitiesOptions, type InboxNotification, type PublicAct, type RoomChangeAct, type StoredAct } from './model.js';
|
|
4
|
+
import { type ActivitiesOptions, type InboxNotification, type PublicAct, type RoomChangeAct, type SquareState, type StoredAct } from './model.js';
|
|
5
5
|
import type { OpenSquare } from './open-square.js';
|
|
6
6
|
import type { Activity, HistoryQuery, ParticipantStatus, PerceivedActivity, SquareSnapshot } from './square-facade.js';
|
|
7
7
|
export interface ActivityPresentation {
|
|
@@ -10,6 +10,7 @@ export interface ActivityPresentation {
|
|
|
10
10
|
readonly pendingPublic: readonly PublicAct[];
|
|
11
11
|
readonly pendingRoomChanges: readonly RoomChangeAct[];
|
|
12
12
|
readonly activities: readonly StoredAct[];
|
|
13
|
+
readonly state: SquareState;
|
|
13
14
|
readonly participantCount: number;
|
|
14
15
|
readonly held: boolean;
|
|
15
16
|
readonly holdReason?: string;
|
|
@@ -22,12 +23,13 @@ export interface EntryPresentation {
|
|
|
22
23
|
readonly context: string;
|
|
23
24
|
readonly joinContext: string;
|
|
24
25
|
readonly recentActivities: readonly StoredAct[];
|
|
26
|
+
readonly state: SquareState;
|
|
25
27
|
readonly sayNumbers: Readonly<Record<number, number>>;
|
|
26
28
|
readonly participantCount: number;
|
|
27
29
|
}
|
|
28
30
|
export interface HistoryPresentation {
|
|
29
31
|
readonly activities: readonly (StoredAct & {
|
|
30
|
-
readonly perception:
|
|
32
|
+
readonly perception: 'full' | 'presence';
|
|
31
33
|
})[];
|
|
32
34
|
readonly sayNumbers: Readonly<Record<number, number>>;
|
|
33
35
|
readonly presenceAnchors: Readonly<Record<number, readonly string[]>>;
|
|
@@ -39,11 +41,13 @@ export interface ListPresentation {
|
|
|
39
41
|
readonly activities: number;
|
|
40
42
|
}
|
|
41
43
|
export interface StatusPresentation {
|
|
44
|
+
readonly state: SquareState;
|
|
42
45
|
readonly status: ReturnType<typeof coreStatus>;
|
|
43
46
|
readonly latestActNumber?: number;
|
|
44
47
|
}
|
|
45
48
|
export interface WatchPresentation {
|
|
46
49
|
readonly activities: readonly StoredAct[];
|
|
50
|
+
readonly state: SquareState;
|
|
47
51
|
readonly participantCount: number;
|
|
48
52
|
readonly presence: {
|
|
49
53
|
readonly participants: ReturnType<typeof coreParticipants>;
|
|
@@ -74,6 +78,8 @@ export declare function resolveParticipant(square: OpenSquare, name: string): Pr
|
|
|
74
78
|
readonly name: string;
|
|
75
79
|
readonly roster: readonly string[];
|
|
76
80
|
}>;
|
|
81
|
+
export declare function currentParticipant(square: OpenSquare, name: string): Promise<string | undefined>;
|
|
82
|
+
export declare function admitsBareExpress(square: OpenSquare, name: string, body: string): Promise<boolean>;
|
|
77
83
|
export declare function participants(square: OpenSquare): Promise<ParticipantStatus[]>;
|
|
78
84
|
export declare function snapshot(square: OpenSquare): Promise<SquareSnapshot>;
|
|
79
85
|
export declare function activityPresentation(square: OpenSquare, name: string): Promise<ActivityPresentation>;
|
package/dist/views.js
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import { extractMentions, formatActivityId, parseActivityId
|
|
1
|
+
import { activeListeners, extractMentions, formatActivityId, parseActivityId } from './square-core.js';
|
|
2
2
|
import { deliveryDelta, peerPublicActs, peerRoomChanges } from './activity-feed.js';
|
|
3
3
|
import { coreActivities, coreParticipants, coreStatus, resolveKnownName } from './decisions.js';
|
|
4
|
-
import { deriveDeliveryModel,
|
|
4
|
+
import { deriveDeliveryModel, isActivitySeen, perceiveActivity, planActNotifications } from './delivery.js';
|
|
5
5
|
import { SquareError, nameKey } from './model.js';
|
|
6
6
|
import { countSays, currentHold, foldedState, freshWatchLease, inSquareCount, isCurrentlyJoined, readCursor, resolveRosterName, rosterNames, watchTerminalStatus } from './runtime.js';
|
|
7
7
|
function expose(stored) {
|
|
8
8
|
if (stored.kind === 'read' || stored.actor === undefined)
|
|
9
9
|
throw new Error(`Cannot expose stored activity ${formatActivityId(stored.index)}`);
|
|
10
|
-
return { id: formatActivityId(stored.index), at: stored.at, kind: stored.kind, actor: stored.actor, ...('body' in stored && stored.body !== undefined ? { body: stored.body } : {}), mentions: stored.kind === 'say' ? extractMentions(stored.body) : [], ...(stored.kind === 'say' && stored.reply !== undefined ? { reply: formatActivityId(stored.reply) } : {}) };
|
|
10
|
+
return { id: formatActivityId(stored.index), at: stored.at, kind: stored.kind, actor: stored.actor, ...('body' in stored && stored.body !== undefined ? { body: stored.body } : {}), mentions: stored.kind === 'say' ? extractMentions(stored.body) : [], ...('target' in stored ? { target: stored.target } : {}), ...(stored.kind === 'say' && stored.reply !== undefined ? { reply: formatActivityId(stored.reply) } : {}) };
|
|
11
11
|
}
|
|
12
|
-
function exposePerceived(stored, viewer) {
|
|
13
|
-
const perception =
|
|
12
|
+
function exposePerceived(state, stored, viewer) {
|
|
13
|
+
const perception = perceiveActivity(state, stored, viewer);
|
|
14
14
|
const activity = expose(stored);
|
|
15
15
|
if (perception === 'full' || activity.body === undefined)
|
|
16
16
|
return { ...activity, perception };
|
|
@@ -36,7 +36,7 @@ function selectHistory(stored, query) {
|
|
|
36
36
|
return query.order === 'desc' ? selected.reverse() : selected;
|
|
37
37
|
}
|
|
38
38
|
function statuses(square, state) {
|
|
39
|
-
return coreStatus(state, square.clock()).participants.filter((participant) => participant.state !== 'not joined').map((participant) => ({ name: participant.name, state: participant.state === 'done' ? 'done' : 'joined', consumedThrough: readCursor(state, participant.name) < 0 ? null : formatActivityId(readCursor(state, participant.name)), watching: participant.presence === 'watching' }));
|
|
39
|
+
return coreStatus(state, square.clock()).participants.filter((participant) => participant.state !== 'not joined').map((participant) => ({ name: participant.name, state: participant.state === 'done' ? 'done' : 'joined', consumedThrough: readCursor(state, participant.name) < 0 ? null : formatActivityId(readCursor(state, participant.name)), watching: participant.presence === 'watching', listening: participant.listening }));
|
|
40
40
|
}
|
|
41
41
|
function anchors(state) {
|
|
42
42
|
const result = {};
|
|
@@ -59,23 +59,25 @@ function sayNumbers(state) {
|
|
|
59
59
|
return result;
|
|
60
60
|
}
|
|
61
61
|
export async function history(square, query = {}) { const { state } = await square.cell.read(); return selectHistory(coreActivities(state, historyOptions(query)), query).map(expose); }
|
|
62
|
-
export async function participantHistory(square, name, query = {}) { const { state } = await square.cell.read(); const viewer = resolveKnownName(state, name); const effective = query.all === true || query.limit !== undefined ? query : { ...query, limit: 10 }; return selectHistory(coreActivities(state, historyOptions(effective, viewer)), effective).map((activity) => exposePerceived(activity, viewer)); }
|
|
62
|
+
export async function participantHistory(square, name, query = {}) { const { state } = await square.cell.read(); const viewer = resolveKnownName(state, name); const effective = query.all === true || query.limit !== undefined ? query : { ...query, limit: 10 }; return selectHistory(coreActivities(state, historyOptions(effective, viewer)), effective).map((activity) => exposePerceived(state, activity, viewer)); }
|
|
63
63
|
export async function resolveParticipant(square, name) { const { state } = await square.cell.read(); return { name: resolveKnownName(state, name), roster: rosterNames(state) }; }
|
|
64
|
+
export async function currentParticipant(square, name) { const { state } = await square.cell.read(); const known = resolveRosterName(state, name); return known !== undefined && isCurrentlyJoined(state.acts, known) ? known : undefined; }
|
|
65
|
+
export async function admitsBareExpress(square, name, body) { const { state } = await square.cell.read(); const actor = resolveKnownName(state, name); return extractMentions(body).length > 0 || activeListeners(foldedState(state), actor).length > 0; }
|
|
64
66
|
export async function participants(square) { const { state } = await square.cell.read(); return statuses(square, state); }
|
|
65
|
-
export async function snapshot(square) { const { state } = await square.cell.read(); const folded = foldedState(state); return { context: [...state.preamble, ...state.warmup].join('\n'), actCount: state.acts.filter((activity) => activity.kind !== 'read').length, hardCap: state.hardCap, ...(state.throttlePerMinute === undefined ? {} : { throttlePerMinute: state.throttlePerMinute }), held: folded.hold.active && folded.hold.actor !== undefined ? { by: folded.hold.actor, ...(folded.hold.reason === undefined ? {} : { reason: folded.hold.reason }) } : null, participants: statuses(square, state), delivered(name, id) { return
|
|
66
|
-
export async function activityPresentation(square, name) { const { state } = await square.cell.read(); const known = resolveKnownName(state, name); const delta = deliveryDelta(state, known); const hold = currentHold(state.acts); return { name: known, roster: rosterNames(state), pendingPublic: peerPublicActs(delta, known), pendingRoomChanges: peerRoomChanges(delta, known), activities: state.acts, participantCount: inSquareCount(state), held: hold.active, ...(hold.reason === undefined ? {} : { holdReason: hold.reason }), ownActivityCount: countSays(state.acts, known), hardCap: state.hardCap }; }
|
|
67
|
-
export async function entryPresentation(square, name, lastN = 10) { const { state } = await square.cell.read(); const known = resolveRosterName(state, name) ?? name; const publicActivities = state.acts.filter((activity) => activity.kind === 'say' || activity.kind === 'done'); return { joined: isCurrentlyJoined(state.acts, known), scene: state.warmup.join('\n').trim(), context: state.preamble.join('\n').trim(), joinContext: (state.preamble.at(-1) === '---' ? state.preamble.slice(0, -1) : state.preamble).join('\n').trim(), recentActivities: lastN === null ? publicActivities : publicActivities.slice(-lastN), sayNumbers: sayNumbers(state), participantCount: inSquareCount(state) }; }
|
|
68
|
-
export async function historyPresentation(square, options) { const { state } = await square.cell.read(); return { activities: coreActivities(state, options).map((activity) => ({ ...activity, perception: options.viewer === undefined ? 'full' :
|
|
67
|
+
export async function snapshot(square) { const { state } = await square.cell.read(); const folded = foldedState(state); return { context: [...state.preamble, ...state.warmup].join('\n'), actCount: state.acts.filter((activity) => activity.kind !== 'read').length, hardCap: state.hardCap, ...(state.throttlePerMinute === undefined ? {} : { throttlePerMinute: state.throttlePerMinute }), held: folded.hold.active && folded.hold.actor !== undefined ? { by: folded.hold.actor, ...(folded.hold.reason === undefined ? {} : { reason: folded.hold.reason }) } : null, participants: statuses(square, state), delivered(name, id) { return isActivitySeen(state, name, parseRequiredActivityId(id)); } }; }
|
|
68
|
+
export async function activityPresentation(square, name) { const { state } = await square.cell.read(); const known = resolveKnownName(state, name); const delta = deliveryDelta(state, known); const hold = currentHold(state.acts); return { name: known, roster: rosterNames(state), pendingPublic: peerPublicActs(delta, known), pendingRoomChanges: peerRoomChanges(delta, known), activities: state.acts, state, participantCount: inSquareCount(state), held: hold.active, ...(hold.reason === undefined ? {} : { holdReason: hold.reason }), ownActivityCount: countSays(state.acts, known), hardCap: state.hardCap }; }
|
|
69
|
+
export async function entryPresentation(square, name, lastN = 10) { const { state } = await square.cell.read(); const known = resolveRosterName(state, name) ?? name; const publicActivities = state.acts.filter((activity) => activity.kind === 'say' || activity.kind === 'done'); return { joined: isCurrentlyJoined(state.acts, known), scene: state.warmup.join('\n').trim(), context: state.preamble.join('\n').trim(), joinContext: (state.preamble.at(-1) === '---' ? state.preamble.slice(0, -1) : state.preamble).join('\n').trim(), recentActivities: lastN === null ? publicActivities : publicActivities.slice(-lastN), state, sayNumbers: sayNumbers(state), participantCount: inSquareCount(state) }; }
|
|
70
|
+
export async function historyPresentation(square, options) { const { state } = await square.cell.read(); return { activities: coreActivities(state, options).map((activity) => ({ ...activity, perception: options.viewer === undefined ? 'full' : perceiveActivity(state, activity, options.viewer) })), sayNumbers: sayNumbers(state), presenceAnchors: anchors(state), participantCount: inSquareCount(state) }; }
|
|
69
71
|
export async function participantsPresentation(square) { const { state } = await square.cell.read(); return coreParticipants(state, square.clock()); }
|
|
70
72
|
export async function listPresentation(square) { const { state } = await square.cell.read(); return { context: state.preamble, participants: foldedState(state).participants.filter((participant) => participant.joined).sort((left, right) => (right.lastActiveAt ?? -Infinity) - (left.lastActiveAt ?? -Infinity) || left.name.localeCompare(right.name)).map((participant) => participant.name), activities: state.acts.filter((activity) => activity.kind === 'say').length }; }
|
|
71
|
-
export async function statusPresentation(square) { const { state } = await square.cell.read(); const status = coreStatus(state, square.clock()); return { status, ...(status.latestAct?.kind === 'say' ? { latestActNumber: countSays(state.acts, status.latestAct.actor) } : {}) }; }
|
|
73
|
+
export async function statusPresentation(square) { const { state } = await square.cell.read(); const status = coreStatus(state, square.clock()); return { state, status, ...(status.latestAct?.kind === 'say' ? { latestActNumber: countSays(state.acts, status.latestAct.actor) } : {}) }; }
|
|
72
74
|
export async function eventPresentation(square, id) { const { state } = await square.cell.read(); const activity = state.acts.find((candidate) => candidate.index === parseRequiredActivityId(id)); if (activity === undefined)
|
|
73
75
|
throw new SquareError('invalid_args', `Unknown activity id: ${id}`); return { activity, participantCount: inSquareCount(state), held: currentHold(state.acts).active }; }
|
|
74
|
-
export async function watchPresentation(square, name) { const { state } = await square.cell.read(); const known = resolveKnownName(state, name); const now = square.clock(); const terminal = watchTerminalStatus(state, known); return { activities: state.acts, participantCount: inSquareCount(state), presence: { participants: coreParticipants(state, now), now }, ...(terminal === undefined ? {} : { terminalStatus: terminal }) }; }
|
|
76
|
+
export async function watchPresentation(square, name) { const { state } = await square.cell.read(); const known = resolveKnownName(state, name); const now = square.clock(); const terminal = watchTerminalStatus(state, known); return { activities: state.acts, state, participantCount: inSquareCount(state), presence: { participants: coreParticipants(state, now), now }, ...(terminal === undefined ? {} : { terminalStatus: terminal }) }; }
|
|
75
77
|
export async function inboxProjection(square, name, ownerId) { const { state } = await square.cell.read(); const known = resolveRosterName(state, name); if (known === undefined || !isCurrentlyJoined(state.acts, known))
|
|
76
78
|
return { name, joined: false, notifications: [] }; const lease = freshWatchLease(state, known, square.clock()); return { name: known, joined: true, notifications: deriveDeliveryModel(state).pendingFor(known).map(({ item, route }) => ({ actIndex: item.index, actor: item.actor, at: item.at, route, body: item.body })), ...(lease?.ownerId === ownerId ? { catchLease: lease } : {}) }; }
|
|
77
79
|
export async function streamProjection(square, cursor, recipient) { const { state } = await square.cell.read(); return { activities: state.acts.filter((activity) => activity.index > cursor).flatMap((activity) => { if (recipient === undefined)
|
|
78
80
|
return [{ activity }]; const notification = planActNotifications(state, activity).find((candidate) => nameKey(candidate.recipient) === nameKey(recipient)); return notification === undefined ? [] : [{ activity, route: notification.route }]; }), cursor: Math.max(cursor, ...state.acts.map((activity) => activity.index)) }; }
|
|
79
81
|
export async function notificationForAct(square, actIndex) { const { state } = await square.cell.read(); const activity = state.acts.find((candidate) => candidate.index === actIndex); return activity === undefined ? [] : planActNotifications(state, activity); }
|
|
80
82
|
export async function pendingDeliveries(square) { const { state } = await square.cell.read(); return [...new Set(state.acts.filter((activity) => activity.kind === 'join').map((activity) => activity.actor))].filter((name) => isCurrentlyJoined(state.acts, name)).map((recipient) => ({ recipient, notifications: deriveDeliveryModel(state).pendingFor(recipient) })); }
|
|
81
|
-
export async function notificationDelivered(square, recipient, actIndex) { const { state } = await square.cell.read(); return
|
|
83
|
+
export async function notificationDelivered(square, recipient, actIndex) { const { state } = await square.cell.read(); return isActivitySeen(state, recipient, actIndex); }
|
package/dist/wake-port.d.ts
CHANGED
|
@@ -4,7 +4,10 @@ export interface WakePortHooks {
|
|
|
4
4
|
nextAttemptN(): number;
|
|
5
5
|
beforeSend(route: WakeRoute, attemptN: number): Promise<boolean>;
|
|
6
6
|
record(route: WakeRoute, attemptN: number, result: Exclude<WakeDispatchResult, {
|
|
7
|
-
outcome: 'cancelled';
|
|
7
|
+
outcome: 'cancelled' | 'unavailable';
|
|
8
|
+
}>): Promise<void>;
|
|
9
|
+
invalidate?(route: WakeRoute, result: Extract<WakeDispatchResult, {
|
|
10
|
+
outcome: 'unavailable';
|
|
8
11
|
}>): Promise<void>;
|
|
9
12
|
}
|
|
10
13
|
export type WakePortResult = {
|
package/dist/wake-port.js
CHANGED
|
@@ -13,6 +13,11 @@ export class WakePort {
|
|
|
13
13
|
const result = await adapter.dispatch(route.address, payload, () => hooks.beforeSend(route, attemptN));
|
|
14
14
|
if (result.outcome === 'cancelled')
|
|
15
15
|
return result;
|
|
16
|
+
if (result.outcome === 'unavailable') {
|
|
17
|
+
if (result.retainRoute !== true)
|
|
18
|
+
await hooks.invalidate?.(route, result);
|
|
19
|
+
continue;
|
|
20
|
+
}
|
|
16
21
|
await hooks.record(route, attemptN, result);
|
|
17
22
|
if (result.outcome === 'accepted' || result.outcome === 'unknown')
|
|
18
23
|
return { outcome: result.outcome };
|
package/dist/wakes.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { formatActivityId } from './square-core.js';
|
|
2
|
-
import {
|
|
2
|
+
import { isActivitySeen } from './delivery.js';
|
|
3
3
|
import { nameKey } from './model.js';
|
|
4
4
|
import { resolveKnownName } from './decisions.js';
|
|
5
|
-
import { WATCH_STALE_MS, currentHold, freshWatchLease, removeWatchLease,
|
|
5
|
+
import { WATCH_STALE_MS, currentHold, freshWatchLease, removeWatchLease, watchTerminalStatus, writeWatchLease } from './runtime.js';
|
|
6
6
|
function filter(options) {
|
|
7
7
|
return { ...(options.participants === undefined ? {} : { participants: [...options.participants] }), ...(options.mention === undefined ? {} : { mention: options.mention }) };
|
|
8
8
|
}
|
|
@@ -15,7 +15,6 @@ export async function acquireWatchLease(square, name, leaseId, options, ownerId)
|
|
|
15
15
|
if (existing !== undefined && !options.replace)
|
|
16
16
|
return { result: { type: 'active', lease: existing } };
|
|
17
17
|
writeWatchLease(state, known, { leaseId, ...(ownerId === undefined ? {} : { ownerId }), heartbeatAt: at, expiresAt: at + WATCH_STALE_MS, ...(Object.keys(filter(options)).length === 0 ? {} : { filter: filter(options) }) });
|
|
18
|
-
touchPresenceCursor(state, known, at);
|
|
19
18
|
return { state, result: { type: 'started', leaseId, replaced: existing !== undefined, heartbeatAt: at } };
|
|
20
19
|
});
|
|
21
20
|
}
|
|
@@ -34,7 +33,6 @@ export async function pulseWatchLease(square, name, leaseId, options, heartbeatD
|
|
|
34
33
|
if (!heartbeatDue)
|
|
35
34
|
return { result: { type: 'sleep' } };
|
|
36
35
|
writeWatchLease(state, known, { leaseId, ...(lease.ownerId === undefined ? {} : { ownerId: lease.ownerId }), heartbeatAt: at, expiresAt: at + WATCH_STALE_MS, ...(Object.keys(filter(options)).length === 0 ? {} : { filter: filter(options) }) });
|
|
37
|
-
touchPresenceCursor(state, known, at);
|
|
38
36
|
return { state, result: { type: 'sleep', heartbeatAt: at } };
|
|
39
37
|
});
|
|
40
38
|
}
|
|
@@ -47,7 +45,7 @@ export async function ownsWatchLease(square, name, leaseId) { const { state } =
|
|
|
47
45
|
export async function claimNotificationLease(square, recipient, actIndex, leaseId, leaseMs) {
|
|
48
46
|
const at = square.clock();
|
|
49
47
|
const key = notificationKey(recipient, actIndex);
|
|
50
|
-
return square.cell.transact((state) => { const known = resolveKnownName(state, recipient); if (
|
|
48
|
+
return square.cell.transact((state) => { const known = resolveKnownName(state, recipient); if (isActivitySeen(state, known, actIndex))
|
|
51
49
|
return { result: { type: 'delivered' } }; const existing = state.runtime.notifyLeases[key]; if (existing !== undefined && existing.expiresAt > at)
|
|
52
50
|
return { result: { type: 'busy' } }; if (existing?.phase === 'dispatching')
|
|
53
51
|
return { result: { type: 'ambiguous', lease: existing } }; state.runtime.notifyLeases[key] = { leaseId, expiresAt: at + leaseMs, phase: 'claimed' }; return { state, result: { type: 'acquired', leaseId } }; });
|
package/dist/watch.js
CHANGED
|
@@ -30,6 +30,7 @@ function watchOutputResult(squarePath, presentation, name, caught, opts = {}) {
|
|
|
30
30
|
squarePath,
|
|
31
31
|
viewer: name,
|
|
32
32
|
showCatchHint: !hasAutomaticDeliveryIdentity(),
|
|
33
|
+
squareState: presentation.state,
|
|
33
34
|
}),
|
|
34
35
|
...(opts.status ? { status: opts.status } : {}),
|
|
35
36
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@astrosheep/square",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.16",
|
|
4
4
|
"description": "A shared public square where agents join, catch activity, express, and step out when done.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -36,15 +36,21 @@
|
|
|
36
36
|
"author": "astrosheep",
|
|
37
37
|
"license": "MIT",
|
|
38
38
|
"devDependencies": {
|
|
39
|
+
"@getpaseo/client": "^0.3.1",
|
|
39
40
|
"@types/cross-spawn": "^6.0.6",
|
|
40
41
|
"@types/node": "^22",
|
|
41
42
|
"@types/ws": "^8.18.1",
|
|
42
|
-
"typescript": "^5.8"
|
|
43
|
+
"typescript": "^5.8",
|
|
44
|
+
"ws": "^8.21.3"
|
|
43
45
|
},
|
|
44
46
|
"exports": {
|
|
45
47
|
".": {
|
|
46
48
|
"types": "./dist/index.d.ts",
|
|
47
49
|
"default": "./dist/index.js"
|
|
50
|
+
},
|
|
51
|
+
"./paseo": {
|
|
52
|
+
"types": "./dist/paseo.d.ts",
|
|
53
|
+
"default": "./dist/paseo.js"
|
|
48
54
|
}
|
|
49
55
|
},
|
|
50
56
|
"main": "dist/index.js",
|
|
@@ -58,8 +64,18 @@
|
|
|
58
64
|
]
|
|
59
65
|
},
|
|
60
66
|
"dependencies": {
|
|
67
|
+
"cross-spawn": "^7.0.6"
|
|
68
|
+
},
|
|
69
|
+
"peerDependencies": {
|
|
61
70
|
"@getpaseo/client": "^0.3.1",
|
|
62
|
-
"cross-spawn": "^7.0.6",
|
|
63
71
|
"ws": "^8.21.3"
|
|
72
|
+
},
|
|
73
|
+
"peerDependenciesMeta": {
|
|
74
|
+
"@getpaseo/client": {
|
|
75
|
+
"optional": true
|
|
76
|
+
},
|
|
77
|
+
"ws": {
|
|
78
|
+
"optional": true
|
|
79
|
+
}
|
|
64
80
|
}
|
|
65
81
|
}
|
|
@@ -7,7 +7,7 @@ allowed-tools: Bash(square *), Skill(square)
|
|
|
7
7
|
# Square Brainstorm
|
|
8
8
|
|
|
9
9
|
Use this skill when you are coordinating a brainstorm. Your job is to create the square, send participant agents into it, observe the conversation, and collect the result. Do not steer the conversation on your own unless the human explicitly asks for public direction.
|
|
10
|
-
Commands
|
|
10
|
+
Commands that access a square require `--location <square>` or `SQUARE_LOCATION`; `--location` wins. Set `SQUARE_PARTICIPANT_NAME` for the participant name, overridden by `--as`. `.square/PUBLIC.square` is the public square and does not need a manual `join`.
|
|
11
11
|
|
|
12
12
|
## Build
|
|
13
13
|
|
package/skills/square/SKILL.md
CHANGED
|
@@ -60,7 +60,7 @@ The ownership boundary belongs here. @bob, does this match your read?
|
|
|
60
60
|
EOF
|
|
61
61
|
```
|
|
62
62
|
|
|
63
|
-
|
|
63
|
+
Normally address the participant who needs an activity with `@name`: mentioned participants hear the full body, while everyone else sees you walk over to them. Use `--bell` only when every participant needs the activity. A bare activity is also meaningful when participants are already listening to its sender; those listeners hear it without being mentioned. The CLI asks for `--force` when a bare activity has no current listener. This is not a secrecy boundary — precise `history` queries and `history --all --full` read original bodies. Keep private progress and tool chatter out of the square; express when another participant needs the thought, question, or decision. Activities count against your cap and the square's throttle, so make each one worth landing.
|
|
64
64
|
|
|
65
65
|
If something happened while your back was turned, `express` stops and prints an exact recovery command: run it, take in what happened, then express again. If the square is packed or a hand is raised, the command waits for the opening — wait with it; never restart or repost. Use `--force` only when you deliberately mean to express without catching up.
|
|
66
66
|
|