@astrosheep/square 0.3.33 → 0.3.35
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 +10 -10
- package/codex-plugin/.codex-plugin/plugin.json +1 -1
- package/dist/activity-feed.js +1 -1
- package/dist/activity.d.ts +1 -0
- package/dist/activity.js +3 -2
- package/dist/artifact.js +2 -1
- package/dist/automatic-session.js +17 -1
- package/dist/boundary-presentation.d.ts +1 -0
- package/dist/boundary-presentation.js +16 -1
- package/dist/catch-decisions.d.ts +4 -0
- package/dist/catch-decisions.js +23 -7
- package/dist/cli/context.d.ts +1 -0
- package/dist/cli/context.js +26 -1
- package/dist/cli/observation-commands.d.ts +7 -1
- package/dist/cli/observation-commands.js +149 -63
- package/dist/cli/program.js +8 -2
- package/dist/cli/square-commands.d.ts +3 -1
- package/dist/cli/square-commands.js +42 -16
- package/dist/codex-queue.d.ts +1 -0
- package/dist/codex-queue.js +1 -1
- package/dist/decisions.d.ts +1 -0
- package/dist/decisions.js +29 -14
- package/dist/delivery-health.d.ts +1 -0
- package/dist/delivery-health.js +19 -6
- package/dist/delivery-operations.js +5 -5
- package/dist/delivery.d.ts +2 -0
- package/dist/delivery.js +1 -0
- package/dist/harness-links.js +15 -3
- package/dist/harness.js +3 -1
- package/dist/help.js +25 -16
- package/dist/inbox.d.ts +2 -0
- package/dist/inbox.js +4 -2
- package/dist/list.js +77 -24
- package/dist/model.d.ts +1 -3
- package/dist/paseo-connection.js +9 -3
- package/dist/paseo-state.d.ts +4 -1
- package/dist/paseo-state.js +2 -2
- package/dist/presentation.d.ts +4 -0
- package/dist/presentation.js +41 -12
- package/dist/runtime.d.ts +1 -0
- package/dist/square-actions.d.ts +5 -0
- package/dist/square-actions.js +31 -7
- package/dist/square-core.d.ts +11 -1
- package/dist/square-core.js +12 -9
- package/dist/square-facade.d.ts +5 -2
- package/dist/square-file-adapter.d.ts +1 -1
- package/dist/square-file-adapter.js +11 -4
- package/dist/square-wiring.d.ts +1 -0
- package/dist/square-wiring.js +5 -1
- package/dist/stream.d.ts +8 -1
- package/dist/stream.js +17 -6
- package/dist/views.d.ts +11 -5
- package/dist/views.js +42 -16
- package/dist/wake-sink.d.ts +2 -0
- package/dist/wake-sink.js +10 -1
- package/dist/watch.js +26 -9
- package/extensions/square-pi.js +41 -7
- package/package.json +1 -1
- package/skills/brainstorm/SKILL.md +8 -6
- package/skills/square/SKILL.md +10 -10
package/dist/decisions.js
CHANGED
|
@@ -1,16 +1,15 @@
|
|
|
1
1
|
import { SquareError, sameName, validateName, } from './model.js';
|
|
2
2
|
import { participantIdentity } from './participant-identity.js';
|
|
3
|
-
import { UNREAD_BLOCK_GRACE_MS, actId, actStableIndex, foldedState, freshWatchLease, publicActs, resolveRosterName,
|
|
3
|
+
import { UNREAD_BLOCK_GRACE_MS, actId, actStableIndex, foldedState, freshWatchLease, publicActs, resolveRosterName, THROTTLE_WINDOW_MS, } from './runtime.js';
|
|
4
4
|
import { actDelta, directedPeerSays } from './activity-feed.js';
|
|
5
|
-
import { formatActivityId, isIgnored, isListening, listeningTo, validate } from './square-core.js';
|
|
5
|
+
import { formatActivityId, isIgnored, isListening, listeningTo, MAX_IDENTITY_SET_SIZE, validate } from './square-core.js';
|
|
6
6
|
import { deriveDeliveryModel } from './delivery.js';
|
|
7
7
|
import { compileSearchPattern } from './search.js';
|
|
8
8
|
export function resolveKnownName(squareState, name) {
|
|
9
9
|
validateName(name);
|
|
10
10
|
const known = resolveRosterName(squareState, name);
|
|
11
11
|
if (known === undefined) {
|
|
12
|
-
|
|
13
|
-
throw new SquareError('invalid_args', `Unknown participant "${participantIdentity(name)}". Expected one of: ${roster.map(participantIdentity).join(', ')}.`);
|
|
12
|
+
throw new SquareError('invalid_args', `Unknown participant "${participantIdentity(name)}".`);
|
|
14
13
|
}
|
|
15
14
|
return known;
|
|
16
15
|
}
|
|
@@ -62,6 +61,8 @@ function requireStanding(squareState, act) {
|
|
|
62
61
|
throw new SquareError('already_done', `${act.actor === undefined ? 'participant' : participantIdentity(act.actor)} is already done`);
|
|
63
62
|
if (result.reason === 'not_joined')
|
|
64
63
|
throw new SquareError('not_joined', `${act.actor === undefined ? 'participant' : participantIdentity(act.actor)} has not joined this square`);
|
|
64
|
+
if (result.reason === 'listening_limit')
|
|
65
|
+
throw new SquareError('invalid_args', `A participant can listen to at most ${result.limit} others`);
|
|
65
66
|
throw new Error(`Unexpected standing validation result: ${result.reason}`);
|
|
66
67
|
}
|
|
67
68
|
const UNREAD_PREVIEW_LIMIT = 3;
|
|
@@ -72,6 +73,26 @@ export function decideAct(squareState, input) {
|
|
|
72
73
|
if (body.trim() === '')
|
|
73
74
|
throw new SquareError('invalid_args', 'express body cannot be empty');
|
|
74
75
|
const reach = input.reach;
|
|
76
|
+
const state = foldedState(squareState);
|
|
77
|
+
const requestedMentions = input.mentions ?? [];
|
|
78
|
+
const mentionNames = [];
|
|
79
|
+
const joinedNames = state.participants.filter((participant) => participant.joined).map((participant) => participant.name);
|
|
80
|
+
for (const requested of requestedMentions) {
|
|
81
|
+
validateName(requested);
|
|
82
|
+
const resolved = joinedNames.find((candidate) => sameName(candidate, requested));
|
|
83
|
+
if (resolved === undefined) {
|
|
84
|
+
throw new SquareError('invalid_args', `Unknown mention target ${participantIdentity(requested)}.`);
|
|
85
|
+
}
|
|
86
|
+
if (!mentionNames.some((existing) => sameName(existing, resolved))) {
|
|
87
|
+
if (mentionNames.length >= MAX_IDENTITY_SET_SIZE) {
|
|
88
|
+
throw new SquareError('invalid_args', `An activity can mention at most ${MAX_IDENTITY_SET_SIZE} participants`);
|
|
89
|
+
}
|
|
90
|
+
mentionNames.push(resolved);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
if (reach === 'bell' && mentionNames.length > 0) {
|
|
94
|
+
throw new SquareError('invalid_args', 'A bell cannot be combined with --mention.');
|
|
95
|
+
}
|
|
75
96
|
const reply = input.reply;
|
|
76
97
|
if (reply !== undefined) {
|
|
77
98
|
if (!Number.isSafeInteger(reply) || reply < 0 || reply >= squareState.runtime.nextActIndex) {
|
|
@@ -79,16 +100,17 @@ export function decideAct(squareState, input) {
|
|
|
79
100
|
throw new SquareError('invalid_args', `Unknown reply activity: ${label}`);
|
|
80
101
|
}
|
|
81
102
|
}
|
|
82
|
-
const state = foldedState(squareState);
|
|
83
103
|
const current = participantState(state, name);
|
|
84
104
|
const result = validate(state, {
|
|
85
|
-
kind: 'say', actor: name, at: now, body,
|
|
105
|
+
kind: 'say', actor: name, at: now, body, mentions: mentionNames,
|
|
86
106
|
...(reach !== undefined ? { reach } : {}),
|
|
87
107
|
...(reply !== undefined ? { reply } : {}),
|
|
88
108
|
}, { hardCap: squareState.hardCap, throttlePerMinute: squareState.throttlePerMinute, throttleWindowMs: THROTTLE_WINDOW_MS });
|
|
89
109
|
if (!result.ok) {
|
|
90
110
|
if (result.reason === 'done')
|
|
91
111
|
throw new SquareError('already_done', `${name} is already done`);
|
|
112
|
+
if (result.reason === 'mention_limit')
|
|
113
|
+
throw new SquareError('invalid_args', `An activity can mention at most ${result.limit} participants`);
|
|
92
114
|
if (result.reason === 'held')
|
|
93
115
|
return { type: 'held', reason: result.hold.reason };
|
|
94
116
|
if (result.reason === 'hard_cap')
|
|
@@ -142,7 +164,7 @@ export function decideAct(squareState, input) {
|
|
|
142
164
|
return {
|
|
143
165
|
type: 'sent',
|
|
144
166
|
act: {
|
|
145
|
-
kind: 'say', actor: name, at: now, body,
|
|
167
|
+
kind: 'say', actor: name, at: now, body, mentions: mentionNames,
|
|
146
168
|
...(reach !== undefined ? { reach } : {}),
|
|
147
169
|
...(reply !== undefined ? { reply } : {}),
|
|
148
170
|
},
|
|
@@ -254,7 +276,6 @@ export function coreParticipants(squareState, now, delivery) {
|
|
|
254
276
|
export function coreActivities(squareState, opts, suppliedDelivery) {
|
|
255
277
|
const participants = opts.participants ?? [];
|
|
256
278
|
const canonicalParticipants = participants.map((participant) => resolveKnownName(squareState, participant));
|
|
257
|
-
const viewer = opts.viewer !== undefined ? resolveKnownName(squareState, opts.viewer) : undefined;
|
|
258
279
|
let acts = [...squareState.acts];
|
|
259
280
|
let delivery = suppliedDelivery;
|
|
260
281
|
const projected = () => delivery ??= deriveDeliveryModel(squareState);
|
|
@@ -285,12 +306,6 @@ export function coreActivities(squareState, opts, suppliedDelivery) {
|
|
|
285
306
|
const mention = resolveKnownName(squareState, opts.mention);
|
|
286
307
|
acts = acts.filter((act) => act.kind === 'say' && projected().plan(act).some((item) => sameName(item.recipient, mention)));
|
|
287
308
|
}
|
|
288
|
-
if (opts.pending) {
|
|
289
|
-
if (viewer === undefined)
|
|
290
|
-
return [];
|
|
291
|
-
const pendingIndexes = new Set(projected().pendingFor(viewer).map((notification) => notification.item.index));
|
|
292
|
-
acts = acts.filter((act) => pendingIndexes.has(act.index));
|
|
293
|
-
}
|
|
294
309
|
const search = opts.grep !== undefined ? { pattern: opts.grep, fixed: false } : opts.fixed !== undefined ? { pattern: opts.fixed, fixed: true } : undefined;
|
|
295
310
|
if (search !== undefined && search.pattern !== '') {
|
|
296
311
|
// Search only the public activity model rendered by history, but include all
|
|
@@ -18,4 +18,5 @@ export declare function classifyDeliveryHealth(squarePath: string, opts: {
|
|
|
18
18
|
now?: number;
|
|
19
19
|
env?: NodeJS.ProcessEnv;
|
|
20
20
|
}): Promise<DeliveryHealthItem[]>;
|
|
21
|
+
export declare function renderDeliveryHealth(items: readonly DeliveryHealthItem[]): string[];
|
|
21
22
|
export declare function doctorDeliveryHealth(squarePath: string, graceMs: number, now?: number, env?: NodeJS.ProcessEnv): Promise<string[]>;
|
package/dist/delivery-health.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { formatActivityId } from './square-core.js';
|
|
2
|
-
import { participantIdentity } from './presentation.js';
|
|
2
|
+
import { participantIdentity, truncateChars } from './presentation.js';
|
|
3
3
|
import { formatDuration } from './time.js';
|
|
4
4
|
import { wakeEvidence } from './wake-evidence.js';
|
|
5
5
|
import { openSquare } from './square-file-adapter.js';
|
|
@@ -13,6 +13,8 @@ const DISPLAY_ORDER = [
|
|
|
13
13
|
'unreachable',
|
|
14
14
|
];
|
|
15
15
|
const ACTIONABLE = new Set(['wake-unknown', 'unreachable']);
|
|
16
|
+
const DETAIL_LIMIT = 20;
|
|
17
|
+
const DISPLAY_FIELD_LIMIT = 160;
|
|
16
18
|
/** Purely classify current pending attention from the artifact and durable ledgers. */
|
|
17
19
|
export async function classifyDeliveryHealth(squarePath, opts) {
|
|
18
20
|
const now = opts.now ?? Date.now();
|
|
@@ -49,21 +51,32 @@ export async function classifyDeliveryHealth(squarePath, opts) {
|
|
|
49
51
|
}
|
|
50
52
|
return items;
|
|
51
53
|
}
|
|
54
|
+
function displayField(value) {
|
|
55
|
+
const truncated = truncateChars(value, DISPLAY_FIELD_LIMIT - 1);
|
|
56
|
+
return truncated.remaining === 0 ? truncated.text : `${truncated.text}…`;
|
|
57
|
+
}
|
|
52
58
|
function formatItem(item) {
|
|
53
|
-
const evidence = item.attempt?.signature === undefined ? '' : ` · ${item.attempt.signature}`;
|
|
54
|
-
return ` · ${formatActivityId(item.actIndex)} → ${participantIdentity(item.recipient)} from ${participantIdentity(item.actor)} · ${formatDuration(item.ageMs)}${evidence}`;
|
|
59
|
+
const evidence = item.attempt?.signature === undefined ? '' : ` · ${displayField(item.attempt.signature)}`;
|
|
60
|
+
return ` · ${formatActivityId(item.actIndex)} → ${displayField(participantIdentity(item.recipient))} from ${displayField(participantIdentity(item.actor))} · ${formatDuration(item.ageMs)}${evidence}`;
|
|
55
61
|
}
|
|
56
|
-
export
|
|
57
|
-
const items = await classifyDeliveryHealth(squarePath, { graceMs, now, env });
|
|
62
|
+
export function renderDeliveryHealth(items) {
|
|
58
63
|
if (items.length === 0)
|
|
59
64
|
return ['✓ no pending delivery attention'];
|
|
60
65
|
const out = [`· delivery attention · ${items.length} pending`];
|
|
66
|
+
let displayed = 0;
|
|
61
67
|
for (const kind of DISPLAY_ORDER) {
|
|
62
68
|
const group = items.filter((item) => item.kind === kind);
|
|
63
69
|
if (group.length === 0)
|
|
64
70
|
continue;
|
|
65
71
|
out.push(`${ACTIONABLE.has(kind) ? '✕' : '○'} ${kind}: ${group.length}`);
|
|
66
|
-
|
|
72
|
+
const details = group.slice(0, DETAIL_LIMIT - displayed);
|
|
73
|
+
out.push(...details.map(formatItem));
|
|
74
|
+
displayed += details.length;
|
|
67
75
|
}
|
|
76
|
+
if (items.length > DETAIL_LIMIT)
|
|
77
|
+
out.push(`${DETAIL_LIMIT} of ${items.length} pending details shown`);
|
|
68
78
|
return out;
|
|
69
79
|
}
|
|
80
|
+
export async function doctorDeliveryHealth(squarePath, graceMs, now = Date.now(), env = process.env) {
|
|
81
|
+
return renderDeliveryHealth(await classifyDeliveryHealth(squarePath, { graceMs, now, env }));
|
|
82
|
+
}
|
|
@@ -59,16 +59,16 @@ export async function deliverPending(input) {
|
|
|
59
59
|
let notCapable = 0;
|
|
60
60
|
for (const membership of observation.pending) {
|
|
61
61
|
for (const notification of membership.notifications) {
|
|
62
|
-
const candidates = routes.filter((route) => nameKey(route.participant) === nameKey(membership.recipient));
|
|
63
|
-
if (candidates.length === 0) {
|
|
64
|
-
notCapable += 1;
|
|
65
|
-
continue;
|
|
66
|
-
}
|
|
67
62
|
if (input.activity !== undefined) {
|
|
68
63
|
const requested = typeof input.activity === 'number' ? input.activity : parseActivityId(input.activity);
|
|
69
64
|
if (requested === undefined || requested !== notification.item.index)
|
|
70
65
|
continue;
|
|
71
66
|
}
|
|
67
|
+
const candidates = routes.filter((route) => nameKey(route.participant) === nameKey(membership.recipient));
|
|
68
|
+
if (candidates.length === 0) {
|
|
69
|
+
notCapable += 1;
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
72
|
let acceptedForAttention = false;
|
|
73
73
|
try {
|
|
74
74
|
const prior = await input.hostLedger.listWakeAttempts({ attention: { squarePath: input.location, actIndex: notification.item.index, recipient: membership.recipient }, now: input.now });
|
package/dist/delivery.d.ts
CHANGED
|
@@ -46,12 +46,14 @@ export interface WakeAdapter {
|
|
|
46
46
|
export interface RoutedNotification {
|
|
47
47
|
actor: string;
|
|
48
48
|
body: string;
|
|
49
|
+
mentions?: readonly string[];
|
|
49
50
|
route: DirectedNotificationRoute;
|
|
50
51
|
recipient?: string;
|
|
51
52
|
}
|
|
52
53
|
export interface CatchFilterShape {
|
|
53
54
|
actor: string;
|
|
54
55
|
body: string;
|
|
56
|
+
mentions?: readonly string[];
|
|
55
57
|
reach?: Reach;
|
|
56
58
|
recipients?: readonly string[];
|
|
57
59
|
}
|
package/dist/delivery.js
CHANGED
|
@@ -125,6 +125,7 @@ export function leaseOwnsNotification(lease, notification) {
|
|
|
125
125
|
return matchesCatchFilter({
|
|
126
126
|
actor: notification.actor,
|
|
127
127
|
body: notification.body,
|
|
128
|
+
...(notification.mentions === undefined ? {} : { mentions: notification.mentions }),
|
|
128
129
|
...(notification.recipient === undefined ? {} : { recipients: [notification.recipient] }),
|
|
129
130
|
...(notification.route === 'bell' ? { reach: 'bell' } : {}),
|
|
130
131
|
}, lease.filter ?? {});
|
package/dist/harness-links.js
CHANGED
|
@@ -4,6 +4,7 @@ import path from 'node:path';
|
|
|
4
4
|
import { fileURLToPath } from 'node:url';
|
|
5
5
|
import crossSpawn from 'cross-spawn';
|
|
6
6
|
import { SQUARE_IDENTITY } from './identity.js';
|
|
7
|
+
import { truncateExternalDiagnostic } from './presentation.js';
|
|
7
8
|
function packageRoot() {
|
|
8
9
|
// Emitted modules live in dist; package assets are one level above them.
|
|
9
10
|
return fileURLToPath(new URL('../', import.meta.url));
|
|
@@ -75,7 +76,16 @@ export function doctorHarnessLinks(links) {
|
|
|
75
76
|
: `○ Square ${link.kind ?? 'link'} missing ${link.target}`);
|
|
76
77
|
}
|
|
77
78
|
function runOpenCode(homeDir, args) {
|
|
78
|
-
const
|
|
79
|
+
const prefix = (() => {
|
|
80
|
+
try {
|
|
81
|
+
const parsed = JSON.parse(process.env.SQUARE_OPENCODE_BIN_ARGS ?? '[]');
|
|
82
|
+
return Array.isArray(parsed) && parsed.every((item) => typeof item === 'string') ? parsed : [];
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
return [];
|
|
86
|
+
}
|
|
87
|
+
})();
|
|
88
|
+
const result = crossSpawn.sync(process.env.SQUARE_OPENCODE_BIN || 'opencode', [...prefix, ...args], {
|
|
79
89
|
encoding: 'utf8',
|
|
80
90
|
env: { ...process.env, HOME: homeDir, XDG_CONFIG_HOME: process.env.XDG_CONFIG_HOME ?? path.join(homeDir, '.config') },
|
|
81
91
|
timeout: 30_000,
|
|
@@ -125,7 +135,8 @@ export function verifyOpenCodeRuntime(homeDir, run = runOpenCode) {
|
|
|
125
135
|
try {
|
|
126
136
|
const result = run(homeDir, ['debug', 'config']);
|
|
127
137
|
if (result.status !== 0) {
|
|
128
|
-
|
|
138
|
+
const diagnostic = result.stderr.trim() || result.stdout.trim() || `exit ${result.status}`;
|
|
139
|
+
return `✕ OpenCode debug config failed: ${truncateExternalDiagnostic(diagnostic)}`;
|
|
129
140
|
}
|
|
130
141
|
let config;
|
|
131
142
|
try {
|
|
@@ -141,7 +152,8 @@ export function verifyOpenCodeRuntime(homeDir, run = runOpenCode) {
|
|
|
141
152
|
return `○ OpenCode npm plugin not loaded: ${expected}`;
|
|
142
153
|
}
|
|
143
154
|
catch (error) {
|
|
144
|
-
|
|
155
|
+
const diagnostic = error instanceof Error ? error.message : String(error);
|
|
156
|
+
return `○ OpenCode runtime unavailable (${truncateExternalDiagnostic(diagnostic)})`;
|
|
145
157
|
}
|
|
146
158
|
}
|
|
147
159
|
export function skillLinks(homeDir = os.homedir(), parents = ['.claude', '.agents']) {
|
package/dist/harness.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import { doctorDeliveryHealth } from './delivery-health.js';
|
|
3
3
|
import { wakeGraceMs } from './notifications.js';
|
|
4
|
+
import { truncateExternalDiagnostic } from './presentation.js';
|
|
4
5
|
import { doctorClaudePlugin, installClaudePlugin, uninstallClaudePlugin, } from './harness-claude.js';
|
|
5
6
|
import { doctorCodexPlugin, installCodexPlugin, uninstallCodexPlugin, } from './harness-codex.js';
|
|
6
7
|
import { doctorPiPackage, installPiPackage, uninstallPiPackage, } from './harness-pi.js';
|
|
@@ -13,7 +14,8 @@ async function doctorHost(label, inspect) {
|
|
|
13
14
|
return result(await inspect());
|
|
14
15
|
}
|
|
15
16
|
catch (error) {
|
|
16
|
-
|
|
17
|
+
const diagnostic = error instanceof Error ? error.message : String(error);
|
|
18
|
+
return result([`○ ${label} doctor unavailable (${truncateExternalDiagnostic(diagnostic)})`]);
|
|
17
19
|
}
|
|
18
20
|
}
|
|
19
21
|
function openCodeLinks(homeDir) {
|
package/dist/help.js
CHANGED
|
@@ -7,46 +7,50 @@ const COMMANDS = [
|
|
|
7
7
|
details: ['Options:', ' --cap <N|unlimited> Set a per-participant activity cap (default unlimited).', ' --template <name> Append a packaged activity guide.', ' --throttle <N> Allow at most N public activities per minute.', ' -f, --force Replace an existing artifact.'],
|
|
8
8
|
},
|
|
9
9
|
{
|
|
10
|
-
names: ['list', 'ls'], usage: '{command} [--depth N]', summary: 'List nearby squares below the current directory.', group: 'host',
|
|
11
|
-
details: ['Options:', ' --depth <N>
|
|
10
|
+
names: ['list', 'ls'], usage: '{command} [--depth N] [--limit N] [--after path]', summary: 'List nearby squares below the current directory.', group: 'host',
|
|
11
|
+
details: ['Options:', ' --depth <N> Descend through at most N directory levels (default 4; maximum 16; 0 scans only the current directory).', ' --limit <N> Show one page (default 20, maximum 100).', ' --after <path> Resume after a relative path from a previous page.'],
|
|
12
12
|
},
|
|
13
13
|
{
|
|
14
|
-
names: ['join'], usage: '--as <name> join [--last N
|
|
14
|
+
names: ['join'], usage: '--as <name> join [--last N] [--kick]', usesSquare: true, group: 'participant',
|
|
15
15
|
summary: 'Step into the square and read its current context.',
|
|
16
|
-
details: ['Options:', ' --last <N> Show the last N public activities (default 10).', ' --
|
|
16
|
+
details: ['Options:', ' --last <N> Show the last N public activities (default 10, maximum 100).', ' --kick End the standing participant and reclaim the name for this session.'],
|
|
17
17
|
},
|
|
18
18
|
{
|
|
19
|
-
names: ['express'], usage: '--as <name> express [-f|--force] [--no-wait]
|
|
19
|
+
names: ['express'], usage: '--as <name> express [-f|--force] [--no-wait] (--mention <name>... | --no-mention | --bell) [--reply <activity-id>] <activity | ->', usesSquare: true, group: 'participant',
|
|
20
20
|
summary: 'Speak, gesture, or do both.',
|
|
21
|
-
details: ['Reach:', '
|
|
21
|
+
details: ['Reach:', ' --mention <name> Address one participant; repeat for multiple participants. The body stays unchanged.', ' --no-mention Land a bare activity explicitly; listen opts someone into future bare delivery.', " --bell Call every participant's attention to this activity.", '', 'Options:', ' -f, --force Express without first catching unread activity or attention etiquette.', ' --no-wait If held or throttled, save a draft and return.', ' --reply <activity-id> Mark this activity as a reply to an earlier activity (for example act/12).'],
|
|
22
22
|
},
|
|
23
23
|
{ names: ['listen'], usage: '--as <name> listen <participant>', usesSquare: true, group: 'participant', summary: 'Turn an ear toward one participant\'s future bare says.' },
|
|
24
24
|
{ names: ['ignore'], usage: '--as <name> ignore <participant>', usesSquare: true, group: 'participant', summary: 'Ignore one participant\'s future mentions and bare says.' },
|
|
25
25
|
{ names: ['listening'], usage: '--as <name> listening', usesSquare: true, group: 'participant', summary: 'Show who you are turned toward.', details: ['Listening is future-only: the edge is fixed when a say lands; it never rewrites history.'] },
|
|
26
26
|
{
|
|
27
|
-
names: ['catch'], usage: '--as <name> catch (--now | --idle <duration>) [--from <names>] [--mention [
|
|
27
|
+
names: ['catch'], usage: '--as <name> catch (--now | --idle <duration>) [--from <names>] [--mention] [--limit <count>] [--replace]', usesSquare: true, group: 'participant',
|
|
28
28
|
summary: 'Catch directed conversation since you last looked.',
|
|
29
|
-
details: ['Modes:', ' --now Catch up immediately.', ' --idle <duration> Wait for something relevant, or for quiet to last this long.', '', 'Attention:', ' Mentions arrive when you are addressed; bells arrive for everyone; bare says require listen.', ' listen and ignore are future-only and fixed when each say lands.', '', 'Filters:', ' --from <names> Match only comma-separated participants.', ' --mention
|
|
29
|
+
details: ['Modes:', ' --now Catch up immediately.', ' --idle <duration> Wait for something relevant, or for quiet to last this long.', '', 'Attention:', ' Mentions arrive when you are addressed; bells arrive for everyone; bare says require listen.', ' listen and ignore are future-only and fixed when each say lands.', '', 'Filters:', ' --from <names> Match only comma-separated participants.', ' --mention Match direct attention for your current participant (and bells).', ' --limit <count> Return one page (default 10, maximum 100).', '', 'Recovery:', ' --replace Replace another active catch for this participant.'],
|
|
30
30
|
},
|
|
31
31
|
{ names: ['done'], usage: '--as <name> done [final | -]', usesSquare: true, group: 'participant', summary: 'Step out, optionally leaving a final note.' },
|
|
32
32
|
{
|
|
33
|
-
names: ['stream'], usage: 'stream [--ndjson [--for <name>]]', usesSquare: true, hiddenFromIndex: true,
|
|
33
|
+
names: ['stream'], usage: 'stream [--ndjson [--for <name>] [--last <N> | --after <id>]]', usesSquare: true, hiddenFromIndex: true,
|
|
34
34
|
summary: 'Follow activity without consuming participant presence.',
|
|
35
|
-
details: ['Options:', ' --ndjson Emit one JSON event per line.', ' --for <name> With --ndjson, emit notifications for one participant.'],
|
|
35
|
+
details: ['Options:', ' --ndjson Emit one JSON event per line.', ' --for <name> With --ndjson, emit notifications for one participant.', ' --last <N> Emit the last N eligible activities first (default 10, maximum 100).', ' --after <id> Resume after a canonical activity id (act/12).'],
|
|
36
36
|
},
|
|
37
37
|
{
|
|
38
|
-
names: ['inbox'], usage: 'inbox --for-session <session-id> [--json]', hiddenFromIndex: true,
|
|
39
|
-
summary: 'Inspect bounded machine-local
|
|
40
|
-
details: ['Options:', ' --for-session <id> Required harness session id.', ' --json Emit structured JSON.'],
|
|
38
|
+
names: ['inbox'], usage: 'inbox --for-session <session-id> [--limit <N>] [--json]', hiddenFromIndex: true,
|
|
39
|
+
summary: 'Inspect a bounded machine-local notification snapshot for a native session.',
|
|
40
|
+
details: ['Options:', ' --for-session <id> Required harness session id.', ' --limit <N> Snapshot memberships (default 20, maximum 100).', ' --json Emit the bounded snapshot as structured JSON.'],
|
|
41
41
|
},
|
|
42
42
|
{ names: ['claude-hook', 'codex-hook'], usage: '{command}', summary: 'Present pending attention at one native agent boundary.', hiddenFromIndex: true },
|
|
43
43
|
{
|
|
44
|
-
names: ['history'], usage: '
|
|
44
|
+
names: ['history'], usage: 'history [filters] [output]', usesSquare: true, group: 'participant',
|
|
45
45
|
summary: 'Read or search the archive without changing what you have caught.',
|
|
46
|
-
details: ['Filters:', ' --from <names> Match activities from participants.', ' --since <time> Match activities after a time.', ' --grep <regex> | --fixed <s> Search activity ids, participants, and original bodies.', ' --mention <name> Match direct attention for a participant.', ' --
|
|
46
|
+
details: ['Filters:', ' --from <names> Match activities from participants.', ' --since <time> Match activities after a time.', ' --grep <regex> | --fixed <s> Search activity ids, participants, and original bodies.', ' --mention <name> Match direct attention for a participant.', ' --at <ids> Center on comma-separated activity ids; may repeat.', ' -B, -A, -C <N> Set non-negative context around every --at coordinate.', ' --before <id> Read the page immediately before an activity.', ' --after <id> Read the page immediately after an activity.', '', 'Results:', ' --limit <N> Page size (default 10, maximum 100).', ' --order <asc|desc> Set display order (default oldest first).', '', 'Output:', ' --no-truncate --json --format <fields>', ' One result shows its full body; multiple results use previews.', ' --no-truncate shows every original body.'],
|
|
47
47
|
},
|
|
48
48
|
{ names: ['status'], usage: '[--as <name>] status', usesSquare: true, group: 'participant', summary: 'Show who is present and what happened most recently.' },
|
|
49
|
-
{
|
|
49
|
+
{
|
|
50
|
+
names: ['participants'], usage: 'participants [--limit <count>]', usesSquare: true, group: 'host',
|
|
51
|
+
summary: 'Show the participant roster and current states.',
|
|
52
|
+
details: ['Options:', ' --limit <count> Show the first count names in roster order (default 20, maximum 100).'],
|
|
53
|
+
},
|
|
50
54
|
{ names: ['hold'], usage: '--as <name> hold [reason | -]', usesSquare: true, group: 'participant', summary: 'Raise a hand and pause participant activity.' },
|
|
51
55
|
{ names: ['resume'], usage: '--as <name> resume', usesSquare: true, group: 'participant', summary: 'Lower the raised hand and resume activity.' },
|
|
52
56
|
{
|
|
@@ -121,17 +125,22 @@ export function renderSubcommandHelp(command) {
|
|
|
121
125
|
}
|
|
122
126
|
export function helpRequest(rawArgs) {
|
|
123
127
|
const args = [];
|
|
128
|
+
let hasExplicitName = false;
|
|
124
129
|
for (let index = 0; index < rawArgs.length; index++) {
|
|
125
130
|
const arg = rawArgs[index];
|
|
126
131
|
if (arg === '--location' || arg === '--as') {
|
|
127
132
|
const value = rawArgs[index + 1];
|
|
128
133
|
if (value === undefined || value.startsWith('--'))
|
|
129
134
|
return undefined;
|
|
135
|
+
if (arg === '--as')
|
|
136
|
+
hasExplicitName = true;
|
|
130
137
|
index++;
|
|
131
138
|
continue;
|
|
132
139
|
}
|
|
133
140
|
args.push(arg);
|
|
134
141
|
}
|
|
142
|
+
if (hasExplicitName && args[0] === 'history')
|
|
143
|
+
return undefined;
|
|
135
144
|
if (isHelpFlag(args[0]))
|
|
136
145
|
return {};
|
|
137
146
|
if (args[0] === 'help') {
|
package/dist/inbox.d.ts
CHANGED
|
@@ -5,6 +5,8 @@ export interface PendingWaitOptions {
|
|
|
5
5
|
excludeKeys?: ReadonlySet<string>;
|
|
6
6
|
/** After a delivery failure, wait for a new state edge before retrying the same pending work. */
|
|
7
7
|
skipImmediate?: boolean;
|
|
8
|
+
/** Reports whether a change wait has been established for a deferred retry. */
|
|
9
|
+
onChangeArmed?: (armed: boolean) => void;
|
|
8
10
|
}
|
|
9
11
|
export declare function sessionInbox(sessionId: string, env?: NodeJS.ProcessEnv): Promise<InboxMembership[]>;
|
|
10
12
|
/** Wait for a bound square to produce a new pending notification without consuming it. */
|
package/dist/inbox.js
CHANGED
|
@@ -59,8 +59,10 @@ export async function waitForSessionPending(sessionId, timeoutMs, options = {},
|
|
|
59
59
|
if (immediate.some((membership) => membership.notifications.length > 0))
|
|
60
60
|
return immediate;
|
|
61
61
|
}
|
|
62
|
-
if (timeoutMs <= 0 || options.signal?.aborted)
|
|
62
|
+
if (timeoutMs <= 0 || options.signal?.aborted) {
|
|
63
|
+
options.onChangeArmed?.(false);
|
|
63
64
|
return [];
|
|
65
|
+
}
|
|
64
66
|
const bindings = await projectSessionBindings({ hostLedger: hostLedgerForEnv(env), sessionId });
|
|
65
67
|
const paths = [...new Set(bindings.map((binding) => binding.location))];
|
|
66
68
|
let aborted = false;
|
|
@@ -77,7 +79,7 @@ export async function waitForSessionPending(sessionId, timeoutMs, options = {},
|
|
|
77
79
|
return undefined;
|
|
78
80
|
const current = withoutExcluded(await sessionInbox(sessionId, env), options.excludeKeys);
|
|
79
81
|
return current.some((membership) => membership.notifications.length > 0) ? current : undefined;
|
|
80
|
-
});
|
|
82
|
+
}, options.onChangeArmed);
|
|
81
83
|
if (aborted || change.status === 'expired')
|
|
82
84
|
return [];
|
|
83
85
|
if (change.status === 'ready')
|
package/dist/list.js
CHANGED
|
@@ -4,10 +4,15 @@ import { probeSquare } from './square-file-adapter.js';
|
|
|
4
4
|
import { closeOpenSquare } from './open-square.js';
|
|
5
5
|
import { listPresentation } from './views.js';
|
|
6
6
|
import { formatRelativeTime } from './time.js';
|
|
7
|
-
import { participantIdentity } from './presentation.js';
|
|
7
|
+
import { participantIdentity, quoteShell } from './presentation.js';
|
|
8
8
|
const DEFAULT_LIST_DEPTH = 4;
|
|
9
|
+
const MAX_LIST_DEPTH = 16;
|
|
10
|
+
const DEFAULT_LIST_LIMIT = 20;
|
|
11
|
+
const MAX_LIST_LIMIT = 100;
|
|
12
|
+
const LIST_DISCOVERY_BUDGET = 10_000;
|
|
9
13
|
const CONTEXT_PREVIEW_LINES = 2;
|
|
10
14
|
const PARTICIPANT_PREVIEW_COUNT = 3;
|
|
15
|
+
const DISPLAY_CHARACTER_LIMIT = 160;
|
|
11
16
|
const LIST_SKIP_DIRS = new Set(['.git', 'node_modules', 'dist']);
|
|
12
17
|
function contextLines(lines) {
|
|
13
18
|
return lines.map((line) => line.trim()).filter(Boolean);
|
|
@@ -35,7 +40,11 @@ async function readSquareListItem(filePath, root) {
|
|
|
35
40
|
}
|
|
36
41
|
async function collectSquareList(root, maxDepth) {
|
|
37
42
|
const items = [];
|
|
43
|
+
let examined = 0;
|
|
44
|
+
let stopped = false;
|
|
38
45
|
async function walk(dir, depth) {
|
|
46
|
+
if (stopped)
|
|
47
|
+
return;
|
|
39
48
|
let entries;
|
|
40
49
|
try {
|
|
41
50
|
entries = await fs.promises.readdir(dir, { withFileTypes: true });
|
|
@@ -44,10 +53,16 @@ async function collectSquareList(root, maxDepth) {
|
|
|
44
53
|
// Directory vanished or became unreadable mid-walk — skip it, don't abort the scan.
|
|
45
54
|
return;
|
|
46
55
|
}
|
|
56
|
+
entries.sort((left, right) => left.name.localeCompare(right.name));
|
|
47
57
|
for (const entry of entries) {
|
|
58
|
+
if (stopped)
|
|
59
|
+
return;
|
|
60
|
+
examined += 1;
|
|
61
|
+
if (examined === LIST_DISCOVERY_BUDGET)
|
|
62
|
+
stopped = true;
|
|
48
63
|
const fullPath = path.join(dir, entry.name);
|
|
49
64
|
if (entry.isDirectory()) {
|
|
50
|
-
if (depth < maxDepth && !LIST_SKIP_DIRS.has(entry.name))
|
|
65
|
+
if (!stopped && depth < maxDepth && !LIST_SKIP_DIRS.has(entry.name))
|
|
51
66
|
await walk(fullPath, depth + 1);
|
|
52
67
|
continue;
|
|
53
68
|
}
|
|
@@ -59,46 +74,84 @@ async function collectSquareList(root, maxDepth) {
|
|
|
59
74
|
}
|
|
60
75
|
}
|
|
61
76
|
await walk(root, 0);
|
|
62
|
-
return items.sort((a, b) => a.path.localeCompare(b.path));
|
|
77
|
+
return { items: items.sort((a, b) => a.path.localeCompare(b.path)), stopped };
|
|
78
|
+
}
|
|
79
|
+
function characterPreview(value) {
|
|
80
|
+
const characters = Array.from(value);
|
|
81
|
+
return characters.length <= DISPLAY_CHARACTER_LIMIT ? value : `${characters.slice(0, DISPLAY_CHARACTER_LIMIT - 1).join('')}…`;
|
|
63
82
|
}
|
|
64
|
-
function renderSquareList(items) {
|
|
65
|
-
|
|
66
|
-
|
|
83
|
+
function renderSquareList(items, stopped, depth, limit, after) {
|
|
84
|
+
const page = after === undefined ? items : items.filter((item) => item.path.localeCompare(after) > 0);
|
|
85
|
+
const shownItems = page.slice(0, limit);
|
|
86
|
+
if (items.length === 0) {
|
|
87
|
+
return [`(no squares found)`, ...(stopped ? [`○ discovery stopped after examining ${LIST_DISCOVERY_BUDGET} filesystem entries; results may be incomplete`] : [])].join('\n') + '\n';
|
|
88
|
+
}
|
|
67
89
|
const now = Date.now();
|
|
68
90
|
const lines = ['squares'];
|
|
69
|
-
for (const item of
|
|
70
|
-
lines.push(`${item.activities > 0 ? '●' : '○'} ${item.path} · ${formatRelativeTime(item.lastActiveAt, now)} · ${item.participants.length} in square · ${item.activities} activities`);
|
|
91
|
+
for (const item of shownItems) {
|
|
92
|
+
lines.push(`${item.activities > 0 ? '●' : '○'} ${characterPreview(item.path)} · ${formatRelativeTime(item.lastActiveAt, now)} · ${item.participants.length} in square · ${item.activities} activities`);
|
|
71
93
|
const shownContext = item.context.slice(0, CONTEXT_PREVIEW_LINES);
|
|
72
94
|
if (shownContext.length === 0) {
|
|
73
95
|
lines.push(' context · (none)');
|
|
74
96
|
}
|
|
75
97
|
else {
|
|
76
|
-
shownContext.forEach((line, index) => lines.push(` ${index === 0 ? 'context' : ' '} · ${line}`));
|
|
98
|
+
shownContext.forEach((line, index) => lines.push(` ${index === 0 ? 'context' : ' '} · ${characterPreview(line)}`));
|
|
77
99
|
const hiddenContext = item.context.length - shownContext.length;
|
|
78
100
|
if (hiddenContext > 0)
|
|
79
101
|
lines.push(` · … ${hiddenContext} more ${hiddenContext === 1 ? 'line' : 'lines'}`);
|
|
80
102
|
}
|
|
81
103
|
const shownParticipants = item.participants.slice(0, PARTICIPANT_PREVIEW_COUNT);
|
|
82
104
|
const hiddenParticipants = item.participants.length - shownParticipants.length;
|
|
83
|
-
lines.push(` participants · ${shownParticipants.length === 0 ? 'nobody' : shownParticipants.map(participantIdentity).join(' · ')}${hiddenParticipants > 0 ? ` · … ${hiddenParticipants} more` : ''}`);
|
|
105
|
+
lines.push(` participants · ${shownParticipants.length === 0 ? 'nobody' : shownParticipants.map((participant) => participantIdentity(characterPreview(participant))).join(' · ')}${hiddenParticipants > 0 ? ` · … ${hiddenParticipants} more` : ''}`);
|
|
84
106
|
}
|
|
107
|
+
const hiddenItems = page.length - shownItems.length;
|
|
108
|
+
if (hiddenItems > 0) {
|
|
109
|
+
const cursor = shownItems.at(-1)?.path;
|
|
110
|
+
lines.push(stopped ? ' … more squares' : ` … ${hiddenItems} more ${hiddenItems === 1 ? 'square' : 'squares'}`);
|
|
111
|
+
if (cursor !== undefined)
|
|
112
|
+
lines.push(`» square list --depth ${depth} --limit ${limit} --after ${quoteShell(cursor)}`);
|
|
113
|
+
}
|
|
114
|
+
if (stopped)
|
|
115
|
+
lines.push(`○ discovery stopped after examining ${LIST_DISCOVERY_BUDGET} filesystem entries; results may be incomplete`);
|
|
85
116
|
return lines.join('\n') + '\n';
|
|
86
117
|
}
|
|
87
|
-
function
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
118
|
+
function parseListOptions(args, usage) {
|
|
119
|
+
let depth = DEFAULT_LIST_DEPTH;
|
|
120
|
+
let limit = DEFAULT_LIST_LIMIT;
|
|
121
|
+
let after;
|
|
122
|
+
for (let index = 0; index < args.length; index += 2) {
|
|
123
|
+
const option = args[index];
|
|
124
|
+
const value = args[index + 1];
|
|
125
|
+
if (value === undefined || (option !== '--depth' && option !== '--limit' && option !== '--after')) {
|
|
126
|
+
usage();
|
|
127
|
+
return { depth, limit };
|
|
128
|
+
}
|
|
129
|
+
if (option === '--after') {
|
|
130
|
+
if (after !== undefined || value.length === 0 || path.isAbsolute(value)) {
|
|
131
|
+
usage();
|
|
132
|
+
return { depth, limit };
|
|
133
|
+
}
|
|
134
|
+
after = value;
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
if (!/^\d+$/.test(value)) {
|
|
138
|
+
usage();
|
|
139
|
+
return { depth, limit };
|
|
140
|
+
}
|
|
141
|
+
const parsed = Number(value);
|
|
142
|
+
if (!Number.isSafeInteger(parsed) || (option === '--depth' ? parsed > MAX_LIST_DEPTH : parsed === 0 || parsed > MAX_LIST_LIMIT)) {
|
|
143
|
+
usage();
|
|
144
|
+
return { depth, limit };
|
|
145
|
+
}
|
|
146
|
+
if (option === '--depth')
|
|
147
|
+
depth = parsed;
|
|
148
|
+
else
|
|
149
|
+
limit = parsed;
|
|
98
150
|
}
|
|
99
|
-
return depth;
|
|
151
|
+
return { depth, limit, after };
|
|
100
152
|
}
|
|
101
153
|
export async function cmdListSquares(args, usage) {
|
|
102
|
-
const
|
|
103
|
-
|
|
154
|
+
const options = parseListOptions(args, usage);
|
|
155
|
+
const discovery = await collectSquareList(process.cwd(), options.depth);
|
|
156
|
+
process.stdout.write(renderSquareList(discovery.items, discovery.stopped, options.depth, options.limit, options.after));
|
|
104
157
|
}
|
package/dist/model.d.ts
CHANGED
|
@@ -101,9 +101,6 @@ export interface ActivitiesOptions {
|
|
|
101
101
|
beforeContext?: number;
|
|
102
102
|
afterContext?: number;
|
|
103
103
|
mention?: string;
|
|
104
|
-
/** Undelivered mention/bell items for viewer only (read-only; requires viewer). */
|
|
105
|
-
pending?: boolean;
|
|
106
|
-
viewer?: string;
|
|
107
104
|
grep?: string;
|
|
108
105
|
fixed?: string;
|
|
109
106
|
order?: 'asc' | 'desc';
|
|
@@ -113,6 +110,7 @@ export interface ActivitiesOptions {
|
|
|
113
110
|
export interface WatchOptions {
|
|
114
111
|
participants?: string[];
|
|
115
112
|
mention?: string;
|
|
113
|
+
limit?: number;
|
|
116
114
|
idleMs?: number;
|
|
117
115
|
replace?: boolean;
|
|
118
116
|
now?: boolean;
|
package/dist/paseo-connection.js
CHANGED
|
@@ -46,6 +46,9 @@ function pidHost(env) {
|
|
|
46
46
|
function isIpc(host) {
|
|
47
47
|
return host !== undefined && (host.startsWith('unix://') || host.startsWith('pipe://'));
|
|
48
48
|
}
|
|
49
|
+
function supportsIpcHost(host) {
|
|
50
|
+
return process.platform !== 'win32' || !host.startsWith('unix://');
|
|
51
|
+
}
|
|
49
52
|
/** Match the host precedence used by the Paseo CLI for local daemon connections. */
|
|
50
53
|
export function paseoDaemonHosts(env = process.env) {
|
|
51
54
|
const explicit = normalizeHost(env.PASEO_HOST);
|
|
@@ -55,11 +58,11 @@ export function paseoDaemonHosts(env = process.env) {
|
|
|
55
58
|
const listen = normalizeHost(env.PASEO_LISTEN);
|
|
56
59
|
const pid = pidHost(env);
|
|
57
60
|
const configured = configuredHost(env);
|
|
58
|
-
if (isIpc(listen))
|
|
61
|
+
if (isIpc(listen) && supportsIpcHost(listen))
|
|
59
62
|
candidates.push(listen);
|
|
60
|
-
if (isIpc(pid))
|
|
63
|
+
if (isIpc(pid) && supportsIpcHost(pid))
|
|
61
64
|
candidates.push(pid);
|
|
62
|
-
if (isIpc(configured))
|
|
65
|
+
if (isIpc(configured) && supportsIpcHost(configured))
|
|
63
66
|
candidates.push(configured);
|
|
64
67
|
if (configured !== undefined && !isIpc(configured) && configured !== '127.0.0.1:6767')
|
|
65
68
|
candidates.push(configured);
|
|
@@ -73,6 +76,9 @@ function uriPassword(uri) {
|
|
|
73
76
|
export function resolvePaseoDaemonTarget(host, env = process.env) {
|
|
74
77
|
const passwordFromEnv = env.PASEO_PASSWORD?.trim() || undefined;
|
|
75
78
|
if (host.startsWith('unix://') || host.startsWith('pipe://')) {
|
|
79
|
+
if (process.platform === 'win32' && host.startsWith('unix://')) {
|
|
80
|
+
throw new Error('Paseo Unix socket targets are unsupported on Windows; use pipe:// or tcp://.');
|
|
81
|
+
}
|
|
76
82
|
const prefix = host.startsWith('unix://') ? 'unix://' : 'pipe://';
|
|
77
83
|
const socketPath = expandHome(host.slice(prefix.length).trim());
|
|
78
84
|
if (socketPath === '')
|
package/dist/paseo-state.d.ts
CHANGED
|
@@ -4,7 +4,10 @@ export interface PaseoAgent {
|
|
|
4
4
|
status: string;
|
|
5
5
|
cwd?: string;
|
|
6
6
|
}
|
|
7
|
-
export declare function discoverPaseoAgents(timeoutMs?: number
|
|
7
|
+
export declare function discoverPaseoAgents(timeoutMs?: number, opts?: {
|
|
8
|
+
args?: string[];
|
|
9
|
+
bin?: string;
|
|
10
|
+
}): {
|
|
8
11
|
agents: PaseoAgent[];
|
|
9
12
|
error?: string;
|
|
10
13
|
};
|