@nudge-ui/mcp 0.1.3 → 0.2.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/README.md +72 -50
- package/dist/bridge.d.ts +9 -7
- package/dist/bridge.js +237 -15
- package/dist/cli.d.ts +2 -1
- package/dist/cli.js +67 -13
- package/dist/cli.mjs +14750 -13958
- package/dist/discovery.d.ts +29 -0
- package/dist/discovery.js +112 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.js +3 -1
- package/dist/internal/agent-protocol.d.ts +296 -0
- package/dist/internal/agent-protocol.js +417 -0
- package/dist/project.d.ts +54 -0
- package/dist/project.js +151 -0
- package/dist/projectSessionClient.d.ts +28 -0
- package/dist/projectSessionClient.js +93 -0
- package/dist/protocol.d.ts +16 -5
- package/dist/protocol.js +15 -4
- package/dist/server.d.ts +16 -2
- package/dist/server.js +102 -23
- package/dist/sessionRegistry.d.ts +8 -0
- package/dist/sessionRegistry.js +89 -0
- package/dist/sessionSelection.d.ts +15 -0
- package/dist/sessionSelection.js +41 -0
- package/package.json +10 -5
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { AgentPromptRequest, AgentStatusSnapshot, AgentStatusUpdate, CanvasCommandResult } from "./internal/agent-protocol.js";
|
|
2
|
+
import type { CanvasCommandInput } from "./bridge.js";
|
|
3
|
+
import { type ProjectSession } from "./project.js";
|
|
4
|
+
export interface DiscoveredProjectSession extends ProjectSession {
|
|
5
|
+
readonly matchesWorkspace: boolean;
|
|
6
|
+
readonly matchesApplication: boolean;
|
|
7
|
+
readonly claimed: boolean;
|
|
8
|
+
readonly status: Pick<AgentStatusSnapshot, "connection" | "listenerActive" | "paired">;
|
|
9
|
+
}
|
|
10
|
+
export declare function discoverProjectSessions(applicationRoot: string, registryRoot?: string): Promise<DiscoveredProjectSession[]>;
|
|
11
|
+
/** Routes MCP tools to a live project in the adapter's exact worktree. */
|
|
12
|
+
export declare class DiscoveredProjectRouter {
|
|
13
|
+
readonly workspaceRoot: string;
|
|
14
|
+
readonly applicationRoot: string;
|
|
15
|
+
readonly registryRoot: string;
|
|
16
|
+
readonly agentId: string;
|
|
17
|
+
private client;
|
|
18
|
+
private releaseGeneration;
|
|
19
|
+
private constructor();
|
|
20
|
+
static create(workspaceRoot: string, registryRoot?: string): Promise<DiscoveredProjectRouter>;
|
|
21
|
+
listSessions(): Promise<DiscoveredProjectSession[]>;
|
|
22
|
+
private connectToSession;
|
|
23
|
+
waitForPrompt(signal?: AbortSignal, sessionId?: string): Promise<AgentPromptRequest>;
|
|
24
|
+
getStatus(): Promise<AgentStatusSnapshot>;
|
|
25
|
+
updateRequestStatus(update: AgentStatusUpdate): Promise<AgentStatusSnapshot>;
|
|
26
|
+
dispatchCanvasCommand(command: CanvasCommandInput): Promise<CanvasCommandResult>;
|
|
27
|
+
release(): Promise<void>;
|
|
28
|
+
close(): Promise<void>;
|
|
29
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { realpath } from "node:fs/promises";
|
|
3
|
+
import { resolve } from "node:path";
|
|
4
|
+
import { ProjectSessionClient } from "./projectSessionClient.js";
|
|
5
|
+
import { readLiveProjectSessions } from "./sessionRegistry.js";
|
|
6
|
+
import { matchesApplication, selectProjectSession } from "./sessionSelection.js";
|
|
7
|
+
import { defaultSessionRegistryRoot, resolveWorkspaceRoot, } from "./project.js";
|
|
8
|
+
function publicSession(session) {
|
|
9
|
+
const { controlToken: _controlToken, pid: _pid, ...visible } = session;
|
|
10
|
+
return visible;
|
|
11
|
+
}
|
|
12
|
+
export async function discoverProjectSessions(applicationRoot, registryRoot = defaultSessionRegistryRoot()) {
|
|
13
|
+
const canonicalApplication = await realpath(resolve(applicationRoot));
|
|
14
|
+
const canonicalWorkspace = await resolveWorkspaceRoot(canonicalApplication);
|
|
15
|
+
const live = await readLiveProjectSessions(resolve(registryRoot));
|
|
16
|
+
return live.map(({ descriptor, health }) => {
|
|
17
|
+
const matchesWorkspace = descriptor.workspaceRoot === canonicalWorkspace;
|
|
18
|
+
return {
|
|
19
|
+
...publicSession(descriptor),
|
|
20
|
+
matchesWorkspace,
|
|
21
|
+
matchesApplication: matchesApplication(descriptor, {
|
|
22
|
+
workspaceRoot: canonicalWorkspace,
|
|
23
|
+
applicationRoot: canonicalApplication,
|
|
24
|
+
}),
|
|
25
|
+
claimed: health.claimed,
|
|
26
|
+
status: {
|
|
27
|
+
connection: health.status.connection,
|
|
28
|
+
listenerActive: health.status.listenerActive,
|
|
29
|
+
paired: health.status.paired,
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
}).sort((left, right) => right.startedAt.localeCompare(left.startedAt));
|
|
33
|
+
}
|
|
34
|
+
/** Routes MCP tools to a live project in the adapter's exact worktree. */
|
|
35
|
+
export class DiscoveredProjectRouter {
|
|
36
|
+
workspaceRoot;
|
|
37
|
+
applicationRoot;
|
|
38
|
+
registryRoot;
|
|
39
|
+
agentId;
|
|
40
|
+
client = null;
|
|
41
|
+
releaseGeneration = 0;
|
|
42
|
+
constructor(workspaceRoot, applicationRoot, registryRoot, agentId) {
|
|
43
|
+
this.workspaceRoot = workspaceRoot;
|
|
44
|
+
this.applicationRoot = applicationRoot;
|
|
45
|
+
this.registryRoot = registryRoot;
|
|
46
|
+
this.agentId = agentId;
|
|
47
|
+
}
|
|
48
|
+
static async create(workspaceRoot, registryRoot = defaultSessionRegistryRoot()) {
|
|
49
|
+
const applicationRoot = await realpath(resolve(workspaceRoot));
|
|
50
|
+
return new DiscoveredProjectRouter(await resolveWorkspaceRoot(applicationRoot), applicationRoot, resolve(registryRoot), randomUUID());
|
|
51
|
+
}
|
|
52
|
+
async listSessions() {
|
|
53
|
+
return await discoverProjectSessions(this.applicationRoot, this.registryRoot);
|
|
54
|
+
}
|
|
55
|
+
async connectToSession(sessionId) {
|
|
56
|
+
const live = await readLiveProjectSessions(this.registryRoot);
|
|
57
|
+
const selected = selectProjectSession(live.map(({ descriptor }) => descriptor), {
|
|
58
|
+
workspaceRoot: this.workspaceRoot,
|
|
59
|
+
applicationRoot: this.applicationRoot,
|
|
60
|
+
requestedSessionId: sessionId,
|
|
61
|
+
previousSession: this.client?.descriptor,
|
|
62
|
+
});
|
|
63
|
+
if (this.client?.descriptor.sessionId === selected.sessionId)
|
|
64
|
+
return this.client;
|
|
65
|
+
await this.client?.close();
|
|
66
|
+
this.client = new ProjectSessionClient(selected, this.agentId);
|
|
67
|
+
return this.client;
|
|
68
|
+
}
|
|
69
|
+
async waitForPrompt(signal, sessionId) {
|
|
70
|
+
const releaseGeneration = this.releaseGeneration;
|
|
71
|
+
const client = await this.connectToSession(sessionId);
|
|
72
|
+
if (releaseGeneration !== this.releaseGeneration) {
|
|
73
|
+
if (this.client === client) {
|
|
74
|
+
this.client = null;
|
|
75
|
+
await client.close();
|
|
76
|
+
}
|
|
77
|
+
throw new Error("The Nudge project session was released.");
|
|
78
|
+
}
|
|
79
|
+
try {
|
|
80
|
+
return await client.waitForPrompt(signal);
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
if (signal?.aborted || sessionId || releaseGeneration !== this.releaseGeneration)
|
|
84
|
+
throw error;
|
|
85
|
+
const replacement = await this.connectToSession();
|
|
86
|
+
if (replacement === client)
|
|
87
|
+
throw error;
|
|
88
|
+
return await replacement.waitForPrompt(signal);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
async getStatus() {
|
|
92
|
+
const client = await this.connectToSession();
|
|
93
|
+
return await client.getStatus();
|
|
94
|
+
}
|
|
95
|
+
async updateRequestStatus(update) {
|
|
96
|
+
const client = await this.connectToSession();
|
|
97
|
+
return await client.updateRequestStatus(update);
|
|
98
|
+
}
|
|
99
|
+
async dispatchCanvasCommand(command) {
|
|
100
|
+
const client = await this.connectToSession();
|
|
101
|
+
return await client.dispatchCanvasCommand(command);
|
|
102
|
+
}
|
|
103
|
+
async release() {
|
|
104
|
+
this.releaseGeneration += 1;
|
|
105
|
+
const client = this.client;
|
|
106
|
+
this.client = null;
|
|
107
|
+
await client?.close();
|
|
108
|
+
}
|
|
109
|
+
async close() {
|
|
110
|
+
await this.release();
|
|
111
|
+
}
|
|
112
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
export { createAgentCompanion, type AgentCompanion, type AgentCompanionOptions } from "./server.js";
|
|
1
|
+
export { createAgentCompanion, createDiscoveredAgentAdapter, type AgentCompanion, type AgentCompanionOptions, type DiscoveredAgentAdapter, } from "./server.js";
|
|
2
|
+
export { DiscoveredProjectRouter, discoverProjectSessions, type DiscoveredProjectSession, } from "./discovery.js";
|
|
3
|
+
export { defaultSessionRegistryRoot, resolveWorkspaceRoot, startProjectBridge, type ProjectBridgeOptions, type ProjectBridgeRuntime, type ProjectSession, } from "./project.js";
|
|
2
4
|
export { createLoopbackBridge, type BrowserBridge, type BrowserBridgeOptions, type BridgeAddress, type BridgeClock, type CanvasCommandInput, } from "./bridge.js";
|
|
3
5
|
export { openPairedPage, parseCliArguments, runCli, type CliOptions, type PageLaunchDependencies, } from "./cli.js";
|
|
4
6
|
export * from "./protocol.js";
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
export { createAgentCompanion } from "./server.js";
|
|
1
|
+
export { createAgentCompanion, createDiscoveredAgentAdapter, } from "./server.js";
|
|
2
|
+
export { DiscoveredProjectRouter, discoverProjectSessions, } from "./discovery.js";
|
|
3
|
+
export { defaultSessionRegistryRoot, resolveWorkspaceRoot, startProjectBridge, } from "./project.js";
|
|
2
4
|
export { createLoopbackBridge, } from "./bridge.js";
|
|
3
5
|
export { openPairedPage, parseCliArguments, runCli, } from "./cli.js";
|
|
4
6
|
export * from "./protocol.js";
|
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public, host-neutral contracts shared by the Nudge browser inspector and
|
|
3
|
+
* its local MCP companion.
|
|
4
|
+
*
|
|
5
|
+
* This module deliberately has no Node, browser, MCP SDK, or framework
|
|
6
|
+
* imports. Hosts can use the same validation and message shapes without
|
|
7
|
+
* pulling the companion into a browser bundle.
|
|
8
|
+
*/
|
|
9
|
+
export declare const AGENT_PROTOCOL_VERSION: 2;
|
|
10
|
+
export declare const AGENT_PROTOCOL_LIMITS: {
|
|
11
|
+
readonly projectId: 256;
|
|
12
|
+
readonly workspaceRoot: 4096;
|
|
13
|
+
readonly origin: 2048;
|
|
14
|
+
readonly sessionToken: 256;
|
|
15
|
+
readonly requestId: 256;
|
|
16
|
+
readonly commandId: 256;
|
|
17
|
+
readonly clientDispatchId: 256;
|
|
18
|
+
readonly prompt: 32000;
|
|
19
|
+
readonly sketchId: 256;
|
|
20
|
+
readonly sketchRevision: 2147483647;
|
|
21
|
+
readonly sketchFilename: 256;
|
|
22
|
+
readonly sketchDescription: 2000;
|
|
23
|
+
readonly sketchCount: 4;
|
|
24
|
+
readonly sketchImageBytes: number;
|
|
25
|
+
readonly sketchTotalBytes: number;
|
|
26
|
+
readonly sketchEncodedBytes: number;
|
|
27
|
+
readonly sketchAnnotationCount: 50;
|
|
28
|
+
readonly sketchUrl: 2048;
|
|
29
|
+
readonly sketchTitle: 512;
|
|
30
|
+
readonly sketchFramework: 128;
|
|
31
|
+
readonly sketchHost: 128;
|
|
32
|
+
readonly groupId: 256;
|
|
33
|
+
readonly label: 160;
|
|
34
|
+
readonly routeUrl: 2048;
|
|
35
|
+
readonly routeTitle: 512;
|
|
36
|
+
readonly routeCount: 64;
|
|
37
|
+
readonly canvasCardCount: 128;
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* Returns the default project-specific loopback port used by the CLI.
|
|
41
|
+
*
|
|
42
|
+
* The value is deterministic so a browser can probe the companion without a
|
|
43
|
+
* port file, while the range stays high enough to avoid common dev servers.
|
|
44
|
+
* Callers may still override it with an explicit port when a collision occurs.
|
|
45
|
+
*/
|
|
46
|
+
export declare function defaultBridgePort(projectId: string): number;
|
|
47
|
+
export type AgentProtocolVersion = typeof AGENT_PROTOCOL_VERSION;
|
|
48
|
+
/** A project identity is the pairing boundary for one companion process. */
|
|
49
|
+
export interface AgentProjectIdentity {
|
|
50
|
+
readonly projectId: string;
|
|
51
|
+
/** Omitted when a trusted host establishes the browser origin out of band. */
|
|
52
|
+
readonly origin?: string;
|
|
53
|
+
readonly workspaceRoot?: string;
|
|
54
|
+
}
|
|
55
|
+
/** A same-origin route that an agent asks the browser to add to Canvas. */
|
|
56
|
+
export interface AgentRoute {
|
|
57
|
+
readonly url: string;
|
|
58
|
+
readonly title?: string;
|
|
59
|
+
/** A short user-facing name. When absent, the browser derives one. */
|
|
60
|
+
readonly label?: string;
|
|
61
|
+
}
|
|
62
|
+
/** The owner marker lets the browser remove only groups created by the agent. */
|
|
63
|
+
export type CanvasGroupOwner = "agent" | "user";
|
|
64
|
+
/** A browser-reported comparison group. */
|
|
65
|
+
export interface CanvasGroup {
|
|
66
|
+
readonly id: string;
|
|
67
|
+
readonly label: string;
|
|
68
|
+
readonly owner: CanvasGroupOwner;
|
|
69
|
+
readonly routes: readonly AgentRoute[];
|
|
70
|
+
}
|
|
71
|
+
/** A compact, serialisable Canvas snapshot returned by the browser. */
|
|
72
|
+
export interface CanvasState {
|
|
73
|
+
readonly mode: "inspect" | "canvas";
|
|
74
|
+
readonly groups: readonly CanvasGroup[];
|
|
75
|
+
readonly focusedGroupId?: string | null;
|
|
76
|
+
readonly focusedRouteUrl?: string | null;
|
|
77
|
+
}
|
|
78
|
+
export declare const CANVAS_COMMAND_TYPES: readonly ["read-state", "present-routes", "focus-group", "fit-all", "remove-group"];
|
|
79
|
+
export type CanvasCommandType = (typeof CANVAS_COMMAND_TYPES)[number];
|
|
80
|
+
export interface ReadCanvasStateCommand {
|
|
81
|
+
readonly type: "read-state";
|
|
82
|
+
readonly commandId: string;
|
|
83
|
+
}
|
|
84
|
+
export interface PresentRoutesCommand {
|
|
85
|
+
readonly type: "present-routes";
|
|
86
|
+
readonly commandId: string;
|
|
87
|
+
readonly groupId: string;
|
|
88
|
+
readonly label: string;
|
|
89
|
+
readonly routes: readonly AgentRoute[];
|
|
90
|
+
}
|
|
91
|
+
export interface FocusCanvasGroupCommand {
|
|
92
|
+
readonly type: "focus-group";
|
|
93
|
+
readonly commandId: string;
|
|
94
|
+
readonly groupId: string;
|
|
95
|
+
}
|
|
96
|
+
export interface FitCanvasCommand {
|
|
97
|
+
readonly type: "fit-all";
|
|
98
|
+
readonly commandId: string;
|
|
99
|
+
}
|
|
100
|
+
export interface RemoveCanvasGroupCommand {
|
|
101
|
+
readonly type: "remove-group";
|
|
102
|
+
readonly commandId: string;
|
|
103
|
+
readonly groupId: string;
|
|
104
|
+
}
|
|
105
|
+
/** Commands sent from the companion to the paired browser over SSE. */
|
|
106
|
+
export type CanvasCommand = ReadCanvasStateCommand | PresentRoutesCommand | FocusCanvasGroupCommand | FitCanvasCommand | RemoveCanvasGroupCommand;
|
|
107
|
+
export interface CanvasCommandError {
|
|
108
|
+
readonly code: string;
|
|
109
|
+
readonly message: string;
|
|
110
|
+
}
|
|
111
|
+
export interface CanvasCommandResult {
|
|
112
|
+
readonly commandId: string;
|
|
113
|
+
readonly ok: boolean;
|
|
114
|
+
readonly state?: CanvasState;
|
|
115
|
+
readonly group?: CanvasGroup;
|
|
116
|
+
readonly error?: CanvasCommandError;
|
|
117
|
+
}
|
|
118
|
+
/** A prompt is immutable after it is accepted by the browser bridge. */
|
|
119
|
+
export interface AgentPromptRequest {
|
|
120
|
+
readonly requestId: string;
|
|
121
|
+
readonly projectId: string;
|
|
122
|
+
readonly prompt: string;
|
|
123
|
+
/** The browser's canonical change revision captured at dispatch time. */
|
|
124
|
+
readonly changeRevision?: number;
|
|
125
|
+
/** Correlates the durable browser handoff batch across a lost response. */
|
|
126
|
+
readonly clientDispatchId?: string;
|
|
127
|
+
/** Metadata for the exact sketch revisions included in this request. */
|
|
128
|
+
readonly sketches?: readonly AgentSketchMetadata[];
|
|
129
|
+
}
|
|
130
|
+
export interface AgentSketchCaptureMetadata {
|
|
131
|
+
readonly url: string;
|
|
132
|
+
readonly title: string;
|
|
133
|
+
readonly timestamp: number;
|
|
134
|
+
readonly viewportWidth: number;
|
|
135
|
+
readonly viewportHeight: number;
|
|
136
|
+
readonly scrollX: number;
|
|
137
|
+
readonly scrollY: number;
|
|
138
|
+
readonly devicePixelRatio: number;
|
|
139
|
+
readonly host: string;
|
|
140
|
+
readonly framework: string;
|
|
141
|
+
}
|
|
142
|
+
export interface AgentSketchAnnotation {
|
|
143
|
+
readonly number: number;
|
|
144
|
+
readonly description: string;
|
|
145
|
+
}
|
|
146
|
+
/** Metadata retained in statuses and acknowledgements without image bytes. */
|
|
147
|
+
export interface AgentSketchMetadata {
|
|
148
|
+
readonly id: string;
|
|
149
|
+
readonly revision: number;
|
|
150
|
+
readonly filename: string;
|
|
151
|
+
readonly mimeType: "image/png";
|
|
152
|
+
readonly width: number;
|
|
153
|
+
readonly height: number;
|
|
154
|
+
readonly byteSize: number;
|
|
155
|
+
readonly capture: AgentSketchCaptureMetadata;
|
|
156
|
+
readonly description?: string;
|
|
157
|
+
readonly annotations?: readonly AgentSketchAnnotation[];
|
|
158
|
+
}
|
|
159
|
+
/** The only protocol shape that carries screenshot bytes. */
|
|
160
|
+
export interface AgentSketchAttachment extends AgentSketchMetadata {
|
|
161
|
+
readonly data: string;
|
|
162
|
+
}
|
|
163
|
+
/** Internal companion delivery shape; attachment bytes are never status data. */
|
|
164
|
+
export interface AgentDeliveredPrompt extends AgentPromptRequest {
|
|
165
|
+
readonly attachments?: readonly AgentSketchAttachment[];
|
|
166
|
+
}
|
|
167
|
+
export type AgentRequestStatus = "working" | "completed" | "failed" | "interrupted";
|
|
168
|
+
export interface AgentRequestOutcome {
|
|
169
|
+
readonly requestId: string;
|
|
170
|
+
readonly status: AgentRequestStatus;
|
|
171
|
+
readonly summary?: string;
|
|
172
|
+
readonly error?: string;
|
|
173
|
+
}
|
|
174
|
+
export type AgentConnectionState = "offline" | "listening" | "paired" | "working";
|
|
175
|
+
export interface AgentStatusSnapshot {
|
|
176
|
+
readonly protocolVersion: AgentProtocolVersion;
|
|
177
|
+
readonly projectId: string;
|
|
178
|
+
readonly connection: AgentConnectionState;
|
|
179
|
+
readonly listenerActive: boolean;
|
|
180
|
+
readonly paired: boolean;
|
|
181
|
+
/** The last paired page, retained only for this process lifetime. */
|
|
182
|
+
readonly pageUrl?: string | null;
|
|
183
|
+
readonly request: (AgentPromptRequest & {
|
|
184
|
+
readonly status: AgentRequestStatus;
|
|
185
|
+
readonly summary?: string;
|
|
186
|
+
readonly error?: string;
|
|
187
|
+
}) | null;
|
|
188
|
+
}
|
|
189
|
+
export type BridgeEventType = "status" | "canvas-command" | "connected" | "disconnected";
|
|
190
|
+
export interface BridgeStatusEvent {
|
|
191
|
+
readonly type: "status";
|
|
192
|
+
readonly status: AgentStatusSnapshot;
|
|
193
|
+
}
|
|
194
|
+
export interface BridgeConnectedEvent {
|
|
195
|
+
readonly type: "connected";
|
|
196
|
+
readonly status: AgentStatusSnapshot;
|
|
197
|
+
}
|
|
198
|
+
export interface BridgeDisconnectedEvent {
|
|
199
|
+
readonly type: "disconnected";
|
|
200
|
+
readonly reason?: string;
|
|
201
|
+
}
|
|
202
|
+
export interface BridgeCanvasCommandEvent {
|
|
203
|
+
readonly type: "canvas-command";
|
|
204
|
+
readonly command: CanvasCommand;
|
|
205
|
+
}
|
|
206
|
+
/** Payload delivered to a browser SSE connection. */
|
|
207
|
+
export type BridgeEvent = BridgeStatusEvent | BridgeConnectedEvent | BridgeDisconnectedEvent | BridgeCanvasCommandEvent;
|
|
208
|
+
export interface BridgeEnvelope {
|
|
209
|
+
readonly protocolVersion: AgentProtocolVersion;
|
|
210
|
+
readonly projectId: string;
|
|
211
|
+
readonly sessionToken: string;
|
|
212
|
+
readonly event: BridgeEvent;
|
|
213
|
+
}
|
|
214
|
+
export interface CanvasCommandAcknowledgement {
|
|
215
|
+
readonly commandId: string;
|
|
216
|
+
readonly ok: boolean;
|
|
217
|
+
readonly state?: CanvasState;
|
|
218
|
+
readonly group?: CanvasGroup;
|
|
219
|
+
readonly error?: CanvasCommandError;
|
|
220
|
+
}
|
|
221
|
+
export interface PairingRequest {
|
|
222
|
+
readonly projectId: string;
|
|
223
|
+
readonly origin: string;
|
|
224
|
+
/** Reuses an existing pairing across a same-browser reload. */
|
|
225
|
+
readonly sessionToken?: string;
|
|
226
|
+
/** The active page is retained only while this process is alive. */
|
|
227
|
+
readonly pageUrl?: string;
|
|
228
|
+
}
|
|
229
|
+
export interface PairingResponse {
|
|
230
|
+
readonly protocolVersion: AgentProtocolVersion;
|
|
231
|
+
readonly projectId: string;
|
|
232
|
+
readonly origin: string;
|
|
233
|
+
readonly sessionToken: string;
|
|
234
|
+
readonly pageUrl?: string;
|
|
235
|
+
readonly status: AgentStatusSnapshot;
|
|
236
|
+
}
|
|
237
|
+
export interface PromptDispatchRequest {
|
|
238
|
+
readonly projectId: string;
|
|
239
|
+
readonly sessionToken: string;
|
|
240
|
+
readonly prompt: string;
|
|
241
|
+
readonly changeRevision?: number;
|
|
242
|
+
readonly clientDispatchId?: string;
|
|
243
|
+
readonly attachments?: readonly AgentSketchAttachment[];
|
|
244
|
+
}
|
|
245
|
+
export interface PromptDispatchResponse {
|
|
246
|
+
readonly request: AgentPromptRequest;
|
|
247
|
+
readonly status: AgentRequestStatus;
|
|
248
|
+
}
|
|
249
|
+
export interface StatusEventRequest {
|
|
250
|
+
readonly projectId: string;
|
|
251
|
+
readonly sessionToken: string;
|
|
252
|
+
}
|
|
253
|
+
export interface AgentStatusUpdate {
|
|
254
|
+
readonly requestId: string;
|
|
255
|
+
readonly status: AgentRequestStatus;
|
|
256
|
+
readonly summary?: string;
|
|
257
|
+
readonly error?: string;
|
|
258
|
+
}
|
|
259
|
+
export interface ProtocolErrorShape {
|
|
260
|
+
readonly code: string;
|
|
261
|
+
readonly message: string;
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Returns a canonical origin or null. Credentials, paths, and fragments are
|
|
265
|
+
* rejected so the browser cannot broaden the pairing boundary accidentally.
|
|
266
|
+
*/
|
|
267
|
+
export declare function canonicalOrigin(value: unknown): string | null;
|
|
268
|
+
/** Returns true only for exact, canonical HTTP(S) origins. */
|
|
269
|
+
export declare function isCanonicalOrigin(value: unknown): value is string;
|
|
270
|
+
/**
|
|
271
|
+
* Checks an origin against an explicit allow-list. An empty allow-list does
|
|
272
|
+
* not mean wildcard access; callers must choose an origin before pairing.
|
|
273
|
+
*/
|
|
274
|
+
export declare function isAllowedOrigin(value: unknown, allowedOrigins: readonly string[]): value is string;
|
|
275
|
+
/**
|
|
276
|
+
* Validates an agent route and ensures it belongs to the paired origin.
|
|
277
|
+
* Fragments are retained because they are useful initial Canvas locations.
|
|
278
|
+
*/
|
|
279
|
+
export declare function isSameOriginRoute(value: unknown, origin: string): value is AgentRoute;
|
|
280
|
+
/** Validates and normalises route values for a presentation command. */
|
|
281
|
+
export declare function validateRoutes(value: unknown, origin: string): AgentRoute[];
|
|
282
|
+
/** Validates the fields shared by every companion message. */
|
|
283
|
+
export declare function isProtocolVersion(value: unknown): value is AgentProtocolVersion;
|
|
284
|
+
export declare function isProjectIdentity(value: unknown): value is AgentProjectIdentity;
|
|
285
|
+
export declare function isAgentSketchCaptureMetadata(value: unknown): value is AgentSketchCaptureMetadata;
|
|
286
|
+
export declare function isAgentSketchAnnotation(value: unknown): value is AgentSketchAnnotation;
|
|
287
|
+
export declare function isAgentSketchMetadata(value: unknown): value is AgentSketchMetadata;
|
|
288
|
+
export declare function isAgentSketchAttachment(value: unknown): value is AgentSketchAttachment;
|
|
289
|
+
export declare function validateSketchAttachments(value: unknown): AgentSketchAttachment[];
|
|
290
|
+
export declare function isAgentPromptRequest(value: unknown): value is AgentPromptRequest;
|
|
291
|
+
export declare function isAgentStatusUpdate(value: unknown): value is AgentStatusUpdate;
|
|
292
|
+
export declare function isCanvasState(value: unknown): value is CanvasState;
|
|
293
|
+
export declare function isCanvasGroup(value: unknown): value is CanvasGroup;
|
|
294
|
+
export declare function isCanvasCommand(value: unknown): value is CanvasCommand;
|
|
295
|
+
/** Creates a stable protocol error shape without exposing thrown values. */
|
|
296
|
+
export declare function protocolError(code: string, message: string): ProtocolErrorShape;
|