@astrosheep/square 0.3.106 → 0.4.0
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 +8 -12
- package/dist/artifact.js +66 -343
- package/dist/attention-presentation.d.ts +33 -7
- package/dist/attention-presentation.js +33 -69
- package/dist/boundary-presentation.d.ts +0 -2
- package/dist/boundary-presentation.js +17 -22
- package/dist/catch-decisions.d.ts +2 -2
- package/dist/catch-decisions.js +14 -4
- package/dist/catch-selection.d.ts +8 -0
- package/dist/catch-selection.js +5 -0
- package/dist/channel-artifact.d.ts +10 -0
- package/dist/channel-artifact.js +55 -0
- package/dist/channel-delivery.d.ts +11 -0
- package/dist/channel-delivery.js +51 -0
- package/dist/channel-domain.d.ts +3 -0
- package/dist/channel-domain.js +83 -0
- package/dist/channel-facade.d.ts +76 -0
- package/dist/channel-facade.js +1 -0
- package/dist/channel-internal.d.ts +126 -0
- package/dist/channel-internal.js +440 -0
- package/dist/channel-metadata.d.ts +11 -0
- package/dist/channel-metadata.js +1 -0
- package/dist/channel-ports.d.ts +241 -0
- package/dist/channel-ports.js +1 -0
- package/dist/channel-presentation.d.ts +17 -0
- package/dist/channel-presentation.js +22 -0
- package/dist/channel-sqlite-schema.d.ts +13 -0
- package/dist/channel-sqlite-schema.js +81 -0
- package/dist/channel-transport.d.ts +62 -0
- package/dist/channel-transport.js +1 -0
- package/dist/channel-values.d.ts +27 -0
- package/dist/channel-values.js +90 -0
- package/dist/channel.d.ts +31 -21
- package/dist/channel.js +42 -74
- package/dist/claude-delivery-status.js +1 -1
- package/dist/claude-delivery.d.ts +2 -5
- package/dist/claude-delivery.js +56 -103
- package/dist/claude-mod.js +4 -4
- package/dist/claude-transport.d.ts +5 -0
- package/dist/claude-transport.js +58 -0
- package/dist/cli/context.d.ts +2 -2
- package/dist/cli/context.js +0 -1
- package/dist/cli/maintenance-commands.d.ts +0 -4
- package/dist/cli/maintenance-commands.js +2 -29
- package/dist/cli/program.js +1 -1
- package/dist/cli/registry.js +1 -2
- package/dist/codex-address.d.ts +1 -1
- package/dist/codex-queue.d.ts +2 -2
- package/dist/codex-queue.js +1 -3
- package/dist/decisions.js +3 -3
- package/dist/delivery-deferral.d.ts +9 -18
- package/dist/delivery-deferral.js +4 -4
- package/dist/delivery-health.d.ts +4 -4
- package/dist/delivery-health.js +11 -11
- package/dist/delivery-operations.d.ts +15 -2
- package/dist/delivery-operations.js +60 -30
- package/dist/delivery.d.ts +44 -33
- package/dist/delivery.js +49 -75
- package/dist/help.js +1 -6
- package/dist/http-delivery.d.ts +2 -2
- package/dist/http-delivery.js +2 -4
- package/dist/inbox.d.ts +10 -18
- package/dist/inbox.js +44 -53
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- 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 +41 -77
- package/dist/model.js +7 -139
- package/dist/neutral.d.ts +72 -0
- package/dist/neutral.js +27 -0
- package/dist/notifications.d.ts +2 -8
- package/dist/notifications.js +15 -50
- 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/paseo-delivery.d.ts +1 -1
- package/dist/paseo-delivery.js +2 -4
- package/dist/plugins/opencode/delivery.js +27 -42
- package/dist/ports.d.ts +46 -168
- package/dist/presentation-operations.d.ts +1 -14
- package/dist/presentation-operations.js +16 -16
- 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/sqlite-channel.d.ts +15 -0
- package/dist/sqlite-channel.js +600 -0
- package/dist/sqlite-framing.d.ts +8 -0
- package/dist/sqlite-framing.js +31 -0
- package/dist/sqlite-square.d.ts +12 -13
- package/dist/sqlite-square.js +192 -248
- 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 +1 -1
- package/dist/square-core.d.ts +1 -1
- package/dist/square-domain.d.ts +21 -7
- package/dist/square-domain.js +93 -94
- package/dist/square-facade.d.ts +12 -66
- package/dist/square-index.d.ts +1 -1
- package/dist/square-index.js +1 -1
- package/dist/square-location.d.ts +6 -1
- package/dist/square-location.js +1 -1
- package/dist/square-receive.d.ts +2 -3
- package/dist/square-sqlite.d.ts +45 -44
- package/dist/square-sqlite.js +308 -764
- package/dist/square-tools.d.ts +8 -0
- package/dist/square-tools.js +39 -0
- package/dist/views.d.ts +6 -6
- package/dist/views.js +15 -9
- package/dist/wake-preview.d.ts +7 -0
- package/dist/wake-preview.js +15 -0
- package/dist/wake-sink.d.ts +2 -2
- package/dist/wake-sink.js +1 -1
- package/dist/wake-transports.d.ts +7 -0
- package/dist/wake-transports.js +42 -0
- package/guides/claude-native.md +13 -10
- package/guides/codex-delivery.md +3 -1
- package/guides/participant-ownership.md +1 -1
- package/guides/row-runtime-delivery-evidence.md +2 -0
- package/guides/row-storage-design.md +19 -44
- package/guides/square-api.md +137 -60
- package/package.json +1 -1
- package/plugins/claude/.claude-plugin/plugin.json +1 -1
- package/plugins/claude/types.d.ts +1 -1
- package/plugins/codex/.codex-plugin/plugin.json +1 -1
- package/plugins/opencode/delivery.ts +28 -41
- package/plugins/pi/square-pi.js +28 -51
- 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
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { SquareError, nameKey } from './neutral.js';
|
|
2
|
+
export const encode = JSON.stringify;
|
|
3
|
+
export const key = (name) => encode(nameKey(name));
|
|
4
|
+
export function invalidArtifact(detail) {
|
|
5
|
+
return new SquareError('invalid_args', `Invalid square artifact: ${detail}`);
|
|
6
|
+
}
|
|
7
|
+
export function requireFact(ok, detail = 'row is malformed.') {
|
|
8
|
+
if (!ok)
|
|
9
|
+
throw invalidArtifact(detail);
|
|
10
|
+
}
|
|
11
|
+
export function integer(value, minimum = 0) {
|
|
12
|
+
requireFact(Number.isSafeInteger(value) && value >= minimum);
|
|
13
|
+
return value;
|
|
14
|
+
}
|
|
15
|
+
export function finite(value) {
|
|
16
|
+
requireFact(typeof value === 'number' && Number.isFinite(value));
|
|
17
|
+
return value;
|
|
18
|
+
}
|
|
19
|
+
export function string(value, nonempty = false) {
|
|
20
|
+
requireFact(typeof value === 'string' && (!nonempty || value.length > 0));
|
|
21
|
+
return value;
|
|
22
|
+
}
|
|
23
|
+
export function json(value) {
|
|
24
|
+
try {
|
|
25
|
+
return JSON.parse(string(value));
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
throw invalidArtifact('row contains invalid JSON.');
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
export function object(value) {
|
|
32
|
+
requireFact(typeof value === 'object' && value !== null && !Array.isArray(value));
|
|
33
|
+
return value;
|
|
34
|
+
}
|
|
35
|
+
export function shape(value, required, optional = []) {
|
|
36
|
+
const result = object(value);
|
|
37
|
+
requireFact(required.every(k => Object.hasOwn(result, k)) && Object.keys(result).every(k => required.includes(k) || optional.includes(k)));
|
|
38
|
+
return result;
|
|
39
|
+
}
|
|
40
|
+
export function strings(value) {
|
|
41
|
+
requireFact(Array.isArray(value) && value.every(v => typeof v === 'string'));
|
|
42
|
+
return value;
|
|
43
|
+
}
|
|
44
|
+
export function decoded(value, nonempty = false) {
|
|
45
|
+
const result = string(json(value), nonempty);
|
|
46
|
+
requireFact(encode(result) === value, 'string encoding is malformed.');
|
|
47
|
+
return result;
|
|
48
|
+
}
|
|
49
|
+
export function immutable(value) {
|
|
50
|
+
if (value !== null && typeof value === 'object') {
|
|
51
|
+
for (const item of Object.values(value))
|
|
52
|
+
immutable(item);
|
|
53
|
+
Object.freeze(value);
|
|
54
|
+
}
|
|
55
|
+
return value;
|
|
56
|
+
}
|
|
57
|
+
// Sorted object keys express small-value structural equality, never whole-state comparison.
|
|
58
|
+
export function stableJson(value) {
|
|
59
|
+
if (value === null || typeof value !== 'object') {
|
|
60
|
+
requireFact(value === null || typeof value === 'string' || typeof value === 'boolean' || typeof value === 'number' && Number.isFinite(value), 'value contains a non-finite or unsupported JSON value.');
|
|
61
|
+
return encode(value);
|
|
62
|
+
}
|
|
63
|
+
if (Array.isArray(value))
|
|
64
|
+
return '[' + value.map(stableJson).join(',') + ']';
|
|
65
|
+
return '{' + Object.keys(value).sort().map(k => encode(k) + ':' + stableJson(value[k])).join(',') + '}';
|
|
66
|
+
}
|
|
67
|
+
export function pageRows(rows, page, decode) {
|
|
68
|
+
const hasMore = rows.length > page.limit;
|
|
69
|
+
if (hasMore)
|
|
70
|
+
rows.pop();
|
|
71
|
+
if (page.edge === 'newest')
|
|
72
|
+
rows.reverse();
|
|
73
|
+
return immutable({ items: rows.map(decode), hasMore });
|
|
74
|
+
}
|
|
75
|
+
export function pageLimit(page) {
|
|
76
|
+
requireFact(page.edge === 'oldest' || page.edge === 'newest');
|
|
77
|
+
return Math.min(integer(page.limit, 1) + 1, Number.MAX_SAFE_INTEGER);
|
|
78
|
+
}
|
package/dist/square-api.d.ts
CHANGED
|
@@ -16,4 +16,4 @@ export declare function selectOwnSeat(square: Pick<SqliteSquare, 'participant' |
|
|
|
16
16
|
}): Promise<Participant | undefined>;
|
|
17
17
|
export { ACTIVITY_METADATA_MAX_BYTES } from './model.js';
|
|
18
18
|
export { localUserOwner, harnessOwner, decodeHarnessOwner } from './owner.js';
|
|
19
|
-
export { squareClock, createSquareResourceOwner, formatActivityId, parseActivityId, MAX_IDENTITY_SET_SIZE, CATCH_DEFAULT_LIMIT, CATCH_MAX_LIMIT, HISTORY_DEFAULT_LIMIT, HISTORY_MAX_LIMIT, DEFAULT_LIST_DEPTH, MAX_LIST_DEPTH, DEFAULT_LIST_LIMIT, MAX_LIST_LIMIT, diagnoseSquare,
|
|
19
|
+
export { squareClock, createSquareResourceOwner, formatActivityId, parseActivityId, MAX_IDENTITY_SET_SIZE, CATCH_DEFAULT_LIMIT, CATCH_MAX_LIMIT, HISTORY_DEFAULT_LIMIT, HISTORY_MAX_LIMIT, DEFAULT_LIST_DEPTH, MAX_LIST_DEPTH, DEFAULT_LIST_LIMIT, MAX_LIST_LIMIT, diagnoseSquare, discover, inbox } from './sqlite-square.js';
|
package/dist/square-api.js
CHANGED
|
@@ -27,4 +27,4 @@ export async function selectOwnSeat(square, owner, name, options) {
|
|
|
27
27
|
}
|
|
28
28
|
export { ACTIVITY_METADATA_MAX_BYTES } from './model.js';
|
|
29
29
|
export { localUserOwner, harnessOwner, decodeHarnessOwner } from './owner.js';
|
|
30
|
-
export { squareClock, createSquareResourceOwner, formatActivityId, parseActivityId, MAX_IDENTITY_SET_SIZE, CATCH_DEFAULT_LIMIT, CATCH_MAX_LIMIT, HISTORY_DEFAULT_LIMIT, HISTORY_MAX_LIMIT, DEFAULT_LIST_DEPTH, MAX_LIST_DEPTH, DEFAULT_LIST_LIMIT, MAX_LIST_LIMIT, diagnoseSquare,
|
|
30
|
+
export { squareClock, createSquareResourceOwner, formatActivityId, parseActivityId, MAX_IDENTITY_SET_SIZE, CATCH_DEFAULT_LIMIT, CATCH_MAX_LIMIT, HISTORY_DEFAULT_LIMIT, HISTORY_MAX_LIMIT, DEFAULT_LIST_DEPTH, MAX_LIST_DEPTH, DEFAULT_LIST_LIMIT, MAX_LIST_LIMIT, diagnoseSquare, discover, inbox } from './sqlite-square.js';
|
package/dist/square-core.d.ts
CHANGED
|
@@ -26,10 +26,10 @@ export type Act = {
|
|
|
26
26
|
at?: number;
|
|
27
27
|
body?: string;
|
|
28
28
|
metadata?: import('./model.js').ActivityMetadata;
|
|
29
|
-
delivery?: import('./model.js').ActivityDelivery;
|
|
30
29
|
mentions?: readonly Participant[];
|
|
31
30
|
reach?: Reach;
|
|
32
31
|
reply?: number;
|
|
32
|
+
messageIndex?: number;
|
|
33
33
|
} | {
|
|
34
34
|
kind: 'read';
|
|
35
35
|
actor: Participant;
|
package/dist/square-domain.d.ts
CHANGED
|
@@ -1,7 +1,16 @@
|
|
|
1
|
-
import { type Seat, type StoredAct } from './model.js';
|
|
1
|
+
import { type ActDraft, type Seat, type StoredAct } from './model.js';
|
|
2
|
+
import { type EndpointGeneration } from './message.js';
|
|
2
3
|
import type { ArtifactWriteAuthority, AttentionFact, LandedRecipient, ParticipantFact, SeatRef, SquareRead, SquareWrite } from './ports.js';
|
|
4
|
+
import type { ChannelWrite, EndpointRef } from './channel-ports.js';
|
|
5
|
+
import type { WatchLease } from './model.js';
|
|
6
|
+
/** Pending messages the live catch currently owns; the lower pipeline only needs this coverage. */
|
|
7
|
+
export declare function catchCoverage(read: SquareRead, name: string, lease: WatchLease): number[];
|
|
8
|
+
/** Artifact-private landing effect; sender capabilities never expose another recipient's claim. */
|
|
9
|
+
export declare function extendLandingCatchCoverage(read: SquareRead, putClaim: ChannelWrite['putReceiveClaim'], activity: StoredAct, audience: readonly LandedRecipient[]): void;
|
|
3
10
|
export interface LandingEffect {
|
|
4
|
-
readonly activity:
|
|
11
|
+
readonly activity: ActDraft & {
|
|
12
|
+
readonly index: number;
|
|
13
|
+
};
|
|
5
14
|
readonly participant?: ParticipantFact;
|
|
6
15
|
readonly removeListeningOf?: string;
|
|
7
16
|
readonly removeListening?: {
|
|
@@ -14,18 +23,23 @@ export interface LandingEffect {
|
|
|
14
23
|
export interface LandingFacts {
|
|
15
24
|
readonly actor?: ParticipantFact;
|
|
16
25
|
readonly standing: readonly ParticipantFact[];
|
|
26
|
+
/** Endpoint custody at landing time, so an address fences the generation it was written for. */
|
|
27
|
+
readonly generations: ReadonlyMap<string, EndpointGeneration>;
|
|
17
28
|
readonly incoming: readonly AttentionFact[];
|
|
18
29
|
readonly outgoing: readonly AttentionFact[];
|
|
19
30
|
readonly replyAuthor?: string;
|
|
20
31
|
}
|
|
21
32
|
/** The single landing transition, shared by both adapters and explicit rebuild. */
|
|
22
|
-
export declare function deriveLanding(activity:
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
33
|
+
export declare function deriveLanding(activity: ActDraft & {
|
|
34
|
+
readonly index: number;
|
|
35
|
+
}, facts: LandingFacts): LandingEffect;
|
|
36
|
+
export declare function landingFacts(read: SquareRead, activity: ActDraft): LandingFacts;
|
|
37
|
+
export interface LandingWriter extends Pick<SquareWrite, 'putLease' | 'removeLease' | 'updateWakeAddress' | 'reattachSeat' | 'detachSeat'> {
|
|
38
|
+
/** Artifact-private endpoint persistence used only by this gate's lifecycle transition. */
|
|
26
39
|
storeSeat(seat: Seat): boolean;
|
|
27
|
-
removeSeat(seat:
|
|
40
|
+
removeSeat(seat: EndpointRef): boolean;
|
|
28
41
|
applyLanding(effect: LandingEffect): void;
|
|
42
|
+
readonly channel: ChannelWrite;
|
|
29
43
|
}
|
|
30
44
|
export interface SquareWriteGate {
|
|
31
45
|
readonly facts: SquareWrite;
|
package/dist/square-domain.js
CHANGED
|
@@ -1,21 +1,51 @@
|
|
|
1
|
-
import { SquareError,
|
|
1
|
+
import { SquareError, nameKey, sameName, validateOwner, validateName } from './model.js';
|
|
2
|
+
import { wrapChannelWrite } from './channel-domain.js';
|
|
3
|
+
import { newEndpointGeneration } from './message.js';
|
|
2
4
|
import { resolveAudience } from './attention.js';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
5
|
+
import { validateEndpointGeneration as endpointGeneration } from './message.js';
|
|
6
|
+
import { leaseOwnsNotification } from './catch-selection.js';
|
|
7
|
+
/** Pending messages the live catch currently owns; the lower pipeline only needs this coverage. */
|
|
8
|
+
export function catchCoverage(read, name, lease) {
|
|
9
|
+
const covered = [];
|
|
10
|
+
let cursor = -1;
|
|
11
|
+
for (;;) {
|
|
12
|
+
const page = read.channel.directed(name, { afterIndex: cursor, unseenOnly: true, currentGeneration: true }, { edge: 'oldest', limit: 100 });
|
|
13
|
+
for (const head of page.items) {
|
|
14
|
+
const relation = read.activityByMessage(head.index);
|
|
15
|
+
const route = relation === undefined ? undefined : read.directedAt(name, relation.index)?.route;
|
|
16
|
+
if (route !== undefined && leaseOwnsNotification(lease, { actor: head.from, route, recipient: name }))
|
|
17
|
+
covered.push(head.index);
|
|
11
18
|
}
|
|
12
|
-
|
|
19
|
+
if (!page.hasMore || page.items.length === 0)
|
|
20
|
+
break;
|
|
21
|
+
cursor = page.items[page.items.length - 1].index;
|
|
22
|
+
}
|
|
23
|
+
return covered;
|
|
24
|
+
}
|
|
25
|
+
/** Artifact-private landing effect; sender capabilities never expose another recipient's claim. */
|
|
26
|
+
export function extendLandingCatchCoverage(read, putClaim, activity, audience) {
|
|
27
|
+
if (activity.kind !== 'say')
|
|
28
|
+
return;
|
|
29
|
+
const index = activity.messageIndex;
|
|
30
|
+
for (const recipient of audience) {
|
|
31
|
+
const claim = read.channel.claimLease(recipient.recipient, 'agora');
|
|
32
|
+
if (claim === undefined || claim.expiresAt <= activity.at || recipient.generation !== undefined && claim.generation !== recipient.generation)
|
|
33
|
+
continue;
|
|
34
|
+
const lease = read.lease(recipient.recipient);
|
|
35
|
+
if (lease === undefined || lease.leaseId !== claim.id
|
|
36
|
+
|| !leaseOwnsNotification(lease, { actor: activity.actor, route: recipient.route, recipient: recipient.recipient }))
|
|
37
|
+
continue;
|
|
38
|
+
if (!claim.suppressed.includes(index))
|
|
39
|
+
putClaim({ ...claim, suppressed: [...claim.suppressed, index] });
|
|
13
40
|
}
|
|
41
|
+
}
|
|
42
|
+
/** The single landing transition, shared by both adapters and explicit rebuild. */
|
|
43
|
+
export function deriveLanding(activity, facts) {
|
|
14
44
|
const audience = activity.kind === 'say' ? resolveAudience({
|
|
15
45
|
actor: activity.actor, recipients: facts.standing.map((item) => item.name),
|
|
16
46
|
mentions: activity.mentions, replyAuthor: facts.replyAuthor, reach: activity.reach,
|
|
17
47
|
incoming: facts.incoming, sameIdentity: sameName,
|
|
18
|
-
}) : [];
|
|
48
|
+
}).map(recipient => ({ ...recipient, generation: facts.generations.get(nameKey(recipient.recipient)) })) : [];
|
|
19
49
|
const actor = activity.actor;
|
|
20
50
|
const previous = facts.actor ?? { name: actor, firstIndex: activity.index, joined: false, done: false, sayCount: 0 };
|
|
21
51
|
const participant = {
|
|
@@ -45,6 +75,7 @@ export function deriveLanding(activity, facts) {
|
|
|
45
75
|
export function landingFacts(read, activity) {
|
|
46
76
|
return {
|
|
47
77
|
actor: read.participant(activity.actor),
|
|
78
|
+
generations: new Map(read.channel.endpoints().map(endpoint => [nameKey(endpoint.participant), endpoint.generation])),
|
|
48
79
|
standing: activity.kind === 'say' ? read.roster().filter((item) => item.joined) : [],
|
|
49
80
|
incoming: activity.kind === 'say' ? read.incomingAttention(activity.actor) : [],
|
|
50
81
|
outgoing: activity.kind === 'listen' || activity.kind === 'ignore' || activity.kind === 'unlisten' ? read.attention(activity.actor) : [],
|
|
@@ -52,8 +83,7 @@ export function landingFacts(read, activity) {
|
|
|
52
83
|
};
|
|
53
84
|
}
|
|
54
85
|
function validateGeneration(value) {
|
|
55
|
-
|
|
56
|
-
throw new SquareError('invalid_args', 'Artifact authority requires a valid join generation.');
|
|
86
|
+
endpointGeneration(value);
|
|
57
87
|
}
|
|
58
88
|
/** Read probes and writes share the same captured-coordinate and attachment fence. */
|
|
59
89
|
export function assertCurrentSeat(read, expected, allowDetached = false) {
|
|
@@ -63,14 +93,21 @@ export function assertCurrentSeat(read, expected, allowDetached = false) {
|
|
|
63
93
|
if (!allowDetached && current.attachment !== 'attached')
|
|
64
94
|
throw new SquareError('already_joined', 'This participant is away; join again before writing.', { reason: 'needs_seat', activityUnsent: true });
|
|
65
95
|
}
|
|
96
|
+
function immutableAct(activity) {
|
|
97
|
+
const copy = { ...activity, ...(activity.kind === 'say' && activity.mentions !== undefined ? { mentions: [...activity.mentions] } : {}) };
|
|
98
|
+
if (copy.kind === 'say' && copy.mentions !== undefined)
|
|
99
|
+
Object.freeze(copy.mentions);
|
|
100
|
+
return Object.freeze(copy);
|
|
101
|
+
}
|
|
66
102
|
/** The artifact transaction supplies one captured authority; every mutation checks it here. */
|
|
67
103
|
export function wrapSquareWrite(read, writes, authority) {
|
|
68
104
|
if (authority === undefined || typeof authority !== 'object' || authority === null)
|
|
69
105
|
throw new SquareError('invalid_args', 'Artifact writes require an explicit authority.');
|
|
70
|
-
const { applyLanding, ...mutations } = writes;
|
|
71
|
-
const seated = authority.kind === 'participant' || authority.kind === 'host-cleanup';
|
|
72
|
-
const expectedName = seated ? authority.seat?.participant : authority.kind === 'send' ? authority.actor
|
|
73
|
-
|
|
106
|
+
const { applyLanding, channel, ...mutations } = writes;
|
|
107
|
+
const seated = authority.kind === 'participant' || authority.kind === 'host-cleanup' || authority.kind === 'endpoint-cleanup';
|
|
108
|
+
const expectedName = seated ? authority.seat?.participant : authority.kind === 'send' ? authority.actor
|
|
109
|
+
: authority.kind === 'endpoint' ? authority.participant : authority.participant;
|
|
110
|
+
if (!['participant', 'host-cleanup', 'endpoint-cleanup', 'endpoint', 'join', 'takeover', 'send'].includes(authority.kind) || typeof expectedName !== 'string')
|
|
74
111
|
throw new SquareError('invalid_args', 'Artifact write authority is malformed.');
|
|
75
112
|
validateName(expectedName);
|
|
76
113
|
if (seated) {
|
|
@@ -82,7 +119,7 @@ export function wrapSquareWrite(read, writes, authority) {
|
|
|
82
119
|
if (authority.kind === 'takeover')
|
|
83
120
|
validateGeneration(authority.expectedGeneration);
|
|
84
121
|
}
|
|
85
|
-
const assertSeat = (seat, expected = authority.kind === 'participant' ? authority.seat : undefined, allowDetached = false) => {
|
|
122
|
+
const assertSeat = (seat, expected = authority.kind === 'participant' || authority.kind === 'host-cleanup' || authority.kind === 'endpoint-cleanup' ? authority.seat : undefined, allowDetached = false) => {
|
|
86
123
|
if (expected === undefined || !sameName(expected.participant, seat.participant)
|
|
87
124
|
|| seat.generation !== expected.generation || seat.owner !== expected.owner)
|
|
88
125
|
throw new SquareError('already_joined', 'This write needs the current participant seat.');
|
|
@@ -91,16 +128,20 @@ export function wrapSquareWrite(read, writes, authority) {
|
|
|
91
128
|
const assertParticipant = (name, generation) => {
|
|
92
129
|
if (authority.kind !== 'participant')
|
|
93
130
|
throw new SquareError('already_joined', 'This write needs the current participant seat.');
|
|
94
|
-
assertSeat({ ...authority.seat, participant: name, generation: generation
|
|
131
|
+
assertSeat({ ...authority.seat, participant: name, generation: generation ?? authority.seat.generation });
|
|
95
132
|
};
|
|
96
133
|
let reconnectSeat;
|
|
97
134
|
let takeoverPhase = authority.kind === 'takeover' ? 'ready' : undefined;
|
|
135
|
+
let establishedSeat;
|
|
98
136
|
if (authority.kind === 'participant') {
|
|
99
137
|
assertSeat(authority.seat);
|
|
100
138
|
}
|
|
101
|
-
else if (authority.kind === 'host-cleanup') {
|
|
139
|
+
else if (authority.kind === 'host-cleanup' || authority.kind === 'endpoint-cleanup') {
|
|
102
140
|
// A late host cleanup is allowed to inspect a stale coordinate and return a no-op.
|
|
103
141
|
}
|
|
142
|
+
else if (authority.kind === 'endpoint') {
|
|
143
|
+
// Endpoint attach/takeover owns no activity.
|
|
144
|
+
}
|
|
104
145
|
else if (authority.kind === 'join') {
|
|
105
146
|
const participant = read.participant(expectedName), seat = read.seat(expectedName);
|
|
106
147
|
if (participant?.joined) {
|
|
@@ -115,7 +156,12 @@ export function wrapSquareWrite(read, writes, authority) {
|
|
|
115
156
|
throw new SquareError('already_joined', 'The participant seat changed before takeover.');
|
|
116
157
|
}
|
|
117
158
|
let lastActivity;
|
|
159
|
+
const lowerAuthority = authority.kind === 'join' || authority.kind === 'takeover'
|
|
160
|
+
? { kind: 'endpoint', participant: authority.participant, owner: authority.owner }
|
|
161
|
+
: authority.kind === 'host-cleanup' ? { kind: 'endpoint-cleanup', seat: authority.seat } : authority;
|
|
162
|
+
const gatedChannel = wrapChannelWrite(read.channel, channel, lowerAuthority);
|
|
118
163
|
const facts = Object.assign({}, read, {
|
|
164
|
+
channel: gatedChannel,
|
|
119
165
|
land(activity) {
|
|
120
166
|
const actor = 'actor' in activity ? activity.actor : undefined;
|
|
121
167
|
if (actor === undefined)
|
|
@@ -123,11 +169,8 @@ export function wrapSquareWrite(read, writes, authority) {
|
|
|
123
169
|
validateName(actor);
|
|
124
170
|
if (!sameName(actor, expectedName))
|
|
125
171
|
throw new SquareError('already_joined', 'Activity actor does not match the artifact authority.');
|
|
126
|
-
if (
|
|
127
|
-
|
|
128
|
-
if (authority.kind === 'send') {
|
|
129
|
-
if (activity.kind !== 'say' || activity.delivery?.mode !== 'direct' || activity.reach !== undefined || activity.reply !== undefined)
|
|
130
|
-
throw new SquareError('invalid_args', 'Send authority may only land direct messages without bell or reply.');
|
|
172
|
+
if (authority.kind === 'send' || authority.kind === 'endpoint' || authority.kind === 'endpoint-cleanup') {
|
|
173
|
+
throw new SquareError('invalid_args', 'This authority may not publish Agora activities.');
|
|
131
174
|
}
|
|
132
175
|
else if (authority.kind === 'participant') {
|
|
133
176
|
assertSeat(authority.seat);
|
|
@@ -160,37 +203,50 @@ export function wrapSquareWrite(read, writes, authority) {
|
|
|
160
203
|
const index = read.header().nextActIndex;
|
|
161
204
|
if (!Number.isSafeInteger(index) || index < 0 || index >= Number.MAX_SAFE_INTEGER)
|
|
162
205
|
throw new SquareError('invalid_args', 'Square activity index is exhausted.');
|
|
163
|
-
const captured = authority.kind === 'takeover' && activity.kind === 'done'
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
206
|
+
const captured = authority.kind === 'takeover' && activity.kind === 'done' ? read.seat(expectedName) : undefined;
|
|
207
|
+
const effect = deriveLanding({ ...activity, index }, landingFacts(read, activity));
|
|
208
|
+
let stored;
|
|
209
|
+
if (activity.kind === 'say') {
|
|
210
|
+
const published = gatedChannel.publishMessage({ from: activity.actor, at: activity.at,
|
|
211
|
+
body: activity.body ?? '', ...(activity.metadata === undefined ? {} : { metadata: activity.metadata }),
|
|
212
|
+
to: effect.audience.map(({ recipient, generation }) => ({ recipient, ...(generation === undefined ? {} : { generation }) })) });
|
|
213
|
+
// The published content lives in the message; only the relation is stored above it.
|
|
214
|
+
const { body: _body, metadata: _metadata, ...relation } = activity;
|
|
215
|
+
stored = { ...relation, index, messageIndex: published.index };
|
|
216
|
+
}
|
|
217
|
+
else {
|
|
218
|
+
stored = { ...activity, index };
|
|
219
|
+
}
|
|
220
|
+
applyLanding({ ...effect, activity: stored });
|
|
167
221
|
if (stored.kind === 'join') {
|
|
168
222
|
if (authority.kind !== 'join' && authority.kind !== 'takeover')
|
|
169
223
|
throw new SquareError('invalid_args', 'Seat authority cannot establish another seat.');
|
|
170
224
|
const seat = {
|
|
171
225
|
participant: stored.actor,
|
|
172
226
|
owner: authority.owner,
|
|
173
|
-
generation:
|
|
227
|
+
generation: newEndpointGeneration(),
|
|
174
228
|
attachment: 'attached',
|
|
175
229
|
...(authority.wakeAddress === undefined ? {} : { wakeAddress: authority.wakeAddress }),
|
|
176
230
|
};
|
|
177
231
|
mutations.storeSeat(seat);
|
|
232
|
+
establishedSeat = seat;
|
|
178
233
|
const established = read.seat(seat.participant);
|
|
179
234
|
if (established === undefined || established.owner !== seat.owner || established.generation !== seat.generation)
|
|
180
|
-
throw new SquareError('invalid_args', 'The join activity did not establish its artifact
|
|
235
|
+
throw new SquareError('invalid_args', 'The join activity did not establish its artifact endpoint.');
|
|
181
236
|
if (authority.kind === 'takeover')
|
|
182
237
|
takeoverPhase = 'joined';
|
|
183
238
|
}
|
|
184
239
|
else if (stored.kind === 'done' && seated) {
|
|
185
240
|
if (!mutations.removeSeat(authority.seat))
|
|
186
|
-
throw new SquareError('already_joined', 'The participant
|
|
241
|
+
throw new SquareError('already_joined', 'The participant endpoint changed while it was being completed.');
|
|
187
242
|
}
|
|
188
243
|
else if (stored.kind === 'done' && authority.kind === 'takeover') {
|
|
189
244
|
if (captured === undefined || !mutations.removeSeat({ participant: expectedName, owner: captured.owner, generation: captured.generation }))
|
|
190
|
-
throw new SquareError('already_joined', 'The participant
|
|
245
|
+
throw new SquareError('already_joined', 'The participant endpoint changed while takeover was completing it.');
|
|
191
246
|
takeoverPhase = 'done';
|
|
192
247
|
}
|
|
193
|
-
|
|
248
|
+
// The persisted fact is the relation; callers that present a say resolve its message content.
|
|
249
|
+
lastActivity = immutableAct(stored);
|
|
194
250
|
return lastActivity;
|
|
195
251
|
},
|
|
196
252
|
updateWakeAddress(seat, wakeAddress) {
|
|
@@ -216,71 +272,14 @@ export function wrapSquareWrite(read, writes, authority) {
|
|
|
216
272
|
return false;
|
|
217
273
|
return mutations.detachSeat(seat);
|
|
218
274
|
},
|
|
219
|
-
cancelThrough(seat, through) {
|
|
220
|
-
assertSeat(seat);
|
|
221
|
-
if (!Number.isSafeInteger(through) || through < 0 || through >= read.header().nextActIndex)
|
|
222
|
-
throw new SquareError('invalid_args', 'Cancellation boundary must be an assigned activity index below the allocator.');
|
|
223
|
-
return mutations.cancelThrough(seat, through);
|
|
224
|
-
},
|
|
225
|
-
markSeen(name, indexes, at) {
|
|
226
|
-
assertParticipant(name);
|
|
227
|
-
return mutations.markSeen(name, indexes, at);
|
|
228
|
-
},
|
|
229
275
|
putLease(name, lease, generation) {
|
|
230
276
|
assertParticipant(name, generation);
|
|
231
|
-
return mutations.putLease(name, lease, generation);
|
|
277
|
+
return mutations.putLease(name, lease, generation, catchCoverage(read, name, lease));
|
|
232
278
|
},
|
|
233
279
|
removeLease(name, leaseId, generation) {
|
|
234
280
|
assertParticipant(name, generation);
|
|
235
281
|
return mutations.removeLease(name, leaseId, generation);
|
|
236
282
|
},
|
|
237
|
-
putDeliveryDeferral(...args) {
|
|
238
|
-
assertSeat(args[0]);
|
|
239
|
-
return mutations.putDeliveryDeferral(...args);
|
|
240
|
-
},
|
|
241
|
-
renewDeliveryDeferral(...args) {
|
|
242
|
-
assertSeat(args[0]);
|
|
243
|
-
return mutations.renewDeliveryDeferral(...args);
|
|
244
|
-
},
|
|
245
|
-
releaseDeliveryDeferral(...args) {
|
|
246
|
-
assertSeat(args[0]);
|
|
247
|
-
return mutations.releaseDeliveryDeferral(...args);
|
|
248
|
-
},
|
|
249
|
-
claimDelivery(input) {
|
|
250
|
-
assertSeat(input.seat);
|
|
251
|
-
const evidence = read.deliveryEvidence(input.seat.participant, input.seat.generation, input.activity);
|
|
252
|
-
if (input.observationOf !== undefined) {
|
|
253
|
-
// Receiver adapters validate native identity/content before entering this transaction.
|
|
254
|
-
// This path records that existing message, rather than acquiring a second send.
|
|
255
|
-
if (input.kind !== 'presentation' || !evidence.some(row => row.kind === 'wake'
|
|
256
|
-
&& row.claimToken === input.observationOf && ['dispatching', 'accepted', 'unknown'].includes(row.outcome)))
|
|
257
|
-
return { status: 'stale' };
|
|
258
|
-
}
|
|
259
|
-
else {
|
|
260
|
-
const blocker = evidence.find(row => row.kind !== input.kind
|
|
261
|
-
&& row.outcome !== 'failed' && row.outcome !== 'released');
|
|
262
|
-
if (blocker !== undefined) {
|
|
263
|
-
if (blocker.outcome === 'dispatching' && blocker.expiresAt !== undefined && blocker.expiresAt <= input.at) {
|
|
264
|
-
// Normalize abandoned custody to unknown in the same transaction, never steal it.
|
|
265
|
-
return mutations.claimDelivery({ ...input, kind: blocker.kind });
|
|
266
|
-
}
|
|
267
|
-
return { status: blocker.outcome === 'dispatching' ? 'busy' : 'terminal', evidence: blocker };
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
return mutations.claimDelivery(input);
|
|
271
|
-
},
|
|
272
|
-
prepareDelivery(input) {
|
|
273
|
-
assertSeat(input.seat);
|
|
274
|
-
return mutations.prepareDelivery(input);
|
|
275
|
-
},
|
|
276
|
-
completeDelivery(input) {
|
|
277
|
-
assertSeat(input.seat);
|
|
278
|
-
return mutations.completeDelivery(input);
|
|
279
|
-
},
|
|
280
|
-
observeNativeDelivery(input) {
|
|
281
|
-
assertSeat(input.seat);
|
|
282
|
-
return mutations.observeNativeDelivery(input);
|
|
283
|
-
},
|
|
284
283
|
});
|
|
285
284
|
return {
|
|
286
285
|
facts,
|
|
@@ -288,8 +287,8 @@ export function wrapSquareWrite(read, writes, authority) {
|
|
|
288
287
|
if (authority.kind !== 'takeover')
|
|
289
288
|
return;
|
|
290
289
|
const seat = read.seat(expectedName);
|
|
291
|
-
if (takeoverPhase !== 'joined' || lastActivity?.kind !== 'join' || seat === undefined
|
|
292
|
-
|| seat.owner !==
|
|
290
|
+
if (takeoverPhase !== 'joined' || lastActivity?.kind !== 'join' || seat === undefined || establishedSeat === undefined
|
|
291
|
+
|| seat.owner !== establishedSeat.owner || seat.generation !== establishedSeat.generation)
|
|
293
292
|
throw new SquareError('already_joined', 'Takeover did not complete its replacement join.');
|
|
294
293
|
},
|
|
295
294
|
};
|
package/dist/square-facade.d.ts
CHANGED
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
import type { DeliveryDeferral, MetadataMatch } from './delivery-deferral.js';
|
|
2
2
|
export type { DeliveryDeferral, MetadataMatch, MetadataScalar } from './delivery-deferral.js';
|
|
3
3
|
import type { ActivityId, Perception, Reach } from './square-core.js';
|
|
4
|
-
import type { Owner,
|
|
4
|
+
import type { Owner, HydratedAct, WakeAddress, ActivityMetadata, DirectedNotificationRoute } from './model.js';
|
|
5
5
|
import type { WakeTransportPort, SquareResourceOwner } from './ports.js';
|
|
6
|
+
import type { OperationControl } from './neutral.js';
|
|
7
|
+
import type { MessageSearch as ActivitySearch, AckResult } from './channel-facade.js';
|
|
8
|
+
export type { ChannelTruncate, ChannelSendInput, ChannelSendResult, ChannelEndpointSummary, ChannelMessage, ChannelPendingResult, MessageCursor, MessageQuery, ChannelHistoryQuery, ChannelPendingOptions, ChannelHistoryResult, ChannelReceiveResult, MessageSearch as ActivitySearch, AckResult, ChannelEndpointHold as HeldSeat } from './channel-facade.js';
|
|
9
|
+
export type { CatchWaitStart, OperationProgress, OperationControl, OperationFailureDetail, OperationError } from './neutral.js';
|
|
6
10
|
export type { ActivityId, Perception, Reach } from './square-core.js';
|
|
7
|
-
export type {
|
|
8
|
-
|
|
9
|
-
|
|
11
|
+
export type { MessageId } from './message.js';
|
|
12
|
+
export type { Owner, WakeAddress, ActivityMetadata, JsonValue, DirectedNotificationRoute } from './model.js';
|
|
13
|
+
/** Indexed archive event, including read bookkeeping and a say's linked content. */
|
|
14
|
+
export type ArchiveRecord = Readonly<HydratedAct>;
|
|
10
15
|
export interface Activity {
|
|
11
16
|
readonly id: ActivityId;
|
|
12
17
|
readonly at: number;
|
|
@@ -14,11 +19,12 @@ export interface Activity {
|
|
|
14
19
|
readonly actor: string;
|
|
15
20
|
readonly body?: string;
|
|
16
21
|
readonly metadata?: ActivityMetadata;
|
|
17
|
-
readonly delivery?: ActivityDelivery;
|
|
18
22
|
readonly mentions: readonly string[];
|
|
19
23
|
readonly reach?: Reach;
|
|
20
24
|
readonly target?: string;
|
|
21
25
|
readonly reply?: ActivityId;
|
|
26
|
+
/** Channel message owning a say's body and metadata. */
|
|
27
|
+
readonly messageId?: import('./message.js').MessageId;
|
|
22
28
|
}
|
|
23
29
|
export interface PerceivedActivity extends Activity {
|
|
24
30
|
readonly perception: Perception;
|
|
@@ -50,22 +56,6 @@ export interface ExpressResult {
|
|
|
50
56
|
readonly hint?: string;
|
|
51
57
|
readonly observation?: ExpressObservation;
|
|
52
58
|
}
|
|
53
|
-
export type ChannelTruncate = number | false;
|
|
54
|
-
export interface ChannelSendInput {
|
|
55
|
-
readonly from: string;
|
|
56
|
-
readonly to: string | readonly string[];
|
|
57
|
-
readonly body: string;
|
|
58
|
-
readonly truncate?: ChannelTruncate;
|
|
59
|
-
readonly metadata?: ActivityMetadata;
|
|
60
|
-
}
|
|
61
|
-
export interface ChannelSendResult {
|
|
62
|
-
readonly id: ActivityId;
|
|
63
|
-
readonly at: number;
|
|
64
|
-
readonly from: string;
|
|
65
|
-
readonly to: readonly string[];
|
|
66
|
-
readonly body: string;
|
|
67
|
-
readonly metadata?: ActivityMetadata;
|
|
68
|
-
}
|
|
69
59
|
export interface ListenerChangeResult {
|
|
70
60
|
readonly activity: Activity | null;
|
|
71
61
|
readonly observation?: ListenerObservation;
|
|
@@ -86,10 +76,6 @@ export interface CatchOptions extends ObservationOptions {
|
|
|
86
76
|
readonly limit?: number;
|
|
87
77
|
readonly replace?: boolean;
|
|
88
78
|
}
|
|
89
|
-
export interface ActivitySearch {
|
|
90
|
-
readonly text: string;
|
|
91
|
-
readonly mode: 'literal' | 'regex';
|
|
92
|
-
}
|
|
93
79
|
export interface ActivityCursor {
|
|
94
80
|
readonly id: ActivityId;
|
|
95
81
|
readonly direction: 'before' | 'after';
|
|
@@ -111,10 +97,6 @@ export interface PendingResult {
|
|
|
111
97
|
/** Matching unconsumed activities outside this page. */
|
|
112
98
|
readonly remaining: number;
|
|
113
99
|
}
|
|
114
|
-
export interface AckResult {
|
|
115
|
-
/** Newly consumed addressed IDs; repeated acknowledgement is a no-op. */
|
|
116
|
-
readonly consumed: number;
|
|
117
|
-
}
|
|
118
100
|
export type CatchReason = 'drained' | 'idle' | 'capped' | 'quorum' | 'replaced' | 'already-active';
|
|
119
101
|
export interface CatchResult {
|
|
120
102
|
readonly activities: readonly PerceivedActivity[];
|
|
@@ -124,37 +106,6 @@ export interface CatchResult {
|
|
|
124
106
|
readonly hint?: string;
|
|
125
107
|
readonly observation?: CatchObservation;
|
|
126
108
|
}
|
|
127
|
-
export interface CatchWaitStart {
|
|
128
|
-
readonly idleMs: number;
|
|
129
|
-
readonly replacementRequested: boolean;
|
|
130
|
-
readonly replaced: boolean;
|
|
131
|
-
}
|
|
132
|
-
export type OperationProgress = {
|
|
133
|
-
readonly kind: 'waiting';
|
|
134
|
-
readonly reason: 'throttled';
|
|
135
|
-
readonly delayMs?: number;
|
|
136
|
-
} | ({
|
|
137
|
-
readonly kind: 'catch-started';
|
|
138
|
-
readonly participant: string;
|
|
139
|
-
} & CatchWaitStart);
|
|
140
|
-
export interface OperationControl {
|
|
141
|
-
readonly signal?: AbortSignal;
|
|
142
|
-
readonly onProgress?: (progress: OperationProgress) => void;
|
|
143
|
-
}
|
|
144
|
-
export interface OperationFailureDetail {
|
|
145
|
-
readonly operation: 'express' | 'join' | 'catch' | 'history' | 'other';
|
|
146
|
-
readonly subject?: 'caller' | 'filter' | 'recipient';
|
|
147
|
-
readonly participant?: string;
|
|
148
|
-
readonly expressEffect?: 'unsent' | 'landed' | 'unknown';
|
|
149
|
-
readonly landedId?: ActivityId;
|
|
150
|
-
readonly historyBounds?: {
|
|
151
|
-
readonly maxLimit: number;
|
|
152
|
-
readonly totalMatches: number;
|
|
153
|
-
};
|
|
154
|
-
}
|
|
155
|
-
export interface OperationError extends Error {
|
|
156
|
-
readonly operation?: OperationFailureDetail;
|
|
157
|
-
}
|
|
158
109
|
export interface HistoryQuery extends ActivityQuery, ObservationOptions {
|
|
159
110
|
/** Ten by default; null explicitly reads the full archive. */
|
|
160
111
|
readonly limit?: number | null;
|
|
@@ -202,7 +153,7 @@ export interface JoinResult {
|
|
|
202
153
|
}
|
|
203
154
|
export interface Participant {
|
|
204
155
|
readonly name: string;
|
|
205
|
-
readonly generation:
|
|
156
|
+
readonly generation: string;
|
|
206
157
|
express(body: string | undefined, options?: ExpressOptions, control?: OperationControl): Promise<ExpressResult>;
|
|
207
158
|
express(input: ExpressInput, control?: OperationControl): Promise<ExpressResult>;
|
|
208
159
|
listen(target: string, options?: ObservationOptions, control?: OperationControl): Promise<ListenerChangeResult>;
|
|
@@ -221,11 +172,6 @@ export interface Participant {
|
|
|
221
172
|
renewDeliveryDeferral(id: string, durationMs: number, control?: OperationControl): Promise<DeliveryDeferral | null>;
|
|
222
173
|
releaseDeliveryDeferral(id: string, control?: OperationControl): Promise<boolean>;
|
|
223
174
|
}
|
|
224
|
-
export interface HeldSeat {
|
|
225
|
-
readonly name: string;
|
|
226
|
-
readonly generation: ActivityId;
|
|
227
|
-
readonly attachment: 'attached' | 'detached';
|
|
228
|
-
}
|
|
229
175
|
export type ParticipantPresence = 'never-joined' | 'active' | 'watching' | 'away' | 'done';
|
|
230
176
|
export interface ParticipantSummary {
|
|
231
177
|
readonly name: string;
|
package/dist/square-index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type VersionObserver } from './file-changes.js';
|
|
2
|
-
import { type Owner } from './
|
|
2
|
+
import { type Owner } from './neutral.js';
|
|
3
3
|
/** A rebuildable discovery hint: the owner that may have used an artifact and its path. */
|
|
4
4
|
export interface SquareIndexEntry {
|
|
5
5
|
readonly location: string;
|
package/dist/square-index.js
CHANGED
|
@@ -5,7 +5,7 @@ import { randomUUID } from 'node:crypto';
|
|
|
5
5
|
import { withFileLock } from './file-lock.js';
|
|
6
6
|
import { canonicalPath } from './canonical-path.js';
|
|
7
7
|
import { observeFileMetadata } from './file-changes.js';
|
|
8
|
-
import { validateOwner } from './
|
|
8
|
+
import { validateOwner } from './neutral.js';
|
|
9
9
|
export function squareIndexPath(env = process.env) {
|
|
10
10
|
const configured = env.SQUARE_INDEX?.trim();
|
|
11
11
|
return path.resolve(configured ?? path.join(os.homedir(), '.square', 'index.ndjsonl'));
|
package/dist/square-location.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
|
-
import { SquareError } from './
|
|
2
|
+
import { SquareError } from './neutral.js';
|
|
3
3
|
export function squareLocation(input) {
|
|
4
4
|
const selected = input.path ?? (input.env ?? process.env).SQUARE_LOCATION;
|
|
5
5
|
if (selected === undefined || selected.trim() === '')
|