@astrosheep/square 0.3.70 → 0.3.72
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 +4 -5
- package/dist/activity-feed.js +14 -10
- package/dist/artifact.d.ts +26 -33
- package/dist/artifact.js +346 -317
- package/dist/attention-presentation.js +2 -9
- package/dist/automatic-session.js +6 -6
- package/dist/boundary-presentation.js +3 -3
- package/dist/catch-decisions.d.ts +19 -12
- package/dist/catch-decisions.js +32 -68
- package/dist/claude-delivery.js +7 -7
- package/dist/claude-mod.js +18 -7
- package/dist/cli/catch-presentation.d.ts +7 -0
- package/dist/cli/catch-presentation.js +55 -0
- package/dist/cli/context.d.ts +1 -1
- package/dist/cli/context.js +5 -23
- package/dist/cli/express-presentation.d.ts +10 -0
- package/dist/cli/express-presentation.js +196 -0
- package/dist/cli/maintenance-commands.d.ts +4 -0
- package/dist/cli/maintenance-commands.js +29 -6
- package/dist/cli/observation-commands.d.ts +7 -5
- package/dist/cli/observation-commands.js +275 -262
- package/dist/cli/program.d.ts +1 -1
- package/dist/cli/program.js +43 -56
- package/dist/cli/registry.js +2 -1
- package/dist/cli/square-commands.d.ts +3 -9
- package/dist/cli/square-commands.js +134 -255
- package/dist/codex-queue.js +4 -1
- package/dist/decisions.d.ts +26 -74
- package/dist/decisions.js +190 -335
- package/dist/delivery-health.js +13 -22
- package/dist/delivery-operations.d.ts +0 -11
- package/dist/delivery-operations.js +44 -33
- package/dist/delivery.d.ts +33 -32
- package/dist/delivery.js +70 -81
- package/dist/help.js +6 -1
- package/dist/inbox.d.ts +27 -0
- package/dist/inbox.js +55 -18
- package/dist/index.d.ts +2 -4
- package/dist/index.js +1 -1
- package/dist/list.d.ts +7 -1
- package/dist/list.js +49 -122
- package/dist/mcp.d.ts +1 -1
- package/dist/mcp.js +7 -37
- package/dist/model.d.ts +4 -44
- package/dist/model.js +1 -3
- package/dist/notifications.d.ts +1 -1
- package/dist/notifications.js +13 -7
- package/dist/open-square.d.ts +16 -2
- package/dist/open-square.js +40 -1
- package/dist/packages/agent-delivery/src/claude.d.ts +2 -11
- package/dist/packages/agent-delivery/src/index.d.ts +2 -42
- package/dist/packages/agent-delivery/src/opencode.d.ts +2 -11
- package/dist/packages/agent-delivery/src/paseo.d.ts +2 -13
- package/dist/packages/agent-delivery/src/pi-client.d.ts +2 -9
- package/dist/packages/agent-delivery/src/types.d.ts +42 -0
- package/dist/participant-host.d.ts +6 -3
- package/dist/participant-host.js +44 -38
- package/dist/perception-projection.d.ts +6 -15
- package/dist/perception-projection.js +6 -26
- package/dist/plugins/opencode/delivery.js +9 -9
- package/dist/plugins/opencode/index.js +3 -3
- package/dist/ports.d.ts +156 -11
- package/dist/presentation-operations.d.ts +1 -1
- package/dist/presentation-operations.js +35 -44
- package/dist/presentation.d.ts +12 -19
- package/dist/presentation.js +33 -54
- package/dist/registry.d.ts +2 -0
- package/dist/registry.js +1 -1
- package/dist/routes.d.ts +7 -14
- package/dist/routes.js +34 -72
- package/dist/runtime.d.ts +12 -39
- package/dist/runtime.js +33 -164
- package/dist/square-actions.d.ts +11 -21
- package/dist/square-actions.js +171 -275
- package/dist/square-application.d.ts +31 -55
- package/dist/square-application.js +625 -141
- package/dist/square-core.d.ts +3 -94
- package/dist/square-core.js +8 -353
- package/dist/square-domain.d.ts +24 -0
- package/dist/square-domain.js +77 -0
- package/dist/square-facade.d.ts +360 -9
- package/dist/square-migration.d.ts +24 -0
- package/dist/square-migration.js +211 -0
- package/dist/square-projections.d.ts +2 -42
- package/dist/square-projections.js +1 -37
- package/dist/square-sqlite.d.ts +59 -0
- package/dist/square-sqlite.js +702 -0
- package/dist/stream.d.ts +3 -10
- package/dist/stream.js +81 -52
- package/dist/views.d.ts +27 -95
- package/dist/views.js +217 -87
- package/dist/wake-eligibility.d.ts +15 -5
- package/dist/wake-eligibility.js +32 -16
- package/dist/wakes.d.ts +3 -3
- package/dist/wakes.js +31 -27
- package/guides/application-facade-delivery-evidence.md +200 -0
- package/guides/application-facade-design.md +95 -0
- package/guides/change-waits.md +4 -4
- package/guides/migration.md +77 -0
- package/guides/postcommit-simplification-performance.md +36 -0
- package/guides/primitive-catch-consolidation.md +85 -0
- package/guides/primitive-history-consolidation.md +76 -0
- package/guides/primitive-status-consolidation.md +87 -0
- package/guides/primitive-storage-consolidation.md +128 -0
- package/guides/row-runtime-delivery-evidence.md +160 -0
- package/guides/row-storage-design.md +567 -0
- package/package.json +1 -1
- package/plugins/claude/.claude-plugin/plugin.json +1 -1
- package/plugins/codex/.codex-plugin/plugin.json +1 -1
- package/plugins/opencode/delivery.ts +11 -11
- package/plugins/opencode/index.ts +3 -3
- package/plugins/paseo/client/square-message.tsx +77 -64
- package/plugins/paseo/shared/message.ts +16 -0
- package/plugins/pi/square-pi.js +5 -1
- package/dist/activity.d.ts +0 -14
- package/dist/activity.js +0 -248
- package/dist/square-file-adapter.d.ts +0 -26
- package/dist/square-file-adapter.js +0 -85
- package/dist/square-state.d.ts +0 -6
- package/dist/square-state.js +0 -138
- package/dist/square-storage.d.ts +0 -14
- package/dist/square-storage.js +0 -188
- package/dist/square-wiring.d.ts +0 -33
- package/dist/square-wiring.js +0 -109
- package/dist/watch.d.ts +0 -8
- package/dist/watch.js +0 -252
|
@@ -1,14 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import type { OpenCodeDeliveryResult, OpenCodeTarget, OpenCodeSendTextOptions } from './types.js';
|
|
3
|
-
export interface OpenCodeConnectExistingOptions {
|
|
4
|
-
readonly harness: 'opencode';
|
|
5
|
-
readonly sessionId: string;
|
|
6
|
-
readonly endpoint?: Endpoint;
|
|
7
|
-
readonly registrationFile?: string;
|
|
8
|
-
readonly timeoutMs?: number;
|
|
9
|
-
readonly signal?: AbortSignal;
|
|
10
|
-
}
|
|
1
|
+
import type { OpenCodeConnectOptions, OpenCodeDeliveryResult, OpenCodeTarget, OpenCodeSendTextOptions } from './types.js';
|
|
11
2
|
/** Resolve an existing service and persisted session. Never starts or stops a service. */
|
|
12
|
-
export declare function connectExisting(options:
|
|
3
|
+
export declare function connectExisting(options: OpenCodeConnectOptions): Promise<OpenCodeTarget>;
|
|
13
4
|
/** Submit once through the shared native sender; HTTP metadata alone refines rejection. */
|
|
14
5
|
export declare function sendText(target: OpenCodeTarget, text: string, options?: OpenCodeSendTextOptions): Promise<OpenCodeDeliveryResult>;
|
|
@@ -1,17 +1,6 @@
|
|
|
1
|
-
import type { PaseoDeliveryResult, PaseoSendTextOptions, PaseoTarget } from './types.js';
|
|
2
|
-
export interface PaseoConnectExistingOptions {
|
|
3
|
-
readonly harness: 'paseo';
|
|
4
|
-
readonly agentId: string;
|
|
5
|
-
readonly endpoint?: string;
|
|
6
|
-
readonly password?: string;
|
|
7
|
-
readonly authHeader?: string;
|
|
8
|
-
readonly localCredential?: string;
|
|
9
|
-
readonly paseoHome?: string;
|
|
10
|
-
readonly timeoutMs?: number;
|
|
11
|
-
readonly signal?: AbortSignal;
|
|
12
|
-
}
|
|
1
|
+
import type { PaseoConnectOptions, PaseoDeliveryResult, PaseoSendTextOptions, PaseoTarget } from './types.js';
|
|
13
2
|
/** Connect to an existing daemon and address one existing agent. Never starts or stops anything. */
|
|
14
|
-
export declare function connectPaseo(options:
|
|
3
|
+
export declare function connectPaseo(options: PaseoConnectOptions): Promise<PaseoTarget>;
|
|
15
4
|
/**
|
|
16
5
|
* Every call owns its daemon connection: one for connect to prove the endpoint
|
|
17
6
|
* and credential, and one per send, closed again as soon as the daemon answers.
|
|
@@ -1,10 +1,3 @@
|
|
|
1
|
-
import type { PiDeliveryResult, PiSendTextOptions, PiTarget } from './types.js';
|
|
2
|
-
export
|
|
3
|
-
readonly harness: 'pi';
|
|
4
|
-
readonly sessionId: string;
|
|
5
|
-
readonly endpoint: string;
|
|
6
|
-
readonly timeoutMs?: number;
|
|
7
|
-
readonly signal?: AbortSignal;
|
|
8
|
-
}
|
|
9
|
-
export declare function connectPi(options: PiConnectExistingOptions): Promise<PiTarget>;
|
|
1
|
+
import type { PiConnectOptions, PiDeliveryResult, PiSendTextOptions, PiTarget } from './types.js';
|
|
2
|
+
export declare function connectPi(options: PiConnectOptions): Promise<PiTarget>;
|
|
10
3
|
export declare function sendPiText(target: PiTarget, text: string, options?: PiSendTextOptions): Promise<PiDeliveryResult>;
|
|
@@ -46,6 +46,48 @@ export interface PaseoSendTextOptions {
|
|
|
46
46
|
readonly signal?: AbortSignal;
|
|
47
47
|
}
|
|
48
48
|
export type SendTextOptions = OpenCodeSendTextOptions | ClaudeSendTextOptions | PiSendTextOptions | PaseoSendTextOptions;
|
|
49
|
+
export interface OpenCodeConnectOptions {
|
|
50
|
+
readonly harness: 'opencode';
|
|
51
|
+
readonly sessionId: string;
|
|
52
|
+
readonly endpoint?: {
|
|
53
|
+
readonly url: string;
|
|
54
|
+
readonly auth?: {
|
|
55
|
+
readonly type: 'basic';
|
|
56
|
+
readonly username: string;
|
|
57
|
+
readonly password: string;
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
readonly registrationFile?: string;
|
|
61
|
+
readonly timeoutMs?: number;
|
|
62
|
+
readonly signal?: AbortSignal;
|
|
63
|
+
}
|
|
64
|
+
export interface ClaudeConnectOptions {
|
|
65
|
+
readonly harness: 'claude';
|
|
66
|
+
readonly sessionId: string;
|
|
67
|
+
readonly endpoint: string;
|
|
68
|
+
readonly token?: string;
|
|
69
|
+
readonly claudeHome?: string;
|
|
70
|
+
readonly timeoutMs?: number;
|
|
71
|
+
readonly signal?: AbortSignal;
|
|
72
|
+
}
|
|
73
|
+
export interface PiConnectOptions {
|
|
74
|
+
readonly harness: 'pi';
|
|
75
|
+
readonly sessionId: string;
|
|
76
|
+
readonly endpoint: string;
|
|
77
|
+
readonly timeoutMs?: number;
|
|
78
|
+
readonly signal?: AbortSignal;
|
|
79
|
+
}
|
|
80
|
+
export interface PaseoConnectOptions {
|
|
81
|
+
readonly harness: 'paseo';
|
|
82
|
+
readonly agentId: string;
|
|
83
|
+
readonly endpoint?: string;
|
|
84
|
+
readonly password?: string;
|
|
85
|
+
readonly authHeader?: string;
|
|
86
|
+
readonly localCredential?: string;
|
|
87
|
+
readonly paseoHome?: string;
|
|
88
|
+
readonly timeoutMs?: number;
|
|
89
|
+
readonly signal?: AbortSignal;
|
|
90
|
+
}
|
|
49
91
|
interface OpenCodeAttempt {
|
|
50
92
|
readonly harness: 'opencode';
|
|
51
93
|
readonly sessionId: string;
|
|
@@ -12,8 +12,11 @@ export declare function processIdentity(env: NodeJS.ProcessEnv): {
|
|
|
12
12
|
channel: PresenceChannel;
|
|
13
13
|
};
|
|
14
14
|
export declare function identityRouteDraft(context: HostContext, participant: string): Promise<Omit<WakeRoute, 'updatedAt'> | undefined>;
|
|
15
|
-
|
|
15
|
+
/** One postcommit host observation; presence and route publication fail independently. */
|
|
16
|
+
export declare function publishCommittedIdentity(context: HostContext, participant: string, epoch?: number): Promise<void>;
|
|
16
17
|
export declare function retireIdentityRoute(context: HostContext, participant: string, expectedEpoch?: number): Promise<void>;
|
|
17
18
|
export declare function assertLiveOwner(context: HostContext, participant: string, expectedEpoch?: number): Promise<boolean>;
|
|
18
|
-
/**
|
|
19
|
-
export declare function ensureLocalPresence(context: HostContext, participant: string, epoch?: number): Promise<
|
|
19
|
+
/** Best-effort postcommit presence; a returned epoch also witnesses a readable host observation. */
|
|
20
|
+
export declare function ensureLocalPresence(context: HostContext, participant: string, epoch?: number): Promise<{
|
|
21
|
+
readonly epoch?: number;
|
|
22
|
+
} | undefined>;
|
package/dist/participant-host.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { currentOwner, presenceEpoch, sessionOwnsParticipant } from './registry.js';
|
|
2
2
|
import { firstHarnessSession } from './participant-identity.js';
|
|
3
|
+
import { canonicalPath } from './canonical-path.js';
|
|
3
4
|
import { defaultWakeRouteCapabilities, publishWakeRoute, retireWakeRouteFromArtifact, resolvePrimaryWakeRoute, ROUTE_FRESH_MS } from './routes.js';
|
|
4
5
|
export function processIdentity(env) {
|
|
5
6
|
const found = firstHarnessSession(env);
|
|
@@ -13,19 +14,17 @@ export async function identityRouteDraft(context, participant) {
|
|
|
13
14
|
const capabilities = context.hostLedger === undefined ? { canUse: () => false } : await defaultWakeRouteCapabilities(context.hostLedger);
|
|
14
15
|
return resolvePrimaryWakeRoute({ location: context.location, participant, sessionId: identity.session, provider }, context.env ?? process.env, capabilities);
|
|
15
16
|
}
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
const owner = await readParticipantOwner(context.location, participant, hostLedger);
|
|
21
|
-
return owner === undefined ? undefined : presenceEpoch(owner);
|
|
22
|
-
}
|
|
23
|
-
export async function publishIdentityRoute(context, participant, epoch) {
|
|
24
|
-
const route = await identityRouteDraft(context, participant);
|
|
25
|
-
if (route === undefined)
|
|
17
|
+
/** One postcommit host observation; presence and route publication fail independently. */
|
|
18
|
+
export async function publishCommittedIdentity(context, participant, epoch) {
|
|
19
|
+
const observed = await ensureLocalPresence(context, participant, epoch).catch(() => undefined);
|
|
20
|
+
if (observed === undefined)
|
|
26
21
|
return;
|
|
27
|
-
|
|
28
|
-
|
|
22
|
+
try {
|
|
23
|
+
const route = await identityRouteDraft(context, participant);
|
|
24
|
+
if (route !== undefined)
|
|
25
|
+
await publishWakeRoute(context.artifact, { ...route, ...observed }, { at: context.clock(), requireCurrentSession: true });
|
|
26
|
+
}
|
|
27
|
+
catch { /* Optional route enrichment cannot undo the committed activity. */ }
|
|
29
28
|
}
|
|
30
29
|
export async function retireIdentityRoute(context, participant, expectedEpoch) {
|
|
31
30
|
if (context.location === undefined || context.location === 'memory')
|
|
@@ -43,35 +42,42 @@ export async function assertLiveOwner(context, participant, expectedEpoch) {
|
|
|
43
42
|
return true;
|
|
44
43
|
return sessionOwnsParticipant(context.location, participant, identity.session, hostLedger, expectedEpoch);
|
|
45
44
|
}
|
|
46
|
-
/**
|
|
45
|
+
/** Best-effort postcommit presence; a returned epoch also witnesses a readable host observation. */
|
|
47
46
|
export async function ensureLocalPresence(context, participant, epoch) {
|
|
48
47
|
if (context.hostLedger === undefined || context.location === undefined || context.location === 'memory')
|
|
49
48
|
return;
|
|
50
49
|
const identity = processIdentity(context.env ?? process.env);
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
// Semantic publish: an unexpired presence row already stands when it carries the same owner epoch.
|
|
50
|
+
const now = Date.now();
|
|
51
|
+
let existing;
|
|
54
52
|
try {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
53
|
+
existing = await context.hostLedger.listPresence({ location: await canonicalPath(context.location), participant, now });
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
process.stderr.write(`! host presence degraded: ${error instanceof Error ? error.message : String(error)}\n`);
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
const owner = currentOwner(existing);
|
|
60
|
+
const ownerEpoch = epoch ?? (owner === undefined ? undefined : presenceEpoch(owner));
|
|
61
|
+
const observed = ownerEpoch === undefined ? {} : { epoch: ownerEpoch };
|
|
62
|
+
// A fresh exact local binding at the observed (or explicit claim) generation already stands.
|
|
63
|
+
if (existing.some((row) => row.session === identity.session && row.channel === identity.channel
|
|
64
|
+
&& now - (row.updatedAt ?? 0) < ROUTE_FRESH_MS
|
|
65
|
+
&& (ownerEpoch === undefined || presenceEpoch(row) === ownerEpoch)))
|
|
66
|
+
return observed;
|
|
67
|
+
try {
|
|
68
|
+
const result = await context.hostLedger.ensurePresence({
|
|
69
|
+
location: context.location,
|
|
70
|
+
participant,
|
|
71
|
+
session: identity.session,
|
|
72
|
+
channel: identity.channel,
|
|
73
|
+
updatedAt: Date.now(),
|
|
74
|
+
...(ownerEpoch === undefined || ownerEpoch <= 0 ? {} : { epoch: ownerEpoch }),
|
|
75
|
+
});
|
|
76
|
+
if (result.status === 'degraded')
|
|
77
|
+
throw result.error;
|
|
78
|
+
}
|
|
79
|
+
catch (error) {
|
|
80
|
+
process.stderr.write(`! host presence degraded: ${error instanceof Error ? error.message : String(error)}\n`);
|
|
60
81
|
}
|
|
61
|
-
|
|
62
|
-
const result = await context.hostLedger.ensurePresence({
|
|
63
|
-
location: context.location,
|
|
64
|
-
participant,
|
|
65
|
-
session: identity.session,
|
|
66
|
-
channel: identity.channel,
|
|
67
|
-
// Presence rows are host-ledger wall-time evidence; the square clock belongs to artifact activities.
|
|
68
|
-
updatedAt: Date.now(),
|
|
69
|
-
...(ownerEpoch === undefined || ownerEpoch <= 0 ? {} : { epoch: ownerEpoch }),
|
|
70
|
-
}).catch((error) => ({
|
|
71
|
-
status: 'degraded',
|
|
72
|
-
record: { location: context.location, participant, session: identity.session, channel: identity.channel },
|
|
73
|
-
error,
|
|
74
|
-
}));
|
|
75
|
-
if (result.status === 'degraded')
|
|
76
|
-
process.stderr.write(`! host presence degraded: ${result.error instanceof Error ? result.error.message : String(result.error)}\n`);
|
|
82
|
+
return observed;
|
|
77
83
|
}
|
|
@@ -1,15 +1,6 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { type
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
export interface PerceptionProjection {
|
|
8
|
-
directedTo(activity: StoredAct, name: string): boolean;
|
|
9
|
-
perceive(activity: StoredAct, name: string): Perception;
|
|
10
|
-
cursorFor(name: string): number;
|
|
11
|
-
isSeen(name: string, index: number): boolean;
|
|
12
|
-
readonly replayedActivityCount: number;
|
|
13
|
-
}
|
|
14
|
-
/** Build perception over one audience replay of a SquareState snapshot. */
|
|
15
|
-
export declare function derivePerceptionProjection(state: SquareState, landed?: LandedAudienceReplay): PerceptionProjection;
|
|
1
|
+
import type { Perception } from './square-core.js';
|
|
2
|
+
import { type StoredAct } from './model.js';
|
|
3
|
+
import type { SquareRead } from './ports.js';
|
|
4
|
+
export declare function directedTo(facts: SquareRead, activity: StoredAct, name: string): boolean;
|
|
5
|
+
/** Audience is settled at landing, never reconstructed from a partial history. */
|
|
6
|
+
export declare function perceiveActivity(facts: SquareRead, activity: StoredAct, name: string): Perception;
|
|
@@ -1,28 +1,8 @@
|
|
|
1
|
-
import { formatActivityId, replayLandedAudiences } from './square-core.js';
|
|
2
1
|
import { sameName } from './model.js';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
function directedTo(activity, name) {
|
|
10
|
-
return activity.kind === 'say' && landed.includes(activity, name);
|
|
11
|
-
}
|
|
12
|
-
function perceive(activity, name) {
|
|
13
|
-
if (activity.kind !== 'say' || sameName(activity.actor, name))
|
|
14
|
-
return 'full';
|
|
15
|
-
return directedTo(activity, name) ? 'full' : 'presence';
|
|
16
|
-
}
|
|
17
|
-
function isSeen(name, index) {
|
|
18
|
-
const recipient = canonicalName(name);
|
|
19
|
-
return state.runtime.observations?.[recipient]?.[formatActivityId(index)]?.state === 'seen';
|
|
20
|
-
}
|
|
21
|
-
return {
|
|
22
|
-
directedTo,
|
|
23
|
-
perceive,
|
|
24
|
-
cursorFor: (name) => readCursor(state, name, landed),
|
|
25
|
-
isSeen,
|
|
26
|
-
replayedActivityCount: landed.replayedActivityCount,
|
|
27
|
-
};
|
|
2
|
+
export function directedTo(facts, activity, name) {
|
|
3
|
+
return activity.kind === 'say' && facts.directedAt(name, activity.index) !== undefined;
|
|
4
|
+
}
|
|
5
|
+
/** Audience is settled at landing, never reconstructed from a partial history. */
|
|
6
|
+
export function perceiveActivity(facts, activity, name) {
|
|
7
|
+
return activity.kind !== 'say' || sameName(activity.actor, name) || directedTo(facts, activity, name) ? 'full' : 'presence';
|
|
28
8
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { nameKey } from '../../model.js';
|
|
2
|
-
import { observeSessionPending, sessionInbox } from '../../inbox.js';
|
|
2
|
+
import { nativePendingPreview, observeSessionPending, sessionInbox } from '../../inbox.js';
|
|
3
3
|
import { hostLedgerForEnv } from '../../registry.js';
|
|
4
|
-
import { openSquare } from '../../square
|
|
4
|
+
import { openSquare } from '../../open-square.js';
|
|
5
5
|
import { closeOpenSquare } from '../../open-square.js';
|
|
6
|
-
import {
|
|
6
|
+
import { presentationSuppressesWake, projectPresentationEvidence } from '../../square-projections.js';
|
|
7
7
|
import { presentPending } from '../../presentation-operations.js';
|
|
8
8
|
import { deliverPending } from '../../delivery-operations.js';
|
|
9
9
|
import { createWakeTransport } from '../../notifications.js';
|
|
@@ -13,8 +13,8 @@ import { createNativeInputId, sendNativeText } from '../../packages/agent-delive
|
|
|
13
13
|
const routeKind = 'opencode-server';
|
|
14
14
|
const key = (location, participant, index) => `${location}\0${nameKey(participant)}\0${index}`;
|
|
15
15
|
/** The one native pending preview: the audience/catch/epoch fence before send and inside presentation. */
|
|
16
|
-
function preview(
|
|
17
|
-
return nativePendingPreview(
|
|
16
|
+
function preview(facts, owner, index) {
|
|
17
|
+
return nativePendingPreview(facts, { location: owner.location, routeKind, sessionId: owner.session, participant: owner.participant, actIndex: index, epoch: owner.epoch, address: { sessionId: owner.session }, cancelledThrough: owner.cancelledThrough, now: Date.now() });
|
|
18
18
|
}
|
|
19
19
|
function createOpenCodeWakeTransport(target, env, lifetime) {
|
|
20
20
|
const ledger = hostLedgerForEnv(env);
|
|
@@ -36,14 +36,14 @@ function createOpenCodeWakeTransport(target, env, lifetime) {
|
|
|
36
36
|
return undefined;
|
|
37
37
|
const square = await openSquare(owner.location, { hostLedger: ledger, env, signal });
|
|
38
38
|
try {
|
|
39
|
-
const prepared =
|
|
39
|
+
const { value: prepared } = await square.artifact.read((facts) => preview(facts, owner, index), signal);
|
|
40
40
|
if (!prepared)
|
|
41
41
|
return undefined;
|
|
42
42
|
const row = { location: owner.location, participant: owner.participant, session: target.sessionId,
|
|
43
43
|
activity: request.activity, kind: 'wake', outcome: 'dispatching', routeKind, attemptN: request.attemptN, claimToken: request.claimToken,
|
|
44
44
|
nativeDelivery: { harness: 'opencode', epoch: owner.epoch ?? 0, inputId: createNativeInputId(), payload: prepared.payload } };
|
|
45
45
|
if (!await ledger.prepareNativeWake(row) || !await (beforeSend?.() ?? Promise.resolve(true)) || signal.aborted
|
|
46
|
-
||
|
|
46
|
+
|| (await square.artifact.read((facts) => preview(facts, owner, index)?.payload, signal)).value !== prepared.payload)
|
|
47
47
|
return undefined;
|
|
48
48
|
return { sending: sendNativeText(target, prepared.payload, { inputId: row.nativeDelivery.inputId, delivery: 'steer',
|
|
49
49
|
timeoutMs: Math.max(1, deadline - Date.now()), signal }) };
|
|
@@ -82,7 +82,7 @@ export async function observeOpenCodeContext(sessionId, messages, env, signal) {
|
|
|
82
82
|
continue;
|
|
83
83
|
const square = await openSquare(row.location, { hostLedger: ledger, env, signal });
|
|
84
84
|
try {
|
|
85
|
-
const prepared =
|
|
85
|
+
const { value: prepared } = await square.artifact.read((facts) => preview(facts, owner, index), signal);
|
|
86
86
|
if (!prepared || prepared.payload !== row.nativeDelivery.payload)
|
|
87
87
|
continue;
|
|
88
88
|
const prior = await projectPresentationEvidence({ hostLedger: ledger, location: row.location, participant: row.participant, sessionId, activity: row.activity });
|
|
@@ -90,7 +90,7 @@ export async function observeOpenCodeContext(sessionId, messages, env, signal) {
|
|
|
90
90
|
continue;
|
|
91
91
|
await presentPending({ artifact: square.artifact, hostLedger: ledger, location: row.location, participant: row.participant, session: sessionId,
|
|
92
92
|
activity: row.activity, sink: { present() { } }, markSeen: !prepared.clipped, signal,
|
|
93
|
-
current: (
|
|
93
|
+
current: (facts) => !signal.aborted && preview(facts, owner, index)?.payload === row.nativeDelivery.payload });
|
|
94
94
|
}
|
|
95
95
|
finally {
|
|
96
96
|
await closeOpenSquare(square);
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { automaticSessionStart, operationEnv } from '../../automatic-session.js';
|
|
2
2
|
import { hostLedgerForEnv } from '../../registry.js';
|
|
3
3
|
import { canonicalPath } from '../../canonical-path.js';
|
|
4
|
-
import { openSquare } from '../../square
|
|
4
|
+
import { openSquare } from '../../open-square.js';
|
|
5
5
|
import { closeOpenSquare } from '../../open-square.js';
|
|
6
|
-
import { Square } from '../../square-
|
|
6
|
+
import { Square } from '../../square-application.js';
|
|
7
7
|
import { connectNative } from '../../packages/agent-delivery/src/opencode-native.js';
|
|
8
8
|
import { observeOpenCodeContext, publishOpenCodeRoutes, receiveOpenCodePending } from './delivery.js';
|
|
9
9
|
/** Actual OpenCode 2.0.20 server plugin. Harness identity belongs to ctx, never process.env. */
|
|
@@ -81,7 +81,7 @@ export default {
|
|
|
81
81
|
for (const owner of (await ledger.listPresence({ session: sessionId })).filter((binding) => binding.channel === 'opencode')) {
|
|
82
82
|
const square = await openSquare(owner.location, { hostLedger: ledger, env, signal: lifetime.signal });
|
|
83
83
|
try {
|
|
84
|
-
await ledger.suppressPresence(owner, (await square.artifact.read(
|
|
84
|
+
await ledger.suppressPresence(owner, (await square.artifact.read((facts) => facts.header().nextActIndex - 1, lifetime.signal)).value);
|
|
85
85
|
}
|
|
86
86
|
finally {
|
|
87
87
|
await closeOpenSquare(square);
|
package/dist/ports.d.ts
CHANGED
|
@@ -1,16 +1,161 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { Act, HardCap, InboxNotification, StoredAct, WakeRoute, WakeRouteKind, WatchLease } from './model.js';
|
|
2
2
|
export type { ClaimResult, EvidenceClaim, EvidenceRelease, EvidenceGc, EvidenceLookup, EvidenceRecord, HostLedgerPort, PresenceKey, PresenceLookup, PresenceRecord, PresenceClaimResult, PresenceChannel, PresenceResult, } from './host-ledger.js';
|
|
3
3
|
import type { HostLedgerPort } from './host-ledger.js';
|
|
4
|
-
|
|
4
|
+
export type ActivityIndex = number;
|
|
5
|
+
export interface SquareHeader {
|
|
6
|
+
readonly revision: number;
|
|
7
|
+
readonly nextActIndex: number;
|
|
8
|
+
readonly lastActIndex: number;
|
|
9
|
+
readonly hardCap: HardCap;
|
|
10
|
+
readonly throttlePerMinute?: number;
|
|
11
|
+
readonly preamble: readonly string[];
|
|
12
|
+
readonly warmup: readonly string[];
|
|
13
|
+
}
|
|
14
|
+
export interface ParticipantFact {
|
|
15
|
+
readonly name: string;
|
|
16
|
+
readonly firstIndex: number;
|
|
17
|
+
readonly joined: boolean;
|
|
18
|
+
readonly done: boolean;
|
|
19
|
+
readonly sayCount: number;
|
|
20
|
+
readonly lastActiveAt?: number;
|
|
21
|
+
readonly lastJoinIndex?: number;
|
|
22
|
+
}
|
|
23
|
+
export interface AttentionFact {
|
|
24
|
+
readonly listener: string;
|
|
25
|
+
readonly target: string;
|
|
26
|
+
readonly kind: 'listen' | 'ignore';
|
|
27
|
+
readonly sinceIndex: number;
|
|
28
|
+
}
|
|
29
|
+
export interface ActivityHead {
|
|
30
|
+
readonly index: ActivityIndex;
|
|
31
|
+
readonly at: number;
|
|
32
|
+
readonly kind: StoredAct['kind'];
|
|
33
|
+
readonly actor?: string;
|
|
34
|
+
readonly reach?: 'bell';
|
|
35
|
+
readonly reply?: ActivityIndex;
|
|
36
|
+
}
|
|
37
|
+
export interface ActivityFilter {
|
|
38
|
+
readonly afterIndex?: number;
|
|
39
|
+
readonly beforeIndex?: number;
|
|
40
|
+
readonly throughIndex?: number;
|
|
41
|
+
readonly indexes?: readonly ActivityIndex[];
|
|
42
|
+
readonly kinds?: readonly StoredAct['kind'][];
|
|
43
|
+
readonly actors?: readonly string[];
|
|
44
|
+
readonly actorMatch?: 'identity' | 'exact';
|
|
45
|
+
readonly actorRequired?: true;
|
|
46
|
+
readonly afterAt?: number;
|
|
47
|
+
}
|
|
48
|
+
export interface IndexPage {
|
|
49
|
+
readonly edge: 'oldest' | 'newest';
|
|
50
|
+
readonly limit: number;
|
|
51
|
+
}
|
|
52
|
+
export interface FactPage<T> {
|
|
53
|
+
readonly items: readonly T[];
|
|
54
|
+
readonly hasMore: boolean;
|
|
55
|
+
}
|
|
56
|
+
export interface DirectedFilter {
|
|
57
|
+
readonly afterIndex?: number;
|
|
58
|
+
readonly beforeIndex?: number;
|
|
59
|
+
readonly throughIndex?: number;
|
|
60
|
+
readonly unseenOnly?: true;
|
|
61
|
+
readonly senders?: readonly string[];
|
|
62
|
+
readonly attentionOnly?: true;
|
|
63
|
+
}
|
|
64
|
+
export interface DirectedHead {
|
|
65
|
+
readonly index: ActivityIndex;
|
|
66
|
+
readonly at: number;
|
|
67
|
+
readonly actor: string;
|
|
68
|
+
readonly recipient: string;
|
|
69
|
+
readonly route: 'mention' | 'reply' | 'attention' | 'bell';
|
|
70
|
+
}
|
|
71
|
+
export interface LandedRecipient {
|
|
72
|
+
readonly recipient: string;
|
|
73
|
+
readonly route: DirectedHead['route'];
|
|
74
|
+
}
|
|
75
|
+
export interface ReceiptFacts {
|
|
76
|
+
readonly latestAt?: number;
|
|
77
|
+
readonly latestActorActivityIndex?: number;
|
|
78
|
+
}
|
|
79
|
+
export interface ReceiptAssignment {
|
|
80
|
+
readonly owner: string;
|
|
81
|
+
readonly index: ActivityIndex;
|
|
82
|
+
}
|
|
83
|
+
export type JsonValue = null | boolean | number | string | readonly JsonValue[] | {
|
|
84
|
+
readonly [key: string]: JsonValue;
|
|
85
|
+
};
|
|
86
|
+
export interface RouteFact {
|
|
87
|
+
readonly location: string;
|
|
88
|
+
readonly participant: string;
|
|
89
|
+
readonly sessionId: string;
|
|
90
|
+
readonly channel: string;
|
|
91
|
+
readonly kind: WakeRouteKind;
|
|
92
|
+
readonly address: Readonly<Record<string, string>>;
|
|
93
|
+
readonly updatedAt: number;
|
|
94
|
+
readonly epoch?: JsonValue;
|
|
95
|
+
readonly extra: Readonly<Record<string, JsonValue>>;
|
|
96
|
+
}
|
|
97
|
+
/** Domain facts exist only during a synchronous artifact callback. Values are detached. */
|
|
98
|
+
export interface SquareRead {
|
|
99
|
+
header(): SquareHeader;
|
|
100
|
+
participant(requestedName: string): ParticipantFact | undefined;
|
|
101
|
+
roster(): readonly ParticipantFact[];
|
|
102
|
+
attention(listener: string): readonly AttentionFact[];
|
|
103
|
+
incomingAttention(sender: string): readonly AttentionFact[];
|
|
104
|
+
hold(): {
|
|
105
|
+
readonly active: boolean;
|
|
106
|
+
readonly at?: number;
|
|
107
|
+
readonly reason?: string;
|
|
108
|
+
readonly actor?: string;
|
|
109
|
+
};
|
|
110
|
+
activity(index: ActivityIndex): StoredAct | undefined;
|
|
111
|
+
activityHeads(filter: ActivityFilter, page: IndexPage): FactPage<ActivityHead>;
|
|
112
|
+
activities(indexes: readonly ActivityIndex[]): readonly StoredAct[];
|
|
113
|
+
activityCount(filter: ActivityFilter): number;
|
|
114
|
+
contextIndexes(centers: readonly ActivityIndex[], before: number, after: number): readonly ActivityIndex[];
|
|
115
|
+
sayOrdinals(indexes: readonly ActivityIndex[]): Readonly<Record<number, number>>;
|
|
116
|
+
recentSayTimes(afterExclusive: number, takeLatest: number, actor?: string, bellOnly?: true): readonly number[];
|
|
117
|
+
audience(index: ActivityIndex): readonly LandedRecipient[];
|
|
118
|
+
directed(recipient: string, filter: DirectedFilter, page: IndexPage): FactPage<DirectedHead>;
|
|
119
|
+
directedAt(recipient: string, index: ActivityIndex): DirectedHead | undefined;
|
|
120
|
+
directedCount(recipient: string, filter: DirectedFilter): number;
|
|
121
|
+
pendingAudience(afterExclusive: number, throughInclusive: number, activityLimit: number): {
|
|
122
|
+
readonly groups: readonly {
|
|
123
|
+
readonly index: ActivityIndex;
|
|
124
|
+
readonly at: number;
|
|
125
|
+
readonly actor: string;
|
|
126
|
+
readonly recipients: readonly LandedRecipient[];
|
|
127
|
+
}[];
|
|
128
|
+
readonly hasMore: boolean;
|
|
129
|
+
};
|
|
130
|
+
receipt(requestedName: string, index: ActivityIndex): {
|
|
131
|
+
readonly at: number;
|
|
132
|
+
} | undefined;
|
|
133
|
+
receiptFacts(requestedName: string, afterIndex: number): ReceiptFacts;
|
|
134
|
+
receiptAssignments(): readonly ReceiptAssignment[];
|
|
135
|
+
lease(requestedName: string): WatchLease | undefined;
|
|
136
|
+
routes(): readonly RouteFact[];
|
|
137
|
+
}
|
|
138
|
+
export interface SquareWrite extends SquareRead {
|
|
139
|
+
land(activity: Act & {
|
|
140
|
+
readonly at: number;
|
|
141
|
+
}): StoredAct;
|
|
142
|
+
markSeen(requestedName: string, indexes: readonly ActivityIndex[], at: number): number;
|
|
143
|
+
putLease(requestedName: string, lease: WatchLease): boolean;
|
|
144
|
+
removeLease(requestedName: string, expectedLeaseId: string): boolean;
|
|
145
|
+
replaceRoutes(routes: readonly RouteFact[]): boolean;
|
|
146
|
+
}
|
|
147
|
+
export interface SquareReadResult<R> {
|
|
148
|
+
readonly value: R;
|
|
149
|
+
readonly version: number;
|
|
150
|
+
}
|
|
151
|
+
export interface SquareCommitResult<R> extends SquareReadResult<R> {
|
|
152
|
+
readonly changed: boolean;
|
|
153
|
+
}
|
|
154
|
+
/** Atomic artifact access; no framing, SQL or lazy transaction capability escapes. */
|
|
5
155
|
export interface SquareArtifactPort {
|
|
6
|
-
read(signal?: AbortSignal): Promise<
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
}>;
|
|
10
|
-
transact<R>(fn: (state: SquareState, version: number) => {
|
|
11
|
-
state?: SquareState;
|
|
12
|
-
result: R;
|
|
13
|
-
}, signal?: AbortSignal): Promise<R>;
|
|
156
|
+
read<R>(select: (facts: SquareRead) => R, signal?: AbortSignal): Promise<SquareReadResult<R>>;
|
|
157
|
+
transact<R>(change: (facts: SquareWrite) => R, signal?: AbortSignal): Promise<SquareCommitResult<R>>;
|
|
158
|
+
revision(signal?: AbortSignal): Promise<number>;
|
|
14
159
|
changed(sinceVersion: number, timeoutMs: number, signal?: AbortSignal): Promise<boolean>;
|
|
15
160
|
close(): Promise<void>;
|
|
16
161
|
}
|
|
@@ -121,5 +266,5 @@ export interface PresentPendingInput {
|
|
|
121
266
|
/** Boundary previews that were clipped remain pending for a later full presentation. */
|
|
122
267
|
readonly markSeen?: boolean;
|
|
123
268
|
/** Receiver-specific fences checked inside the artifact observation transaction. */
|
|
124
|
-
readonly current?: (
|
|
269
|
+
readonly current?: (facts: SquareRead) => boolean;
|
|
125
270
|
}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { PresentationResult, PresentPendingInput } from './ports.js';
|
|
2
|
-
/**
|
|
2
|
+
/** Presentation evidence is not a receipt; only the fenced receipt transaction marks seen. */
|
|
3
3
|
export declare function presentPending(input: PresentPendingInput): Promise<PresentationResult>;
|