@astrosheep/square 0.3.106 → 0.4.1
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.js +1 -1
- package/dist/artifact-store.d.ts +41 -0
- package/dist/artifact-store.js +272 -0
- package/dist/artifact.d.ts +6 -12
- package/dist/artifact.js +43 -344
- package/dist/attention-presentation.d.ts +13 -7
- package/dist/attention-presentation.js +29 -68
- package/dist/boundary-presentation.d.ts +3 -16
- package/dist/boundary-presentation.js +29 -109
- package/dist/card-presentation.d.ts +1 -0
- package/dist/card-presentation.js +2 -0
- package/dist/catch-decisions.d.ts +2 -2
- package/dist/catch-decisions.js +7 -3
- package/dist/catch-selection.d.ts +8 -0
- package/dist/catch-selection.js +5 -0
- package/dist/claude-delivery.d.ts +14 -12
- package/dist/claude-delivery.js +42 -142
- package/dist/claude-mcp-context.js +2 -2
- package/dist/claude-mod.js +28 -140
- package/dist/claude-transport.d.ts +5 -0
- package/dist/claude-transport.js +34 -0
- package/dist/cli/context.d.ts +2 -2
- package/dist/cli/context.js +7 -10
- package/dist/cli/maintenance-commands.d.ts +0 -4
- package/dist/cli/maintenance-commands.js +2 -29
- package/dist/cli/observation-commands.d.ts +2 -0
- package/dist/cli/observation-commands.js +12 -2
- package/dist/cli/program.js +1 -1
- package/dist/cli/registry.js +4 -3
- package/dist/codex-address.d.ts +2 -2
- package/dist/codex-boundary-state.d.ts +1 -5
- package/dist/codex-boundary-state.js +0 -4
- package/dist/codex-hook.d.ts +7 -10
- package/dist/codex-hook.js +69 -33
- package/dist/codex-queue.d.ts +10 -11
- package/dist/codex-queue.js +32 -34
- package/dist/codex-watch.d.ts +2 -0
- package/dist/codex-watch.js +100 -0
- package/dist/decisions.js +3 -3
- package/dist/delivery-deferral.d.ts +1 -19
- package/dist/delivery-deferral.js +1 -29
- package/dist/delivery-frame.d.ts +7 -0
- package/dist/delivery-frame.js +11 -0
- package/dist/delivery-ledger-sqlite.d.ts +97 -0
- package/dist/delivery-ledger-sqlite.js +496 -0
- package/dist/delivery-ledger.d.ts +196 -0
- package/dist/delivery-ledger.js +268 -0
- package/dist/delivery-lifetime.d.ts +6 -0
- package/dist/delivery-lifetime.js +45 -0
- package/dist/harness-links.js +61 -7
- package/dist/harness.js +12 -17
- package/dist/help.js +3 -6
- package/dist/http-delivery.d.ts +5 -9
- package/dist/http-delivery.js +20 -79
- package/dist/inbox.d.ts +6 -57
- package/dist/inbox.js +24 -380
- package/dist/index.d.ts +7 -4
- package/dist/index.js +5 -2
- package/dist/mcp.d.ts +2 -1
- package/dist/mcp.js +40 -70
- package/dist/message.d.ts +7 -0
- package/dist/message.js +23 -0
- package/dist/model.d.ts +15 -91
- package/dist/model.js +2 -140
- package/dist/neutral.d.ts +72 -0
- package/dist/neutral.js +27 -0
- package/dist/notifications.d.ts +24 -26
- package/dist/notifications.js +39 -143
- package/dist/operation-control.d.ts +4 -0
- package/dist/operation-control.js +20 -0
- package/dist/operation-presentation.d.ts +1 -2
- package/dist/operation-presentation.js +1 -7
- package/dist/owner.d.ts +2 -2
- package/dist/owner.js +1 -1
- package/dist/packages/agent-delivery/src/claude-native.d.ts +2 -0
- package/dist/packages/agent-delivery/src/claude-native.js +5 -0
- package/dist/packages/agent-delivery/src/codex-boundary.d.ts +11 -6
- package/dist/packages/agent-delivery/src/codex-boundary.js +31 -40
- package/dist/packages/agent-delivery/src/codex-hook.d.ts +17 -12
- package/dist/packages/agent-delivery/src/codex-hook.js +26 -39
- package/dist/packages/agent-delivery/src/codex.d.ts +3 -0
- package/dist/packages/agent-delivery/src/codex.js +41 -4
- package/dist/packages/agent-delivery/src/index.d.ts +3 -1
- package/dist/packages/agent-delivery/src/index.js +1 -1
- package/dist/packages/agent-delivery/src/paseo.js +11 -2
- package/dist/packages/agent-delivery/src/types.d.ts +1 -0
- package/dist/paseo-delivery.d.ts +5 -5
- package/dist/paseo-delivery.js +19 -99
- package/dist/paseo.d.ts +1 -1
- package/dist/paseo.js +1 -1
- package/dist/plugins/opencode/index.d.ts +5 -3
- package/dist/plugins/opencode/index.js +99 -21
- package/dist/plugins/opencode-shared/delivery.d.ts +23 -0
- package/dist/plugins/opencode-shared/delivery.js +109 -0
- package/dist/plugins/opencode-v1/index.d.ts +28 -0
- package/dist/plugins/opencode-v1/index.js +41 -0
- package/dist/plugins/opencode-v1/runtime.d.ts +56 -0
- package/dist/plugins/opencode-v1/runtime.js +152 -0
- package/dist/plugins/opencode-v1/transport.d.ts +13 -0
- package/dist/plugins/opencode-v1/transport.js +50 -0
- package/dist/plugins/paseo/shared/card-presentation.d.ts +10 -0
- package/dist/plugins/paseo/shared/card-presentation.js +7 -0
- package/dist/ports.d.ts +33 -214
- package/dist/presentation.d.ts +5 -5
- package/dist/presentation.js +1 -0
- package/dist/runtime.js +2 -2
- package/dist/search.js +1 -1
- package/dist/session-lifecycle.d.ts +8 -7
- package/dist/session-lifecycle.js +40 -42
- package/dist/sqlite-framing.d.ts +8 -0
- package/dist/sqlite-framing.js +31 -0
- package/dist/sqlite-square.d.ts +16 -26
- package/dist/sqlite-square.js +199 -262
- package/dist/sqlite-values.d.ts +21 -0
- package/dist/sqlite-values.js +78 -0
- package/dist/square-api.d.ts +1 -1
- package/dist/square-api.js +5 -8
- package/dist/square-core.d.ts +0 -1
- package/dist/square-domain.d.ts +12 -10
- package/dist/square-domain.js +105 -223
- package/dist/square-facade.d.ts +25 -76
- package/dist/square-location.d.ts +6 -1
- package/dist/square-location.js +1 -1
- package/dist/square-post.d.ts +53 -0
- package/dist/square-post.js +4 -0
- package/dist/square-posting.d.ts +13 -0
- package/dist/square-posting.js +174 -0
- package/dist/square-producer-sqlite.d.ts +11 -0
- package/dist/square-producer-sqlite.js +210 -0
- package/dist/square-receive.d.ts +2 -3
- package/dist/square-sqlite.d.ts +33 -42
- package/dist/square-sqlite.js +236 -768
- package/dist/square-tools.d.ts +8 -0
- package/dist/square-tools.js +39 -0
- package/dist/square-values.d.ts +27 -0
- package/dist/square-values.js +90 -0
- package/dist/views.d.ts +6 -6
- package/dist/views.js +14 -9
- package/dist/wake-sink.d.ts +4 -11
- package/dist/wake-sink.js +8 -32
- package/dist/wake-transports.d.ts +4 -0
- package/dist/wake-transports.js +11 -0
- package/examples/symmetric-domains.mjs +29 -249
- package/guides/change-waits.md +13 -53
- package/guides/claude-native.md +19 -172
- package/guides/codex-delivery.md +55 -78
- package/guides/delivery-primitives.md +48 -207
- package/guides/operation-cancellation.md +2 -5
- package/guides/participant-ownership.md +25 -89
- package/guides/pi-native-delivery.md +19 -56
- package/guides/pi-tools.md +6 -8
- package/guides/row-runtime-delivery-evidence.md +2 -0
- package/guides/row-storage-design.md +19 -44
- package/guides/square-api.md +113 -538
- package/package.json +8 -8
- package/plugins/claude/.claude-plugin/plugin.json +1 -1
- package/plugins/claude/hooks/hooks.json +1 -1
- package/plugins/claude/{hooks/register.js → mods/square.js} +4 -7
- package/plugins/claude/types.d.ts +1 -1
- package/plugins/codex/.codex-plugin/plugin.json +1 -1
- package/plugins/codex/hooks/hooks.json +11 -23
- package/plugins/opencode/index.ts +91 -23
- package/plugins/opencode-shared/delivery.ts +91 -0
- package/plugins/opencode-v1/index.ts +36 -0
- package/plugins/opencode-v1/runtime.ts +134 -0
- package/plugins/opencode-v1/transport.ts +41 -0
- package/plugins/paseo/OVERVIEW.md +5 -5
- package/plugins/paseo/README.md +7 -6
- package/plugins/paseo/client/markdown.tsx +5 -5
- package/plugins/paseo/client/square-message.tsx +28 -24
- package/plugins/paseo/client/transform.ts +8 -5
- package/plugins/paseo/shared/card-presentation.ts +16 -0
- package/plugins/paseo/shared/message.ts +6 -11
- package/plugins/pi/square-pi.js +167 -451
- package/dist/channel.d.ts +0 -74
- package/dist/channel.js +0 -92
- package/dist/claude-delivery-status.d.ts +0 -13
- package/dist/claude-delivery-status.js +0 -46
- package/dist/cmd/notify-once.d.ts +0 -2
- package/dist/cmd/notify-once.js +0 -29
- package/dist/delivery-attempts.d.ts +0 -52
- package/dist/delivery-attempts.js +0 -73
- package/dist/delivery-effects.d.ts +0 -139
- package/dist/delivery-effects.js +0 -163
- package/dist/delivery-health.d.ts +0 -51
- package/dist/delivery-health.js +0 -173
- package/dist/delivery-operations.d.ts +0 -9
- package/dist/delivery-operations.js +0 -168
- package/dist/delivery-primitives.d.ts +0 -5
- package/dist/delivery-primitives.js +0 -3
- package/dist/delivery.d.ts +0 -45
- package/dist/delivery.js +0 -106
- package/dist/plugins/opencode/delivery.d.ts +0 -19
- package/dist/plugins/opencode/delivery.js +0 -238
- package/dist/presentation-operations.d.ts +0 -18
- package/dist/presentation-operations.js +0 -86
- package/dist/square-index.d.ts +0 -16
- package/dist/square-index.js +0 -106
- package/dist/square-legacy-framing.d.ts +0 -11
- package/dist/square-legacy-framing.js +0 -64
- package/dist/square-migration-host-ledger.d.ts +0 -26
- package/dist/square-migration-host-ledger.js +0 -169
- package/dist/square-migration.d.ts +0 -30
- package/dist/square-migration.js +0 -599
- package/guides/migration.md +0 -156
- package/plugins/opencode/delivery.ts +0 -211
package/dist/delivery-effects.js
DELETED
|
@@ -1,163 +0,0 @@
|
|
|
1
|
-
async function settle(port, claim, completion) {
|
|
2
|
-
try {
|
|
3
|
-
return { completion, persistence: { status: await port.settle(claim, completion) ? 'recorded' : 'not-recorded' } };
|
|
4
|
-
}
|
|
5
|
-
catch (error) {
|
|
6
|
-
return { completion, persistence: { status: 'error', error } };
|
|
7
|
-
}
|
|
8
|
-
}
|
|
9
|
-
async function current(port, signal) {
|
|
10
|
-
try {
|
|
11
|
-
return await port.current(signal);
|
|
12
|
-
}
|
|
13
|
-
catch {
|
|
14
|
-
return false;
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
/** Timer bounds the external attempt only, not claim/currentness/persistence. No automatic retry. */
|
|
18
|
-
export async function dispatchEffect(port, send, options) {
|
|
19
|
-
const notInvoked = { kind: 'not-invoked' };
|
|
20
|
-
if (options.signal?.aborted)
|
|
21
|
-
return { observation: notInvoked };
|
|
22
|
-
const claim = await port.claim(options.signal);
|
|
23
|
-
if (claim === undefined)
|
|
24
|
-
return { observation: notInvoked };
|
|
25
|
-
if (!await current(port, options.signal))
|
|
26
|
-
return { observation: notInvoked,
|
|
27
|
-
settlement: await settle(port, claim, { outcome: 'released', reason: 'not-current', phase: 'initial' }) };
|
|
28
|
-
if (options.signal?.aborted)
|
|
29
|
-
return { observation: notInvoked,
|
|
30
|
-
settlement: await settle(port, claim, { outcome: 'released', reason: 'cancelled' }) };
|
|
31
|
-
let denied = false;
|
|
32
|
-
let timer;
|
|
33
|
-
const deadline = Date.now() + options.timeoutMs;
|
|
34
|
-
const timeout = new Promise(resolve => {
|
|
35
|
-
timer = setTimeout(() => resolve({ kind: 'timeout' }), options.timeoutMs);
|
|
36
|
-
});
|
|
37
|
-
let observation;
|
|
38
|
-
let completion;
|
|
39
|
-
try {
|
|
40
|
-
observation = await Promise.race([timeout, (async () => {
|
|
41
|
-
try {
|
|
42
|
-
return { kind: 'returned', result: await send({ claim, deadline, ...options,
|
|
43
|
-
beforeSend: async () => {
|
|
44
|
-
const allowed = await current(port, options.signal);
|
|
45
|
-
if (!allowed)
|
|
46
|
-
denied = true;
|
|
47
|
-
return allowed;
|
|
48
|
-
},
|
|
49
|
-
}) };
|
|
50
|
-
}
|
|
51
|
-
catch (error) {
|
|
52
|
-
return { kind: 'threw', error };
|
|
53
|
-
}
|
|
54
|
-
})()]);
|
|
55
|
-
// Freeze before persistence. Late policy results/sender completions cannot rewrite it.
|
|
56
|
-
completion = observation.kind === 'timeout' ? { outcome: 'unknown', reason: 'timeout' }
|
|
57
|
-
: denied ? { outcome: 'released', reason: 'not-current', phase: 'final' }
|
|
58
|
-
: observation.kind === 'threw' ? { outcome: 'unknown', reason: 'threw', error: observation.error }
|
|
59
|
-
: observation.result.outcome === 'not-capable'
|
|
60
|
-
? { outcome: 'released', reason: 'not-capable', data: observation.result.data }
|
|
61
|
-
: { outcome: observation.result.outcome, reason: 'returned', data: observation.result.data };
|
|
62
|
-
}
|
|
63
|
-
finally {
|
|
64
|
-
if (timer !== undefined)
|
|
65
|
-
clearTimeout(timer);
|
|
66
|
-
}
|
|
67
|
-
return { observation, settlement: await settle(port, claim, completion) };
|
|
68
|
-
}
|
|
69
|
-
const preparedBrand = Symbol('prepared presentation');
|
|
70
|
-
const custody = new WeakMap();
|
|
71
|
-
export async function preparePresentation(work, control) {
|
|
72
|
-
if (control?.signal?.aborted)
|
|
73
|
-
return undefined;
|
|
74
|
-
const claim = await work.port.claim(control?.signal);
|
|
75
|
-
if (claim === undefined)
|
|
76
|
-
return undefined;
|
|
77
|
-
let resolve;
|
|
78
|
-
let decided = false;
|
|
79
|
-
const state = {
|
|
80
|
-
owned: false, coverage: work.coverage,
|
|
81
|
-
eligible: signal => signal?.aborted ? Promise.resolve(false) : current(work.port, signal),
|
|
82
|
-
done: new Promise(res => { resolve = res; }),
|
|
83
|
-
finish(completion) {
|
|
84
|
-
if (decided)
|
|
85
|
-
return;
|
|
86
|
-
decided = true;
|
|
87
|
-
// Defer callbacks: every included handle is marked before any settlement starts.
|
|
88
|
-
void Promise.resolve().then(() => settle(work.port, claim, completion)).then(resolve);
|
|
89
|
-
},
|
|
90
|
-
};
|
|
91
|
-
const prepared = Object.freeze({
|
|
92
|
-
[preparedBrand]: true,
|
|
93
|
-
payload: work.payload,
|
|
94
|
-
eligible: (signal) => state.owned ? Promise.resolve(false) : state.eligible(signal),
|
|
95
|
-
release() {
|
|
96
|
-
if (!state.owned) {
|
|
97
|
-
state.owned = true;
|
|
98
|
-
state.finish({ outcome: 'released', reason: 'unused' });
|
|
99
|
-
}
|
|
100
|
-
return state.done;
|
|
101
|
-
},
|
|
102
|
-
});
|
|
103
|
-
custody.set(prepared, state);
|
|
104
|
-
return prepared;
|
|
105
|
-
}
|
|
106
|
-
export function presentPrepared(prepared, sink, control) {
|
|
107
|
-
return presentPreparedBatch([prepared], eligible => ({ payload: prepared.payload, included: eligible }), sink, control);
|
|
108
|
-
}
|
|
109
|
-
/** Takes all local custody synchronously, then owns eligibility/effect/settlement/cleanup. */
|
|
110
|
-
export async function presentPreparedBatch(prepared, render, sink, control = {}) {
|
|
111
|
-
const handles = [...prepared];
|
|
112
|
-
const states = handles.map(handle => custody.get(handle));
|
|
113
|
-
if (new Set(handles).size !== handles.length || states.some(state => state === undefined || state.owned)) {
|
|
114
|
-
await Promise.all([...new Set(handles)].filter(handle => custody.has(handle) && !custody.get(handle).owned).map(handle => handle.release()));
|
|
115
|
-
throw new TypeError('Presentation requires unique, unused prepared custody.');
|
|
116
|
-
}
|
|
117
|
-
const owned = states;
|
|
118
|
-
for (const state of owned)
|
|
119
|
-
state.owned = true;
|
|
120
|
-
let observation = { kind: 'not-invoked' };
|
|
121
|
-
try {
|
|
122
|
-
const eligible = [];
|
|
123
|
-
for (const [index, state] of owned.entries()) {
|
|
124
|
-
if (await state.eligible(control.signal))
|
|
125
|
-
eligible.push(handles[index]);
|
|
126
|
-
else
|
|
127
|
-
state.finish({ outcome: 'released', reason: control.signal?.aborted ? 'cancelled' : 'not-current' });
|
|
128
|
-
}
|
|
129
|
-
const rendered = render(Object.freeze(eligible));
|
|
130
|
-
const included = [...rendered.included];
|
|
131
|
-
if (new Set(included).size !== included.length || included.some(handle => !eligible.includes(handle)))
|
|
132
|
-
throw new TypeError('Included presentations must be a unique subset of eligible custody.');
|
|
133
|
-
if (included.length > 0 && !control.signal?.aborted) {
|
|
134
|
-
let completion;
|
|
135
|
-
try {
|
|
136
|
-
const value = await sink(rendered.payload);
|
|
137
|
-
observation = { kind: 'returned', value };
|
|
138
|
-
completion = { outcome: 'presented', reason: 'returned' };
|
|
139
|
-
}
|
|
140
|
-
catch (error) {
|
|
141
|
-
let outcome = 'unknown';
|
|
142
|
-
try {
|
|
143
|
-
if (control.classifyError?.(error) === 'failed')
|
|
144
|
-
outcome = 'failed';
|
|
145
|
-
}
|
|
146
|
-
catch { /* conservative */ }
|
|
147
|
-
observation = { kind: 'threw', error, outcome };
|
|
148
|
-
completion = { outcome, reason: 'threw', error };
|
|
149
|
-
}
|
|
150
|
-
for (const handle of included) {
|
|
151
|
-
const state = custody.get(handle);
|
|
152
|
-
state.finish(completion.outcome === 'presented'
|
|
153
|
-
? { outcome: state.coverage === 'full' ? 'presented' : 'clipped', reason: 'returned' } : completion);
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
finally {
|
|
158
|
-
for (const state of owned)
|
|
159
|
-
state.finish({ outcome: 'released', reason: control.signal?.aborted ? 'cancelled' : 'unused' });
|
|
160
|
-
await Promise.all(owned.map(state => state.done));
|
|
161
|
-
}
|
|
162
|
-
return { observation, settlements: await Promise.all(handles.map(async (handle, index) => ({ prepared: handle, result: await owned[index].done }))) };
|
|
163
|
-
}
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import { type DirectedNotificationRoute } from './delivery.js';
|
|
2
|
-
import type { DeliveryEvidence } from './ports.js';
|
|
3
|
-
export interface WakeAttempt {
|
|
4
|
-
readonly nativeObservations?: readonly NonNullable<DeliveryEvidence['nativeObservations']>[number][];
|
|
5
|
-
readonly at: number;
|
|
6
|
-
readonly attention: {
|
|
7
|
-
readonly squarePath: string;
|
|
8
|
-
readonly recipient: string;
|
|
9
|
-
readonly actIndex: number;
|
|
10
|
-
};
|
|
11
|
-
readonly routeKind: import('./model.js').WakeRouteKind;
|
|
12
|
-
readonly outcome: 'accepted' | 'unknown' | 'failed';
|
|
13
|
-
readonly signature?: string;
|
|
14
|
-
readonly attemptN: number;
|
|
15
|
-
readonly message?: string;
|
|
16
|
-
readonly diagnostic?: unknown;
|
|
17
|
-
}
|
|
18
|
-
export interface WakeReleaseDiagnostic {
|
|
19
|
-
readonly at: number;
|
|
20
|
-
readonly attention: {
|
|
21
|
-
readonly squarePath: string;
|
|
22
|
-
readonly recipient: string;
|
|
23
|
-
readonly actIndex: number;
|
|
24
|
-
};
|
|
25
|
-
readonly routeKind?: import('./model.js').WakeRouteKind;
|
|
26
|
-
readonly attemptN?: number;
|
|
27
|
-
readonly session?: string;
|
|
28
|
-
readonly signature?: string;
|
|
29
|
-
readonly message?: string;
|
|
30
|
-
readonly diagnostic?: unknown;
|
|
31
|
-
}
|
|
32
|
-
export type DeliveryHealthKind = 'awaiting' | 'wake-accepted' | 'wake-unknown' | 'presented-not-delivered' | 'unreachable';
|
|
33
|
-
export interface DeliveryHealthItem {
|
|
34
|
-
squarePath: string;
|
|
35
|
-
recipient: string;
|
|
36
|
-
actIndex: number;
|
|
37
|
-
actor: string;
|
|
38
|
-
at: number;
|
|
39
|
-
ageMs: number;
|
|
40
|
-
route: DirectedNotificationRoute;
|
|
41
|
-
kind: DeliveryHealthKind;
|
|
42
|
-
attempt?: WakeAttempt;
|
|
43
|
-
}
|
|
44
|
-
/** Classify current pending attention from the artifact's seats and delivery evidence. */
|
|
45
|
-
export declare function classifyDeliveryHealth(squarePath: string, opts: {
|
|
46
|
-
graceMs: number;
|
|
47
|
-
now?: number;
|
|
48
|
-
env?: NodeJS.ProcessEnv;
|
|
49
|
-
}): Promise<DeliveryHealthItem[]>;
|
|
50
|
-
export declare function renderDeliveryHealth(items: readonly DeliveryHealthItem[], releases?: readonly WakeReleaseDiagnostic[], now?: number, nativeAttempts?: readonly WakeAttempt[]): string[];
|
|
51
|
-
export declare function doctorDeliveryHealth(squarePath: string, graceMs: number, now?: number, env?: NodeJS.ProcessEnv): Promise<string[]>;
|
package/dist/delivery-health.js
DELETED
|
@@ -1,173 +0,0 @@
|
|
|
1
|
-
import { collectPending } from './delivery.js';
|
|
2
|
-
import { formatActivityId } from './square-core.js';
|
|
3
|
-
import { participantIdentity, truncateChars } from './presentation.js';
|
|
4
|
-
import { formatDuration } from './time.js';
|
|
5
|
-
import { InternalSquareError, SquareError } from './model.js';
|
|
6
|
-
import { createArtifactPort } from './artifact.js';
|
|
7
|
-
const DISPLAY_ORDER = [
|
|
8
|
-
'awaiting',
|
|
9
|
-
'wake-accepted',
|
|
10
|
-
'wake-unknown',
|
|
11
|
-
'presented-not-delivered',
|
|
12
|
-
'unreachable',
|
|
13
|
-
];
|
|
14
|
-
const ACTIONABLE = new Set(['wake-unknown', 'unreachable']);
|
|
15
|
-
const DETAIL_LIMIT = 20;
|
|
16
|
-
const DISPLAY_FIELD_LIMIT = 160;
|
|
17
|
-
/** Classify current pending attention from the artifact's seats and delivery evidence. */
|
|
18
|
-
export async function classifyDeliveryHealth(squarePath, opts) {
|
|
19
|
-
const now = opts.now ?? Date.now();
|
|
20
|
-
const artifact = createArtifactPort(squarePath);
|
|
21
|
-
try {
|
|
22
|
-
const { pending } = await collectPending(artifact);
|
|
23
|
-
const current = (await artifact.read((facts) => pending.map((note) => {
|
|
24
|
-
const seat = facts.seat(note.recipient);
|
|
25
|
-
const evidence = seat === undefined ? [] : facts.deliveryEvidence(seat.participant, seat.generation, formatActivityId(note.index));
|
|
26
|
-
return { note, seat, evidence };
|
|
27
|
-
}))).value;
|
|
28
|
-
const items = [];
|
|
29
|
-
for (const { note, seat, evidence } of current) {
|
|
30
|
-
const ageMs = Math.max(0, now - note.at);
|
|
31
|
-
const presentation = evidence.some((row) => row.kind === 'presentation' && (row.outcome === 'presented' || row.outcome === 'clipped' || row.outcome === 'unknown'
|
|
32
|
-
|| row.outcome === 'dispatching'));
|
|
33
|
-
const terminal = evidence.findLast((row) => row.kind === 'wake' && (row.outcome === 'accepted' || row.outcome === 'unknown'));
|
|
34
|
-
const attemptRow = evidence.findLast((row) => row.kind === 'wake' && (row.outcome === 'accepted' || row.outcome === 'unknown' || row.outcome === 'failed'));
|
|
35
|
-
const attempt = attemptRow === undefined || seat === undefined ? undefined : deliveryAttempt(squarePath, attemptRow, { squarePath, recipient: seat.participant, actIndex: note.index });
|
|
36
|
-
const kind = presentation
|
|
37
|
-
? 'presented-not-delivered'
|
|
38
|
-
: terminal?.outcome === 'accepted'
|
|
39
|
-
? 'wake-accepted'
|
|
40
|
-
: terminal?.outcome === 'unknown'
|
|
41
|
-
? 'wake-unknown'
|
|
42
|
-
: ageMs > opts.graceMs && seat?.wakeAddress === undefined
|
|
43
|
-
? 'unreachable'
|
|
44
|
-
: 'awaiting';
|
|
45
|
-
items.push({
|
|
46
|
-
squarePath,
|
|
47
|
-
recipient: note.recipient,
|
|
48
|
-
actIndex: note.index,
|
|
49
|
-
actor: note.actor,
|
|
50
|
-
at: note.at,
|
|
51
|
-
ageMs,
|
|
52
|
-
route: note.route,
|
|
53
|
-
kind,
|
|
54
|
-
...(attempt === undefined ? {} : { attempt }),
|
|
55
|
-
});
|
|
56
|
-
}
|
|
57
|
-
// The captured pending set is the ownership boundary: a candidate that was
|
|
58
|
-
// not pending at the scan cannot become a health item during this read.
|
|
59
|
-
return items;
|
|
60
|
-
}
|
|
61
|
-
catch (error) {
|
|
62
|
-
if (error instanceof InternalSquareError && error.code === 'not_found')
|
|
63
|
-
throw new SquareError('unavailable', `Square is unavailable at ${squarePath}`);
|
|
64
|
-
throw error;
|
|
65
|
-
}
|
|
66
|
-
finally {
|
|
67
|
-
await artifact.close();
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
function displayField(value) {
|
|
71
|
-
const truncated = truncateChars(value, DISPLAY_FIELD_LIMIT - 1);
|
|
72
|
-
return truncated.remaining === 0 ? truncated.text : `${truncated.text}…`;
|
|
73
|
-
}
|
|
74
|
-
export function renderDeliveryHealth(items, releases = [], now = Date.now(), nativeAttempts = []) {
|
|
75
|
-
const out = items.length === 0 ? ['✓ no pending delivery attention'] : [`· delivery attention · ${items.length} pending`];
|
|
76
|
-
if (items.length > 0) {
|
|
77
|
-
let displayed = 0;
|
|
78
|
-
for (const kind of DISPLAY_ORDER) {
|
|
79
|
-
const group = items.filter((item) => item.kind === kind);
|
|
80
|
-
if (group.length === 0)
|
|
81
|
-
continue;
|
|
82
|
-
out.push(`${ACTIONABLE.has(kind) ? '✕' : '○'} ${kind}: ${group.length}`);
|
|
83
|
-
const details = group.slice(0, DETAIL_LIMIT - displayed);
|
|
84
|
-
out.push(...details.map((item) => {
|
|
85
|
-
const evidence = item.attempt?.signature === undefined ? '' : ` · ${displayField(item.attempt.signature)}`;
|
|
86
|
-
return ` · ${formatActivityId(item.actIndex)} → ${displayField(participantIdentity(item.recipient))} from ${displayField(participantIdentity(item.actor))} · ${formatDuration(item.ageMs)}${evidence}`;
|
|
87
|
-
}));
|
|
88
|
-
displayed += details.length;
|
|
89
|
-
}
|
|
90
|
-
if (items.length > DETAIL_LIMIT)
|
|
91
|
-
out.push(`${DETAIL_LIMIT} of ${items.length} pending details shown`);
|
|
92
|
-
}
|
|
93
|
-
if (nativeAttempts.length > 0) {
|
|
94
|
-
out.push(`· Claude native custody · ${nativeAttempts.length}`);
|
|
95
|
-
out.push(...nativeAttempts.slice(0, DETAIL_LIMIT).map((attempt) => {
|
|
96
|
-
const observations = [...attempt.nativeObservations ?? []].sort((a, b) => a.observedAt - b.observedAt);
|
|
97
|
-
const last = observations.at(-1);
|
|
98
|
-
const states = observations.map((observation) => `${observation.state}${observation.reason ? ` (${observation.reason})` : ''}`).join(' → ');
|
|
99
|
-
return ` · ${formatActivityId(attempt.attention.actIndex)} → ${displayField(participantIdentity(attempt.attention.recipient))} · ${attempt.outcome} · native ${displayField(states)} · ${formatDuration(Math.max(0, now - last.observedAt))} · message ${displayField(last.messageId)}`;
|
|
100
|
-
}));
|
|
101
|
-
if (nativeAttempts.length > DETAIL_LIMIT)
|
|
102
|
-
out.push(`${DETAIL_LIMIT} of ${nativeAttempts.length} native custody details shown`);
|
|
103
|
-
}
|
|
104
|
-
if (releases.length > 0) {
|
|
105
|
-
out.push(`· recent wake releases · ${releases.length}`);
|
|
106
|
-
out.push(...releases.slice(0, DETAIL_LIMIT).map((release) => formatRelease(release, now)));
|
|
107
|
-
if (releases.length > DETAIL_LIMIT)
|
|
108
|
-
out.push(`${DETAIL_LIMIT} of ${releases.length} wake releases shown`);
|
|
109
|
-
}
|
|
110
|
-
return out;
|
|
111
|
-
}
|
|
112
|
-
function formatRelease(release, now) {
|
|
113
|
-
const route = displayField(release.routeKind ?? 'unknown route');
|
|
114
|
-
const reason = displayField(release.signature ?? 'reason not recorded');
|
|
115
|
-
const age = formatDuration(Math.max(0, now - release.at));
|
|
116
|
-
const message = release.message === undefined ? '' : ` — ${displayField(release.message)}`;
|
|
117
|
-
const diagnostic = release.diagnostic === undefined ? '' : ` · ${displayField(JSON.stringify(release.diagnostic))}`;
|
|
118
|
-
return ` · ${formatActivityId(release.attention.actIndex)} → ${displayField(participantIdentity(release.attention.recipient))} · ${route} · ${reason} · ${age}${message}${diagnostic}`;
|
|
119
|
-
}
|
|
120
|
-
function deliveryAttempt(squarePath, row, attention = { squarePath, recipient: row.participant, actIndex: Number(row.activity.slice(4)) }) {
|
|
121
|
-
if (row.route?.kind === undefined || row.outcome === 'released' || row.outcome === 'dispatching')
|
|
122
|
-
return undefined;
|
|
123
|
-
return {
|
|
124
|
-
at: row.at,
|
|
125
|
-
attention,
|
|
126
|
-
routeKind: row.route.kind,
|
|
127
|
-
outcome: row.outcome,
|
|
128
|
-
attemptN: row.attemptN,
|
|
129
|
-
...(row.signature === undefined ? {} : { signature: row.signature }),
|
|
130
|
-
...(row.message === undefined ? {} : { message: row.message }),
|
|
131
|
-
...(row.diagnostic === undefined ? {} : { diagnostic: row.diagnostic }),
|
|
132
|
-
...(row.nativeObservations === undefined ? {} : { nativeObservations: row.nativeObservations }),
|
|
133
|
-
};
|
|
134
|
-
}
|
|
135
|
-
function deliveryRelease(squarePath, row) {
|
|
136
|
-
return {
|
|
137
|
-
at: row.at,
|
|
138
|
-
attention: { squarePath, recipient: row.participant, actIndex: Number(row.activity.slice(4)) },
|
|
139
|
-
routeKind: row.route?.kind,
|
|
140
|
-
attemptN: row.attemptN,
|
|
141
|
-
...(row.signature === undefined ? {} : { signature: row.signature }),
|
|
142
|
-
...(row.message === undefined ? {} : { message: row.message }),
|
|
143
|
-
...(row.diagnostic === undefined ? {} : { diagnostic: row.diagnostic }),
|
|
144
|
-
};
|
|
145
|
-
}
|
|
146
|
-
export async function doctorDeliveryHealth(squarePath, graceMs, now = Date.now(), env = process.env) {
|
|
147
|
-
const items = await classifyDeliveryHealth(squarePath, { graceMs, now, env });
|
|
148
|
-
const artifact = createArtifactPort(squarePath);
|
|
149
|
-
try {
|
|
150
|
-
const { value: rows } = await artifact.read((facts) => facts.roster().flatMap((participant) => {
|
|
151
|
-
const seat = facts.seat(participant.name);
|
|
152
|
-
return seat === undefined ? [] : facts.deliveryEvidence(seat.participant, seat.generation);
|
|
153
|
-
}));
|
|
154
|
-
const releases = rows.filter((row) => row.kind === 'wake' && row.outcome === 'released')
|
|
155
|
-
.map((row) => deliveryRelease(squarePath, row))
|
|
156
|
-
.sort((left, right) => right.at - left.at);
|
|
157
|
-
const nativeAttempts = rows.flatMap((row) => {
|
|
158
|
-
if (row.kind !== 'wake' || row.nativeObservations?.length === 0)
|
|
159
|
-
return [];
|
|
160
|
-
const attempt = deliveryAttempt(squarePath, row);
|
|
161
|
-
return attempt?.nativeObservations?.length ? [attempt] : [];
|
|
162
|
-
}).sort((a, b) => Math.max(...b.nativeObservations.map((row) => row.observedAt)) - Math.max(...a.nativeObservations.map((row) => row.observedAt)));
|
|
163
|
-
return renderDeliveryHealth(items, releases, now, nativeAttempts);
|
|
164
|
-
}
|
|
165
|
-
catch (error) {
|
|
166
|
-
if (error instanceof InternalSquareError && error.code === 'not_found')
|
|
167
|
-
throw new SquareError('unavailable', `Square is unavailable at ${squarePath}`);
|
|
168
|
-
throw error;
|
|
169
|
-
}
|
|
170
|
-
finally {
|
|
171
|
-
await artifact.close();
|
|
172
|
-
}
|
|
173
|
-
}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import type { SquareArtifactPort, DeliverPendingInput } from './ports.js';
|
|
2
|
-
export declare function deliverPending(input: DeliverPendingInput): Promise<void>;
|
|
3
|
-
export declare function sweepPending(input: {
|
|
4
|
-
readonly artifact: SquareArtifactPort;
|
|
5
|
-
readonly location: string;
|
|
6
|
-
readonly now: number;
|
|
7
|
-
readonly graceMs: number;
|
|
8
|
-
readonly limit: number;
|
|
9
|
-
}): Promise<number[]>;
|
|
@@ -1,168 +0,0 @@
|
|
|
1
|
-
import { randomUUID } from 'node:crypto';
|
|
2
|
-
import { formatActivityId, parseActivityId } from './square-core.js';
|
|
3
|
-
import { pendingHead, pendingHeads, pendingRecipients, presentationBlocksWake } from './delivery.js';
|
|
4
|
-
import { asSeatRef } from './seats.js';
|
|
5
|
-
import { freshWatchLease } from './runtime.js';
|
|
6
|
-
import { deliveryDeferralExpiry } from './delivery-deferral.js';
|
|
7
|
-
import { leaseOwnsNotification } from './delivery.js';
|
|
8
|
-
import { dispatchEffect } from './delivery-effects.js';
|
|
9
|
-
function routeFor(location, seat, now) {
|
|
10
|
-
if (seat.attachment !== 'attached' || seat.wakeAddress === undefined)
|
|
11
|
-
return undefined;
|
|
12
|
-
return {
|
|
13
|
-
location, participant: seat.participant,
|
|
14
|
-
kind: seat.wakeAddress.kind, address: { ...seat.wakeAddress.address }, updatedAt: now,
|
|
15
|
-
};
|
|
16
|
-
}
|
|
17
|
-
async function currentness(artifact, request, now) {
|
|
18
|
-
const index = parseActivityId(request.activity);
|
|
19
|
-
const { value } = await artifact.read((facts) => {
|
|
20
|
-
const currentSeat = facts.seat(request.participant);
|
|
21
|
-
const seatCurrent = currentSeat !== undefined && currentSeat.attachment === 'attached' && currentSeat.generation === request.seat.generation
|
|
22
|
-
&& currentSeat.owner === request.seat.owner
|
|
23
|
-
&& currentSeat.wakeAddress?.kind === request.route.kind
|
|
24
|
-
&& Object.keys(currentSeat.wakeAddress.address).length === Object.keys(request.route.address).length
|
|
25
|
-
&& Object.entries(currentSeat.wakeAddress.address).every(([key, val]) => request.route.address[key] === val);
|
|
26
|
-
const head = pendingHead(facts, request.participant, index);
|
|
27
|
-
const activityPending = seatCurrent && head !== undefined;
|
|
28
|
-
const cancelledThrough = facts.cancelledThrough(request.participant, request.seat.generation);
|
|
29
|
-
const cancelled = cancelledThrough !== undefined && index <= cancelledThrough;
|
|
30
|
-
const evidence = facts.deliveryEvidence(request.participant, request.seat.generation, formatActivityId(index));
|
|
31
|
-
const presented = presentationBlocksWake(evidence, now);
|
|
32
|
-
const lease = freshWatchLease(facts, request.participant, now);
|
|
33
|
-
const caught = head !== undefined && lease !== undefined && leaseOwnsNotification(lease, {
|
|
34
|
-
actor: request.actor, route: head.route, recipient: request.participant,
|
|
35
|
-
});
|
|
36
|
-
const deferred = deliveryDeferralExpiry(facts, request.seat, index, now) !== undefined;
|
|
37
|
-
return { current: activityPending && !cancelled && !presented && !caught && !deferred, activityPending, seatCurrent, cancelled, presented };
|
|
38
|
-
});
|
|
39
|
-
return value;
|
|
40
|
-
}
|
|
41
|
-
async function candidates(artifact, requested, now = Date.now()) {
|
|
42
|
-
const { value } = await artifact.read((facts) => {
|
|
43
|
-
const heads = requested === undefined
|
|
44
|
-
? facts.roster().flatMap((participant) => participant.joined ? pendingHeads(facts, participant.name) : [])
|
|
45
|
-
: pendingRecipients(facts, requested);
|
|
46
|
-
return heads.flatMap((head) => {
|
|
47
|
-
const seat = facts.seat(head.recipient);
|
|
48
|
-
return seat === undefined || seat.attachment !== 'attached' || deliveryDeferralExpiry(facts, seat, head.index, now) !== undefined ? [] : [{ seat, head }];
|
|
49
|
-
});
|
|
50
|
-
});
|
|
51
|
-
return value;
|
|
52
|
-
}
|
|
53
|
-
function safeJson(value) {
|
|
54
|
-
if (value === null || typeof value === 'string' || typeof value === 'boolean' || typeof value === 'number')
|
|
55
|
-
return value;
|
|
56
|
-
if (Array.isArray(value))
|
|
57
|
-
return value.map(safeJson);
|
|
58
|
-
if (typeof value === 'object')
|
|
59
|
-
return Object.fromEntries(Object.entries(value)
|
|
60
|
-
.filter(([, item]) => item !== undefined).map(([key, item]) => [key, safeJson(item)]));
|
|
61
|
-
return String(value);
|
|
62
|
-
}
|
|
63
|
-
export async function deliverPending(input) {
|
|
64
|
-
// The resource owner supplies its identity; delivery does not interpret it as a file.
|
|
65
|
-
const location = input.location;
|
|
66
|
-
const requested = input.activity === undefined ? undefined
|
|
67
|
-
: typeof input.activity === 'number' ? input.activity : parseActivityId(input.activity);
|
|
68
|
-
if (input.activity !== undefined && requested === undefined)
|
|
69
|
-
return;
|
|
70
|
-
const pending = await candidates(input.artifact, requested, input.now ?? Date.now());
|
|
71
|
-
// Preserve order within a receiving owner; unrelated receivers need not wait for each other.
|
|
72
|
-
const receivers = new Map();
|
|
73
|
-
for (const candidate of pending) {
|
|
74
|
-
const key = candidate.seat.owner;
|
|
75
|
-
const group = receivers.get(key) ?? [];
|
|
76
|
-
group.push(candidate);
|
|
77
|
-
receivers.set(key, group);
|
|
78
|
-
}
|
|
79
|
-
const dispatch = async ({ seat, head }) => {
|
|
80
|
-
const route = routeFor(location, seat, input.now ?? Date.now());
|
|
81
|
-
if (route === undefined)
|
|
82
|
-
return;
|
|
83
|
-
const request = {
|
|
84
|
-
location, participant: seat.participant, activity: formatActivityId(head.index), actor: head.actor,
|
|
85
|
-
seat: asSeatRef(seat), route,
|
|
86
|
-
artifact: input.artifact,
|
|
87
|
-
};
|
|
88
|
-
if (input.transport.probe !== undefined) {
|
|
89
|
-
try {
|
|
90
|
-
const probe = await input.transport.probe(route);
|
|
91
|
-
if (probe === false || typeof probe === 'object' && probe.outcome === 'not-capable')
|
|
92
|
-
return;
|
|
93
|
-
}
|
|
94
|
-
catch {
|
|
95
|
-
return;
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
const claimToken = randomUUID();
|
|
99
|
-
const leaseMs = input.timeoutMs ?? 5000;
|
|
100
|
-
let snapshot;
|
|
101
|
-
await dispatchEffect({
|
|
102
|
-
async claim() {
|
|
103
|
-
const claim = await input.artifact.claimDelivery({ seat: request.seat, activity: request.activity, kind: 'wake',
|
|
104
|
-
route: seat.wakeAddress, at: input.now ?? Date.now(), leaseMs, claimToken }).catch(() => ({ status: 'stale' }));
|
|
105
|
-
return claim.status === 'acquired' ? { token: claimToken, ordinal: claim.attemptN } : undefined;
|
|
106
|
-
},
|
|
107
|
-
async current() {
|
|
108
|
-
snapshot = undefined;
|
|
109
|
-
snapshot = await currentness(input.artifact, request, input.now ?? Date.now());
|
|
110
|
-
return snapshot.current;
|
|
111
|
-
},
|
|
112
|
-
async settle(claim, completion) {
|
|
113
|
-
let fields = {};
|
|
114
|
-
if (completion.reason === 'not-current')
|
|
115
|
-
fields = {
|
|
116
|
-
signature: 'pre_send_revalidation_failed',
|
|
117
|
-
message: completion.phase === 'final' ? 'The notification changed before the final send check.'
|
|
118
|
-
: snapshot === undefined ? 'Square delivery state could not be verified.' : 'The notification is no longer current.',
|
|
119
|
-
diagnostic: snapshot ?? (completion.phase === 'final' ? { observationAvailable: false } : undefined),
|
|
120
|
-
};
|
|
121
|
-
else if (completion.reason === 'timeout')
|
|
122
|
-
fields = { diagnostic: 'transport timeout' };
|
|
123
|
-
else if (completion.reason === 'threw')
|
|
124
|
-
fields = { diagnostic: completion.error instanceof Error ? completion.error.message : String(completion.error) };
|
|
125
|
-
else if (completion.reason === 'not-capable')
|
|
126
|
-
fields = {
|
|
127
|
-
signature: 'transport_not_capable', diagnostic: completion.data?.diagnostic,
|
|
128
|
-
};
|
|
129
|
-
else if (completion.reason === 'returned')
|
|
130
|
-
fields = completion.data;
|
|
131
|
-
return input.artifact.completeDelivery({ seat: request.seat, activity: request.activity, claimToken: claim.token,
|
|
132
|
-
outcome: completion.outcome, at: Date.now(),
|
|
133
|
-
...(fields.signature === undefined ? {} : { signature: fields.signature }),
|
|
134
|
-
...(fields.message === undefined ? {} : { message: fields.message }),
|
|
135
|
-
...(fields.diagnostic === undefined ? {} : { diagnostic: safeJson(fields.diagnostic) }),
|
|
136
|
-
}).catch(() => false);
|
|
137
|
-
},
|
|
138
|
-
}, async ({ claim, timeoutMs, beforeSend }) => {
|
|
139
|
-
const outcome = await input.transport.attempt({ ...request, claimToken: claim.token, attemptN: claim.ordinal }, timeoutMs, beforeSend);
|
|
140
|
-
return { outcome: outcome.outcome, data: outcome };
|
|
141
|
-
}, { timeoutMs: leaseMs });
|
|
142
|
-
};
|
|
143
|
-
const groups = receivers.values();
|
|
144
|
-
const settled = await Promise.allSettled(Array.from({ length: Math.min(4, receivers.size) }, async () => {
|
|
145
|
-
for (const group of groups)
|
|
146
|
-
for (const candidate of group)
|
|
147
|
-
await dispatch(candidate);
|
|
148
|
-
}));
|
|
149
|
-
// Even an unexpected failure must drain siblings before the caller closes its artifact.
|
|
150
|
-
for (const result of settled)
|
|
151
|
-
if (result.status === 'rejected')
|
|
152
|
-
throw result.reason;
|
|
153
|
-
}
|
|
154
|
-
export async function sweepPending(input) {
|
|
155
|
-
if (input.limit <= 0)
|
|
156
|
-
return [];
|
|
157
|
-
const pending = await candidates(input.artifact, undefined, input.now);
|
|
158
|
-
const selected = [];
|
|
159
|
-
for (const { head } of pending) {
|
|
160
|
-
if (input.now - head.at <= input.graceMs)
|
|
161
|
-
continue;
|
|
162
|
-
if (!selected.includes(head.index))
|
|
163
|
-
selected.push(head.index);
|
|
164
|
-
if (selected.length >= input.limit)
|
|
165
|
-
break;
|
|
166
|
-
}
|
|
167
|
-
return selected;
|
|
168
|
-
}
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
/** Storage-independent attempt transitions and bound effect lifecycles. */
|
|
2
|
-
export { claimAttempt, prepareAttempt, settleAttempt, presentationBlocksDispatch, automaticDispatchEligible } from './delivery-attempts.js';
|
|
3
|
-
export type { DeliveryPurpose, AttemptOutcome, Attempt, AttemptRows, AttemptClaim } from './delivery-attempts.js';
|
|
4
|
-
export { dispatchEffect, preparePresentation, presentPrepared, presentPreparedBatch } from './delivery-effects.js';
|
|
5
|
-
export type { EffectClaim, EffectPort, Persistence, Settlement, DispatchOutcome, DispatchCompletion, DispatchContext, DispatchReport, PresentationCompletion, PresentationWork, PreparedPresentation, PresentationControl, PresentationReport } from './delivery-effects.js';
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
/** Storage-independent attempt transitions and bound effect lifecycles. */
|
|
2
|
-
export { claimAttempt, prepareAttempt, settleAttempt, presentationBlocksDispatch, automaticDispatchEligible } from './delivery-attempts.js';
|
|
3
|
-
export { dispatchEffect, preparePresentation, presentPrepared, presentPreparedBatch } from './delivery-effects.js';
|
package/dist/delivery.d.ts
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import type { DirectedNotificationRoute, WatchLease } from './model.js';
|
|
2
|
-
import type { DeliveryEvidence, DirectedHead, ParticipantFact, SquareArtifactPort, SquareRead, WakeRequest } from './ports.js';
|
|
3
|
-
export type { DirectedNotificationRoute } from './model.js';
|
|
4
|
-
/** Exact stored activity projection for transports that send an awareness reminder. */
|
|
5
|
-
export declare function wakePreview(facts: SquareRead, request: WakeRequest): string | undefined;
|
|
6
|
-
export interface RoutedNotification {
|
|
7
|
-
actor: string;
|
|
8
|
-
route: DirectedNotificationRoute;
|
|
9
|
-
recipient: string;
|
|
10
|
-
}
|
|
11
|
-
/** Presentation custody blocks a wake, independently of native wake acceptance. */
|
|
12
|
-
export declare function presentationBlocksWake(evidence: readonly DeliveryEvidence[], now: number): boolean;
|
|
13
|
-
/** Preselection only: an expired wake dispatch is uncertain, never safe automatic replay. */
|
|
14
|
-
export declare function automaticWakeEligible(evidence: readonly DeliveryEvidence[], now: number): boolean;
|
|
15
|
-
/** Notification pending is not cursor suffix or historical catch membership. */
|
|
16
|
-
export declare function pendingHead(facts: SquareRead, name: string, index: number): DirectedHead | undefined;
|
|
17
|
-
/** One activity's landed recipients that still owe a wake; the rest of the roster is untouched. */
|
|
18
|
-
export declare function pendingRecipients(facts: SquareRead, index: number): DirectedHead[];
|
|
19
|
-
/** Still-pending directed heads for one recipient, oldest first. Bodies belong to presentation. */
|
|
20
|
-
export declare function pendingHeads(facts: SquareRead, name: string): DirectedHead[];
|
|
21
|
-
export interface PendingScan {
|
|
22
|
-
readonly roster: readonly ParticipantFact[];
|
|
23
|
-
readonly throughIndex: number;
|
|
24
|
-
}
|
|
25
|
-
export declare function capturePendingScan(facts: SquareRead): PendingScan;
|
|
26
|
-
export declare function sameJoin(facts: SquareRead, captured: ParticipantFact): boolean;
|
|
27
|
-
/** Finite bodyless pass: unrelated revisions never rewind the last examined group. */
|
|
28
|
-
export declare function pendingPages(artifact: SquareArtifactPort, scan: PendingScan, afterIndex?: number): AsyncGenerator<{
|
|
29
|
-
index: number;
|
|
30
|
-
at: number;
|
|
31
|
-
actor: string;
|
|
32
|
-
recipient: string;
|
|
33
|
-
route: import("./attention.js").AudienceRoute;
|
|
34
|
-
}[], void, unknown>;
|
|
35
|
-
/** A pass retains only its captured joins; routes and individual receipts are fresh. */
|
|
36
|
-
export declare function pendingFacts(facts: SquareRead, scan: PendingScan, heads: readonly DirectedHead[]): {
|
|
37
|
-
pending: DirectedHead[];
|
|
38
|
-
};
|
|
39
|
-
/** Global discovery alone sweeps pendingAudience; exact dispatch uses pendingRecipients. */
|
|
40
|
-
export declare function collectPending(artifact: SquareArtifactPort): Promise<{
|
|
41
|
-
pending: DirectedHead[];
|
|
42
|
-
scan: PendingScan;
|
|
43
|
-
}>;
|
|
44
|
-
/** A live catch owns every matching notification, independent of its page size. */
|
|
45
|
-
export declare function leaseOwnsNotification(lease: WatchLease, notification: RoutedNotification): boolean;
|