pmx-canvas 0.4.8 → 0.5.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/.github/extensions/pmx-canvas/extension.mjs +154 -5
- package/.github/extensions/pmx-canvas/steering-delivery.mjs +79 -0
- package/CHANGELOG.md +156 -0
- package/Readme.md +72 -23
- package/dist/canvas/global.css +3071 -796
- package/dist/canvas/index.js +122 -104
- package/dist/json-render/index.css +1 -1
- package/dist/types/cli/agent.d.ts +1 -0
- package/dist/types/cli/commands/pump.d.ts +9 -0
- package/dist/types/client/App.d.ts +1 -1
- package/dist/types/client/canvas/AgentPresenceLayer.d.ts +11 -0
- package/dist/types/client/canvas/BarHint.d.ts +22 -0
- package/dist/types/client/canvas/CanvasNode.d.ts +5 -0
- package/dist/types/client/canvas/CanvasViewport.d.ts +4 -4
- package/dist/types/client/canvas/CommandBar.d.ts +10 -0
- package/dist/types/client/canvas/ConnectionBanner.d.ts +13 -0
- package/dist/types/client/canvas/ContextMenu.d.ts +6 -0
- package/dist/types/client/canvas/EdgeLayer.d.ts +2 -1
- package/dist/types/client/canvas/EmptyState.d.ts +11 -0
- package/dist/types/client/canvas/ExternalWriters.d.ts +5 -0
- package/dist/types/client/canvas/HumanPresenceLayer.d.ts +8 -0
- package/dist/types/client/canvas/Minimap.d.ts +12 -1
- package/dist/types/client/canvas/ScopeFenceLayer.d.ts +8 -0
- package/dist/types/client/canvas/SelectionBar.d.ts +6 -0
- package/dist/types/client/canvas/SessionPanel.d.ts +1 -0
- package/dist/types/client/canvas/SessionReceipt.d.ts +17 -0
- package/dist/types/client/canvas/TextPrompt.d.ts +25 -0
- package/dist/types/client/canvas/ToolRail.d.ts +21 -0
- package/dist/types/client/canvas/TopBar.d.ts +7 -0
- package/dist/types/client/canvas/canvas-area.d.ts +39 -0
- package/dist/types/client/canvas/create-in-view.d.ts +18 -0
- package/dist/types/client/canvas/import-files.d.ts +8 -0
- package/dist/types/client/canvas/kind-colors.d.ts +3 -0
- package/dist/types/client/canvas/use-focus-trap.d.ts +14 -0
- package/dist/types/client/canvas/use-now.d.ts +6 -0
- package/dist/types/client/icons.d.ts +11 -4
- package/dist/types/client/nodes/ExtAppFrame.d.ts +2 -0
- package/dist/types/client/nodes/GroupNode.d.ts +6 -1
- package/dist/types/client/nodes/MarkdownNode.d.ts +2 -0
- package/dist/types/client/nodes/inline-editor-commands.d.ts +3 -4
- package/dist/types/client/state/canvas-store.d.ts +49 -5
- package/dist/types/client/state/human-store.d.ts +26 -0
- package/dist/types/client/state/iframe-mode.d.ts +1 -0
- package/dist/types/client/state/intent-bridge.d.ts +37 -5
- package/dist/types/client/state/node-factory.d.ts +0 -1
- package/dist/types/client/state/presence-store.d.ts +78 -0
- package/dist/types/client/state/session-store.d.ts +176 -0
- package/dist/types/client/types.d.ts +2 -1
- package/dist/types/client/utils/platform.d.ts +2 -0
- package/dist/types/server/agent-presence.d.ts +192 -0
- package/dist/types/server/ax-gate-ttl.d.ts +6 -0
- package/dist/types/server/ax-interaction.d.ts +4 -10
- package/dist/types/server/ax-state-manager.d.ts +21 -2
- package/dist/types/server/ax-state.d.ts +49 -3
- package/dist/types/server/ax-wait.d.ts +13 -0
- package/dist/types/server/canvas-db.d.ts +9 -1
- package/dist/types/server/canvas-operations.d.ts +11 -0
- package/dist/types/server/canvas-state.d.ts +27 -13
- package/dist/types/server/canvas-validation.d.ts +0 -14
- package/dist/types/server/html-surface.d.ts +1 -1
- package/dist/types/server/human-presence.d.ts +40 -0
- package/dist/types/server/index.d.ts +29 -3
- package/dist/types/server/intent-registry.d.ts +7 -0
- package/dist/types/server/mutation-history.d.ts +15 -2
- package/dist/types/server/operations/invoker.d.ts +13 -2
- package/dist/types/server/operations/ops/ax-presence.d.ts +2 -0
- package/dist/types/server/operations/ops/human-presence.d.ts +3 -0
- package/dist/types/server/operations/registry.d.ts +11 -0
- package/dist/types/server/operations/types.d.ts +1 -1
- package/dist/types/server/scope-fence.d.ts +62 -0
- package/dist/types/server/server.d.ts +0 -12
- package/dist/types/shared/agent-presence.d.ts +130 -0
- package/dist/types/shared/approval-gates.d.ts +19 -0
- package/dist/types/shared/auto-arrange.d.ts +0 -1
- package/dist/types/shared/ax-kinds.d.ts +11 -0
- package/dist/types/shared/human-presence.d.ts +31 -0
- package/dist/types/shared/iframe-probe.d.ts +8 -0
- package/dist/types/shared/scope-fence.d.ts +21 -0
- package/docs/RELEASE.md +20 -0
- package/docs/ax-host-adapter-contract.md +30 -14
- package/docs/cli.md +37 -1
- package/docs/environment.md +3 -0
- package/docs/http-api.md +222 -5
- package/docs/mcp.md +6 -5
- package/docs/node-types.md +3 -1
- package/docs/plans/plan-009-tech-debt-backlog.md +13 -0
- package/docs/screenshot.png +0 -0
- package/docs/screenshots/multi-agent-live.png +0 -0
- package/docs/screenshots/workbench-live-dark.png +0 -0
- package/docs/screenshots/workbench-live-light.png +0 -0
- package/docs/sdk.md +1 -1
- package/package.json +4 -4
- package/skills/pmx-canvas/SKILL.md +112 -17
- package/skills/pmx-canvas/references/codex-app-adapter.md +28 -0
- package/skills/pmx-canvas/references/full-reference.md +55 -16
- package/skills/pmx-canvas/references/github-copilot-app-adapter.md +41 -24
- package/skills/pmx-canvas-orchestration/SKILL.md +56 -2
- package/skills/pmx-canvas-testing/SKILL.md +17 -0
- package/src/cli/agent.ts +1 -0
- package/src/cli/commands/copilot.ts +15 -8
- package/src/cli/commands/nodes.ts +1 -19
- package/src/cli/commands/pump.ts +263 -0
- package/src/cli/index.ts +2 -5
- package/src/cli/shared.ts +1 -1
- package/src/client/App.tsx +209 -585
- package/src/client/canvas/AgentPresenceLayer.tsx +74 -0
- package/src/client/canvas/AttentionHistory.tsx +0 -10
- package/src/client/canvas/BarHint.tsx +49 -0
- package/src/client/canvas/CanvasNode.tsx +488 -136
- package/src/client/canvas/CanvasViewport.tsx +190 -94
- package/src/client/canvas/CommandBar.tsx +140 -0
- package/src/client/canvas/CommandPalette.tsx +133 -58
- package/src/client/canvas/ConnectionBanner.tsx +65 -0
- package/src/client/canvas/ContextMenu.tsx +88 -27
- package/src/client/canvas/ContextPinBar.tsx +2 -2
- package/src/client/canvas/EdgeLayer.tsx +121 -38
- package/src/client/canvas/EmptyState.tsx +93 -0
- package/src/client/canvas/ExpandedNodeOverlay.tsx +64 -118
- package/src/client/canvas/ExternalWriters.tsx +308 -0
- package/src/client/canvas/FocusFieldLayer.tsx +12 -1
- package/src/client/canvas/HumanPresenceLayer.tsx +45 -0
- package/src/client/canvas/IntentLayer.tsx +1 -1
- package/src/client/canvas/Minimap.tsx +117 -190
- package/src/client/canvas/ScopeFenceLayer.tsx +38 -0
- package/src/client/canvas/SelectionBar.tsx +175 -23
- package/src/client/canvas/SessionPanel.tsx +481 -0
- package/src/client/canvas/SessionReceipt.tsx +141 -0
- package/src/client/canvas/ShortcutOverlay.tsx +21 -6
- package/src/client/canvas/SnapshotPanel.tsx +166 -80
- package/src/client/canvas/TextPrompt.tsx +128 -0
- package/src/client/canvas/ToolRail.tsx +447 -0
- package/src/client/canvas/TopBar.tsx +308 -0
- package/src/client/canvas/auto-fit.ts +1 -5
- package/src/client/canvas/canvas-area.ts +74 -0
- package/src/client/canvas/create-in-view.ts +48 -0
- package/src/client/canvas/import-files.ts +64 -0
- package/src/client/canvas/kind-colors.ts +22 -0
- package/src/client/canvas/snap-guides.ts +1 -1
- package/src/client/canvas/use-focus-trap.ts +54 -0
- package/src/client/canvas/use-now.ts +17 -0
- package/src/client/canvas/use-pan-zoom.ts +13 -2
- package/src/client/icons.tsx +57 -18
- package/src/client/nodes/ExtAppFrame.tsx +86 -20
- package/src/client/nodes/GroupNode.tsx +9 -28
- package/src/client/nodes/InlineFormatBar.tsx +4 -3
- package/src/client/nodes/InlineMarkdownEditor.tsx +27 -0
- package/src/client/nodes/MarkdownNode.tsx +59 -24
- package/src/client/nodes/MdFormatBar.tsx +2 -4
- package/src/client/nodes/inline-editor-commands.ts +17 -6
- package/src/client/nodes/use-surface-frame.ts +3 -1
- package/src/client/state/attention-bridge.ts +3 -0
- package/src/client/state/canvas-store.ts +285 -90
- package/src/client/state/human-store.ts +175 -0
- package/src/client/state/iframe-mode.ts +33 -9
- package/src/client/state/intent-bridge.ts +75 -13
- package/src/client/state/node-factory.ts +2 -8
- package/src/client/state/presence-store.ts +168 -0
- package/src/client/state/session-store.ts +419 -0
- package/src/client/state/sse-bridge.ts +93 -30
- package/src/client/theme/global.css +3071 -796
- package/src/client/types.ts +3 -1
- package/src/client/utils/platform.ts +6 -1
- package/src/mcp/canvas-access.ts +2 -2
- package/src/server/agent-presence.ts +755 -0
- package/src/server/ax-context.ts +45 -0
- package/src/server/ax-gate-ttl.ts +61 -0
- package/src/server/ax-interaction.ts +29 -1
- package/src/server/ax-state-manager.ts +78 -6
- package/src/server/ax-state.ts +82 -15
- package/src/server/ax-wait.ts +33 -0
- package/src/server/canvas-db.ts +103 -33
- package/src/server/canvas-operations.ts +58 -14
- package/src/server/canvas-state.ts +131 -58
- package/src/server/canvas-validation.ts +3 -53
- package/src/server/demo-state.json +2 -70
- package/src/server/html-surface.ts +11 -2
- package/src/server/human-presence.ts +160 -0
- package/src/server/index.ts +111 -6
- package/src/server/intent-registry.ts +13 -0
- package/src/server/mutation-history.ts +47 -2
- package/src/server/operations/composites.ts +6 -3
- package/src/server/operations/http.ts +10 -1
- package/src/server/operations/index.ts +4 -0
- package/src/server/operations/invoker.ts +33 -6
- package/src/server/operations/ops/ax-presence.ts +62 -0
- package/src/server/operations/ops/ax-read.ts +8 -0
- package/src/server/operations/ops/ax-state.ts +106 -1
- package/src/server/operations/ops/ax-timeline.ts +54 -5
- package/src/server/operations/ops/ax-work.ts +46 -0
- package/src/server/operations/ops/batch.ts +3 -1
- package/src/server/operations/ops/edges.ts +88 -2
- package/src/server/operations/ops/groups.ts +4 -3
- package/src/server/operations/ops/human-presence.ts +35 -0
- package/src/server/operations/ops/json-render.ts +11 -1
- package/src/server/operations/ops/nodes.ts +77 -16
- package/src/server/operations/ops/query.ts +1 -0
- package/src/server/operations/ops/snapshots.ts +7 -4
- package/src/server/operations/registry.ts +196 -1
- package/src/server/operations/types.ts +1 -1
- package/src/server/scope-fence.ts +207 -0
- package/src/server/server.ts +177 -79
- package/src/server/trace-manager.ts +0 -2
- package/src/server/web-artifacts.ts +0 -1
- package/src/shared/agent-presence.ts +162 -0
- package/src/shared/approval-gates.ts +35 -0
- package/src/shared/auto-arrange.ts +121 -13
- package/src/shared/ax-kinds.ts +23 -0
- package/src/shared/human-presence.ts +30 -0
- package/src/shared/iframe-probe.ts +8 -0
- package/src/shared/scope-fence.ts +31 -0
- package/dist/types/client/canvas/DockedNode.d.ts +0 -4
- package/src/client/canvas/DockedNode.tsx +0 -165
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import type { AxApprovalStatus, AxEventKind, AxWorkItemStatus } from '../../shared/ax-kinds.js';
|
|
2
|
+
export type WorkItemStatus = AxWorkItemStatus;
|
|
3
|
+
export interface WorkItemView {
|
|
4
|
+
id: string;
|
|
5
|
+
title: string;
|
|
6
|
+
status: WorkItemStatus;
|
|
7
|
+
detail: string | null;
|
|
8
|
+
nodeIds: string[];
|
|
9
|
+
updatedAt: string;
|
|
10
|
+
}
|
|
11
|
+
export interface ApprovalGateView {
|
|
12
|
+
id: string;
|
|
13
|
+
title: string;
|
|
14
|
+
detail: string | null;
|
|
15
|
+
status: AxApprovalStatus;
|
|
16
|
+
nodeIds: string[];
|
|
17
|
+
createdAt: string;
|
|
18
|
+
/** Unattended-approval TTL: when a pending gate auto-holds. */
|
|
19
|
+
expiresAt: string | null;
|
|
20
|
+
}
|
|
21
|
+
export interface AxEventView {
|
|
22
|
+
id: string;
|
|
23
|
+
kind: AxEventKind;
|
|
24
|
+
summary: string;
|
|
25
|
+
detail: string | null;
|
|
26
|
+
createdAt: string;
|
|
27
|
+
/** Who recorded it — host/source label and per-agent identity. */
|
|
28
|
+
source?: string | null;
|
|
29
|
+
agentId?: string | null;
|
|
30
|
+
}
|
|
31
|
+
export interface AxEvidenceView {
|
|
32
|
+
id: string;
|
|
33
|
+
title: string;
|
|
34
|
+
body: string | null;
|
|
35
|
+
createdAt: string;
|
|
36
|
+
source?: string | null;
|
|
37
|
+
agentId?: string | null;
|
|
38
|
+
}
|
|
39
|
+
export interface AxSteeringView {
|
|
40
|
+
id: string;
|
|
41
|
+
message: string;
|
|
42
|
+
createdAt: string;
|
|
43
|
+
/** Consumer label this steer was addressed to; null/absent = broadcast. */
|
|
44
|
+
target?: string | null;
|
|
45
|
+
/** Who sent it — an agent label, or "browser" for the human's composer. */
|
|
46
|
+
source?: string | null;
|
|
47
|
+
/** Per-agent identity within the host — preferred over `source` for the row's sender. */
|
|
48
|
+
agentId?: string | null;
|
|
49
|
+
/** False until the target (or any consumer, for broadcasts) claims + marks it. */
|
|
50
|
+
delivered?: boolean;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Session panel data (rail-chrome-v2 phase 4). Nothing here is a second source
|
|
54
|
+
* of truth: work items and gates come from the AX surface snapshot the SSE
|
|
55
|
+
* bridge already refreshes on `ax-state-changed`; the timeline is the bounded
|
|
56
|
+
* AX timeline read, refreshed on `ax-event-created` while a session is
|
|
57
|
+
* attached. Gate decisions go through the existing resolve route.
|
|
58
|
+
*/
|
|
59
|
+
export interface ScopeFenceView {
|
|
60
|
+
nodeIds: string[];
|
|
61
|
+
padding: number;
|
|
62
|
+
}
|
|
63
|
+
export declare const sessionWorkItems: import("@preact/signals-core").ReadonlySignal<WorkItemView[]>;
|
|
64
|
+
export declare const sessionGates: import("@preact/signals-core").ReadonlySignal<ApprovalGateView[]>;
|
|
65
|
+
export declare const pendingGates: import("@preact/signals-core").ReadonlySignal<ApprovalGateView[]>;
|
|
66
|
+
/** The scope fence the human granted the session (null = unscoped). */
|
|
67
|
+
export declare const scopeFence: import("@preact/signals-core").ReadonlySignal<ScopeFenceView | null>;
|
|
68
|
+
/** Grant or clear the fence: writes outside it are refused server-side; reads stay open. */
|
|
69
|
+
export declare function setScopeFence(nodeIds: string[] | null): Promise<boolean>;
|
|
70
|
+
/** Auto-held gates: the policy said no on the human's behalf; they can be reopened. */
|
|
71
|
+
export declare const heldGates: import("@preact/signals-core").ReadonlySignal<ApprovalGateView[]>;
|
|
72
|
+
export interface AxTimelineView {
|
|
73
|
+
events: AxEventView[];
|
|
74
|
+
evidence: AxEvidenceView[];
|
|
75
|
+
steering: AxSteeringView[];
|
|
76
|
+
}
|
|
77
|
+
export declare const axTimeline: import("@preact/signals-core").Signal<AxTimelineView>;
|
|
78
|
+
export type TimelineEntryKind = AxEventKind | 'evidence' | 'steer' | 'update';
|
|
79
|
+
/** Timeline filter chips: a handful of human categories over the many kinds. */
|
|
80
|
+
export type TimelineFilter = 'all' | 'update' | 'steer' | 'assistant' | 'event' | 'evidence';
|
|
81
|
+
export declare const timelineFilter: import("@preact/signals-core").Signal<TimelineFilter>;
|
|
82
|
+
/** Which chip an entry belongs to: board writes / steering-shaped rows / evidence / the rest. */
|
|
83
|
+
export declare function timelineCategory(kind: TimelineEntryKind): Exclude<TimelineFilter, 'all'>;
|
|
84
|
+
export interface TimelineEntry {
|
|
85
|
+
id: string;
|
|
86
|
+
kind: TimelineEntryKind;
|
|
87
|
+
label: string;
|
|
88
|
+
body: string;
|
|
89
|
+
createdAt: string;
|
|
90
|
+
/** Writer key for the row (agentId, else non-transport source; 'browser' = the human).
|
|
91
|
+
* With several assistants on one board, a row without this is unanswerable:
|
|
92
|
+
* "Assistant · 23:11" from WHOM? Null when only a bare transport is known. */
|
|
93
|
+
who?: string | null;
|
|
94
|
+
/** Item 10: this agent edit is the top of the shared undo stack — "↩ undo this edit". */
|
|
95
|
+
undoable?: boolean;
|
|
96
|
+
}
|
|
97
|
+
/** The row's writer key: per-agent identity first, else a non-transport source. */
|
|
98
|
+
export declare function writerKeyFor(agentId?: string | null, source?: string | null): string | null;
|
|
99
|
+
/** The entry Ctrl+Z would undo next, from GET /api/canvas/history. */
|
|
100
|
+
export declare const historyTop: import("@preact/signals-core").Signal<{
|
|
101
|
+
id: string;
|
|
102
|
+
actor: "human" | "agent";
|
|
103
|
+
description: string;
|
|
104
|
+
} | null>;
|
|
105
|
+
/** Agent edits undone from the panel this page-life — rendered "undone · steering sent". */
|
|
106
|
+
export declare const undoneActivityIds: import("@preact/signals-core").Signal<Set<string>>;
|
|
107
|
+
/**
|
|
108
|
+
* One reverse-chronological feed out of the three timeline tables plus the
|
|
109
|
+
* agent's board writes (the presence activity feed), so the panel shows what
|
|
110
|
+
* the agent DID between its tool runs and gates. The newest agent write gets
|
|
111
|
+
* the undo affordance when it is also the top of the shared undo stack.
|
|
112
|
+
*/
|
|
113
|
+
export declare function mergeTimeline(timeline: AxTimelineView, limit?: number, writes?: Array<{
|
|
114
|
+
id: string;
|
|
115
|
+
at: string;
|
|
116
|
+
op: string;
|
|
117
|
+
summary: string;
|
|
118
|
+
sessionId?: string;
|
|
119
|
+
label?: string;
|
|
120
|
+
}>, top?: {
|
|
121
|
+
actor: 'human' | 'agent';
|
|
122
|
+
} | null, filter?: TimelineFilter): TimelineEntry[];
|
|
123
|
+
export declare const timelineEntries: import("@preact/signals-core").ReadonlySignal<TimelineEntry[]>;
|
|
124
|
+
export declare function refreshTimeline(): Promise<void>;
|
|
125
|
+
/**
|
|
126
|
+
* Undo the agent's latest edit through the ONE shared undo stack (the same
|
|
127
|
+
* POST /api/canvas/undo Ctrl+Z uses), then tell the agent: steering feedback
|
|
128
|
+
* goes out through the same path a veto takes.
|
|
129
|
+
*/
|
|
130
|
+
export declare function undoAgentEdit(entry: TimelineEntry): Promise<boolean>;
|
|
131
|
+
/** Ctrl+Z / Ctrl+Shift+Z: whichever op is top of the shared stack, agent or human. */
|
|
132
|
+
export declare function undoFromKeyboard(redo?: boolean): Promise<boolean>;
|
|
133
|
+
/**
|
|
134
|
+
* Resolve a gate through the existing AX path. A rejection also posts steering
|
|
135
|
+
* feedback so the agent learns WHY its next turn — the same `vetoGhostSteering`
|
|
136
|
+
* contract ghost vetoes use.
|
|
137
|
+
*/
|
|
138
|
+
export declare function resolveGate(gate: ApprovalGateView, decision: 'approved' | 'rejected'): Promise<boolean>;
|
|
139
|
+
/** Reopen an auto-held gate so it can be answered (fresh TTL). */
|
|
140
|
+
export declare function reopenGate(gate: ApprovalGateView): Promise<boolean>;
|
|
141
|
+
/** Post a steering message the agent reads on its next turn. */
|
|
142
|
+
export declare function sendSteering(message: string, target?: string | null): Promise<boolean>;
|
|
143
|
+
/** Attach a human-started session; the agent's writes are attributed to it. */
|
|
144
|
+
export declare function startSession(): Promise<boolean>;
|
|
145
|
+
/** End the attached session (whoever attached it) — the server answers with a receipt. */
|
|
146
|
+
export declare function endSession(session: {
|
|
147
|
+
source: string;
|
|
148
|
+
agentId: string | null;
|
|
149
|
+
}): Promise<boolean>;
|
|
150
|
+
export interface SessionReceipt {
|
|
151
|
+
label: string;
|
|
152
|
+
endedAt: string;
|
|
153
|
+
/** Why it ended — the receipt should answer this, not leave the human asking. */
|
|
154
|
+
endedBy?: 'human' | 'agent' | 'idle-timeout';
|
|
155
|
+
/** The session changed nothing on the board (its pre-session snapshot was dropped). */
|
|
156
|
+
unchanged?: boolean;
|
|
157
|
+
/** Cancelled (withdrawn items), rejected (human's explicit no on a gate), and
|
|
158
|
+
* held (TTL expired unanswered) are three different outcomes — never one
|
|
159
|
+
* "vetoed" pile. */
|
|
160
|
+
counts: {
|
|
161
|
+
items: number;
|
|
162
|
+
done: number;
|
|
163
|
+
cancelled: number;
|
|
164
|
+
rejected: number;
|
|
165
|
+
held: number;
|
|
166
|
+
};
|
|
167
|
+
snapshot: {
|
|
168
|
+
id: string;
|
|
169
|
+
name: string;
|
|
170
|
+
} | null;
|
|
171
|
+
}
|
|
172
|
+
/** The last ended session's receipt (design item 2); client-side, cleared on dismiss. */
|
|
173
|
+
export declare const sessionReceipt: import("@preact/signals-core").Signal<SessionReceipt | null>;
|
|
174
|
+
export declare function applySessionReceipt(data: Record<string, unknown>): void;
|
|
175
|
+
export declare function dismissSessionReceipt(): void;
|
|
176
|
+
export declare function resetSessionStore(): void;
|
|
@@ -18,7 +18,6 @@ export interface CanvasNodeState {
|
|
|
18
18
|
zIndex: number;
|
|
19
19
|
collapsed: boolean;
|
|
20
20
|
pinned: boolean;
|
|
21
|
-
dockPosition: 'left' | 'right' | null;
|
|
22
21
|
data: Record<string, unknown>;
|
|
23
22
|
}
|
|
24
23
|
export interface CanvasEdge {
|
|
@@ -50,6 +49,8 @@ export interface CanvasAnnotation {
|
|
|
50
49
|
label?: string;
|
|
51
50
|
createdAt: string;
|
|
52
51
|
}
|
|
52
|
+
/** The rail's annotate modes; null = not annotating. */
|
|
53
|
+
export type AnnotationTool = 'pen' | 'eraser' | 'text' | null;
|
|
53
54
|
export type ConnectionStatus = 'connecting' | 'connected' | 'disconnected';
|
|
54
55
|
export declare const TYPE_LABELS: Record<CanvasNodeState['type'], string>;
|
|
55
56
|
/** Node types that support the full-viewport expand/focus overlay. */
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent presence registry (rail-chrome-v2 phase 2).
|
|
3
|
+
*
|
|
4
|
+
* Lives beside IntentRegistry and follows its discipline: in-memory, TTL-swept,
|
|
5
|
+
* count-capped, and emitting through an injected workbench emitter so this
|
|
6
|
+
* module never imports server.ts. One `agent-presence` SSE frame carries the
|
|
7
|
+
* full snapshot on every change, so a reconnecting client is never stale and
|
|
8
|
+
* never needs its own expiry ticker.
|
|
9
|
+
*
|
|
10
|
+
* Presence is derived, not declared: agent-originated mutations (anything
|
|
11
|
+
* `executeOperation` runs without the workbench marker) and AX activity
|
|
12
|
+
* ingests (`tool-start`, `session-start`, …) touch a writer; adapters with
|
|
13
|
+
* richer hooks may `set` a phase, cursor, or focus explicitly.
|
|
14
|
+
*/
|
|
15
|
+
import { z } from 'zod';
|
|
16
|
+
import { type AgentPhase, type AgentPresence, type AgentPresenceSnapshot, type ContextBudget } from '../shared/agent-presence.js';
|
|
17
|
+
import type { PmxAxActivityKind } from './ax-state.js';
|
|
18
|
+
type PresenceEmitter = (event: string, payload: Record<string, unknown>) => void;
|
|
19
|
+
/** A legal writer label: short, alphanumeric/dash, letter-first (header and env values). */
|
|
20
|
+
export declare const SOURCE_LABEL_RE: RegExp;
|
|
21
|
+
export interface PresenceTouch {
|
|
22
|
+
source: string;
|
|
23
|
+
agentId?: string | null;
|
|
24
|
+
label?: string;
|
|
25
|
+
phase?: AgentPhase;
|
|
26
|
+
detail?: string | null;
|
|
27
|
+
focusNodeId?: string | null;
|
|
28
|
+
parentAgentId?: string | null;
|
|
29
|
+
/** Op-derived tooling: overlay the phase without clobbering the explicit one. */
|
|
30
|
+
derivedTooling?: boolean;
|
|
31
|
+
cursor?: {
|
|
32
|
+
x: number;
|
|
33
|
+
y: number;
|
|
34
|
+
} | null;
|
|
35
|
+
attached?: boolean;
|
|
36
|
+
/** With `attached: false`: who ended it (receipt transparency). Default 'agent'. */
|
|
37
|
+
endedBy?: 'human' | 'agent';
|
|
38
|
+
/** The host's real token usage for this agent, if it knows it. */
|
|
39
|
+
contextUsage?: {
|
|
40
|
+
used: number;
|
|
41
|
+
total: number;
|
|
42
|
+
} | null;
|
|
43
|
+
/** Count this touch as an agent write. */
|
|
44
|
+
op?: boolean;
|
|
45
|
+
/** What the write did, for the activity feed (only meaningful with `op`). */
|
|
46
|
+
activity?: {
|
|
47
|
+
op: string;
|
|
48
|
+
summary: string;
|
|
49
|
+
nodeId: string | null;
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* One sentence for the activity feed, from the op name plus whatever the
|
|
54
|
+
* input/result name. Titles are read AFTER the op ran, so creates and updates
|
|
55
|
+
* resolve; removes describe what is gone by id.
|
|
56
|
+
*/
|
|
57
|
+
export declare function describeWrite(op: string, rawInput: unknown, result: unknown): {
|
|
58
|
+
summary: string;
|
|
59
|
+
nodeId: string | null;
|
|
60
|
+
};
|
|
61
|
+
/**
|
|
62
|
+
* The one validation schema for an explicit presence update. The HTTP/MCP op
|
|
63
|
+
* spreads these fields into its tool shape so the two cannot drift.
|
|
64
|
+
*
|
|
65
|
+
* Identity note: presence is a UX signal, not an authenticated identity — any
|
|
66
|
+
* local process can assert any `source`/`agentId` (the single-workspace trust
|
|
67
|
+
* model). It shows the human WHO claims to be working; it grants no write
|
|
68
|
+
* capability that the caller did not already have.
|
|
69
|
+
*/
|
|
70
|
+
export declare const PRESENCE_SET_SHAPE: {
|
|
71
|
+
source: z.ZodOptional<z.ZodString>;
|
|
72
|
+
agentId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
73
|
+
label: z.ZodOptional<z.ZodString>;
|
|
74
|
+
phase: z.ZodOptional<z.ZodEnum<{
|
|
75
|
+
idle: "idle";
|
|
76
|
+
thinking: "thinking";
|
|
77
|
+
tooling: "tooling";
|
|
78
|
+
"waiting-approval": "waiting-approval";
|
|
79
|
+
}>>;
|
|
80
|
+
detail: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
81
|
+
focusNodeId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
82
|
+
cursor: z.ZodOptional<z.ZodNullable<z.ZodObject<{
|
|
83
|
+
x: z.ZodNumber;
|
|
84
|
+
y: z.ZodNumber;
|
|
85
|
+
}, z.core.$strip>>>;
|
|
86
|
+
attached: z.ZodOptional<z.ZodBoolean>;
|
|
87
|
+
parentAgentId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
88
|
+
endedBy: z.ZodOptional<z.ZodEnum<{
|
|
89
|
+
agent: "agent";
|
|
90
|
+
human: "human";
|
|
91
|
+
}>>;
|
|
92
|
+
contextUsage: z.ZodOptional<z.ZodNullable<z.ZodObject<{
|
|
93
|
+
used: z.ZodNumber;
|
|
94
|
+
total: z.ZodNumber;
|
|
95
|
+
}, z.core.$strip>>>;
|
|
96
|
+
};
|
|
97
|
+
/** Token estimate of the pinned-context payload — the same serialization the MCP resource ships. */
|
|
98
|
+
export declare function estimateContextBudget(): ContextBudget;
|
|
99
|
+
/** Returns the id of the pre-session snapshot the server took, if any. */
|
|
100
|
+
type SessionStartListener = (presence: AgentPresence) => string | null;
|
|
101
|
+
export type SessionEndReason = 'human' | 'agent' | 'idle-timeout';
|
|
102
|
+
type SessionEndListener = (presence: AgentPresence, startSnapshotId: string | null, endedBy: SessionEndReason) => void;
|
|
103
|
+
export declare class AgentPresenceRegistry {
|
|
104
|
+
private readonly presences;
|
|
105
|
+
/** Newest first; bounded. Survives a writer fading — the feed is history, the writer list is presence. */
|
|
106
|
+
private activity;
|
|
107
|
+
private activitySeq;
|
|
108
|
+
private emit;
|
|
109
|
+
/** Single slots (like the emitter): server.ts owns the pre-session snapshot + receipt. */
|
|
110
|
+
private onSessionStart;
|
|
111
|
+
private onSessionEnd;
|
|
112
|
+
private sweepTimer;
|
|
113
|
+
private emitTimer;
|
|
114
|
+
/** Inject the workbench SSE emitter (server.ts wires this at module load). */
|
|
115
|
+
setEmitter(emitter: PresenceEmitter | null): void;
|
|
116
|
+
/**
|
|
117
|
+
* Fires when a session attaches (false → true). The listener may snapshot the
|
|
118
|
+
* board and return the snapshot id; the receipt at session end diffs against it.
|
|
119
|
+
*/
|
|
120
|
+
setSessionStartListener(listener: SessionStartListener | null): void;
|
|
121
|
+
/**
|
|
122
|
+
* Fires once when an ATTACHED session ends — by `session-end`, by an explicit
|
|
123
|
+
* `attached: false`, or by the idle-TTL sweep — with the presence as it was
|
|
124
|
+
* and the pre-session snapshot id. Unattached writers fading away never fire it.
|
|
125
|
+
*/
|
|
126
|
+
setSessionEndListener(listener: SessionEndListener | null): void;
|
|
127
|
+
/**
|
|
128
|
+
* Attribute an agent-less write to the one attached session, so the
|
|
129
|
+
* session's cursor and phase follow its own work no matter which transport
|
|
130
|
+
* carried it. An agent-started session absorbs transport labels only
|
|
131
|
+
* (api/mcp/sdk/cli); a human-started one (`browser`, *Start agent session*)
|
|
132
|
+
* is a placeholder for whichever agent comes next and absorbs any label.
|
|
133
|
+
* Ambiguous (several sessions) or identified (agentId) writes, and a writer
|
|
134
|
+
* that is itself attached, keep their own key.
|
|
135
|
+
*/
|
|
136
|
+
private attributedKey;
|
|
137
|
+
/**
|
|
138
|
+
* Fold an unattached writer into a session: its ops and feed entries were
|
|
139
|
+
* the session's work all along. A human-started session still carrying its
|
|
140
|
+
* placeholder label takes the writer's name.
|
|
141
|
+
*/
|
|
142
|
+
private fold;
|
|
143
|
+
/** Aliased channels: a key that attach-merged into another session (extension + its MCP server). */
|
|
144
|
+
private aliases;
|
|
145
|
+
/** Consumer keys that have claimed steering deliveries this server-run → last claim time. */
|
|
146
|
+
private steeringConsumers;
|
|
147
|
+
/** A delivery claim proves this consumer polls steering — its presence turns
|
|
148
|
+
* steerable, and the claim time is the roster's proof-of-polling freshness. */
|
|
149
|
+
noteSteeringConsumer(consumer: string): void;
|
|
150
|
+
/** Drop aliases that point at a session that no longer exists. */
|
|
151
|
+
private dropAliasesTo;
|
|
152
|
+
/** Touch a writer: upsert, bump lastSeen, apply the patch. Derived `tooling` decays on its own. */
|
|
153
|
+
touch(input: PresenceTouch, now?: number): AgentPresence;
|
|
154
|
+
/**
|
|
155
|
+
* A host reported the agent's real context window without naming the
|
|
156
|
+
* writer (the legacy `context-usage` workbench event): it belongs to the
|
|
157
|
+
* single attached session, if there is exactly one. Returns false otherwise.
|
|
158
|
+
*/
|
|
159
|
+
reportContextUsage(usage: {
|
|
160
|
+
used: number;
|
|
161
|
+
total: number;
|
|
162
|
+
}): boolean;
|
|
163
|
+
/** Explicit update from an adapter / MCP client (validated). */
|
|
164
|
+
set(raw: unknown, fallbackSource: string): AgentPresence;
|
|
165
|
+
/** Map an AX activity ingest onto presence — the feed that already exists. */
|
|
166
|
+
observeActivity(kind: PmxAxActivityKind, input: {
|
|
167
|
+
source: string;
|
|
168
|
+
agentId?: string | null;
|
|
169
|
+
title: string;
|
|
170
|
+
}, now?: number): void;
|
|
171
|
+
/**
|
|
172
|
+
* Re-emit the snapshot after something the phase is DERIVED from changed
|
|
173
|
+
* (a gate opened or resolved) without any writer being touched.
|
|
174
|
+
*/
|
|
175
|
+
refresh(): void;
|
|
176
|
+
/** Remove a writer (session-end). */
|
|
177
|
+
detach(sessionId: string): boolean;
|
|
178
|
+
snapshot(now?: number): AgentPresenceSnapshot;
|
|
179
|
+
/** Test / shutdown hook. */
|
|
180
|
+
reset(): void;
|
|
181
|
+
private publicView;
|
|
182
|
+
private hasPendingGate;
|
|
183
|
+
private evictOverflow;
|
|
184
|
+
private sweep;
|
|
185
|
+
/** Coalesce bursts (batch churn) into one frame per tick. */
|
|
186
|
+
private scheduleEmit;
|
|
187
|
+
private ensureSweeper;
|
|
188
|
+
private maybeStopSweeper;
|
|
189
|
+
}
|
|
190
|
+
/** Process-wide singleton, shared across HTTP handlers, MCP ops, and the SDK. */
|
|
191
|
+
export declare const agentPresence: AgentPresenceRegistry;
|
|
192
|
+
export {};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
type GateEmitter = (event: string, payload: Record<string, unknown>) => void;
|
|
2
|
+
/** Hold every pending gate whose TTL has elapsed. Returns the gates it held. */
|
|
3
|
+
export declare function sweepExpiredGates(now?: number): string[];
|
|
4
|
+
export declare function startGateTtlSweeper(emitter: GateEmitter): void;
|
|
5
|
+
export declare function stopGateTtlSweeper(): void;
|
|
6
|
+
export {};
|
|
@@ -47,15 +47,15 @@ export declare function normalizeNodeAxCapabilities(value: unknown): Partial<Nod
|
|
|
47
47
|
export declare function resolveNodeAxCapabilities(node: CanvasNodeState): NodeAxCapabilities;
|
|
48
48
|
declare const InteractionEnvelopeSchema: z.ZodObject<{
|
|
49
49
|
type: z.ZodEnum<{
|
|
50
|
-
"ax.event.record": "ax.event.record";
|
|
51
|
-
"ax.steer": "ax.steer";
|
|
52
50
|
"ax.work.create": "ax.work.create";
|
|
53
51
|
"ax.work.update": "ax.work.update";
|
|
54
|
-
"ax.evidence.add": "ax.evidence.add";
|
|
55
52
|
"ax.approval.request": "ax.approval.request";
|
|
56
53
|
"ax.approval.resolve": "ax.approval.resolve";
|
|
57
|
-
"ax.
|
|
54
|
+
"ax.evidence.add": "ax.evidence.add";
|
|
55
|
+
"ax.event.record": "ax.event.record";
|
|
56
|
+
"ax.steer": "ax.steer";
|
|
58
57
|
"ax.focus.set": "ax.focus.set";
|
|
58
|
+
"ax.review.add": "ax.review.add";
|
|
59
59
|
"ax.command.invoke": "ax.command.invoke";
|
|
60
60
|
"ax.elicitation.request": "ax.elicitation.request";
|
|
61
61
|
"ax.mode.request": "ax.mode.request";
|
|
@@ -219,11 +219,5 @@ export interface AxFlowMaterializeInput {
|
|
|
219
219
|
maxRuns?: number;
|
|
220
220
|
};
|
|
221
221
|
}
|
|
222
|
-
/**
|
|
223
|
-
* Validate + execute a node-originated AX interaction. Returns the public result
|
|
224
|
-
* plus the SSE events the caller should emit (accepted/rejected outcome + the
|
|
225
|
-
* underlying AX state event). Never throws on bad input — returns an `ok: false`
|
|
226
|
-
* result with an appropriate HTTP-ish status.
|
|
227
|
-
*/
|
|
228
222
|
export declare function applyAxInteraction(manager: AxInteractionManager, rawBody: unknown, source: PmxAxSource): AxInteractionResult;
|
|
229
223
|
export {};
|
|
@@ -96,13 +96,22 @@ export declare class AxStateManager {
|
|
|
96
96
|
detail?: string | null;
|
|
97
97
|
action?: string | null;
|
|
98
98
|
nodeIds?: string[];
|
|
99
|
+
ttlMs?: number;
|
|
99
100
|
}, options?: {
|
|
100
101
|
source?: PmxAxSource;
|
|
101
102
|
}): PmxAxApprovalGate;
|
|
102
|
-
resolveApproval(id: string, decision: 'approved' | 'rejected', options?: {
|
|
103
|
+
resolveApproval(id: string, decision: 'approved' | 'rejected' | 'held', options?: {
|
|
103
104
|
resolution?: string;
|
|
104
105
|
source?: PmxAxSource;
|
|
105
106
|
}): PmxAxApprovalGate | null;
|
|
107
|
+
/**
|
|
108
|
+
* Reopen a resolved gate (typically one the unattended-approval policy
|
|
109
|
+
* auto-held): back to pending with a fresh TTL, so the human can answer it.
|
|
110
|
+
*/
|
|
111
|
+
reopenApproval(id: string, options?: {
|
|
112
|
+
ttlMs?: number;
|
|
113
|
+
source?: PmxAxSource;
|
|
114
|
+
}): PmxAxApprovalGate | null;
|
|
106
115
|
getReviewAnnotations(): PmxAxReviewAnnotation[];
|
|
107
116
|
addReviewAnnotation(input: {
|
|
108
117
|
body: string;
|
|
@@ -161,6 +170,16 @@ export declare class AxStateManager {
|
|
|
161
170
|
setPolicy(patch: {
|
|
162
171
|
tools?: Partial<PmxAxPolicy['tools']>;
|
|
163
172
|
prompt?: Partial<PmxAxPolicy['prompt']>;
|
|
173
|
+
/** Replace semantics: an object sets the fence, `null` clears it, absent leaves it. */
|
|
174
|
+
scope?: {
|
|
175
|
+
nodeIds: string[];
|
|
176
|
+
padding?: number;
|
|
177
|
+
} | null;
|
|
178
|
+
/** Per-key merge: an object sets that agent's territory, `null` clears it, absent keys keep theirs. */
|
|
179
|
+
agentScopes?: Record<string, {
|
|
180
|
+
nodeIds: string[];
|
|
181
|
+
padding?: number;
|
|
182
|
+
} | null>;
|
|
164
183
|
}, _options?: {
|
|
165
184
|
source?: PmxAxSource;
|
|
166
185
|
}): PmxAxPolicy;
|
|
@@ -192,7 +211,7 @@ export declare class AxStateManager {
|
|
|
192
211
|
agentId?: string | null;
|
|
193
212
|
target?: string | null;
|
|
194
213
|
}): PmxAxSteeringMessage;
|
|
195
|
-
markSteeringDelivered(id: string): boolean;
|
|
214
|
+
markSteeringDelivered(id: string, consumer?: string | null): boolean;
|
|
196
215
|
/**
|
|
197
216
|
* Ingest a normalized agent activity (a tool/session event a harness forwards)
|
|
198
217
|
* and apply kind-driven board reactions, so the agent's real work flows back into
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { CanvasLayout, CanvasNodeState } from './canvas-state.js';
|
|
2
|
+
import type { AxApprovalStatus, AxEventKind, AxWorkItemStatus } from '../shared/ax-kinds.js';
|
|
2
3
|
import type { AgentContextNode } from './agent-context.js';
|
|
3
4
|
export type PmxAxSource = 'agent' | 'amp' | 'api' | 'browser' | 'cli' | 'codex' | 'copilot' | 'mcp' | 'sdk' | 'system';
|
|
4
5
|
export interface PmxAxFocusState {
|
|
@@ -7,10 +8,10 @@ export interface PmxAxFocusState {
|
|
|
7
8
|
updatedAt: string | null;
|
|
8
9
|
source: PmxAxSource | null;
|
|
9
10
|
}
|
|
10
|
-
export type PmxAxEventKind =
|
|
11
|
+
export type PmxAxEventKind = AxEventKind;
|
|
11
12
|
export type PmxAxEvidenceKind = 'logs' | 'tool-result' | 'screenshot' | 'file' | 'diff' | 'test-output';
|
|
12
|
-
export type PmxAxWorkItemStatus =
|
|
13
|
-
export type PmxAxApprovalStatus =
|
|
13
|
+
export type PmxAxWorkItemStatus = AxWorkItemStatus;
|
|
14
|
+
export type PmxAxApprovalStatus = AxApprovalStatus;
|
|
14
15
|
export type PmxAxReviewKind = 'comment' | 'finding';
|
|
15
16
|
export type PmxAxReviewSeverity = 'info' | 'warning' | 'error';
|
|
16
17
|
export type PmxAxReviewStatus = 'open' | 'resolved' | 'dismissed';
|
|
@@ -34,6 +35,8 @@ export interface PmxAxApprovalGate {
|
|
|
34
35
|
status: PmxAxApprovalStatus;
|
|
35
36
|
nodeIds: string[];
|
|
36
37
|
createdAt: string;
|
|
38
|
+
/** When a still-pending gate auto-holds (unattended-approval policy). */
|
|
39
|
+
expiresAt: string | null;
|
|
37
40
|
resolvedAt: string | null;
|
|
38
41
|
resolution: string | null;
|
|
39
42
|
source: PmxAxSource | null;
|
|
@@ -87,6 +90,8 @@ export interface PmxAxSteeringMessage {
|
|
|
87
90
|
seq: number;
|
|
88
91
|
message: string;
|
|
89
92
|
delivered: boolean;
|
|
93
|
+
/** Broadcast pickups: which consumers marked this steer (per-consumer delivery). */
|
|
94
|
+
deliveredTo?: string[];
|
|
90
95
|
createdAt: string;
|
|
91
96
|
source: PmxAxSource | null;
|
|
92
97
|
agentId: string | null;
|
|
@@ -154,6 +159,22 @@ export interface PmxAxDeliveryContext {
|
|
|
154
159
|
omittedPending: number;
|
|
155
160
|
pendingActivity: PendingAxActivityItem[];
|
|
156
161
|
}
|
|
162
|
+
/** Human ink on the board — freehand strokes and text notes, anchored to the nodes they overlap. */
|
|
163
|
+
export interface PmxAxHumanAnnotation {
|
|
164
|
+
id: string;
|
|
165
|
+
type: string;
|
|
166
|
+
/** The human's words, when this is a text note (or a labelled stroke). */
|
|
167
|
+
text: string | null;
|
|
168
|
+
/** Nodes whose padded frame the annotation overlaps — what it is "on". */
|
|
169
|
+
onNodes: Array<{
|
|
170
|
+
id: string;
|
|
171
|
+
title: string | null;
|
|
172
|
+
}>;
|
|
173
|
+
center: {
|
|
174
|
+
x: number;
|
|
175
|
+
y: number;
|
|
176
|
+
};
|
|
177
|
+
}
|
|
157
178
|
export interface PmxAxContext {
|
|
158
179
|
version: 1;
|
|
159
180
|
generatedAt: string;
|
|
@@ -167,6 +188,8 @@ export interface PmxAxContext {
|
|
|
167
188
|
workItems: PmxAxWorkItem[];
|
|
168
189
|
approvalGates: PmxAxApprovalGate[];
|
|
169
190
|
reviewAnnotations: PmxAxReviewAnnotation[];
|
|
191
|
+
/** What the human drew/wrote on the board (the annotate tool) — not agent review comments. */
|
|
192
|
+
humanAnnotations: PmxAxHumanAnnotation[];
|
|
170
193
|
elicitations: PmxAxElicitation[];
|
|
171
194
|
modeRequests: PmxAxModeRequest[];
|
|
172
195
|
policy: PmxAxPolicy;
|
|
@@ -194,6 +217,16 @@ export interface PmxAxCommandDescriptor {
|
|
|
194
217
|
export declare const AX_COMMAND_REGISTRY: Record<string, PmxAxCommandDescriptor>;
|
|
195
218
|
export declare function isAxCommand(name: unknown): name is string;
|
|
196
219
|
export declare function listAxCommands(): PmxAxCommandDescriptor[];
|
|
220
|
+
/**
|
|
221
|
+
* Scope fence (rail-chrome-v2 design item 4): the region an attached agent
|
|
222
|
+
* may WRITE to — the fenced node set plus `padding` px around its bounding
|
|
223
|
+
* box for new nodes. Reads are never fenced. `null` = unscoped.
|
|
224
|
+
*/
|
|
225
|
+
export interface PmxAxScopeFence {
|
|
226
|
+
nodeIds: string[];
|
|
227
|
+
padding: number;
|
|
228
|
+
}
|
|
229
|
+
export declare const DEFAULT_SCOPE_FENCE_PADDING = 40;
|
|
197
230
|
export interface PmxAxPolicy {
|
|
198
231
|
tools: {
|
|
199
232
|
allowed: string[];
|
|
@@ -204,9 +237,18 @@ export interface PmxAxPolicy {
|
|
|
204
237
|
systemAppend: string | null;
|
|
205
238
|
mode: string | null;
|
|
206
239
|
};
|
|
240
|
+
scope: PmxAxScopeFence | null;
|
|
241
|
+
/**
|
|
242
|
+
* Per-agent territories (fleet orchestration): writer key (agentId when the
|
|
243
|
+
* write carries one, else its source label) → fence. Overrides `scope` for
|
|
244
|
+
* that writer; agents without an entry fall under the global fence.
|
|
245
|
+
*/
|
|
246
|
+
agentScopes: Record<string, PmxAxScopeFence>;
|
|
207
247
|
}
|
|
208
248
|
export declare function createEmptyAxPolicy(): PmxAxPolicy;
|
|
249
|
+
export declare function normalizeAxScopeFence(input: unknown): PmxAxScopeFence | null;
|
|
209
250
|
export declare function normalizeAxPolicy(input: unknown): PmxAxPolicy;
|
|
251
|
+
export declare function normalizeAxAgentScopes(input: unknown): Record<string, PmxAxScopeFence>;
|
|
210
252
|
export declare function isAxEventKind(value: unknown): value is PmxAxEventKind;
|
|
211
253
|
export declare function isAxEvidenceKind(value: unknown): value is PmxAxEvidenceKind;
|
|
212
254
|
export declare function createEmptyAxFocusState(): PmxAxFocusState;
|
|
@@ -269,7 +311,10 @@ export declare function createAxApprovalGate(input: {
|
|
|
269
311
|
detail?: string | null;
|
|
270
312
|
action?: string | null;
|
|
271
313
|
nodeIds?: string[];
|
|
314
|
+
ttlMs?: number;
|
|
272
315
|
}, source: PmxAxSource | null, validNodeIds?: Set<string>): PmxAxApprovalGate;
|
|
316
|
+
/** Server default for a gate's TTL: `PMX_CANVAS_GATE_TTL_MS`, else five minutes. */
|
|
317
|
+
export declare function defaultGateTtlMs(): number;
|
|
273
318
|
export declare function createAxReviewAnnotation(input: {
|
|
274
319
|
body: string;
|
|
275
320
|
kind?: PmxAxReviewKind;
|
|
@@ -306,6 +351,7 @@ export declare function buildAxContext(input: {
|
|
|
306
351
|
workItems: PmxAxWorkItem[];
|
|
307
352
|
approvalGates: PmxAxApprovalGate[];
|
|
308
353
|
reviewAnnotations: PmxAxReviewAnnotation[];
|
|
354
|
+
humanAnnotations: PmxAxHumanAnnotation[];
|
|
309
355
|
elicitations: PmxAxElicitation[];
|
|
310
356
|
modeRequests: PmxAxModeRequest[];
|
|
311
357
|
policy: PmxAxPolicy;
|
|
@@ -21,3 +21,16 @@ export declare function waitForAxResolution<T extends {
|
|
|
21
21
|
timeoutMs: number;
|
|
22
22
|
signal?: AbortSignal;
|
|
23
23
|
}): Promise<AxWaitResult<T>>;
|
|
24
|
+
/**
|
|
25
|
+
* Block until `ready()` turns true after a change on `channel` (default
|
|
26
|
+
* 'ax-timeline'), or the timeout elapses. The steering long-poll: the gate
|
|
27
|
+
* waiter above is item/status-shaped; this one waits on a plain condition —
|
|
28
|
+
* the reactive loop for agent hosts that cannot be woken from outside (their
|
|
29
|
+
* model only runs while their host gives it a turn, so one call parks here
|
|
30
|
+
* instead of burning that turn on tight polling).
|
|
31
|
+
*/
|
|
32
|
+
export declare function waitForAxCondition(opts: {
|
|
33
|
+
ready: () => boolean;
|
|
34
|
+
timeoutMs: number;
|
|
35
|
+
channel?: string;
|
|
36
|
+
}): Promise<void>;
|
|
@@ -47,6 +47,7 @@ export declare function loadSnapshotFromDB(db: Database, idOrName: string): {
|
|
|
47
47
|
state: PersistedCanvasState;
|
|
48
48
|
} | null;
|
|
49
49
|
export declare function listSnapshotsFromDB(db: Database, options?: CanvasSnapshotListOptions): CanvasSnapshot[];
|
|
50
|
+
export declare function renameSnapshotInDB(db: Database, id: string, name: string): boolean;
|
|
50
51
|
export declare function deleteSnapshotFromDB(db: Database, id: string): boolean;
|
|
51
52
|
export declare function writeBlobToDB(db: Database, sha256: string, jsonValue: string): number;
|
|
52
53
|
export declare function readBlobFromDB(db: Database, sha256: string): string | null;
|
|
@@ -57,9 +58,16 @@ export interface AxTimelineQuery {
|
|
|
57
58
|
export declare function appendAxEventToDB(db: Database, ev: Omit<PmxAxEvent, 'seq'>): PmxAxEvent;
|
|
58
59
|
export declare function appendAxEvidenceToDB(db: Database, ev: Omit<PmxAxEvidence, 'seq'>): PmxAxEvidence;
|
|
59
60
|
export declare function appendAxSteeringToDB(db: Database, s: Omit<PmxAxSteeringMessage, 'seq'>): PmxAxSteeringMessage;
|
|
60
|
-
export declare function markAxSteeringDeliveredInDB(db: Database, id: string): boolean;
|
|
61
|
+
export declare function markAxSteeringDeliveredInDB(db: Database, id: string, consumer?: string | null): boolean;
|
|
61
62
|
export declare function loadAxEventsFromDB(db: Database, q?: AxTimelineQuery): PmxAxEvent[];
|
|
62
63
|
export declare function loadAxEvidenceFromDB(db: Database, q?: AxTimelineQuery): PmxAxEvidence[];
|
|
64
|
+
/**
|
|
65
|
+
* Broadcasts age out of PENDING (they stay on the timeline): per-consumer
|
|
66
|
+
* delivery otherwise means every broadcast greets every FUTURE consumer key
|
|
67
|
+
* forever — a brand-new pump inherited two-day-old "all workers" calls.
|
|
68
|
+
* Addressed steers never expire here; they wait for their named consumer.
|
|
69
|
+
*/
|
|
70
|
+
export declare const BROADCAST_PENDING_TTL_MS: number;
|
|
63
71
|
export declare function loadAxSteeringFromDB(db: Database, q?: AxTimelineQuery & {
|
|
64
72
|
onlyPending?: boolean;
|
|
65
73
|
}): PmxAxSteeringMessage[];
|