@astrosheep/square 0.3.93 → 0.3.95
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/activity-feed.d.ts +3 -5
- package/dist/activity-feed.js +16 -14
- package/dist/artifact.js +3 -3
- package/dist/attention.d.ts +19 -0
- package/dist/attention.js +30 -0
- package/dist/boundary-presentation.d.ts +2 -2
- package/dist/boundary-presentation.js +33 -40
- package/dist/catch-decisions.d.ts +5 -8
- package/dist/catch-decisions.js +45 -25
- package/dist/claude-delivery-status.js +10 -4
- package/dist/claude-delivery.js +19 -11
- package/dist/claude-mod.js +24 -53
- package/dist/cli/context.d.ts +9 -4
- package/dist/cli/context.js +30 -27
- package/dist/cli/express-presentation.d.ts +3 -1
- package/dist/cli/express-presentation.js +28 -16
- package/dist/cli/json.d.ts +3 -0
- package/dist/cli/json.js +14 -0
- package/dist/cli/mcp-server-command.js +2 -2
- package/dist/cli/observation-commands.d.ts +1 -3
- package/dist/cli/observation-commands.js +43 -56
- package/dist/cli/program.js +3 -3
- package/dist/cli/registry.js +7 -6
- package/dist/cli/square-commands.d.ts +0 -2
- package/dist/cli/square-commands.js +30 -44
- package/dist/codex-hook.d.ts +3 -2
- package/dist/codex-hook.js +13 -4
- package/dist/codex-queue.js +4 -4
- package/dist/decisions.d.ts +5 -16
- package/dist/decisions.js +9 -33
- package/dist/delivery-attempts.d.ts +52 -0
- package/dist/delivery-attempts.js +73 -0
- package/dist/delivery-deferral.js +2 -2
- package/dist/delivery-effects.d.ts +139 -0
- package/dist/delivery-effects.js +163 -0
- package/dist/delivery-health.d.ts +0 -1
- package/dist/delivery-health.js +1 -3
- package/dist/delivery-operations.d.ts +2 -2
- package/dist/delivery-operations.js +76 -101
- package/dist/delivery-primitives.d.ts +5 -0
- package/dist/delivery-primitives.js +3 -0
- package/dist/delivery.d.ts +1 -1
- package/dist/delivery.js +7 -6
- package/dist/help.js +14 -14
- package/dist/http-delivery.d.ts +16 -0
- package/dist/http-delivery.js +101 -0
- package/dist/inbox.d.ts +9 -22
- package/dist/inbox.js +23 -27
- package/dist/index.d.ts +1 -3
- package/dist/index.js +1 -1
- package/dist/mcp.d.ts +3 -0
- package/dist/mcp.js +23 -24
- package/dist/model.d.ts +12 -21
- package/dist/model.js +5 -8
- package/dist/notifications.d.ts +1 -1
- package/dist/notifications.js +8 -5
- package/dist/operation-presentation.d.ts +6 -6
- package/dist/operation-presentation.js +55 -58
- package/dist/owner.d.ts +11 -0
- package/dist/owner.js +32 -0
- package/dist/paseo-delivery.d.ts +4 -1
- package/dist/paseo-delivery.js +7 -12
- package/dist/paseo-state.d.ts +2 -2
- package/dist/paseo-state.js +6 -4
- package/dist/plugins/opencode/delivery.js +27 -15
- package/dist/ports.d.ts +18 -47
- package/dist/presentation-operations.d.ts +14 -19
- package/dist/presentation-operations.js +51 -61
- package/dist/presentation.d.ts +7 -17
- package/dist/presentation.js +46 -91
- package/dist/receive.d.ts +66 -0
- package/dist/receive.js +54 -0
- package/dist/runtime.d.ts +1 -8
- package/dist/runtime.js +2 -17
- package/dist/seats.d.ts +2 -3
- package/dist/seats.js +7 -15
- package/dist/session-lifecycle.d.ts +6 -2
- package/dist/session-lifecycle.js +39 -11
- package/dist/sqlite-square.d.ts +36 -23
- package/dist/sqlite-square.js +162 -211
- package/dist/square-api.d.ts +16 -11
- package/dist/square-api.js +27 -23
- package/dist/square-core.d.ts +0 -14
- package/dist/square-core.js +0 -9
- package/dist/square-domain.d.ts +4 -2
- package/dist/square-domain.js +65 -52
- package/dist/square-facade.d.ts +47 -105
- package/dist/square-index.d.ts +5 -13
- package/dist/square-index.js +13 -38
- package/dist/square-legacy-framing.d.ts +2 -0
- package/dist/square-legacy-framing.js +8 -0
- package/dist/square-location.d.ts +1 -14
- package/dist/square-location.js +4 -70
- package/dist/square-migration-host-ledger.d.ts +2 -2
- package/dist/square-migration-host-ledger.js +6 -5
- package/dist/square-migration.d.ts +4 -1
- package/dist/square-migration.js +93 -38
- package/dist/square-receive.d.ts +6 -0
- package/dist/square-receive.js +18 -0
- package/dist/square-sqlite.d.ts +9 -3
- package/dist/square-sqlite.js +139 -114
- package/dist/square-tools.d.ts +7 -10
- package/dist/square-tools.js +21 -61
- package/dist/stream.js +4 -5
- package/dist/views.d.ts +23 -13
- package/dist/views.js +47 -53
- package/dist/wakes.d.ts +1 -5
- package/dist/wakes.js +4 -6
- package/examples/symmetric-domains.mjs +250 -0
- package/guides/application-facade-delivery-evidence.md +6 -6
- package/guides/attention-primitive.md +32 -0
- package/guides/change-waits.md +2 -2
- package/guides/claude-native.md +18 -9
- package/guides/codex-delivery.md +17 -6
- package/guides/delivery-primitives.md +180 -0
- package/guides/mcp-connection-lifetime.md +1 -1
- package/guides/mcp.md +3 -3
- package/guides/migration.md +148 -151
- package/guides/operation-cancellation.md +1 -1
- package/guides/participant-ownership.md +78 -47
- package/guides/pi-tools.md +34 -5
- package/guides/primitive-catch-consolidation.md +5 -5
- package/guides/primitive-history-consolidation.md +2 -2
- package/guides/primitive-status-consolidation.md +3 -3
- package/guides/primitive-storage-consolidation.md +1 -1
- package/guides/receive-primitive.md +90 -0
- package/guides/row-runtime-delivery-evidence.md +1 -1
- package/guides/row-storage-design.md +22 -28
- package/guides/square-api.md +314 -91
- package/guides/symmetric-domains.md +92 -0
- package/package.json +14 -1
- package/plugins/claude/.claude-plugin/plugin.json +1 -1
- package/plugins/claude/skills/square/SKILL.md +2 -6
- package/plugins/codex/.codex-plugin/plugin.json +1 -1
- package/plugins/opencode/delivery.ts +27 -17
- package/plugins/paseo/client/palette.ts +18 -18
- package/plugins/paseo/client/square-message.tsx +17 -23
- package/plugins/pi/square-pi.js +17 -17
- package/skills/square/SKILL.md +2 -6
- package/dist/square-backend.d.ts +0 -13
- package/dist/square-backend.js +0 -1
- package/dist/square-stdio.d.ts +0 -22
- package/dist/square-stdio.js +0 -235
- package/dist/stdio-server.d.ts +0 -3
- package/dist/stdio-server.js +0 -212
- package/guides/backends.md +0 -193
package/dist/model.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Act, ActivityId } from './square-core.js';
|
|
2
2
|
export { formatActivityId, parseActivityId } from './square-core.js';
|
|
3
3
|
export type { Act, ActivityId, Audience, Reach } from './square-core.js';
|
|
4
|
-
export declare const WAKE_ROUTE_KINDS: readonly ["opencode-server", "codex-queue", "claude-native", "paseo"];
|
|
4
|
+
export declare const WAKE_ROUTE_KINDS: readonly ["opencode-server", "codex-queue", "claude-native", "paseo", "http"];
|
|
5
5
|
export type WakeRouteKind = typeof WAKE_ROUTE_KINDS[number];
|
|
6
6
|
export type JsonValue = null | boolean | number | string | readonly JsonValue[] | {
|
|
7
7
|
readonly [key: string]: JsonValue;
|
|
@@ -12,11 +12,8 @@ export declare const ACTIVITY_METADATA_MAX_DEPTH = 256;
|
|
|
12
12
|
/** Validate the bounded, lossless JSON object carried by a say. */
|
|
13
13
|
export declare function validateActivityMetadata(value: unknown): ActivityMetadata | undefined;
|
|
14
14
|
export declare function activityMetadataHasContent(metadata: ActivityMetadata | undefined): boolean;
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
readonly session: string;
|
|
18
|
-
readonly agent?: string;
|
|
19
|
-
}
|
|
15
|
+
/** Opaque custody identity. Harness coordinates are adapter-owned. */
|
|
16
|
+
export type Owner = string;
|
|
20
17
|
export interface WakeAddress {
|
|
21
18
|
readonly kind: WakeRouteKind;
|
|
22
19
|
readonly address: Readonly<Record<string, string>>;
|
|
@@ -24,35 +21,35 @@ export interface WakeAddress {
|
|
|
24
21
|
/** Artifact-owned custody binding. Generation is the join activity that established it. */
|
|
25
22
|
export interface Seat {
|
|
26
23
|
readonly participant: string;
|
|
27
|
-
readonly
|
|
24
|
+
readonly owner: Owner;
|
|
28
25
|
readonly generation: ActivityId;
|
|
26
|
+
readonly attachment: 'attached' | 'detached';
|
|
29
27
|
readonly wakeAddress?: WakeAddress;
|
|
30
28
|
}
|
|
31
29
|
export interface SeatWatchLease {
|
|
32
30
|
readonly generation: ActivityId;
|
|
33
31
|
readonly lease: WatchLease;
|
|
34
32
|
}
|
|
35
|
-
export declare function
|
|
36
|
-
export declare function validateBody(body: Body): void;
|
|
33
|
+
export declare function validateOwner(owner: Owner): Owner;
|
|
37
34
|
export declare function isWakeRouteKind(value: unknown): value is WakeRouteKind;
|
|
38
35
|
export interface WakeRoute {
|
|
39
36
|
/** Ownership generation, when the receiver publishes a fenced route. */
|
|
40
37
|
epoch?: number;
|
|
41
38
|
location: string;
|
|
42
39
|
participant: string;
|
|
43
|
-
sessionId: string;
|
|
44
|
-
channel: string;
|
|
45
40
|
kind: WakeRouteKind;
|
|
46
41
|
address: Record<string, string>;
|
|
47
42
|
updatedAt: number;
|
|
48
43
|
}
|
|
49
|
-
export type SquareErrorCode = 'invalid_name' | 'invalid_args' | 'unknown_participant' | 'not_joined' | 'already_joined' | 'already_done' | '
|
|
44
|
+
export type SquareErrorCode = 'invalid_name' | 'invalid_args' | 'unknown_participant' | 'not_joined' | 'already_joined' | 'already_done' | 'capped' | 'throttled' | 'bell_quota' | 'behind' | 'io' | 'unavailable';
|
|
50
45
|
export type InternalSquareErrorCode = SquareErrorCode | 'not_found' | 'cap_reached' | 'conflict' | 'pending_peer';
|
|
51
46
|
export interface SquareErrorFacts {
|
|
47
|
+
/** Copyable recovery for a missing, detached or foreign seat. */
|
|
48
|
+
join?: string;
|
|
52
49
|
/** Express admission rejected before any activity was committed. */
|
|
53
50
|
activityUnsent?: true;
|
|
54
51
|
/** Refusal reason, including absent participants, conflicting reach, and inaccessible activities. */
|
|
55
|
-
reason?: 'never_joined' | 'not_standing' | 'bell_mention_conflict' | 'not_addressed' | 'migration_required' | 'invalid_reply' | 'invalid_done_body';
|
|
52
|
+
reason?: 'never_joined' | 'not_standing' | 'bell_mention_conflict' | 'not_addressed' | 'migration_required' | 'invalid_reply' | 'invalid_done_body' | 'needs_seat';
|
|
56
53
|
/** The activity id a `catch --id` refusal named. */
|
|
57
54
|
activityId?: string;
|
|
58
55
|
/** The host ledger requiring offline migration, rather than the selected artifact. */
|
|
@@ -62,8 +59,6 @@ export interface SquareErrorFacts {
|
|
|
62
59
|
/** Whether the artifact holds that activity at all; an unknown id needs an ordinary page. */
|
|
63
60
|
activityExists?: boolean;
|
|
64
61
|
pending?: number;
|
|
65
|
-
holder?: string;
|
|
66
|
-
holdReason?: string;
|
|
67
62
|
retryAfterMs?: number;
|
|
68
63
|
}
|
|
69
64
|
declare class SquareErrorBase<Code extends string> extends Error {
|
|
@@ -103,7 +98,7 @@ export interface WatchLease {
|
|
|
103
98
|
expiresAt: number;
|
|
104
99
|
filter?: WatchLeaseFilter;
|
|
105
100
|
}
|
|
106
|
-
export type DirectedNotificationRoute = '
|
|
101
|
+
export type DirectedNotificationRoute = import('./attention.js').AudienceRoute;
|
|
107
102
|
export interface InboxNotification {
|
|
108
103
|
actIndex: number;
|
|
109
104
|
actor: string;
|
|
@@ -122,19 +117,15 @@ export interface PendingMembership extends LocatedSeat {
|
|
|
122
117
|
readonly deliveryDeferralExpiry?: number;
|
|
123
118
|
}
|
|
124
119
|
export interface WatchOptions {
|
|
125
|
-
id?: ActivityId;
|
|
126
120
|
participants?: string[];
|
|
127
121
|
mention?: string;
|
|
128
|
-
limit?: number;
|
|
129
|
-
idleMs?: number;
|
|
130
122
|
replace?: boolean;
|
|
131
|
-
now?: boolean;
|
|
132
123
|
}
|
|
133
124
|
export type PublicAct = Extract<StoredAct, {
|
|
134
125
|
kind: 'say' | 'done';
|
|
135
126
|
}>;
|
|
136
127
|
export type RoomChangeAct = Extract<StoredAct, {
|
|
137
|
-
kind: 'join' | 'done' | '
|
|
128
|
+
kind: 'join' | 'done' | 'listen' | 'ignore' | 'unlisten';
|
|
138
129
|
}>;
|
|
139
130
|
export declare function formatHardCap(hardCap: HardCap): string;
|
|
140
131
|
export declare function parseParticipantList(value: string): string[];
|
package/dist/model.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Shared model and constants for Square.
|
|
2
2
|
export { formatActivityId, parseActivityId } from './square-core.js';
|
|
3
|
-
export const WAKE_ROUTE_KINDS = ['opencode-server', 'codex-queue', 'claude-native', 'paseo'];
|
|
3
|
+
export const WAKE_ROUTE_KINDS = ['opencode-server', 'codex-queue', 'claude-native', 'paseo', 'http'];
|
|
4
4
|
export const ACTIVITY_METADATA_MAX_BYTES = 16 * 1024;
|
|
5
5
|
export const ACTIVITY_METADATA_MAX_DEPTH = 256;
|
|
6
6
|
/** Validate the bounded, lossless JSON object carried by a say. */
|
|
@@ -76,14 +76,11 @@ export function validateActivityMetadata(value) {
|
|
|
76
76
|
export function activityMetadataHasContent(metadata) {
|
|
77
77
|
return metadata !== undefined && Object.keys(metadata).length > 0;
|
|
78
78
|
}
|
|
79
|
-
export function
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
export function validateBody(body) {
|
|
83
|
-
if (!body || typeof body.channel !== 'string' || !body.channel || typeof body.session !== 'string' || !body.session
|
|
84
|
-
|| (body.agent !== undefined && (typeof body.agent !== 'string' || !body.agent))) {
|
|
85
|
-
throw new SquareError('invalid_args', 'A participant write requires an explicit channel and session body.');
|
|
79
|
+
export function validateOwner(owner) {
|
|
80
|
+
if (typeof owner !== 'string' || !owner || Buffer.byteLength(owner, 'utf8') > 512 || /[\u0000-\u001f\u007f-\u009f]/u.test(owner)) {
|
|
81
|
+
throw new SquareError('invalid_args', 'A participant write requires a non-empty owner without control characters (at most 512 UTF-8 bytes).');
|
|
86
82
|
}
|
|
83
|
+
return owner;
|
|
87
84
|
}
|
|
88
85
|
export function isWakeRouteKind(value) {
|
|
89
86
|
return typeof value === 'string' && WAKE_ROUTE_KINDS.includes(value);
|
package/dist/notifications.d.ts
CHANGED
|
@@ -13,7 +13,7 @@ interface ProcessNotificationOptions {
|
|
|
13
13
|
export declare function createDefaultWakeTransport(env?: NodeJS.ProcessEnv, suppliedTransports?: WakeTransports): Promise<WakeTransportPort>;
|
|
14
14
|
/** Route selection only: all implementations receive the same request and final gate. */
|
|
15
15
|
export declare function createWakeTransport(transports: WakeTransports): WakeTransportPort;
|
|
16
|
-
export declare function processActNotificationsOnce(squarePath: string, actIndex: number, opts?: ProcessNotificationOptions): Promise<
|
|
16
|
+
export declare function processActNotificationsOnce(squarePath: string, actIndex: number, opts?: ProcessNotificationOptions): Promise<void>;
|
|
17
17
|
/** Privileged hook fallback: sweep indexed squares plus the current cwd's local squares within one boundary budget. */
|
|
18
18
|
export declare function sweepPrivilegedPending(cwd: string, env?: NodeJS.ProcessEnv, suppliedTransports?: WakeTransports, deadline?: number, signal?: AbortSignal): Promise<void>;
|
|
19
19
|
export interface SweepPendingNotificationsOptions {
|
package/dist/notifications.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
|
+
import { canonicalPath } from './canonical-path.js';
|
|
2
3
|
import fs from 'node:fs';
|
|
3
4
|
import { indexedSquareEntries } from './square-index.js';
|
|
4
5
|
import { InternalSquareError, SquareError } from './model.js';
|
|
@@ -31,6 +32,8 @@ export async function createDefaultWakeTransport(env = process.env, suppliedTran
|
|
|
31
32
|
}
|
|
32
33
|
const { createClaudeWakeTransport } = await import('./claude-delivery.js');
|
|
33
34
|
transports['claude-native'] = createClaudeWakeTransport(env);
|
|
35
|
+
const { HttpWakeTransport } = await import('./http-delivery.js');
|
|
36
|
+
transports.http = new HttpWakeTransport({ env });
|
|
34
37
|
return createWakeTransport(transports);
|
|
35
38
|
}
|
|
36
39
|
/** Route selection only: all implementations receive the same request and final gate. */
|
|
@@ -55,16 +58,15 @@ export function createWakeTransport(transports) {
|
|
|
55
58
|
export async function processActNotificationsOnce(squarePath, actIndex, opts = {}) {
|
|
56
59
|
const env = opts.env ?? process.env;
|
|
57
60
|
const now = opts.now ?? Date.now;
|
|
61
|
+
squarePath = await canonicalPath(squarePath);
|
|
58
62
|
const artifact = createArtifactPort(squarePath);
|
|
59
63
|
try {
|
|
60
64
|
await artifact.read(facts => facts.header());
|
|
61
65
|
const transport = await createDefaultWakeTransport(env, opts.transports);
|
|
62
66
|
try {
|
|
63
|
-
|
|
64
|
-
}
|
|
65
|
-
catch {
|
|
66
|
-
return { attempted: 0, accepted: 0, failed: 0, unknown: 0, notCapable: 1 };
|
|
67
|
+
await deliverPending({ artifact, transport, location: squarePath, activity: actIndex, timeoutMs: Number(env.SQUARE_NOTIFY_DELIVERY_WAIT_MS ?? 5000), now: now() });
|
|
67
68
|
}
|
|
69
|
+
catch { /* Delivery failure does not undo the activity. */ }
|
|
68
70
|
}
|
|
69
71
|
catch (error) {
|
|
70
72
|
if (error instanceof InternalSquareError && error.code === 'not_found')
|
|
@@ -92,10 +94,11 @@ export async function sweepPrivilegedPending(cwd, env = process.env, suppliedTra
|
|
|
92
94
|
if (remainingMs() === 0 || signal?.aborted)
|
|
93
95
|
return;
|
|
94
96
|
const transport = await createDefaultWakeTransport(env, suppliedTransports);
|
|
95
|
-
for (const
|
|
97
|
+
for (const candidate of paths) {
|
|
96
98
|
if (remainingMs() === 0 || signal?.aborted)
|
|
97
99
|
break;
|
|
98
100
|
try {
|
|
101
|
+
const squarePath = await canonicalPath(candidate);
|
|
99
102
|
const artifact = createArtifactPort(squarePath, undefined, signal);
|
|
100
103
|
try {
|
|
101
104
|
await artifact.read(facts => facts.header(), signal);
|
|
@@ -7,10 +7,10 @@ export type JoinPresentation = Omit<JoinResult, 'participant'> & {
|
|
|
7
7
|
readonly name: string;
|
|
8
8
|
} | string;
|
|
9
9
|
};
|
|
10
|
-
export declare function renderJoinResult(data: JoinPresentation): string | undefined;
|
|
11
|
-
export declare function renderExpression(squarePath: string, data: ExpressResult): string | undefined;
|
|
10
|
+
export declare function renderJoinResult(data: JoinPresentation, owner?: string): string | undefined;
|
|
11
|
+
export declare function renderExpression(squarePath: string, data: ExpressResult, owner?: string): string | undefined;
|
|
12
12
|
/** Render settled catch facts; no selection, terminal decisions, receipts or wait machinery. */
|
|
13
|
-
export declare function renderCatchOutcome(squarePath: string, data: CatchResult, options?: CatchOptions): {
|
|
13
|
+
export declare function renderCatchOutcome(squarePath: string, data: CatchResult, options?: CatchOptions, owner?: string): {
|
|
14
14
|
stdout: string;
|
|
15
15
|
exitCode: number;
|
|
16
16
|
};
|
|
@@ -24,14 +24,13 @@ export declare function renderStatusResult(squarePath: string, data: StatusResul
|
|
|
24
24
|
export declare function renderListeningResult(squarePath: string, data: ListeningResult): string | undefined;
|
|
25
25
|
export type ListenerVerb = 'listen' | 'ignore' | 'unlisten';
|
|
26
26
|
export declare function renderListenerChange(squarePath: string, verb: ListenerVerb, data: ListenerChangeResult): string | undefined;
|
|
27
|
-
export
|
|
28
|
-
export declare function renderLifecycleResult(squarePath: string, verb: LifecycleVerb, data: LifecycleResult): string | undefined;
|
|
27
|
+
export declare function renderLifecycleResult(squarePath: string, data: LifecycleResult): string | undefined;
|
|
29
28
|
/** The refusal facts a transport has after normalizing a failure, without the live error. */
|
|
30
29
|
export interface FailureReport {
|
|
31
30
|
readonly code: string;
|
|
32
31
|
readonly message: string;
|
|
33
32
|
readonly facts?: {
|
|
34
|
-
readonly reason?: 'never_joined' | 'not_standing' | 'bell_mention_conflict' | 'not_addressed' | 'migration_required' | 'invalid_reply' | 'invalid_done_body';
|
|
33
|
+
readonly reason?: 'never_joined' | 'not_standing' | 'bell_mention_conflict' | 'not_addressed' | 'migration_required' | 'invalid_reply' | 'invalid_done_body' | 'needs_seat';
|
|
35
34
|
readonly activityId?: string;
|
|
36
35
|
readonly ledgerRoot?: string;
|
|
37
36
|
readonly activityExists?: boolean;
|
|
@@ -42,4 +41,5 @@ export interface FailureReport {
|
|
|
42
41
|
export declare function renderFailureLines(failure: FailureReport, options?: {
|
|
43
42
|
squarePath?: string;
|
|
44
43
|
name?: string;
|
|
44
|
+
owner?: string;
|
|
45
45
|
}): string[];
|
|
@@ -1,26 +1,24 @@
|
|
|
1
1
|
// Human-facing text for one settled operation. The CLI and the MCP transport both
|
|
2
2
|
// render through these functions, so a person sees the same square either way.
|
|
3
3
|
import { sameName } from './model.js';
|
|
4
|
-
import { formatActivityId
|
|
5
|
-
import { commandPrefix, joinRecoveryCommand, participantCommandPrefix, participantIdentity, participantsRecoveryCommand, quoteShell, renderAmbientEvent, renderAmbientEventFacts, renderEventCli, renderGrepActivitiesView,
|
|
4
|
+
import { formatActivityId } from './square-core.js';
|
|
5
|
+
import { commandPrefix, joinRecoveryCommand, participantCommandPrefix, participantIdentity, participantsRecoveryCommand, quoteShell, renderAmbientEvent, renderAmbientEventFacts, renderEventCli, renderGrepActivitiesView, renderPresenceAnchor, renderWatchAlreadyActive, renderWatchReplaced, renderWatchStatus, takeoverRecoveryLines, withPathOutput, } from './presentation.js';
|
|
6
6
|
import { formatRelativeTime, formatTimestamp } from './time.js';
|
|
7
7
|
import { style } from './tty-style.js';
|
|
8
8
|
export const PARTICIPANTS_DEFAULT_LIMIT = 20;
|
|
9
9
|
export const PARTICIPANTS_MAX_LIMIT = 100;
|
|
10
10
|
const STATUS_PARTICIPANT_PREVIEW_LIMIT = 10;
|
|
11
|
-
export function renderJoinResult(data) {
|
|
11
|
+
export function renderJoinResult(data, owner) {
|
|
12
12
|
const after = data.observation;
|
|
13
13
|
if (after === undefined)
|
|
14
14
|
return undefined;
|
|
15
15
|
const entry = after.entry;
|
|
16
16
|
const name = typeof data.participant === 'string' ? data.participant : data.participant.name;
|
|
17
17
|
const activities = (entry?.recentActivities ?? []).map((event) => renderAmbientEvent(event, name, {
|
|
18
|
-
now: after.now, preview: 200,
|
|
19
|
-
actNumber: event.kind === 'say' ? entry.sayNumbers[event.index] : undefined,
|
|
20
|
-
perception: entry.perceptions[event.index],
|
|
18
|
+
now: after.now, preview: 200, perception: event.perception,
|
|
21
19
|
})).filter(Boolean).join('\n\n');
|
|
22
|
-
const fallback = after.
|
|
23
|
-
'', `${participantCommandPrefix(after.location, name)} catch --idle 30m`,
|
|
20
|
+
const fallback = after.deliveryAvailable ? ['', '· when someone calls you, you’ll hear them here'] : [
|
|
21
|
+
'', `${participantCommandPrefix(after.location, name, owner)} catch --idle 30m`,
|
|
24
22
|
' · stay within earshot — keep this catch open for new activity',
|
|
25
23
|
];
|
|
26
24
|
const entryLine = data.kind === 'joined' ? '● you stepped into the square'
|
|
@@ -36,21 +34,23 @@ export function renderJoinResult(data) {
|
|
|
36
34
|
...(after.enrichmentUnavailable ? [' · joined; recent activity and context are unavailable right now'] : []),
|
|
37
35
|
...(isRejoin || activities === '' ? [] : ['', style('dim', 'recent activity'), activities]),
|
|
38
36
|
...fallback,
|
|
39
|
-
].join('\n'), { participantCount: after.standingCount
|
|
37
|
+
].join('\n'), { participantCount: after.standingCount });
|
|
40
38
|
}
|
|
41
39
|
function isGestureOnly(body) {
|
|
42
40
|
return /\*[^*]*\*/.test(body) && body.replace(/\*[^*]*\*/g, '').trim() === '';
|
|
43
41
|
}
|
|
44
|
-
export function renderExpression(squarePath, data) {
|
|
42
|
+
export function renderExpression(squarePath, data, owner) {
|
|
45
43
|
const projection = data.observation;
|
|
46
44
|
if (projection === undefined)
|
|
47
45
|
return undefined;
|
|
48
46
|
const name = projection.participant;
|
|
49
|
-
const
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
:
|
|
47
|
+
const context = projection.context;
|
|
48
|
+
const pending = context.activities.length === 0 ? '' : '\n\n' + [
|
|
49
|
+
'Unread context · preview only, not consumed',
|
|
50
|
+
...context.activities.map(item => `· ${participantIdentity(item.actor)} · ${item.id}\n ${item.preview}${item.truncated ? '… (truncated)' : ''}`),
|
|
51
|
+
...(context.remaining === 0 ? [] : [`· ${context.remaining} more unread activities`]),
|
|
52
|
+
`${participantCommandPrefix(projection.location, name, owner)} catch`,
|
|
53
|
+
].join('\n');
|
|
54
54
|
const ownCount = projection.ownActivityCount;
|
|
55
55
|
const capCount = projection.hardCap === null ? '' : ` · ${ownCount}/${projection.hardCap}`;
|
|
56
56
|
const activity = data.activity;
|
|
@@ -63,9 +63,9 @@ export function renderExpression(squarePath, data) {
|
|
|
63
63
|
: `\n○ ${participantIdentity(data.replyAuthorNotHere)} isn't in the square right now — the reply landed without reaching them`;
|
|
64
64
|
const unmatchedNotice = data.unmatchedMentions?.length
|
|
65
65
|
? `\n · ${data.unmatchedMentions.map((token) => `@${token} isn't standing here`).join('; ')} — ${activity.mentions.length === 0 && activity.reply === undefined ? 'activity landed bare' : 'left as literal text'}` : '';
|
|
66
|
-
return withPathOutput(projection.location ?? squarePath, confirmation + (data.hint ? `\n${style('dim', `· ${data.hint}`)}` : '') + replyNotice + unmatchedNotice + pending, { participantCount: projection.standingCount
|
|
66
|
+
return withPathOutput(projection.location ?? squarePath, confirmation + (data.hint ? `\n${style('dim', `· ${data.hint}`)}` : '') + replyNotice + unmatchedNotice + pending, { participantCount: projection.standingCount });
|
|
67
67
|
}
|
|
68
|
-
function continuationCommand(squarePath, name, options) {
|
|
68
|
+
function continuationCommand(squarePath, name, options, owner) {
|
|
69
69
|
const args = ['--now'];
|
|
70
70
|
if (options.from?.length)
|
|
71
71
|
args.push('--from', options.from.join(','));
|
|
@@ -73,20 +73,20 @@ function continuationCommand(squarePath, name, options) {
|
|
|
73
73
|
args.push('--mention');
|
|
74
74
|
if (options.limit !== undefined)
|
|
75
75
|
args.push('--limit', String(options.limit));
|
|
76
|
-
return `${participantCommandPrefix(squarePath, name)} catch ${args.join(' ')}`;
|
|
76
|
+
return `${participantCommandPrefix(squarePath, name, owner)} catch ${args.join(' ')}`;
|
|
77
77
|
}
|
|
78
78
|
/** Render settled catch facts; no selection, terminal decisions, receipts or wait machinery. */
|
|
79
|
-
export function renderCatchOutcome(squarePath, data, options = {}) {
|
|
79
|
+
export function renderCatchOutcome(squarePath, data, options = {}, owner) {
|
|
80
80
|
const projection = data.observation;
|
|
81
81
|
if (projection === undefined)
|
|
82
82
|
return { stdout: '', exitCode: 0 };
|
|
83
83
|
const location = projection.location ?? squarePath;
|
|
84
84
|
const name = projection.participant;
|
|
85
|
-
const stop =
|
|
86
|
-
const header = { participantCount: projection.standingCount
|
|
85
|
+
const stop = data.reason === 'drained' && data.activities.length > 0 ? undefined : data.reason;
|
|
86
|
+
const header = { participantCount: projection.standingCount };
|
|
87
87
|
const statusOptions = {
|
|
88
|
-
squarePath: location, name, presence: projection.presence,
|
|
89
|
-
showCatchHint: !projection.
|
|
88
|
+
squarePath: location, name, owner, presence: projection.presence,
|
|
89
|
+
showCatchHint: !projection.deliveryAvailable,
|
|
90
90
|
ownActivityCount: projection.ownActivityCount, hardCap: projection.hardCap,
|
|
91
91
|
};
|
|
92
92
|
if (stop === 'already-active' || stop === 'replaced') {
|
|
@@ -97,17 +97,16 @@ export function renderCatchOutcome(squarePath, data, options = {}) {
|
|
|
97
97
|
};
|
|
98
98
|
}
|
|
99
99
|
const rendered = data.activities.map((activity) => renderAmbientEvent(activity, name, {
|
|
100
|
-
now: projection.now,
|
|
101
|
-
perception: activity.perception, mention: options.mention ? name : undefined,
|
|
100
|
+
now: projection.now, perception: activity.perception, mention: options.mention ? name : undefined,
|
|
102
101
|
})).filter(Boolean).join('\n\n');
|
|
103
102
|
const remaining = data.remaining === 0 ? ''
|
|
104
|
-
: `· ${data.remaining} matching ${data.remaining === 1 ? 'activity remains' : 'activities remain'}\n${continuationCommand(location, name, options)}`;
|
|
103
|
+
: `· ${data.remaining} matching ${data.remaining === 1 ? 'activity remains' : 'activities remain'}\n${continuationCommand(location, name, options, owner)}`;
|
|
105
104
|
const terminal = stop === undefined ? '' : renderWatchStatus({
|
|
106
105
|
...statusOptions, status: stop,
|
|
107
|
-
...(stop === '
|
|
106
|
+
...(stop === 'idle' && options.idle !== undefined ? { idleMs: options.idle } : {}),
|
|
108
107
|
});
|
|
109
|
-
const fallback = stop === undefined && !projection.
|
|
110
|
-
? `${participantCommandPrefix(location, name)} catch --idle 30m\n stay available for new activity` : '';
|
|
108
|
+
const fallback = stop === undefined && !projection.deliveryAvailable && data.remaining === 0
|
|
109
|
+
? `${participantCommandPrefix(location, name, owner)} catch --idle 30m\n stay available for new activity` : '';
|
|
111
110
|
const hint = data.hint === undefined ? '' : style('dim', `· ${data.hint}`);
|
|
112
111
|
return {
|
|
113
112
|
stdout: withPathOutput(location, [terminal, rendered, hint, remaining, fallback].filter(Boolean).join('\n\n'), header),
|
|
@@ -121,11 +120,7 @@ function renderHistoryProjection(projection, visible, noTruncate, squarePath) {
|
|
|
121
120
|
// Presence anchors collect into one closing line instead of interrupting the page.
|
|
122
121
|
const anchored = [];
|
|
123
122
|
for (const activity of shown) {
|
|
124
|
-
const
|
|
125
|
-
preview,
|
|
126
|
-
actNumber: activity.kind === 'say' ? projection.sayNumbers[activity.index] : undefined,
|
|
127
|
-
};
|
|
128
|
-
const rendered = renderEventCli(activity, options);
|
|
123
|
+
const rendered = renderEventCli(activity, { preview });
|
|
129
124
|
if (rendered !== '')
|
|
130
125
|
chunks.push(rendered);
|
|
131
126
|
for (const participant of projection.presenceAnchors[activity.index] ?? []) {
|
|
@@ -193,8 +188,8 @@ export function renderParticipantsResult(squarePath, data, limit = PARTICIPANTS_
|
|
|
193
188
|
const now = projection.now;
|
|
194
189
|
const participants = data.participants;
|
|
195
190
|
const lines = participants.slice(0, limit).map((participant) => {
|
|
196
|
-
const glyph = participant.
|
|
197
|
-
const state = participant.
|
|
191
|
+
const glyph = participant.presence === 'done' ? '○' : participant.presence === 'watching' ? '◎' : participant.activityCount > 0 && projection.classificationByName[participant.name] === 'here' ? '●' : '○';
|
|
192
|
+
const state = participant.presence === 'watching' ? 'catching' : participant.presence === 'never-joined' ? 'not joined' : participant.presence;
|
|
198
193
|
const last = participant.lastActiveAt === undefined ? '—' : formatRelativeTime(participant.lastActiveAt, now);
|
|
199
194
|
return ` ${glyph} ${participant.name}${style('dim', ` · ${state} · ${participant.activityCount} ${participant.activityCount === 1 ? 'activity' : 'activities'} · ${last}`)}`;
|
|
200
195
|
});
|
|
@@ -217,8 +212,9 @@ export function renderStatusResult(squarePath, data) {
|
|
|
217
212
|
const participantsByName = new Map(data.participants.map((participant) => [participant.name, participant]));
|
|
218
213
|
const orderedHere = presentation.orderedHereNames.map((name) => participantsByName.get(name));
|
|
219
214
|
const lingering = presentation.lingeringCount;
|
|
215
|
+
const away = data.participants.filter(participant => participant.presence === 'away');
|
|
220
216
|
const people = [];
|
|
221
|
-
if (
|
|
217
|
+
if (presentation.standingCount === 0) {
|
|
222
218
|
people.push(' ○ nobody in the square');
|
|
223
219
|
}
|
|
224
220
|
else {
|
|
@@ -243,7 +239,11 @@ export function renderStatusResult(squarePath, data) {
|
|
|
243
239
|
: 'caught up';
|
|
244
240
|
return ` ${glyph} ${participantIdentity(participant.name)}${style('dim', ` ${summary}${attention === '' ? '' : ` · ${attention}`}`)}`;
|
|
245
241
|
}));
|
|
246
|
-
|
|
242
|
+
people.push(...away.slice(0, STATUS_PARTICIPANT_PREVIEW_LIMIT).map(participant => ` ○ ${participantIdentity(participant.name)}${style('dim', ' · away')}`));
|
|
243
|
+
if (away.length > STATUS_PARTICIPANT_PREVIEW_LIMIT)
|
|
244
|
+
people.push(` ○ … ${away.length - STATUS_PARTICIPANT_PREVIEW_LIMIT} more away`);
|
|
245
|
+
const unshown = Math.max(0, orderedHere.length - STATUS_PARTICIPANT_PREVIEW_LIMIT)
|
|
246
|
+
+ Math.max(0, away.length - STATUS_PARTICIPANT_PREVIEW_LIMIT) + lingering;
|
|
247
247
|
if (orderedHere.length > STATUS_PARTICIPANT_PREVIEW_LIMIT) {
|
|
248
248
|
people.push(` ○ … ${orderedHere.length - STATUS_PARTICIPANT_PREVIEW_LIMIT} more here`);
|
|
249
249
|
}
|
|
@@ -256,16 +256,11 @@ export function renderStatusResult(squarePath, data) {
|
|
|
256
256
|
}
|
|
257
257
|
}
|
|
258
258
|
const cap = data.hardCap === null ? 'unlimited' : `${data.hardCap} each`;
|
|
259
|
-
const holdTime = data.hold?.at === undefined ? 'just now' : formatRelativeTime(data.hold.at, data.now);
|
|
260
|
-
const hold = data.hold !== null
|
|
261
|
-
? `· ${data.hold.by === undefined ? 'someone' : participantIdentity(data.hold.by)} raised a hand${data.hold.reason ? ` — ${data.hold.reason}` : ''}${style('dim', ` · ${holdTime}`)}`
|
|
262
|
-
: undefined;
|
|
263
259
|
const visible = data.latestActivity === undefined
|
|
264
260
|
? { text: '', bodyClipped: false }
|
|
265
261
|
: renderAmbientEventFacts(data.latestActivity, presentation.viewer, {
|
|
266
262
|
now: data.now,
|
|
267
263
|
preview: 200,
|
|
268
|
-
actNumber: presentation.latestActNumber,
|
|
269
264
|
perception: presentation.latestPerception,
|
|
270
265
|
});
|
|
271
266
|
const latest = visible.text === ''
|
|
@@ -285,20 +280,21 @@ export function renderStatusResult(squarePath, data) {
|
|
|
285
280
|
}
|
|
286
281
|
const counts = [
|
|
287
282
|
`${orderedHere.length} here`,
|
|
283
|
+
...(away.length > 0 ? [`${away.length} away`] : []),
|
|
288
284
|
...(lingering > 0 ? [`${lingering} lingering`] : []),
|
|
289
|
-
`${data.
|
|
285
|
+
`${data.participants.filter((participant) => participant.presence === 'done').length} done`,
|
|
290
286
|
`cap ${cap}`,
|
|
291
287
|
`throttle ${data.throttlePerMinute === undefined ? 'none' : `${data.throttlePerMinute}/min`}`,
|
|
292
288
|
].join(' · ');
|
|
293
289
|
const output = [
|
|
294
290
|
style('dim', counts),
|
|
295
|
-
|
|
291
|
+
'', style('dim', 'around the square'), ...people, '', style('dim', 'latest'), ...latest,
|
|
296
292
|
...(data.listening === undefined ? [] : [
|
|
297
293
|
'', style('dim', 'you listen to'),
|
|
298
294
|
...(data.listening.length === 0 ? [' ○ not turned toward anyone'] : data.listening.map((name) => ` · ${participantIdentity(name)}`)),
|
|
299
295
|
]),
|
|
300
296
|
].join('\n');
|
|
301
|
-
return withPathOutput(squarePath, output, { participantCount: presentation.standingCount
|
|
297
|
+
return withPathOutput(squarePath, output, { participantCount: presentation.standingCount });
|
|
302
298
|
}
|
|
303
299
|
export function renderListeningResult(squarePath, data) {
|
|
304
300
|
const projection = data.observation;
|
|
@@ -307,7 +303,7 @@ export function renderListeningResult(squarePath, data) {
|
|
|
307
303
|
const body = data.listening.length === 0
|
|
308
304
|
? `○ ${participantIdentity(projection.participant)} is not turned toward anyone`
|
|
309
305
|
: ['listening', ...data.listening.map((target) => ` · ${participantIdentity(target)}`)].join('\n');
|
|
310
|
-
return withPathOutput(squarePath, body, { participantCount: projection.standingCount
|
|
306
|
+
return withPathOutput(squarePath, body, { participantCount: projection.standingCount });
|
|
311
307
|
}
|
|
312
308
|
export function renderListenerChange(squarePath, verb, data) {
|
|
313
309
|
const projection = data.observation;
|
|
@@ -323,23 +319,20 @@ export function renderListenerChange(squarePath, verb, data) {
|
|
|
323
319
|
: verb === 'ignore' ? `${actor} already ignores ${target} — only bells will reach you from them`
|
|
324
320
|
: `${actor} is not listening to ${target}`;
|
|
325
321
|
return withPathOutput(squarePath, `${data.activity === null ? '○' : '·'} ${action}`, {
|
|
326
|
-
participantCount: projection.standingCount,
|
|
322
|
+
participantCount: projection.standingCount,
|
|
327
323
|
});
|
|
328
324
|
}
|
|
329
|
-
export function renderLifecycleResult(squarePath,
|
|
325
|
+
export function renderLifecycleResult(squarePath, data) {
|
|
330
326
|
const projection = data.observation;
|
|
331
327
|
if (projection === undefined)
|
|
332
328
|
return undefined;
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
}
|
|
337
|
-
const line = `${renderRoomChangeText(projection.activity)} · ${formatActivityId(projection.activity.index)} · just now`;
|
|
338
|
-
return withPathOutput(projection.location ?? squarePath, verb === 'hold' ? `· ${line}` : `✓ ${line}`, header);
|
|
329
|
+
return withPathOutput(projection.location ?? squarePath, `○ you stepped out — your footsteps fade · ${data.activity.id}`, {
|
|
330
|
+
participantCount: projection.standingCount,
|
|
331
|
+
});
|
|
339
332
|
}
|
|
340
333
|
/** Refusal lines with the same recovery commands the CLI prints. */
|
|
341
334
|
export function renderFailureLines(failure, options = {}) {
|
|
342
|
-
const { squarePath, name } = options;
|
|
335
|
+
const { squarePath, name, owner } = options;
|
|
343
336
|
const facts = failure.facts;
|
|
344
337
|
const reason = facts?.reason;
|
|
345
338
|
const marked = reason === 'never_joined' || reason === 'not_standing';
|
|
@@ -350,13 +343,17 @@ export function renderFailureLines(failure, options = {}) {
|
|
|
350
343
|
else if (squarePath !== undefined)
|
|
351
344
|
lines.push(`${commandPrefix(squarePath)} migrate`);
|
|
352
345
|
}
|
|
346
|
+
else if (squarePath !== undefined && name !== undefined && reason === 'needs_seat') {
|
|
347
|
+
lines.splice(0, 1, `✕ ${failure.message}`);
|
|
348
|
+
lines.push(joinRecoveryCommand(squarePath, name, owner));
|
|
349
|
+
}
|
|
353
350
|
else if (squarePath !== undefined && name !== undefined && failure.code === 'already_joined') {
|
|
354
351
|
lines.splice(0, 1, `✕ ${participantIdentity(name)} shoos you out of the square`, ` · ${participantIdentity(name)} already stands here — another session holds the name`);
|
|
355
|
-
lines.push(...takeoverRecoveryLines(squarePath, name));
|
|
352
|
+
lines.push(...takeoverRecoveryLines(squarePath, name, owner));
|
|
356
353
|
}
|
|
357
354
|
else if (squarePath !== undefined && reason === 'never_joined') {
|
|
358
355
|
lines.push(failure.operation?.subject !== 'filter' && name !== undefined
|
|
359
|
-
? joinRecoveryCommand(squarePath, name) : participantsRecoveryCommand(squarePath));
|
|
356
|
+
? joinRecoveryCommand(squarePath, name, owner) : participantsRecoveryCommand(squarePath));
|
|
360
357
|
}
|
|
361
358
|
else if (squarePath !== undefined && reason === 'not_standing') {
|
|
362
359
|
lines.push(participantsRecoveryCommand(squarePath));
|
package/dist/owner.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type Owner } from './model.js';
|
|
2
|
+
export type { Owner } from './model.js';
|
|
3
|
+
export interface HarnessCoordinate {
|
|
4
|
+
readonly channel: string;
|
|
5
|
+
readonly session: string;
|
|
6
|
+
readonly agent?: string;
|
|
7
|
+
}
|
|
8
|
+
export declare function harnessOwner(coordinate: HarnessCoordinate): Owner;
|
|
9
|
+
/** Decode only at harness adapter boundaries; core never consumes the coordinate. */
|
|
10
|
+
export declare function decodeHarnessOwner(owner: Owner): HarnessCoordinate | undefined;
|
|
11
|
+
export declare function localUserOwner(): Owner;
|
package/dist/owner.js
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import os from 'node:os';
|
|
2
|
+
import { validateOwner } from './model.js';
|
|
3
|
+
export function harnessOwner(coordinate) {
|
|
4
|
+
const channel = nonempty(coordinate.channel, 'channel');
|
|
5
|
+
const session = nonempty(coordinate.session, 'session');
|
|
6
|
+
const agent = coordinate.agent === undefined ? undefined : nonempty(coordinate.agent, 'agent');
|
|
7
|
+
return validateOwner([channel, session, ...(agent === undefined ? [] : ['agent', agent])].map(encodeURIComponent).join(':'));
|
|
8
|
+
}
|
|
9
|
+
/** Decode only at harness adapter boundaries; core never consumes the coordinate. */
|
|
10
|
+
export function decodeHarnessOwner(owner) {
|
|
11
|
+
const parts = owner.split(':');
|
|
12
|
+
if ((parts.length !== 2 && parts.length !== 4) || (parts.length === 4 && parts[2] !== 'agent'))
|
|
13
|
+
return undefined;
|
|
14
|
+
try {
|
|
15
|
+
const [channel, session] = parts;
|
|
16
|
+
const decoded = { channel: decodeURIComponent(channel), session: decodeURIComponent(session) };
|
|
17
|
+
if (parts.length === 4)
|
|
18
|
+
return { ...decoded, agent: decodeURIComponent(parts[3]) };
|
|
19
|
+
return decoded;
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
return undefined;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
export function localUserOwner() {
|
|
26
|
+
return validateOwner(`user:${os.userInfo().username}@${os.hostname()}`);
|
|
27
|
+
}
|
|
28
|
+
function nonempty(value, label) {
|
|
29
|
+
if (typeof value !== 'string' || value.length === 0)
|
|
30
|
+
throw new Error(`Harness ${label} must be non-empty.`);
|
|
31
|
+
return value;
|
|
32
|
+
}
|
package/dist/paseo-delivery.d.ts
CHANGED
|
@@ -2,12 +2,15 @@ import type { WakeRequest, WakeOutcome, WakeTransportPort } from './ports.js';
|
|
|
2
2
|
import { discoverPaseoAgents, waitForPaseoWakeBoundary } from './paseo-state.js';
|
|
3
3
|
import { sendPaseoWake } from './wake-sink.js';
|
|
4
4
|
export interface PaseoWakeTransportOptions {
|
|
5
|
-
discover?: typeof discoverPaseoAgents
|
|
5
|
+
discover?: (timeoutMs: number) => ReturnType<typeof discoverPaseoAgents> | Awaited<ReturnType<typeof discoverPaseoAgents>>;
|
|
6
6
|
waitForBoundary?: typeof waitForPaseoWakeBoundary;
|
|
7
7
|
sendWake?: typeof sendPaseoWake;
|
|
8
8
|
}
|
|
9
9
|
export declare class PaseoWakeTransport implements WakeTransportPort {
|
|
10
10
|
private readonly opts;
|
|
11
|
+
private discovering?;
|
|
11
12
|
constructor(opts?: PaseoWakeTransportOptions);
|
|
13
|
+
/** Coalesce overlapping inventory reads only; a later send must rediscover current status. */
|
|
14
|
+
private discover;
|
|
12
15
|
attempt(request: WakeRequest, timeoutMs: number, beforeSend: () => Promise<boolean>): Promise<WakeOutcome>;
|
|
13
16
|
}
|