@nudge-ui/mcp 0.2.1 → 0.2.3
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 +103 -75
- package/dist/adapterRouting.d.ts +16 -0
- package/dist/adapterRouting.js +59 -0
- package/dist/bridge.d.ts +4 -2
- package/dist/bridge.js +51 -6
- package/dist/cli.d.ts +2 -2
- package/dist/cli.js +14 -6
- package/dist/cli.mjs +319 -69
- package/dist/discovery.d.ts +22 -3
- package/dist/discovery.js +62 -10
- package/dist/internal/agent-protocol.d.ts +19 -2
- package/dist/internal/agent-protocol.js +13 -0
- package/dist/projectSessionClient.d.ts +8 -1
- package/dist/projectSessionClient.js +18 -4
- package/dist/protocol.d.ts +4 -2
- package/dist/protocol.js +3 -1
- package/dist/server.d.ts +3 -2
- package/dist/server.js +98 -34
- package/dist/sessionRegistry.d.ts +10 -1
- package/dist/sessionRegistry.js +48 -16
- package/package.json +1 -1
package/dist/discovery.d.ts
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
|
+
import type { AgentActivity } from "./internal/agent-protocol.js";
|
|
1
2
|
import type { AgentPromptRequest, AgentStatusSnapshot, AgentStatusUpdate, CanvasCommandResult } from "./internal/agent-protocol.js";
|
|
2
3
|
import type { CanvasCommandInput } from "./bridge.js";
|
|
3
|
-
import { type ProjectSession } from "./project.js";
|
|
4
|
+
import { type ProjectSession, type StoredProjectSession } from "./project.js";
|
|
4
5
|
export interface DiscoveredProjectSession extends ProjectSession {
|
|
5
6
|
readonly matchesWorkspace: boolean;
|
|
6
7
|
readonly matchesApplication: boolean;
|
|
7
8
|
readonly claimed: boolean;
|
|
8
9
|
readonly status: Pick<AgentStatusSnapshot, "connection" | "listenerActive" | "paired">;
|
|
9
10
|
}
|
|
10
|
-
export declare function discoverProjectSessions(applicationRoot: string, registryRoot?: string): Promise<DiscoveredProjectSession[]>;
|
|
11
|
+
export declare function discoverProjectSessions(applicationRoot: string | undefined, registryRoot?: string): Promise<DiscoveredProjectSession[]>;
|
|
11
12
|
/** Routes MCP tools to a live project in the adapter's exact worktree. */
|
|
12
13
|
export declare class DiscoveredProjectRouter {
|
|
13
14
|
readonly workspaceRoot: string;
|
|
@@ -16,14 +17,32 @@ export declare class DiscoveredProjectRouter {
|
|
|
16
17
|
readonly agentId: string;
|
|
17
18
|
private client;
|
|
18
19
|
private releaseGeneration;
|
|
20
|
+
private connectionQueue;
|
|
19
21
|
private constructor();
|
|
22
|
+
get selectedSessionId(): string | undefined;
|
|
23
|
+
static forSession(session: StoredProjectSession, registryRoot: string): DiscoveredProjectRouter;
|
|
20
24
|
static create(workspaceRoot: string, registryRoot?: string): Promise<DiscoveredProjectRouter>;
|
|
21
25
|
listSessions(): Promise<DiscoveredProjectSession[]>;
|
|
22
26
|
private connectToSession;
|
|
23
|
-
|
|
27
|
+
private selectSession;
|
|
28
|
+
waitForPrompt(signal?: AbortSignal, sessionId?: string, agentClientName?: string): Promise<AgentPromptRequest>;
|
|
24
29
|
getStatus(): Promise<AgentStatusSnapshot>;
|
|
30
|
+
reportActivity(activity: AgentActivity): Promise<void>;
|
|
25
31
|
updateRequestStatus(update: AgentStatusUpdate): Promise<AgentStatusSnapshot>;
|
|
26
32
|
dispatchCanvasCommand(command: CanvasCommandInput): Promise<CanvasCommandResult>;
|
|
27
33
|
release(): Promise<void>;
|
|
28
34
|
close(): Promise<void>;
|
|
29
35
|
}
|
|
36
|
+
/** Returns diagnostic counts, scope, and public paths without exposing registry credentials. */
|
|
37
|
+
export declare function diagnoseProjectSessions(applicationRoot?: string, registryRoot?: string): Promise<{
|
|
38
|
+
registryRoot: string;
|
|
39
|
+
workspaceRoot: string | undefined;
|
|
40
|
+
applicationRoot: string | undefined;
|
|
41
|
+
descriptorCount: number;
|
|
42
|
+
invalidCount: number;
|
|
43
|
+
incompatibleCount: number;
|
|
44
|
+
reachableCount: number;
|
|
45
|
+
matchingReachableCount: number;
|
|
46
|
+
matchingUnreachableCount: number;
|
|
47
|
+
guidance: string[];
|
|
48
|
+
}>;
|
package/dist/discovery.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
2
|
import { realpath } from "node:fs/promises";
|
|
3
|
-
import { resolve } from "node:path";
|
|
3
|
+
import { isAbsolute, resolve } from "node:path";
|
|
4
4
|
import { ProjectSessionClient } from "./projectSessionClient.js";
|
|
5
|
-
import { readLiveProjectSessions } from "./sessionRegistry.js";
|
|
5
|
+
import { inspectProjectSessions, readLiveProjectSessions } from "./sessionRegistry.js";
|
|
6
6
|
import { matchesApplication, selectProjectSession } from "./sessionSelection.js";
|
|
7
7
|
import { defaultSessionRegistryRoot, resolveWorkspaceRoot, } from "./project.js";
|
|
8
8
|
function publicSession(session) {
|
|
@@ -10,15 +10,17 @@ function publicSession(session) {
|
|
|
10
10
|
return visible;
|
|
11
11
|
}
|
|
12
12
|
export async function discoverProjectSessions(applicationRoot, registryRoot = defaultSessionRegistryRoot()) {
|
|
13
|
-
const canonicalApplication =
|
|
14
|
-
|
|
13
|
+
const canonicalApplication = applicationRoot === undefined
|
|
14
|
+
? undefined
|
|
15
|
+
: await realpath(requireAbsoluteWorkspaceRoot(applicationRoot));
|
|
16
|
+
const canonicalWorkspace = canonicalApplication === undefined ? undefined : await resolveWorkspaceRoot(canonicalApplication);
|
|
15
17
|
const live = await readLiveProjectSessions(resolve(registryRoot));
|
|
16
18
|
return live.map(({ descriptor, health }) => {
|
|
17
19
|
const matchesWorkspace = descriptor.workspaceRoot === canonicalWorkspace;
|
|
18
20
|
return {
|
|
19
21
|
...publicSession(descriptor),
|
|
20
22
|
matchesWorkspace,
|
|
21
|
-
matchesApplication: matchesApplication(descriptor, {
|
|
23
|
+
matchesApplication: canonicalWorkspace !== undefined && canonicalApplication !== undefined && matchesApplication(descriptor, {
|
|
22
24
|
workspaceRoot: canonicalWorkspace,
|
|
23
25
|
applicationRoot: canonicalApplication,
|
|
24
26
|
}),
|
|
@@ -39,20 +41,34 @@ export class DiscoveredProjectRouter {
|
|
|
39
41
|
agentId;
|
|
40
42
|
client = null;
|
|
41
43
|
releaseGeneration = 0;
|
|
44
|
+
connectionQueue = Promise.resolve();
|
|
42
45
|
constructor(workspaceRoot, applicationRoot, registryRoot, agentId) {
|
|
43
46
|
this.workspaceRoot = workspaceRoot;
|
|
44
47
|
this.applicationRoot = applicationRoot;
|
|
45
48
|
this.registryRoot = registryRoot;
|
|
46
49
|
this.agentId = agentId;
|
|
47
50
|
}
|
|
51
|
+
get selectedSessionId() {
|
|
52
|
+
return this.client?.descriptor.sessionId;
|
|
53
|
+
}
|
|
54
|
+
static forSession(session, registryRoot) {
|
|
55
|
+
const router = new DiscoveredProjectRouter(session.workspaceRoot, session.appRoot, registryRoot, randomUUID());
|
|
56
|
+
router.client = new ProjectSessionClient(session, router.agentId);
|
|
57
|
+
return router;
|
|
58
|
+
}
|
|
48
59
|
static async create(workspaceRoot, registryRoot = defaultSessionRegistryRoot()) {
|
|
49
|
-
const applicationRoot = await realpath(
|
|
60
|
+
const applicationRoot = await realpath(requireAbsoluteWorkspaceRoot(workspaceRoot));
|
|
50
61
|
return new DiscoveredProjectRouter(await resolveWorkspaceRoot(applicationRoot), applicationRoot, resolve(registryRoot), randomUUID());
|
|
51
62
|
}
|
|
52
63
|
async listSessions() {
|
|
53
64
|
return await discoverProjectSessions(this.applicationRoot, this.registryRoot);
|
|
54
65
|
}
|
|
55
|
-
|
|
66
|
+
connectToSession(sessionId) {
|
|
67
|
+
const connection = this.connectionQueue.then(() => this.selectSession(sessionId));
|
|
68
|
+
this.connectionQueue = connection.then(() => undefined, () => undefined);
|
|
69
|
+
return connection;
|
|
70
|
+
}
|
|
71
|
+
async selectSession(sessionId) {
|
|
56
72
|
const live = await readLiveProjectSessions(this.registryRoot);
|
|
57
73
|
const selected = selectProjectSession(live.map(({ descriptor }) => descriptor), {
|
|
58
74
|
workspaceRoot: this.workspaceRoot,
|
|
@@ -66,7 +82,7 @@ export class DiscoveredProjectRouter {
|
|
|
66
82
|
this.client = new ProjectSessionClient(selected, this.agentId);
|
|
67
83
|
return this.client;
|
|
68
84
|
}
|
|
69
|
-
async waitForPrompt(signal, sessionId) {
|
|
85
|
+
async waitForPrompt(signal, sessionId, agentClientName) {
|
|
70
86
|
const releaseGeneration = this.releaseGeneration;
|
|
71
87
|
const client = await this.connectToSession(sessionId);
|
|
72
88
|
if (releaseGeneration !== this.releaseGeneration) {
|
|
@@ -77,7 +93,7 @@ export class DiscoveredProjectRouter {
|
|
|
77
93
|
throw new Error("The Nudge project session was released.");
|
|
78
94
|
}
|
|
79
95
|
try {
|
|
80
|
-
return await client.waitForPrompt(signal);
|
|
96
|
+
return await client.waitForPrompt(signal, agentClientName);
|
|
81
97
|
}
|
|
82
98
|
catch (error) {
|
|
83
99
|
if (signal?.aborted || sessionId || releaseGeneration !== this.releaseGeneration)
|
|
@@ -85,13 +101,17 @@ export class DiscoveredProjectRouter {
|
|
|
85
101
|
const replacement = await this.connectToSession();
|
|
86
102
|
if (replacement === client)
|
|
87
103
|
throw error;
|
|
88
|
-
return await replacement.waitForPrompt(signal);
|
|
104
|
+
return await replacement.waitForPrompt(signal, agentClientName);
|
|
89
105
|
}
|
|
90
106
|
}
|
|
91
107
|
async getStatus() {
|
|
92
108
|
const client = await this.connectToSession();
|
|
93
109
|
return await client.getStatus();
|
|
94
110
|
}
|
|
111
|
+
async reportActivity(activity) {
|
|
112
|
+
const client = await this.connectToSession();
|
|
113
|
+
await client.reportActivity(activity);
|
|
114
|
+
}
|
|
95
115
|
async updateRequestStatus(update) {
|
|
96
116
|
const client = await this.connectToSession();
|
|
97
117
|
return await client.updateRequestStatus(update);
|
|
@@ -102,6 +122,7 @@ export class DiscoveredProjectRouter {
|
|
|
102
122
|
}
|
|
103
123
|
async release() {
|
|
104
124
|
this.releaseGeneration += 1;
|
|
125
|
+
await this.connectionQueue;
|
|
105
126
|
const client = this.client;
|
|
106
127
|
this.client = null;
|
|
107
128
|
await client?.close();
|
|
@@ -110,3 +131,34 @@ export class DiscoveredProjectRouter {
|
|
|
110
131
|
await this.release();
|
|
111
132
|
}
|
|
112
133
|
}
|
|
134
|
+
/** Returns diagnostic counts, scope, and public paths without exposing registry credentials. */
|
|
135
|
+
export async function diagnoseProjectSessions(applicationRoot, registryRoot = defaultSessionRegistryRoot()) {
|
|
136
|
+
const resolvedRegistryRoot = resolve(registryRoot);
|
|
137
|
+
const app = applicationRoot === undefined
|
|
138
|
+
? undefined
|
|
139
|
+
: await realpath(requireAbsoluteWorkspaceRoot(applicationRoot));
|
|
140
|
+
const workspace = app === undefined ? undefined : await resolveWorkspaceRoot(app);
|
|
141
|
+
const inspection = await inspectProjectSessions(resolvedRegistryRoot);
|
|
142
|
+
const matching = (session) => app === undefined || (session.workspaceRoot === workspace && (app === workspace || session.appRoot === app));
|
|
143
|
+
return {
|
|
144
|
+
registryRoot: resolvedRegistryRoot,
|
|
145
|
+
workspaceRoot: workspace,
|
|
146
|
+
applicationRoot: app,
|
|
147
|
+
descriptorCount: inspection.descriptorCount,
|
|
148
|
+
invalidCount: inspection.invalidCount,
|
|
149
|
+
incompatibleCount: inspection.incompatibleCount,
|
|
150
|
+
reachableCount: inspection.live.length,
|
|
151
|
+
matchingReachableCount: inspection.live.filter(({ descriptor }) => matching(descriptor)).length,
|
|
152
|
+
matchingUnreachableCount: inspection.unreachable.filter(matching).length,
|
|
153
|
+
guidance: [
|
|
154
|
+
...(inspection.invalidCount > 0 ? ["Some session descriptors or authenticated health responses are invalid. Check the adapter and project bridge versions, descriptor permissions, and bridge logs."] : []),
|
|
155
|
+
...(inspection.unreachable.some(matching) ? ["Matching descriptors exist but their loopback endpoints are unreachable. The server may have stopped or local networking may be blocked. Retry outside the agent command sandbox; do not treat this as proof that no bridge registered."] : []),
|
|
156
|
+
...(inspection.incompatibleCount > 0 ? ["Some registrations use an incompatible protocol. Upgrade the reusable adapter and the project's @nudge-ui/mcp dependency, then restart the development server and agent host."] : []),
|
|
157
|
+
],
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
function requireAbsoluteWorkspaceRoot(workspaceRoot) {
|
|
161
|
+
if (!isAbsolute(workspaceRoot))
|
|
162
|
+
throw new TypeError("workspaceRoot must be an absolute path.");
|
|
163
|
+
return workspaceRoot;
|
|
164
|
+
}
|
|
@@ -177,6 +177,8 @@ export interface AgentStatusSnapshot {
|
|
|
177
177
|
readonly projectId: string;
|
|
178
178
|
readonly connection: AgentConnectionState;
|
|
179
179
|
readonly listenerActive: boolean;
|
|
180
|
+
/** MCP client name supplied during initialization; absent for older adapters. */
|
|
181
|
+
readonly agentClientName?: string;
|
|
180
182
|
readonly paired: boolean;
|
|
181
183
|
/** The last paired page, retained only for this process lifetime. */
|
|
182
184
|
readonly pageUrl?: string | null;
|
|
@@ -186,7 +188,7 @@ export interface AgentStatusSnapshot {
|
|
|
186
188
|
readonly error?: string;
|
|
187
189
|
}) | null;
|
|
188
190
|
}
|
|
189
|
-
export type BridgeEventType = "status" | "canvas-command" | "connected" | "disconnected";
|
|
191
|
+
export type BridgeEventType = "activity" | "status" | "canvas-command" | "connected" | "disconnected";
|
|
190
192
|
export interface BridgeStatusEvent {
|
|
191
193
|
readonly type: "status";
|
|
192
194
|
readonly status: AgentStatusSnapshot;
|
|
@@ -203,8 +205,23 @@ export interface BridgeCanvasCommandEvent {
|
|
|
203
205
|
readonly type: "canvas-command";
|
|
204
206
|
readonly command: CanvasCommand;
|
|
205
207
|
}
|
|
208
|
+
/** Temporary attribution for one file operation in an authoritative request. */
|
|
209
|
+
export interface AgentActivity {
|
|
210
|
+
readonly requestId: string;
|
|
211
|
+
/** Workspace-relative source path. */
|
|
212
|
+
readonly file: string;
|
|
213
|
+
readonly operation: "read" | "edit";
|
|
214
|
+
readonly line?: number;
|
|
215
|
+
readonly endLine?: number;
|
|
216
|
+
readonly componentId?: string;
|
|
217
|
+
}
|
|
218
|
+
export declare function isAgentActivity(value: unknown): value is AgentActivity;
|
|
219
|
+
export interface BridgeActivityEvent {
|
|
220
|
+
readonly type: "activity";
|
|
221
|
+
readonly activity: AgentActivity;
|
|
222
|
+
}
|
|
206
223
|
/** Payload delivered to a browser SSE connection. */
|
|
207
|
-
export type BridgeEvent = BridgeStatusEvent | BridgeConnectedEvent | BridgeDisconnectedEvent | BridgeCanvasCommandEvent;
|
|
224
|
+
export type BridgeEvent = BridgeActivityEvent | BridgeStatusEvent | BridgeConnectedEvent | BridgeDisconnectedEvent | BridgeCanvasCommandEvent;
|
|
208
225
|
export interface BridgeEnvelope {
|
|
209
226
|
readonly protocolVersion: AgentProtocolVersion;
|
|
210
227
|
readonly projectId: string;
|
|
@@ -61,6 +61,19 @@ export const CANVAS_COMMAND_TYPES = [
|
|
|
61
61
|
"fit-all",
|
|
62
62
|
"remove-group",
|
|
63
63
|
];
|
|
64
|
+
export function isAgentActivity(value) {
|
|
65
|
+
if (!isRecord(value) || !hasOnlyKeys(value, ["requestId", "file", "operation", "line", "endLine", "componentId"]))
|
|
66
|
+
return false;
|
|
67
|
+
const line = (value) => Number.isSafeInteger(value) && Number(value) > 0 && Number(value) <= 10_000_000;
|
|
68
|
+
return nonEmptyString(value.requestId, AGENT_PROTOCOL_LIMITS.requestId)
|
|
69
|
+
&& nonEmptyString(value.file, AGENT_PROTOCOL_LIMITS.workspaceRoot)
|
|
70
|
+
&& !/^(?:[\\/]|[a-z]:)/i.test(value.file) && !/[\\\u0000-\u001f]/.test(value.file)
|
|
71
|
+
&& !value.file.split("/").some((part, index, parts) => !part || part === "." || (part === ".." && parts.slice(0, index).some((previous) => previous !== "..")))
|
|
72
|
+
&& (value.operation === "read" || value.operation === "edit")
|
|
73
|
+
&& (value.line === undefined || line(value.line))
|
|
74
|
+
&& (value.endLine === undefined || (line(value.endLine) && line(value.line) && Number(value.endLine) >= Number(value.line)))
|
|
75
|
+
&& (value.componentId === undefined || nonEmptyString(value.componentId, 512));
|
|
76
|
+
}
|
|
64
77
|
const ORIGIN_PROTOCOLS = new Set(["http:", "https:"]);
|
|
65
78
|
function isRecord(value) {
|
|
66
79
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { AgentActivity } from "./internal/agent-protocol.js";
|
|
1
2
|
import type { AgentPromptRequest, AgentStatusSnapshot, AgentStatusUpdate, CanvasCommandResult } from "./internal/agent-protocol.js";
|
|
2
3
|
import type { CanvasCommandInput } from "./bridge.js";
|
|
3
4
|
import type { StoredProjectSession } from "./project.js";
|
|
@@ -7,6 +8,11 @@ export interface SessionHealth {
|
|
|
7
8
|
readonly claimed: boolean;
|
|
8
9
|
readonly status: AgentStatusSnapshot;
|
|
9
10
|
}
|
|
11
|
+
/** Represents an HTTP response from a project bridge that could be classified. */
|
|
12
|
+
export declare class ProjectSessionResponseError extends Error {
|
|
13
|
+
readonly status: number;
|
|
14
|
+
constructor(status: number, message: string);
|
|
15
|
+
}
|
|
10
16
|
export declare function readSessionHealth(session: StoredProjectSession, timeoutMs?: number): Promise<SessionHealth>;
|
|
11
17
|
/** Owns one project's claim, heartbeat, and authenticated control requests. */
|
|
12
18
|
export declare class ProjectSessionClient {
|
|
@@ -20,8 +26,9 @@ export declare class ProjectSessionClient {
|
|
|
20
26
|
private send;
|
|
21
27
|
private acquireClaim;
|
|
22
28
|
private claim;
|
|
23
|
-
waitForPrompt(signal?: AbortSignal): Promise<AgentPromptRequest>;
|
|
29
|
+
waitForPrompt(signal?: AbortSignal, agentClientName?: string): Promise<AgentPromptRequest>;
|
|
24
30
|
getStatus(): Promise<AgentStatusSnapshot>;
|
|
31
|
+
reportActivity(activity: AgentActivity): Promise<void>;
|
|
25
32
|
updateRequestStatus(update: AgentStatusUpdate): Promise<AgentStatusSnapshot>;
|
|
26
33
|
dispatchCanvasCommand(input: CanvasCommandInput): Promise<CanvasCommandResult>;
|
|
27
34
|
close(): Promise<void>;
|
|
@@ -2,6 +2,15 @@ import { randomUUID } from "node:crypto";
|
|
|
2
2
|
import { AGENT_CONTROL_ENDPOINTS } from "./protocol.js";
|
|
3
3
|
const CONTROL_TIMEOUT_MS = 5_000;
|
|
4
4
|
const CANVAS_TIMEOUT_MS = 65_000;
|
|
5
|
+
/** Represents an HTTP response from a project bridge that could be classified. */
|
|
6
|
+
export class ProjectSessionResponseError extends Error {
|
|
7
|
+
status;
|
|
8
|
+
constructor(status, message) {
|
|
9
|
+
super(message);
|
|
10
|
+
this.name = "ProjectSessionResponseError";
|
|
11
|
+
this.status = status;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
5
14
|
async function requestJson(session, path, init = {}, { signal, timeoutMs = CONTROL_TIMEOUT_MS } = {}) {
|
|
6
15
|
const response = await fetch(`${session.endpoint}${path}`, {
|
|
7
16
|
...init,
|
|
@@ -14,8 +23,9 @@ async function requestJson(session, path, init = {}, { signal, timeoutMs = CONTR
|
|
|
14
23
|
},
|
|
15
24
|
});
|
|
16
25
|
const body = await response.json().catch(() => undefined);
|
|
17
|
-
if (!response.ok)
|
|
18
|
-
throw new
|
|
26
|
+
if (!response.ok) {
|
|
27
|
+
throw new ProjectSessionResponseError(response.status, body?.error?.message ?? `Nudge project bridge returned ${response.status}.`);
|
|
28
|
+
}
|
|
19
29
|
return body;
|
|
20
30
|
}
|
|
21
31
|
export async function readSessionHealth(session, timeoutMs = CONTROL_TIMEOUT_MS) {
|
|
@@ -62,14 +72,18 @@ export class ProjectSessionClient {
|
|
|
62
72
|
this.claimPromise = null;
|
|
63
73
|
}
|
|
64
74
|
}
|
|
65
|
-
async waitForPrompt(signal) {
|
|
75
|
+
async waitForPrompt(signal, agentClientName) {
|
|
66
76
|
await this.claim();
|
|
67
|
-
return await this.send(AGENT_CONTROL_ENDPOINTS.listen, {}, { signal, timeoutMs: null });
|
|
77
|
+
return await this.send(AGENT_CONTROL_ENDPOINTS.listen, { agentClientName }, { signal, timeoutMs: null });
|
|
68
78
|
}
|
|
69
79
|
async getStatus() {
|
|
70
80
|
const health = await readSessionHealth(this.descriptor);
|
|
71
81
|
return health.status;
|
|
72
82
|
}
|
|
83
|
+
async reportActivity(activity) {
|
|
84
|
+
await this.claim();
|
|
85
|
+
await this.send(AGENT_CONTROL_ENDPOINTS.activity, { activity });
|
|
86
|
+
}
|
|
73
87
|
async updateRequestStatus(update) {
|
|
74
88
|
await this.claim();
|
|
75
89
|
return await this.send(AGENT_CONTROL_ENDPOINTS.reportStatus, { update });
|
package/dist/protocol.d.ts
CHANGED
|
@@ -5,12 +5,13 @@
|
|
|
5
5
|
* subpath keeps transport names discoverable for Node consumers while
|
|
6
6
|
* preserving one protocol vocabulary for browser and agent adapters.
|
|
7
7
|
*/
|
|
8
|
-
export { AGENT_PROTOCOL_LIMITS, AGENT_PROTOCOL_VERSION, CANVAS_COMMAND_TYPES, canonicalOrigin, defaultBridgePort, isAgentPromptRequest, isAgentSketchAttachment, isAgentSketchCaptureMetadata, isAgentSketchMetadata, isAgentStatusUpdate, isAllowedOrigin, isCanvasCommand, isCanvasGroup, isCanvasState, isCanonicalOrigin, isProjectIdentity, isSameOriginRoute, protocolError, validateSketchAttachments, validateRoutes, } from "./internal/agent-protocol.js";
|
|
9
|
-
export type { AgentConnectionState, AgentProjectIdentity, AgentPromptRequest, AgentDeliveredPrompt, AgentSketchAttachment, AgentSketchCaptureMetadata, AgentSketchMetadata, AgentRequestOutcome, AgentRequestStatus, AgentRoute, AgentStatusSnapshot, AgentStatusUpdate, BridgeCanvasCommandEvent, BridgeConnectedEvent, BridgeDisconnectedEvent, BridgeEnvelope, BridgeEvent, BridgeEventType, BridgeStatusEvent, CanvasCommand, CanvasCommandAcknowledgement, CanvasCommandError, CanvasCommandResult, CanvasGroup, CanvasGroupOwner, CanvasState, FitCanvasCommand, FocusCanvasGroupCommand, PairingRequest, PairingResponse, PresentRoutesCommand, PromptDispatchRequest, PromptDispatchResponse, ReadCanvasStateCommand, RemoveCanvasGroupCommand, StatusEventRequest, } from "./internal/agent-protocol.js";
|
|
8
|
+
export { AGENT_PROTOCOL_LIMITS, AGENT_PROTOCOL_VERSION, CANVAS_COMMAND_TYPES, canonicalOrigin, defaultBridgePort, isAgentPromptRequest, isAgentSketchAttachment, isAgentSketchCaptureMetadata, isAgentSketchMetadata, isAgentStatusUpdate, isAgentActivity, isAllowedOrigin, isCanvasCommand, isCanvasGroup, isCanvasState, isCanonicalOrigin, isProjectIdentity, isSameOriginRoute, protocolError, validateSketchAttachments, validateRoutes, } from "./internal/agent-protocol.js";
|
|
9
|
+
export type { AgentActivity, BridgeActivityEvent, AgentConnectionState, AgentProjectIdentity, AgentPromptRequest, AgentDeliveredPrompt, AgentSketchAttachment, AgentSketchCaptureMetadata, AgentSketchMetadata, AgentRequestOutcome, AgentRequestStatus, AgentRoute, AgentStatusSnapshot, AgentStatusUpdate, BridgeCanvasCommandEvent, BridgeConnectedEvent, BridgeDisconnectedEvent, BridgeEnvelope, BridgeEvent, BridgeEventType, BridgeStatusEvent, CanvasCommand, CanvasCommandAcknowledgement, CanvasCommandError, CanvasCommandResult, CanvasGroup, CanvasGroupOwner, CanvasState, FitCanvasCommand, FocusCanvasGroupCommand, PairingRequest, PairingResponse, PresentRoutesCommand, PromptDispatchRequest, PromptDispatchResponse, ReadCanvasStateCommand, RemoveCanvasGroupCommand, StatusEventRequest, } from "./internal/agent-protocol.js";
|
|
10
10
|
/** Stable endpoint names used by the loopback browser bridge. */
|
|
11
11
|
export declare const BRIDGE_ENDPOINTS: {
|
|
12
12
|
readonly health: "/health";
|
|
13
13
|
readonly pair: "/pair";
|
|
14
|
+
readonly takeover: "/takeover";
|
|
14
15
|
readonly events: "/events";
|
|
15
16
|
readonly prompt: "/prompt";
|
|
16
17
|
readonly status: "/status";
|
|
@@ -26,6 +27,7 @@ export declare const AGENT_CONTROL_ENDPOINTS: {
|
|
|
26
27
|
readonly listen: "/__nudge/agent/listen";
|
|
27
28
|
readonly status: "/__nudge/agent/status";
|
|
28
29
|
readonly reportStatus: "/__nudge/agent/report-status";
|
|
30
|
+
readonly activity: "/__nudge/agent/activity";
|
|
29
31
|
readonly canvas: "/__nudge/agent/canvas";
|
|
30
32
|
};
|
|
31
33
|
export type BridgeEndpoint = (typeof BRIDGE_ENDPOINTS)[keyof typeof BRIDGE_ENDPOINTS];
|
package/dist/protocol.js
CHANGED
|
@@ -5,11 +5,12 @@
|
|
|
5
5
|
* subpath keeps transport names discoverable for Node consumers while
|
|
6
6
|
* preserving one protocol vocabulary for browser and agent adapters.
|
|
7
7
|
*/
|
|
8
|
-
export { AGENT_PROTOCOL_LIMITS, AGENT_PROTOCOL_VERSION, CANVAS_COMMAND_TYPES, canonicalOrigin, defaultBridgePort, isAgentPromptRequest, isAgentSketchAttachment, isAgentSketchCaptureMetadata, isAgentSketchMetadata, isAgentStatusUpdate, isAllowedOrigin, isCanvasCommand, isCanvasGroup, isCanvasState, isCanonicalOrigin, isProjectIdentity, isSameOriginRoute, protocolError, validateSketchAttachments, validateRoutes, } from "./internal/agent-protocol.js";
|
|
8
|
+
export { AGENT_PROTOCOL_LIMITS, AGENT_PROTOCOL_VERSION, CANVAS_COMMAND_TYPES, canonicalOrigin, defaultBridgePort, isAgentPromptRequest, isAgentSketchAttachment, isAgentSketchCaptureMetadata, isAgentSketchMetadata, isAgentStatusUpdate, isAgentActivity, isAllowedOrigin, isCanvasCommand, isCanvasGroup, isCanvasState, isCanonicalOrigin, isProjectIdentity, isSameOriginRoute, protocolError, validateSketchAttachments, validateRoutes, } from "./internal/agent-protocol.js";
|
|
9
9
|
/** Stable endpoint names used by the loopback browser bridge. */
|
|
10
10
|
export const BRIDGE_ENDPOINTS = {
|
|
11
11
|
health: "/health",
|
|
12
12
|
pair: "/pair",
|
|
13
|
+
takeover: "/takeover",
|
|
13
14
|
events: "/events",
|
|
14
15
|
prompt: "/prompt",
|
|
15
16
|
status: "/status",
|
|
@@ -25,5 +26,6 @@ export const AGENT_CONTROL_ENDPOINTS = {
|
|
|
25
26
|
listen: "/__nudge/agent/listen",
|
|
26
27
|
status: "/__nudge/agent/status",
|
|
27
28
|
reportStatus: "/__nudge/agent/report-status",
|
|
29
|
+
activity: "/__nudge/agent/activity",
|
|
28
30
|
canvas: "/__nudge/agent/canvas",
|
|
29
31
|
};
|
package/dist/server.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
|
2
2
|
import type { Transport } from "@modelcontextprotocol/sdk/shared/transport.js";
|
|
3
3
|
import type { AgentProjectIdentity } from "./internal/agent-protocol.js";
|
|
4
4
|
import { type BrowserBridge, type BrowserBridgeOptions, type BridgeAddress } from "./bridge.js";
|
|
5
|
+
import { AdapterRouting } from "./adapterRouting.js";
|
|
5
6
|
import { DiscoveredProjectRouter } from "./discovery.js";
|
|
6
7
|
export declare const MCP_SERVER_NAME = "nudge-ui";
|
|
7
8
|
export declare const MCP_SERVER_VERSION: string;
|
|
@@ -29,13 +30,13 @@ export interface AgentCompanion {
|
|
|
29
30
|
export declare function createAgentCompanion(options: AgentCompanionOptions): AgentCompanion;
|
|
30
31
|
export interface DiscoveredAgentAdapter {
|
|
31
32
|
readonly mcpServer: McpServer;
|
|
32
|
-
readonly router: DiscoveredProjectRouter;
|
|
33
|
+
readonly router: DiscoveredProjectRouter | AdapterRouting;
|
|
33
34
|
start(transport?: Transport): Promise<void>;
|
|
34
35
|
close(): Promise<void>;
|
|
35
36
|
}
|
|
36
37
|
/** Creates a stdio MCP adapter that discovers project-owned bridges. */
|
|
37
38
|
export declare function createDiscoveredAgentAdapter(options: {
|
|
38
|
-
readonly workspaceRoot
|
|
39
|
+
readonly workspaceRoot?: string;
|
|
39
40
|
readonly registryRoot?: string;
|
|
40
41
|
readonly serverName?: string;
|
|
41
42
|
readonly serverVersion?: string;
|