@synergenius/flow-weaver 0.20.7 → 0.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api/command-runner.d.ts +13 -0
- package/dist/api/command-runner.js +217 -0
- package/dist/api/index.d.ts +1 -0
- package/dist/api/index.js +1 -0
- package/dist/cli/flow-weaver.mjs +24064 -38374
- package/dist/cli/index.js +0 -60
- package/dist/doc-metadata/extractors/cli-commands.js +37 -56
- package/dist/doc-metadata/extractors/mcp-tools.d.ts +1 -1
- package/dist/doc-metadata/extractors/mcp-tools.js +1 -213
- package/dist/doc-metadata/types.d.ts +2 -0
- package/dist/generated-version.d.ts +1 -1
- package/dist/generated-version.js +1 -1
- package/dist/mcp/index.d.ts +1 -5
- package/dist/mcp/index.js +0 -4
- package/dist/mcp/server.js +3 -55
- package/dist/mcp/types.d.ts +0 -50
- package/dist/mcp/types.js +1 -7
- package/dist/mcp/workflow-executor.js +23 -1
- package/dist/parser.js +5 -1
- package/package.json +1 -2
- package/dist/cli/commands/listen.d.ts +0 -16
- package/dist/cli/commands/listen.js +0 -39
- package/dist/cli/commands/tunnel.d.ts +0 -19
- package/dist/cli/commands/tunnel.js +0 -119
- package/dist/cli/commands/ui.d.ts +0 -16
- package/dist/cli/commands/ui.js +0 -130
- package/dist/cli/tunnel/dispatch.d.ts +0 -18
- package/dist/cli/tunnel/dispatch.js +0 -36
- package/dist/cli/tunnel/file-lock.d.ts +0 -9
- package/dist/cli/tunnel/file-lock.js +0 -36
- package/dist/cli/tunnel/handlers/ast-ops.d.ts +0 -10
- package/dist/cli/tunnel/handlers/ast-ops.js +0 -252
- package/dist/cli/tunnel/handlers/execution.d.ts +0 -7
- package/dist/cli/tunnel/handlers/execution.js +0 -89
- package/dist/cli/tunnel/handlers/file-ops.d.ts +0 -7
- package/dist/cli/tunnel/handlers/file-ops.js +0 -204
- package/dist/cli/tunnel/handlers/mutations.d.ts +0 -7
- package/dist/cli/tunnel/handlers/mutations.js +0 -285
- package/dist/cli/tunnel/handlers/stubs.d.ts +0 -7
- package/dist/cli/tunnel/handlers/stubs.js +0 -143
- package/dist/cli/tunnel/handlers/templates.d.ts +0 -7
- package/dist/cli/tunnel/handlers/templates.js +0 -123
- package/dist/cli/tunnel/path-resolver.d.ts +0 -17
- package/dist/cli/tunnel/path-resolver.js +0 -54
- package/dist/defaults.d.ts +0 -3
- package/dist/defaults.js +0 -3
- package/dist/mcp/editor-connection.d.ts +0 -52
- package/dist/mcp/editor-connection.js +0 -142
- package/dist/mcp/event-buffer.d.ts +0 -62
- package/dist/mcp/event-buffer.js +0 -150
- package/dist/mcp/resources.d.ts +0 -14
- package/dist/mcp/resources.js +0 -55
- package/dist/mcp/tools-editor.d.ts +0 -5
- package/dist/mcp/tools-editor.js +0 -283
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import type { AckResponse, EditorConnectionOptions } from './types.js';
|
|
2
|
-
import type { EventBuffer } from './event-buffer.js';
|
|
3
|
-
/**
|
|
4
|
-
* Manages a WebSocket connection to Flow Weaver Studio via socket.io.
|
|
5
|
-
* Supports sending commands and batches with request/response correlation,
|
|
6
|
-
* and forwards incoming `fw:` and `integration:` events to an {@link EventBuffer}.
|
|
7
|
-
*/
|
|
8
|
-
export declare class EditorConnection {
|
|
9
|
-
private socket;
|
|
10
|
-
private serverUrl;
|
|
11
|
-
private buffer;
|
|
12
|
-
private ioFactory;
|
|
13
|
-
private ackTimeout;
|
|
14
|
-
private hasLoggedDisconnect;
|
|
15
|
-
private wasConnected;
|
|
16
|
-
/**
|
|
17
|
-
* @param serverUrl - The base URL of the Studio WebSocket server.
|
|
18
|
-
* @param buffer - The event buffer to push incoming events into.
|
|
19
|
-
* @param options - Optional connection configuration (custom io factory, ack timeout).
|
|
20
|
-
*/
|
|
21
|
-
constructor(serverUrl: string, buffer: EventBuffer, options?: EditorConnectionOptions);
|
|
22
|
-
/**
|
|
23
|
-
* Establishes a WebSocket connection to Studio's `/integrations` namespace.
|
|
24
|
-
* Cleans up any previous connection first. Incoming `fw:` and `integration:` events
|
|
25
|
-
* are automatically forwarded to the event buffer.
|
|
26
|
-
* @param log - Optional logging callback for connection lifecycle events.
|
|
27
|
-
*/
|
|
28
|
-
connect(log?: (msg: string) => void): void;
|
|
29
|
-
/** Whether the socket is currently connected to Studio. */
|
|
30
|
-
get isConnected(): boolean;
|
|
31
|
-
/**
|
|
32
|
-
* Sends a single command to Studio and waits for an acknowledgement.
|
|
33
|
-
* Returns an error response if not connected or if the ack times out.
|
|
34
|
-
* @param action - The command action name (e.g. "get-state", "add-node").
|
|
35
|
-
* @param params - Parameters for the command.
|
|
36
|
-
* @returns Studio's acknowledgement response.
|
|
37
|
-
*/
|
|
38
|
-
sendCommand(action: string, params: Record<string, unknown>): Promise<AckResponse>;
|
|
39
|
-
/**
|
|
40
|
-
* Sends a batch of commands to Studio as a single request and waits for acknowledgement.
|
|
41
|
-
* Returns an error response if not connected or if the ack times out.
|
|
42
|
-
* @param commands - Array of commands, each with an action name and optional params.
|
|
43
|
-
* @returns Studio's acknowledgement response for the entire batch.
|
|
44
|
-
*/
|
|
45
|
-
sendBatch(commands: Array<{
|
|
46
|
-
action: string;
|
|
47
|
-
params?: Record<string, unknown>;
|
|
48
|
-
}>): Promise<AckResponse>;
|
|
49
|
-
/** Disconnects from Studio and releases the socket. */
|
|
50
|
-
disconnect(): void;
|
|
51
|
-
}
|
|
52
|
-
//# sourceMappingURL=editor-connection.d.ts.map
|
|
@@ -1,142 +0,0 @@
|
|
|
1
|
-
import { io as socketIO } from 'socket.io-client';
|
|
2
|
-
/**
|
|
3
|
-
* Manages a WebSocket connection to Flow Weaver Studio via socket.io.
|
|
4
|
-
* Supports sending commands and batches with request/response correlation,
|
|
5
|
-
* and forwards incoming `fw:` and `integration:` events to an {@link EventBuffer}.
|
|
6
|
-
*/
|
|
7
|
-
export class EditorConnection {
|
|
8
|
-
socket = null;
|
|
9
|
-
serverUrl;
|
|
10
|
-
buffer;
|
|
11
|
-
ioFactory;
|
|
12
|
-
ackTimeout;
|
|
13
|
-
hasLoggedDisconnect = false;
|
|
14
|
-
wasConnected = false;
|
|
15
|
-
/**
|
|
16
|
-
* @param serverUrl - The base URL of the Studio WebSocket server.
|
|
17
|
-
* @param buffer - The event buffer to push incoming events into.
|
|
18
|
-
* @param options - Optional connection configuration (custom io factory, ack timeout).
|
|
19
|
-
*/
|
|
20
|
-
constructor(serverUrl, buffer, options) {
|
|
21
|
-
this.serverUrl = serverUrl;
|
|
22
|
-
this.buffer = buffer;
|
|
23
|
-
this.ioFactory = options?.ioFactory ?? socketIO;
|
|
24
|
-
this.ackTimeout = options?.ackTimeout ?? 10_000;
|
|
25
|
-
}
|
|
26
|
-
/**
|
|
27
|
-
* Establishes a WebSocket connection to Studio's `/integrations` namespace.
|
|
28
|
-
* Cleans up any previous connection first. Incoming `fw:` and `integration:` events
|
|
29
|
-
* are automatically forwarded to the event buffer.
|
|
30
|
-
* @param log - Optional logging callback for connection lifecycle events.
|
|
31
|
-
*/
|
|
32
|
-
connect(log) {
|
|
33
|
-
// Clean up previous connection to prevent duplicate listeners
|
|
34
|
-
if (this.socket) {
|
|
35
|
-
this.socket.removeAllListeners();
|
|
36
|
-
this.socket.disconnect();
|
|
37
|
-
this.socket = null;
|
|
38
|
-
}
|
|
39
|
-
// Write a startup event immediately so the hook file exists from the start
|
|
40
|
-
this.buffer.push('mcp:status', { status: 'connecting', server: this.serverUrl });
|
|
41
|
-
this.socket = this.ioFactory(`${this.serverUrl}/integrations`, {
|
|
42
|
-
query: { clientType: 'mcp' },
|
|
43
|
-
transports: ['websocket', 'polling'],
|
|
44
|
-
reconnection: true,
|
|
45
|
-
reconnectionDelay: 1000,
|
|
46
|
-
reconnectionAttempts: Infinity,
|
|
47
|
-
});
|
|
48
|
-
this.socket.on('connect', () => {
|
|
49
|
-
const msg = this.wasConnected
|
|
50
|
-
? `Reconnected to Studio at ${this.serverUrl}`
|
|
51
|
-
: `Connected to Studio at ${this.serverUrl}`;
|
|
52
|
-
log?.(msg);
|
|
53
|
-
this.hasLoggedDisconnect = false;
|
|
54
|
-
this.wasConnected = true;
|
|
55
|
-
this.buffer.push('mcp:status', { status: 'connected', server: this.serverUrl });
|
|
56
|
-
});
|
|
57
|
-
if (log) {
|
|
58
|
-
this.socket.on('disconnect', () => {
|
|
59
|
-
if (!this.hasLoggedDisconnect) {
|
|
60
|
-
log('Studio disconnected');
|
|
61
|
-
this.hasLoggedDisconnect = true;
|
|
62
|
-
}
|
|
63
|
-
});
|
|
64
|
-
this.socket.on('connect_error', () => {
|
|
65
|
-
if (!this.hasLoggedDisconnect) {
|
|
66
|
-
log(`Studio not reachable at ${this.serverUrl}`);
|
|
67
|
-
this.hasLoggedDisconnect = true;
|
|
68
|
-
}
|
|
69
|
-
});
|
|
70
|
-
}
|
|
71
|
-
this.socket.onAny((event, data) => {
|
|
72
|
-
if (event.startsWith('fw:') || event.startsWith('integration:')) {
|
|
73
|
-
this.buffer.push(event, data);
|
|
74
|
-
}
|
|
75
|
-
});
|
|
76
|
-
}
|
|
77
|
-
/** Whether the socket is currently connected to Studio. */
|
|
78
|
-
get isConnected() {
|
|
79
|
-
return this.socket?.connected ?? false;
|
|
80
|
-
}
|
|
81
|
-
/**
|
|
82
|
-
* Sends a single command to Studio and waits for an acknowledgement.
|
|
83
|
-
* Returns an error response if not connected or if the ack times out.
|
|
84
|
-
* @param action - The command action name (e.g. "get-state", "add-node").
|
|
85
|
-
* @param params - Parameters for the command.
|
|
86
|
-
* @returns Studio's acknowledgement response.
|
|
87
|
-
*/
|
|
88
|
-
async sendCommand(action, params) {
|
|
89
|
-
if (!this.socket) {
|
|
90
|
-
return { requestId: '', success: false, error: 'Not connected' };
|
|
91
|
-
}
|
|
92
|
-
const requestId = `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
93
|
-
return new Promise((resolve) => {
|
|
94
|
-
const handler = (data) => {
|
|
95
|
-
if (data.requestId === requestId) {
|
|
96
|
-
clearTimeout(timeout);
|
|
97
|
-
this.socket.off('fw:ack', handler);
|
|
98
|
-
resolve(data);
|
|
99
|
-
}
|
|
100
|
-
};
|
|
101
|
-
const timeout = setTimeout(() => {
|
|
102
|
-
this.socket.off('fw:ack', handler);
|
|
103
|
-
resolve({ requestId, success: false, error: 'Timeout' });
|
|
104
|
-
}, this.ackTimeout);
|
|
105
|
-
this.socket.on('fw:ack', handler);
|
|
106
|
-
this.socket.emit('integration:command', { requestId, action, params });
|
|
107
|
-
});
|
|
108
|
-
}
|
|
109
|
-
/**
|
|
110
|
-
* Sends a batch of commands to Studio as a single request and waits for acknowledgement.
|
|
111
|
-
* Returns an error response if not connected or if the ack times out.
|
|
112
|
-
* @param commands - Array of commands, each with an action name and optional params.
|
|
113
|
-
* @returns Studio's acknowledgement response for the entire batch.
|
|
114
|
-
*/
|
|
115
|
-
async sendBatch(commands) {
|
|
116
|
-
if (!this.socket) {
|
|
117
|
-
return { requestId: '', success: false, error: 'Not connected' };
|
|
118
|
-
}
|
|
119
|
-
const requestId = `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
120
|
-
return new Promise((resolve) => {
|
|
121
|
-
const handler = (data) => {
|
|
122
|
-
if (data.requestId === requestId) {
|
|
123
|
-
clearTimeout(timeout);
|
|
124
|
-
this.socket.off('fw:ack', handler);
|
|
125
|
-
resolve(data);
|
|
126
|
-
}
|
|
127
|
-
};
|
|
128
|
-
const timeout = setTimeout(() => {
|
|
129
|
-
this.socket.off('fw:ack', handler);
|
|
130
|
-
resolve({ requestId, success: false, error: 'Timeout' });
|
|
131
|
-
}, this.ackTimeout);
|
|
132
|
-
this.socket.on('fw:ack', handler);
|
|
133
|
-
this.socket.emit('integration:batch', { requestId, commands });
|
|
134
|
-
});
|
|
135
|
-
}
|
|
136
|
-
/** Disconnects from Studio and releases the socket. */
|
|
137
|
-
disconnect() {
|
|
138
|
-
this.socket?.disconnect();
|
|
139
|
-
this.socket = null;
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
//# sourceMappingURL=editor-connection.js.map
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import type { BufferedEvent, EventFilterConfig } from './types.js';
|
|
2
|
-
/**
|
|
3
|
-
* In-memory circular buffer for editor events with filtering, deduplication, and optional
|
|
4
|
-
* file-based persistence. Events are filtered by include/exclude patterns and deduplicated
|
|
5
|
-
* within a configurable time window.
|
|
6
|
-
*/
|
|
7
|
-
export declare class EventBuffer {
|
|
8
|
-
private events;
|
|
9
|
-
private maxSize;
|
|
10
|
-
private eventsFilePath;
|
|
11
|
-
private filter;
|
|
12
|
-
private lastEventByType;
|
|
13
|
-
/**
|
|
14
|
-
* @param maxSize - Maximum buffer capacity. Defaults to the filter's `maxBufferSize`.
|
|
15
|
-
* @param eventsFilePath - Path to a file for appending events as NDJSON. Pass `null` to disable.
|
|
16
|
-
* Falls back to the `FW_EVENTS_FILE` environment variable if not specified.
|
|
17
|
-
* @param filter - Partial filter config merged with {@link DEFAULT_EVENT_FILTER}.
|
|
18
|
-
*/
|
|
19
|
-
constructor(maxSize?: number, eventsFilePath?: string | null, filter?: Partial<EventFilterConfig>);
|
|
20
|
-
/**
|
|
21
|
-
* Updates the event filter configuration. If `maxBufferSize` changes, trims the buffer to fit.
|
|
22
|
-
* @param partial - Partial filter fields to merge into the current config.
|
|
23
|
-
* @returns The full updated filter configuration.
|
|
24
|
-
*/
|
|
25
|
-
setFilter(partial: Partial<EventFilterConfig>): EventFilterConfig;
|
|
26
|
-
/** Returns a copy of the current event filter configuration. */
|
|
27
|
-
getFilter(): EventFilterConfig;
|
|
28
|
-
/**
|
|
29
|
-
* Pushes an event into the buffer. The event is dropped if it does not pass the
|
|
30
|
-
* include/exclude filters. If deduplication is enabled and an identical event type
|
|
31
|
-
* was pushed within the dedup window, the previous entry is replaced instead.
|
|
32
|
-
* Evicts the oldest events when the buffer exceeds `maxSize`.
|
|
33
|
-
* @param event - The event name.
|
|
34
|
-
* @param data - The event payload.
|
|
35
|
-
*/
|
|
36
|
-
push(event: string, data: unknown): void;
|
|
37
|
-
private matchesFilter;
|
|
38
|
-
private appendToFile;
|
|
39
|
-
/**
|
|
40
|
-
* Returns all buffered events and clears the buffer.
|
|
41
|
-
* @returns A copy of all events that were in the buffer.
|
|
42
|
-
*/
|
|
43
|
-
drain(): BufferedEvent[];
|
|
44
|
-
/**
|
|
45
|
-
* Returns a copy of all buffered events without clearing the buffer.
|
|
46
|
-
* @returns A copy of the current events.
|
|
47
|
-
*/
|
|
48
|
-
peek(): BufferedEvent[];
|
|
49
|
-
/** Clears all events from the buffer. */
|
|
50
|
-
clear(): void;
|
|
51
|
-
/** The number of events currently in the buffer. */
|
|
52
|
-
get length(): number;
|
|
53
|
-
}
|
|
54
|
-
/**
|
|
55
|
-
* Tests whether an event name matches a filter pattern.
|
|
56
|
-
* Supports exact matching and prefix matching when the pattern ends with `*`.
|
|
57
|
-
* @param event - The event name to test.
|
|
58
|
-
* @param pattern - The pattern to match against. Trailing `*` enables prefix matching.
|
|
59
|
-
* @returns `true` if the event matches the pattern.
|
|
60
|
-
*/
|
|
61
|
-
export declare function matchPattern(event: string, pattern: string): boolean;
|
|
62
|
-
//# sourceMappingURL=event-buffer.d.ts.map
|
package/dist/mcp/event-buffer.js
DELETED
|
@@ -1,150 +0,0 @@
|
|
|
1
|
-
import * as fs from 'fs';
|
|
2
|
-
import { DEFAULT_EVENT_FILTER } from './types.js';
|
|
3
|
-
/**
|
|
4
|
-
* In-memory circular buffer for editor events with filtering, deduplication, and optional
|
|
5
|
-
* file-based persistence. Events are filtered by include/exclude patterns and deduplicated
|
|
6
|
-
* within a configurable time window.
|
|
7
|
-
*/
|
|
8
|
-
export class EventBuffer {
|
|
9
|
-
events = [];
|
|
10
|
-
maxSize;
|
|
11
|
-
eventsFilePath;
|
|
12
|
-
filter;
|
|
13
|
-
lastEventByType = new Map();
|
|
14
|
-
/**
|
|
15
|
-
* @param maxSize - Maximum buffer capacity. Defaults to the filter's `maxBufferSize`.
|
|
16
|
-
* @param eventsFilePath - Path to a file for appending events as NDJSON. Pass `null` to disable.
|
|
17
|
-
* Falls back to the `FW_EVENTS_FILE` environment variable if not specified.
|
|
18
|
-
* @param filter - Partial filter config merged with {@link DEFAULT_EVENT_FILTER}.
|
|
19
|
-
*/
|
|
20
|
-
constructor(maxSize, eventsFilePath, filter) {
|
|
21
|
-
this.filter = { ...DEFAULT_EVENT_FILTER, ...filter };
|
|
22
|
-
this.maxSize = maxSize ?? this.filter.maxBufferSize;
|
|
23
|
-
// null = explicitly disabled, undefined = check env
|
|
24
|
-
this.eventsFilePath =
|
|
25
|
-
eventsFilePath === null ? null : (eventsFilePath ?? process.env.FW_EVENTS_FILE ?? null);
|
|
26
|
-
}
|
|
27
|
-
/**
|
|
28
|
-
* Updates the event filter configuration. If `maxBufferSize` changes, trims the buffer to fit.
|
|
29
|
-
* @param partial - Partial filter fields to merge into the current config.
|
|
30
|
-
* @returns The full updated filter configuration.
|
|
31
|
-
*/
|
|
32
|
-
setFilter(partial) {
|
|
33
|
-
this.filter = { ...this.filter, ...partial };
|
|
34
|
-
if (partial.maxBufferSize !== undefined) {
|
|
35
|
-
this.maxSize = partial.maxBufferSize;
|
|
36
|
-
if (this.events.length > this.maxSize) {
|
|
37
|
-
this.events = this.events.slice(this.events.length - this.maxSize);
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
return { ...this.filter };
|
|
41
|
-
}
|
|
42
|
-
/** Returns a copy of the current event filter configuration. */
|
|
43
|
-
getFilter() {
|
|
44
|
-
return { ...this.filter };
|
|
45
|
-
}
|
|
46
|
-
/**
|
|
47
|
-
* Pushes an event into the buffer. The event is dropped if it does not pass the
|
|
48
|
-
* include/exclude filters. If deduplication is enabled and an identical event type
|
|
49
|
-
* was pushed within the dedup window, the previous entry is replaced instead.
|
|
50
|
-
* Evicts the oldest events when the buffer exceeds `maxSize`.
|
|
51
|
-
* @param event - The event name.
|
|
52
|
-
* @param data - The event payload.
|
|
53
|
-
*/
|
|
54
|
-
push(event, data) {
|
|
55
|
-
if (!this.matchesFilter(event))
|
|
56
|
-
return;
|
|
57
|
-
const entry = {
|
|
58
|
-
event,
|
|
59
|
-
data,
|
|
60
|
-
timestamp: new Date().toISOString(),
|
|
61
|
-
};
|
|
62
|
-
// Dedup: if same event type within window, replace the last instance
|
|
63
|
-
if (this.filter.dedupeWindowMs > 0) {
|
|
64
|
-
const now = Date.now();
|
|
65
|
-
const lastTime = this.lastEventByType.get(event);
|
|
66
|
-
if (lastTime !== undefined && now - lastTime < this.filter.dedupeWindowMs) {
|
|
67
|
-
// Replace the last event of this type in the buffer
|
|
68
|
-
for (let i = this.events.length - 1; i >= 0; i--) {
|
|
69
|
-
if (this.events[i].event === event) {
|
|
70
|
-
this.events[i] = entry;
|
|
71
|
-
this.lastEventByType.set(event, now);
|
|
72
|
-
this.appendToFile(entry);
|
|
73
|
-
return;
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
this.lastEventByType.set(event, now);
|
|
78
|
-
}
|
|
79
|
-
this.events.push(entry);
|
|
80
|
-
// Evict oldest if over limit
|
|
81
|
-
if (this.events.length > this.maxSize) {
|
|
82
|
-
this.events = this.events.slice(this.events.length - this.maxSize);
|
|
83
|
-
}
|
|
84
|
-
this.appendToFile(entry);
|
|
85
|
-
}
|
|
86
|
-
matchesFilter(event) {
|
|
87
|
-
const { include, exclude } = this.filter;
|
|
88
|
-
// If include list is non-empty, event must match at least one pattern
|
|
89
|
-
if (include.length > 0) {
|
|
90
|
-
if (!include.some((pattern) => matchPattern(event, pattern))) {
|
|
91
|
-
return false;
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
// If event matches any exclude pattern, reject it
|
|
95
|
-
if (exclude.length > 0) {
|
|
96
|
-
if (exclude.some((pattern) => matchPattern(event, pattern))) {
|
|
97
|
-
return false;
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
return true;
|
|
101
|
-
}
|
|
102
|
-
appendToFile(entry) {
|
|
103
|
-
if (!this.eventsFilePath)
|
|
104
|
-
return;
|
|
105
|
-
try {
|
|
106
|
-
fs.appendFileSync(this.eventsFilePath, JSON.stringify(entry) + '\n');
|
|
107
|
-
}
|
|
108
|
-
catch {
|
|
109
|
-
// File may have been atomically moved by the hook — next push creates a new one
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
/**
|
|
113
|
-
* Returns all buffered events and clears the buffer.
|
|
114
|
-
* @returns A copy of all events that were in the buffer.
|
|
115
|
-
*/
|
|
116
|
-
drain() {
|
|
117
|
-
const result = [...this.events];
|
|
118
|
-
this.events = [];
|
|
119
|
-
return result;
|
|
120
|
-
}
|
|
121
|
-
/**
|
|
122
|
-
* Returns a copy of all buffered events without clearing the buffer.
|
|
123
|
-
* @returns A copy of the current events.
|
|
124
|
-
*/
|
|
125
|
-
peek() {
|
|
126
|
-
return [...this.events];
|
|
127
|
-
}
|
|
128
|
-
/** Clears all events from the buffer. */
|
|
129
|
-
clear() {
|
|
130
|
-
this.events = [];
|
|
131
|
-
}
|
|
132
|
-
/** The number of events currently in the buffer. */
|
|
133
|
-
get length() {
|
|
134
|
-
return this.events.length;
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
/**
|
|
138
|
-
* Tests whether an event name matches a filter pattern.
|
|
139
|
-
* Supports exact matching and prefix matching when the pattern ends with `*`.
|
|
140
|
-
* @param event - The event name to test.
|
|
141
|
-
* @param pattern - The pattern to match against. Trailing `*` enables prefix matching.
|
|
142
|
-
* @returns `true` if the event matches the pattern.
|
|
143
|
-
*/
|
|
144
|
-
export function matchPattern(event, pattern) {
|
|
145
|
-
if (pattern.endsWith('*')) {
|
|
146
|
-
return event.startsWith(pattern.slice(0, -1));
|
|
147
|
-
}
|
|
148
|
-
return event === pattern;
|
|
149
|
-
}
|
|
150
|
-
//# sourceMappingURL=event-buffer.js.map
|
package/dist/mcp/resources.d.ts
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
-
import type { EditorConnection } from './editor-connection.js';
|
|
3
|
-
import type { EventBuffer } from './event-buffer.js';
|
|
4
|
-
/**
|
|
5
|
-
* Registers MCP resources that expose Studio state and event data.
|
|
6
|
-
* Registers two resources:
|
|
7
|
-
* - `fw://events` - read-only peek at the event buffer.
|
|
8
|
-
* - `fw://state` - current Studio/workflow state fetched via the Studio connection.
|
|
9
|
-
* @param mcp - The MCP server instance to register resources on.
|
|
10
|
-
* @param connection - The Studio WebSocket connection used to query state.
|
|
11
|
-
* @param buffer - The event buffer to read events from.
|
|
12
|
-
*/
|
|
13
|
-
export declare function registerResources(mcp: McpServer, connection: EditorConnection, buffer: EventBuffer): void;
|
|
14
|
-
//# sourceMappingURL=resources.d.ts.map
|
package/dist/mcp/resources.js
DELETED
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Registers MCP resources that expose Studio state and event data.
|
|
3
|
-
* Registers two resources:
|
|
4
|
-
* - `fw://events` - read-only peek at the event buffer.
|
|
5
|
-
* - `fw://state` - current Studio/workflow state fetched via the Studio connection.
|
|
6
|
-
* @param mcp - The MCP server instance to register resources on.
|
|
7
|
-
* @param connection - The Studio WebSocket connection used to query state.
|
|
8
|
-
* @param buffer - The event buffer to read events from.
|
|
9
|
-
*/
|
|
10
|
-
export function registerResources(mcp, connection, buffer) {
|
|
11
|
-
mcp.resource('events', 'fw://events', { description: 'Read-only view of the event buffer (does not clear it)' }, async () => ({
|
|
12
|
-
contents: [
|
|
13
|
-
{
|
|
14
|
-
uri: 'fw://events',
|
|
15
|
-
text: JSON.stringify(buffer.peek(), null, 2),
|
|
16
|
-
},
|
|
17
|
-
],
|
|
18
|
-
}));
|
|
19
|
-
mcp.resource('state', 'fw://state', { description: 'Current Studio/workflow state' }, async () => {
|
|
20
|
-
if (!connection.isConnected) {
|
|
21
|
-
return {
|
|
22
|
-
contents: [
|
|
23
|
-
{
|
|
24
|
-
uri: 'fw://state',
|
|
25
|
-
text: JSON.stringify({ error: 'Not connected to Studio' }),
|
|
26
|
-
},
|
|
27
|
-
],
|
|
28
|
-
};
|
|
29
|
-
}
|
|
30
|
-
try {
|
|
31
|
-
const result = await connection.sendCommand('get-state', {});
|
|
32
|
-
return {
|
|
33
|
-
contents: [
|
|
34
|
-
{
|
|
35
|
-
uri: 'fw://state',
|
|
36
|
-
text: JSON.stringify(result, null, 2),
|
|
37
|
-
},
|
|
38
|
-
],
|
|
39
|
-
};
|
|
40
|
-
}
|
|
41
|
-
catch (err) {
|
|
42
|
-
return {
|
|
43
|
-
contents: [
|
|
44
|
-
{
|
|
45
|
-
uri: 'fw://state',
|
|
46
|
-
text: JSON.stringify({
|
|
47
|
-
error: `Failed to get state: ${err instanceof Error ? err.message : String(err)}`,
|
|
48
|
-
}),
|
|
49
|
-
},
|
|
50
|
-
],
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
|
-
//# sourceMappingURL=resources.js.map
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
-
import type { EditorConnection } from './editor-connection.js';
|
|
3
|
-
import type { EventBuffer } from './event-buffer.js';
|
|
4
|
-
export declare function registerEditorTools(mcp: McpServer, connection: EditorConnection, buffer: EventBuffer): void;
|
|
5
|
-
//# sourceMappingURL=tools-editor.d.ts.map
|