@luckydraw/cumulus 0.27.19 → 0.27.21

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.
Files changed (48) hide show
  1. package/dist/cli/cumulus.js +0 -0
  2. package/dist/gateway/adapters/webchat.d.ts +3 -1
  3. package/dist/gateway/adapters/webchat.d.ts.map +1 -1
  4. package/dist/gateway/adapters/webchat.js +168 -4
  5. package/dist/gateway/adapters/webchat.js.map +1 -1
  6. package/dist/gateway/daemon.js +8 -0
  7. package/dist/gateway/daemon.js.map +1 -1
  8. package/dist/gateway/device-mcp.d.ts +21 -0
  9. package/dist/gateway/device-mcp.d.ts.map +1 -0
  10. package/dist/gateway/device-mcp.js +165 -0
  11. package/dist/gateway/device-mcp.js.map +1 -0
  12. package/dist/gateway/gateway-agents-mcp.js +1 -1
  13. package/dist/gateway/gateway-agents-mcp.js.map +1 -1
  14. package/dist/gateway/server.d.ts +9 -0
  15. package/dist/gateway/server.d.ts.map +1 -1
  16. package/dist/gateway/server.js +243 -6
  17. package/dist/gateway/server.js.map +1 -1
  18. package/dist/gateway/static/widget.js +861 -43
  19. package/dist/index.d.ts +4 -0
  20. package/dist/index.d.ts.map +1 -1
  21. package/dist/index.js +6 -0
  22. package/dist/index.js.map +1 -1
  23. package/dist/lib/config.d.ts +8 -0
  24. package/dist/lib/config.d.ts.map +1 -1
  25. package/dist/lib/config.js +61 -1
  26. package/dist/lib/config.js.map +1 -1
  27. package/dist/lib/content-detector.d.ts.map +1 -1
  28. package/dist/lib/content-detector.js +9 -2
  29. package/dist/lib/content-detector.js.map +1 -1
  30. package/dist/lib/executor.d.ts +168 -0
  31. package/dist/lib/executor.d.ts.map +1 -0
  32. package/dist/lib/executor.js +284 -0
  33. package/dist/lib/executor.js.map +1 -0
  34. package/dist/lib/gateway.d.ts +14 -2
  35. package/dist/lib/gateway.d.ts.map +1 -1
  36. package/dist/lib/gateway.js +234 -103
  37. package/dist/lib/gateway.js.map +1 -1
  38. package/dist/lib/summaries.d.ts.map +1 -1
  39. package/dist/lib/summaries.js +9 -2
  40. package/dist/lib/summaries.js.map +1 -1
  41. package/dist/mcp/index.js +0 -0
  42. package/dist/mcp/tool-handler.d.ts.map +1 -1
  43. package/dist/mcp/tool-handler.js +10 -3
  44. package/dist/mcp/tool-handler.js.map +1 -1
  45. package/dist/tui/hooks/useClaudeProcess.d.ts.map +1 -1
  46. package/dist/tui/hooks/useClaudeProcess.js +18 -23
  47. package/dist/tui/hooks/useClaudeProcess.js.map +1 -1
  48. package/package.json +1 -1
@@ -0,0 +1,165 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Device MCP Server
4
+ *
5
+ * Stdio-based MCP server that gives Claude subprocesses running on the gateway
6
+ * the ability to read/write files and execute commands on a remote device
7
+ * (e.g., the user's Mac) via the gateway's device routing API.
8
+ *
9
+ * Environment variables (set by generateMcpConfig):
10
+ * GATEWAY_API_URL - Gateway HTTP base URL (e.g., http://127.0.0.1:8090)
11
+ * GATEWAY_API_KEY - API key for authentication
12
+ * DEVICE_EXECUTOR_ID - Target device executor ID (e.g., "mac-karl")
13
+ *
14
+ * Tools:
15
+ * device_read_file - Read a file from the remote device
16
+ * device_write_file - Write content to a file on the remote device
17
+ * device_list_directory - List files in a directory on the remote device
18
+ * device_execute_command - Execute a shell command on the remote device
19
+ */
20
+ import * as http from 'http';
21
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
22
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
23
+ import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';
24
+ const API_URL = process.env.GATEWAY_API_URL || 'http://127.0.0.1:8090';
25
+ const API_KEY = process.env.GATEWAY_API_KEY || '';
26
+ const DEVICE_ID = process.env.DEVICE_EXECUTOR_ID || 'unknown';
27
+ function apiRequest(method, urlPath, body) {
28
+ return new Promise(resolve => {
29
+ const url = new URL(urlPath, API_URL);
30
+ const options = {
31
+ hostname: url.hostname,
32
+ port: url.port,
33
+ path: url.pathname + url.search,
34
+ method,
35
+ headers: {
36
+ 'Content-Type': 'application/json',
37
+ 'X-API-Key': API_KEY,
38
+ },
39
+ };
40
+ const req = http.request(options, res => {
41
+ let data = '';
42
+ res.on('data', (chunk) => (data += chunk.toString()));
43
+ res.on('end', () => {
44
+ try {
45
+ resolve(JSON.parse(data));
46
+ }
47
+ catch {
48
+ resolve({ error: 'Invalid JSON response' });
49
+ }
50
+ });
51
+ });
52
+ req.on('error', (err) => {
53
+ resolve({ error: `Request failed: ${err.message}` });
54
+ });
55
+ if (body) {
56
+ req.write(JSON.stringify(body));
57
+ }
58
+ req.end();
59
+ });
60
+ }
61
+ // ─── MCP Server ─────────────────────────────────────────────────────────────
62
+ const server = new Server({ name: `device-${DEVICE_ID}`, version: '1.0.0' }, { capabilities: { tools: {} } });
63
+ server.setRequestHandler(ListToolsRequestSchema, async () => ({
64
+ tools: [
65
+ {
66
+ name: 'device_read_file',
67
+ description: `Read the contents of a file on the remote device "${DEVICE_ID}". Returns the file content as text.`,
68
+ inputSchema: {
69
+ type: 'object',
70
+ properties: {
71
+ path: {
72
+ type: 'string',
73
+ description: 'Absolute file path on the device',
74
+ },
75
+ },
76
+ required: ['path'],
77
+ },
78
+ },
79
+ {
80
+ name: 'device_write_file',
81
+ description: `Write content to a file on the remote device "${DEVICE_ID}". Creates parent directories if needed.`,
82
+ inputSchema: {
83
+ type: 'object',
84
+ properties: {
85
+ path: {
86
+ type: 'string',
87
+ description: 'Absolute file path on the device',
88
+ },
89
+ content: {
90
+ type: 'string',
91
+ description: 'File content to write',
92
+ },
93
+ },
94
+ required: ['path', 'content'],
95
+ },
96
+ },
97
+ {
98
+ name: 'device_list_directory',
99
+ description: `List files and directories at a path on the remote device "${DEVICE_ID}".`,
100
+ inputSchema: {
101
+ type: 'object',
102
+ properties: {
103
+ path: {
104
+ type: 'string',
105
+ description: 'Absolute directory path on the device',
106
+ },
107
+ },
108
+ required: ['path'],
109
+ },
110
+ },
111
+ {
112
+ name: 'device_execute_command',
113
+ description: `Execute a shell command on the remote device "${DEVICE_ID}". Returns stdout, stderr, and exit code. Use for builds, git, local tools, etc.`,
114
+ inputSchema: {
115
+ type: 'object',
116
+ properties: {
117
+ command: {
118
+ type: 'string',
119
+ description: 'Shell command to execute',
120
+ },
121
+ cwd: {
122
+ type: 'string',
123
+ description: 'Working directory for the command (optional)',
124
+ },
125
+ timeout: {
126
+ type: 'number',
127
+ description: 'Timeout in milliseconds (default: 30000)',
128
+ },
129
+ },
130
+ required: ['command'],
131
+ },
132
+ },
133
+ ],
134
+ }));
135
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
136
+ const { name, arguments: args } = request.params;
137
+ const result = await apiRequest('POST', `/api/device/${encodeURIComponent(DEVICE_ID)}/tool`, {
138
+ tool: name,
139
+ args: args || {},
140
+ });
141
+ if (result.error) {
142
+ return {
143
+ content: [{ type: 'text', text: `Device error: ${result.error}` }],
144
+ isError: true,
145
+ };
146
+ }
147
+ return {
148
+ content: [
149
+ {
150
+ type: 'text',
151
+ text: typeof result.result === 'string'
152
+ ? result.result
153
+ : JSON.stringify(result.result, null, 2),
154
+ },
155
+ ],
156
+ isError: !!result.isError,
157
+ };
158
+ });
159
+ // ─── Start ──────────────────────────────────────────────────────────────────
160
+ const transport = new StdioServerTransport();
161
+ server.connect(transport).catch((err) => {
162
+ console.error(`[device-mcp] Failed to start: ${err.message}`);
163
+ process.exit(1);
164
+ });
165
+ //# sourceMappingURL=device-mcp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"device-mcp.js","sourceRoot":"","sources":["../../src/gateway/device-mcp.ts"],"names":[],"mappings":"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"}
@@ -130,7 +130,7 @@ async function main() {
130
130
  },
131
131
  {
132
132
  name: 'notify_user',
133
- description: 'Send a push notification to the user\'s phone/device. Use this when you need to alert the user about something important — task completion, errors, questions that need human input, or anything worth interrupting them for. The notification appears even if they\'re not looking at the chat.',
133
+ description: "Send a push notification to the user's phone/device. Use this when you need to alert the user about something important — task completion, errors, questions that need human input, or anything worth interrupting them for. The notification appears even if they're not looking at the chat.",
134
134
  inputSchema: {
135
135
  type: 'object',
136
136
  properties: {
@@ -1 +1 @@
1
- {"version":3,"file":"gateway-agents-mcp.js","sourceRoot":"","sources":["../../src/gateway/gateway-agents-mcp.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAE7B,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,oCAAoC,CAAC;AAEnG,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,uBAAuB,CAAC;AACvE,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,EAAE,CAAC;AAClD,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,SAAS,CAAC;AAE/D;;GAEG;AACH,SAAS,UAAU,CACjB,MAAc,EACd,OAAe,EACf,IAA8B;IAE9B,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE;QAC3B,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACtC,MAAM,OAAO,GAAG;YACd,QAAQ,EAAE,GAAG,CAAC,QAAQ;YACtB,IAAI,EAAE,GAAG,CAAC,IAAI;YACd,IAAI,EAAE,GAAG,CAAC,QAAQ,GAAG,GAAG,CAAC,MAAM;YAC/B,MAAM;YACN,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,WAAW,EAAE,OAAO;aACrB;SACF,CAAC;QAEF,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,EAAE;YACtC,IAAI,IAAI,GAAG,EAAE,CAAC;YACd,GAAG,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE,CAAC,CAAC,IAAI,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;YAC9D,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE;gBACjB,IAAI,CAAC;oBACH,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAA4B,CAAC,CAAC;gBACvD,CAAC;gBAAC,MAAM,CAAC;oBACP,OAAO,CAAC,EAAE,KAAK,EAAE,uBAAuB,EAAE,CAAC,CAAC;gBAC9C,CAAC;YACH,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAU,EAAE,EAAE;YAC7B,OAAO,CAAC,EAAE,KAAK,EAAE,+BAA+B,GAAG,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;QACnE,CAAC,CAAC,CAAC;QAEH,IAAI,IAAI,EAAE,CAAC;YACT,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;QAClC,CAAC;QACD,GAAG,CAAC,GAAG,EAAE,CAAC;IACZ,CAAC,CAAC,CAAC;AACL,CAAC;AAED,KAAK,UAAU,IAAI;IACjB,MAAM,MAAM,GAAG,IAAI,MAAM,CACvB,EAAE,IAAI,EAAE,gBAAgB,EAAE,OAAO,EAAE,OAAO,EAAE,EAC5C,EAAE,YAAY,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,CAChC,CAAC;IAEF,uBAAuB;IACvB,MAAM,CAAC,iBAAiB,CAAC,sBAAsB,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC;QAC5D,KAAK,EAAE;YACL;gBACE,IAAI,EAAE,aAAa;gBACnB,WAAW,EACT,iLAAiL;gBACnL,WAAW,EAAE;oBACX,IAAI,EAAE,QAAiB;oBACvB,UAAU,EAAE,EAAE;oBACd,QAAQ,EAAE,EAAE;iBACb;aACF;YACD;gBACE,IAAI,EAAE,eAAe;gBACrB,WAAW,EACT,uQAAuQ;gBACzQ,WAAW,EAAE;oBACX,IAAI,EAAE,QAAiB;oBACvB,UAAU,EAAE;wBACV,MAAM,EAAE;4BACN,WAAW,EACT,wGAAwG;4BAC1G,KAAK,EAAE;gCACL,EAAE,IAAI,EAAE,QAAiB,EAAE;gCAC3B,EAAE,IAAI,EAAE,OAAgB,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,QAAiB,EAAE,EAAE;6BAC/D;yBACF;wBACD,OAAO,EAAE;4BACP,IAAI,EAAE,QAAiB;4BACvB,WAAW,EACT,6EAA6E;yBAChF;wBACD,UAAU,EAAE;4BACV,WAAW,EACT,2PAA2P;4BAC7P,KAAK,EAAE;gCACL,EAAE,IAAI,EAAE,QAAiB,EAAE,IAAI,EAAE,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE;gCAClD;oCACE,IAAI,EAAE,QAAiB;oCACvB,UAAU,EAAE;wCACV,MAAM,EAAE;4CACN,IAAI,EAAE,OAAgB;4CACtB,KAAK,EAAE,EAAE,IAAI,EAAE,QAAiB,EAAE;4CAClC,WAAW,EAAE,4CAA4C;yCAC1D;qCACF;oCACD,QAAQ,EAAE,CAAC,QAAQ,CAAC;iCACrB;6BACF;yBACF;qBACF;oBACD,QAAQ,EAAE,CAAC,QAAQ,EAAE,SAAS,CAAC;iBAChC;aACF;YACD;gBACE,IAAI,EAAE,WAAW;gBACjB,WAAW,EACT,wJAAwJ;gBAC1J,WAAW,EAAE;oBACX,IAAI,EAAE,QAAiB;oBACvB,UAAU,EAAE;wBACV,OAAO,EAAE;4BACP,IAAI,EAAE,QAAiB;4BACvB,WAAW,EAAE,yCAAyC;yBACvD;qBACF;oBACD,QAAQ,EAAE,CAAC,SAAS,CAAC;iBACtB;aACF;YACD;gBACE,IAAI,EAAE,aAAa;gBACnB,WAAW,EACT,kSAAkS;gBACpS,WAAW,EAAE;oBACX,IAAI,EAAE,QAAiB;oBACvB,UAAU,EAAE;wBACV,OAAO,EAAE;4BACP,IAAI,EAAE,QAAiB;4BACvB,WAAW,EACT,sGAAsG;yBACzG;wBACD,KAAK,EAAE;4BACL,IAAI,EAAE,QAAiB;4BACvB,WAAW,EACT,wFAAwF;yBAC3F;wBACD,QAAQ,EAAE;4BACR,IAAI,EAAE,QAAiB;4BACvB,IAAI,EAAE,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,CAAC;4BAC/B,WAAW,EACT,kHAAkH;yBACrH;qBACF;oBACD,QAAQ,EAAE,CAAC,SAAS,CAAC;iBACtB;aACF;SACF;KACF,CAAC,CAAC,CAAC;IAEJ,oBAAoB;IACpB,MAAM,CAAC,iBAAiB,CAAC,qBAAqB,EAAE,KAAK,EAAC,OAAO,EAAC,EAAE;QAC9D,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;QAEjD,IAAI,IAAI,KAAK,aAAa,EAAE,CAAC;YAC3B,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,KAAK,EAAE,aAAa,CAAC,CAAC;YACtD,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;gBACjB,OAAO;oBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC;oBACnF,OAAO,EAAE,IAAI;iBACd,CAAC;YACJ,CAAC;YACD,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;4BACnB,MAAM,EAAE,MAAM,CAAC,MAAM,IAAI,EAAE;4BAC3B,IAAI,EAAE,UAAU;yBACjB,CAAC;qBACH;iBACF;aACF,CAAC;QACJ,CAAC;QAED,IAAI,IAAI,KAAK,eAAe,EAAE,CAAC;YAC7B,MAAM,MAAM,GAAG,IAAI,EAAE,MAAuC,CAAC;YAC7D,MAAM,OAAO,GAAG,IAAI,EAAE,OAA6B,CAAC;YACpD,MAAM,UAAU,GAAG,IAAI,EAAE,UAAuD,CAAC;YAEjF,IAAI,CAAC,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;gBACxB,OAAO;oBACL,OAAO,EAAE;wBACP;4BACE,IAAI,EAAE,MAAe;4BACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,EAAE,2BAA2B,EAAE,CAAC;yBAC/E;qBACF;oBACD,OAAO,EAAE,IAAI;iBACd,CAAC;YACJ,CAAC;YAED,4BAA4B;YAC5B,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;YAE1D,kBAAkB;YAClB,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,UAAU,CAAC,CAAC;YACvD,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC1B,OAAO;oBACL,OAAO,EAAE;wBACP;4BACE,IAAI,EAAE,MAAe;4BACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,EAAE,6BAA6B,EAAE,CAAC;yBACjF;qBACF;oBACD,OAAO,EAAE,IAAI;iBACd,CAAC;YACJ,CAAC;YAED,MAAM,IAAI,GAA4B;gBACpC,OAAO,EAAE,QAAQ;gBACjB,OAAO;gBACP,MAAM,EAAE,UAAU;gBAClB,WAAW,EAAE,QAAQ;aACtB,CAAC;YACF,IAAI,UAAU,EAAE,CAAC;gBACf,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;YAC/B,CAAC;YAED,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,MAAM,EAAE,oBAAoB,EAAE,IAAI,CAAC,CAAC;YAEpE,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC;gBAClE,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC,KAAK;aACxB,CAAC;QACJ,CAAC;QAED,IAAI,IAAI,KAAK,WAAW,EAAE,CAAC;YACzB,MAAM,OAAO,GAAG,IAAI,EAAE,OAA6B,CAAC;YACpD,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,OAAO;oBACL,OAAO,EAAE;wBACP;4BACE,IAAI,EAAE,MAAe;4BACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,EAAE,iBAAiB,EAAE,CAAC;yBACrE;qBACF;oBACD,OAAO,EAAE,IAAI;iBACd,CAAC;YACJ,CAAC;YAED,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,MAAM,EAAE,oBAAoB,EAAE;gBAC5D,OAAO,EAAE,eAAe;gBACxB,OAAO;gBACP,MAAM,EAAE,UAAU;gBAClB,WAAW,EAAE,WAAW;aACzB,CAAC,CAAC;YAEH,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC;gBAClE,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC,KAAK;aACxB,CAAC;QACJ,CAAC;QAED,IAAI,IAAI,KAAK,aAAa,EAAE,CAAC;YAC3B,MAAM,OAAO,GAAG,IAAI,EAAE,OAA6B,CAAC;YACpD,MAAM,KAAK,GAAI,IAAI,EAAE,KAAgB,IAAI,UAAU,CAAC;YACpD,MAAM,QAAQ,GAAI,IAAI,EAAE,QAAmB,IAAI,QAAQ,CAAC;YAExD,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,OAAO;oBACL,OAAO,EAAE;wBACP;4BACE,IAAI,EAAE,MAAe;4BACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,iBAAiB,EAAE,CAAC;yBAChE;qBACF;oBACD,OAAO,EAAE,IAAI;iBACd,CAAC;YACJ,CAAC;YAED,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,MAAM,EAAE,aAAa,EAAE;gBACrD,KAAK;gBACL,IAAI,EAAE,OAAO;gBACb,UAAU,EAAE,UAAU;gBACtB,QAAQ;aACT,CAAC,CAAC;YAEH,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC;gBAClE,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC,KAAK;aACxB,CAAC;QACJ,CAAC;QAED,OAAO;YACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,iBAAiB,IAAI,EAAE,EAAE,CAAC;YACnE,OAAO,EAAE,IAAI;SACd,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,oBAAoB;IACpB,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;AAClC,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE;IACjB,OAAO,CAAC,KAAK,CAAC,kCAAkC,EAAE,GAAG,CAAC,CAAC;IACvD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"gateway-agents-mcp.js","sourceRoot":"","sources":["../../src/gateway/gateway-agents-mcp.ts"],"names":[],"mappings":"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"}
@@ -12,6 +12,7 @@
12
12
  * POST /api/migrate — sync thread + clone repo + set projectDir
13
13
  * GET /health — health check (no auth)
14
14
  */
15
+ import { ExecutorRegistry } from '../lib/executor.js';
15
16
  import { type McpServerEntry, type GatewayAgentsConfig } from '../lib/gateway.js';
16
17
  import { type VapidConfig } from './push.js';
17
18
  export interface GatewayServerOptions {
@@ -26,6 +27,10 @@ export interface GatewayServerOptions {
26
27
  extraMcpServers?: Record<string, McpServerEntry>;
27
28
  /** Auto-include gateway-agents MCP server with these settings */
28
29
  gatewayAgentsConfig?: GatewayAgentsConfig;
30
+ /** Executor registry for remote dispatch (created internally if not provided) */
31
+ executorRegistry?: ExecutorRegistry;
32
+ /** Broadcast to WebSocket clients watching a thread (set by webchat adapter after startup) */
33
+ broadcastToThread?: (threadName: string, event: Record<string, unknown>) => void;
29
34
  /** VAPID config for web push notifications */
30
35
  vapid?: VapidConfig;
31
36
  }
@@ -37,6 +42,10 @@ export interface GatewayServerHandle {
37
42
  close: () => Promise<void>;
38
43
  /** Hot-reload API keys without restarting the server */
39
44
  updateApiKeys?: (newKeys: string[]) => void;
45
+ /** Executor registry for remote dispatch */
46
+ executorRegistry: ExecutorRegistry;
47
+ /** Set broadcast function — routes agent inject notifications to WebSocket clients */
48
+ setBroadcastToThread: (fn: (threadName: string, event: Record<string, unknown>) => void) => void;
40
49
  }
41
50
  /**
42
51
  * Format an agent message for a specific recipient, applying visibility rules.
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/gateway/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAUH,OAAO,EAIL,KAAK,cAAc,EACnB,KAAK,mBAAmB,EACzB,MAAM,mBAAmB,CAAC;AAU3B,OAAO,EAML,KAAK,WAAW,EACjB,MAAM,WAAW,CAAC;AAInB,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,2FAA2F;IAC3F,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,mFAAmF;IACnF,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IACjD,iEAAiE;IACjE,mBAAmB,CAAC,EAAE,mBAAmB,CAAC;IAC1C,8CAA8C;IAC9C,KAAK,CAAC,EAAE,WAAW,CAAC;CACrB;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,iFAAiF;IACjF,MAAM,EAAE,OAAO,MAAM,EAAE,MAAM,CAAC;IAC9B,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3B,wDAAwD;IACxD,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;CAC7C;AAgQD;;;;;;;;GAQG;AACH,wBAAgB,8BAA8B,CAC5C,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,EAClB,aAAa,EAAE,MAAM,EACrB,IAAI,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,GAAG;QAAE,MAAM,EAAE,MAAM,EAAE,CAAA;KAAE,CAAA;CAAE,GACpF,MAAM,CA2DR;AA8qBD,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,mBAAmB,CAAC,CA4K9B"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/gateway/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAYH,OAAO,EAAE,gBAAgB,EAAgC,MAAM,oBAAoB,CAAC;AACpF,OAAO,EAIL,KAAK,cAAc,EACnB,KAAK,mBAAmB,EACzB,MAAM,mBAAmB,CAAC;AAU3B,OAAO,EAML,KAAK,WAAW,EACjB,MAAM,WAAW,CAAC;AAInB,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,2FAA2F;IAC3F,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,mFAAmF;IACnF,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IACjD,iEAAiE;IACjE,mBAAmB,CAAC,EAAE,mBAAmB,CAAC;IAC1C,iFAAiF;IACjF,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC,8FAA8F;IAC9F,iBAAiB,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IACjF,8CAA8C;IAC9C,KAAK,CAAC,EAAE,WAAW,CAAC;CACrB;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,iFAAiF;IACjF,MAAM,EAAE,OAAO,MAAM,EAAE,MAAM,CAAC;IAC9B,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3B,wDAAwD;IACxD,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IAC5C,4CAA4C;IAC5C,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,sFAAsF;IACtF,oBAAoB,EAAE,CAAC,EAAE,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,KAAK,IAAI,CAAC;CAClG;AAoSD;;;;;;;;GAQG;AACH,wBAAgB,8BAA8B,CAC5C,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,EAClB,aAAa,EAAE,MAAM,EACrB,IAAI,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,GAAG;QAAE,MAAM,EAAE,MAAM,EAAE,CAAA;KAAE,CAAA;CAAE,GACpF,MAAM,CA2DR;AA40BD,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,mBAAmB,CAAC,CAiQ9B"}
@@ -17,8 +17,10 @@ import * as fs from 'fs';
17
17
  import * as http from 'http';
18
18
  import * as os from 'os';
19
19
  import * as path from 'path';
20
+ import { WebSocketServer } from 'ws';
20
21
  import { loadThreadConfig, saveThreadConfig } from '../lib/config.js';
21
22
  import { loadEmbeddings, generateMissingEmbeddings } from '../lib/embeddings.js';
23
+ import { ExecutorRegistry } from '../lib/executor.js';
22
24
  import { sendMessage, getOrCreateThread, clearThreadCache, } from '../lib/gateway.js';
23
25
  import { catchUpSegmentation, loadSegmentBoundaries, saveSegmentBoundaries, } from '../lib/segments.js';
24
26
  import { listTemplates, scaffoldFromTemplate } from '../lib/templates.js';
@@ -85,6 +87,7 @@ async function processMessage(threadName, item, opts) {
85
87
  projectRoot: opts.projectRoot,
86
88
  extraMcpServers: opts.extraMcpServers,
87
89
  gatewayAgentsConfig: opts.gatewayAgentsConfig,
90
+ executorRegistry: opts.executorRegistry,
88
91
  signal: ac.signal,
89
92
  onToken: text => sendSSE('token', { text }),
90
93
  onSegment: segment => sendSSE('segment', segment),
@@ -202,6 +205,7 @@ async function handleAgentInject(req, res, pipelineOpts) {
202
205
  await getOrCreateThread(targetName);
203
206
  // Send as a message through the pipeline (fire-and-forget)
204
207
  threadBusy.set(targetName, true);
208
+ const broadcast = pipelineOpts.broadcastToThread;
205
209
  sendMessage({
206
210
  threadName: targetName,
207
211
  message: formatted,
@@ -211,6 +215,35 @@ async function handleAgentInject(req, res, pipelineOpts) {
211
215
  projectRoot: pipelineOpts.projectRoot,
212
216
  extraMcpServers: pipelineOpts.extraMcpServers,
213
217
  gatewayAgentsConfig: pipelineOpts.gatewayAgentsConfig,
218
+ executorRegistry: pipelineOpts.executorRegistry,
219
+ })
220
+ .then(result => {
221
+ // Notify connected clients that new messages arrived on this thread
222
+ console.log(`[Gateway] Agent inject completed for "${targetName}", broadcast=${!!broadcast}, result=${!!result}`);
223
+ if (broadcast && result) {
224
+ const newMessages = [];
225
+ if (result.userMessage) {
226
+ newMessages.push({ id: result.userMessage.id, role: 'user', content: formatted });
227
+ }
228
+ if (result.assistantMessage) {
229
+ newMessages.push({
230
+ id: result.assistantMessage.id,
231
+ role: 'assistant',
232
+ content: result.response,
233
+ });
234
+ }
235
+ if (newMessages.length > 0) {
236
+ console.log(`[Gateway] Broadcasting new_messages to "${targetName}": ${newMessages.length} messages`);
237
+ broadcast(targetName, {
238
+ type: 'new_messages',
239
+ threadName: targetName,
240
+ messages: newMessages,
241
+ });
242
+ }
243
+ }
244
+ else if (!broadcast) {
245
+ console.warn(`[Gateway] No broadcast function — agent inject for "${targetName}" won't notify clients`);
246
+ }
214
247
  })
215
248
  .catch(err => console.error(`[Gateway] agent inject error for ${targetName}:`, err))
216
249
  .finally(() => {
@@ -322,6 +355,7 @@ function drainAgentQueue(threadName, pipelineOpts) {
322
355
  projectRoot: pipelineOpts.projectRoot,
323
356
  extraMcpServers: pipelineOpts.extraMcpServers,
324
357
  gatewayAgentsConfig: pipelineOpts.gatewayAgentsConfig,
358
+ executorRegistry: pipelineOpts.executorRegistry,
325
359
  })
326
360
  .catch(err => console.error(`[Gateway] agent queue drain error for ${threadName}:`, err))
327
361
  .finally(() => {
@@ -349,6 +383,15 @@ function parseRoute(url) {
349
383
  query,
350
384
  };
351
385
  }
386
+ // Match /api/device/:executorId/tool
387
+ const deviceMatch = pathPart.match(/^\/api\/device\/([^/]+)\/tool$/);
388
+ if (deviceMatch) {
389
+ return {
390
+ path: '/api/device/:executorId/tool',
391
+ params: { executorId: decodeURIComponent(deviceMatch[1]) },
392
+ query,
393
+ };
394
+ }
352
395
  return { path: pathPart, params: {}, query };
353
396
  }
354
397
  function readBody(req) {
@@ -384,16 +427,27 @@ async function handlePostMessage(threadName, req, res, opts) {
384
427
  drainQueue(threadName, opts).catch(err => console.error(`[Gateway] drain error:`, err));
385
428
  }
386
429
  async function handleGetHistory(threadName, query, res) {
387
- const limit = Math.min(parseInt(query.limit || '20', 10) || 20, 200);
430
+ const limit = Math.min(parseInt(query.limit || '50', 10) || 50, 500);
431
+ const hasOffset = query.offset !== undefined;
388
432
  const offset = parseInt(query.offset || '0', 10) || 0;
389
433
  try {
390
434
  const thread = await getOrCreateThread(threadName);
391
435
  const all = await thread.history.getAll();
392
436
  const total = all.length;
393
- const slice = all.slice(offset, offset + limit);
437
+ // If no explicit offset, return the MOST RECENT messages (tail of history)
438
+ let slice;
439
+ let startIndex;
440
+ if (!hasOffset) {
441
+ startIndex = Math.max(0, total - limit);
442
+ slice = all.slice(startIndex);
443
+ }
444
+ else {
445
+ startIndex = offset;
446
+ slice = all.slice(offset, offset + limit);
447
+ }
394
448
  const messages = slice.map((m, i) => ({
395
449
  id: m.id,
396
- index: offset + i,
450
+ index: startIndex + i,
397
451
  role: m.role,
398
452
  content: m.content,
399
453
  timestamp: m.timestamp,
@@ -424,7 +478,7 @@ async function handleGetStatus(threadName, res) {
424
478
  jsonResponse(res, 500, { error: String(err) });
425
479
  }
426
480
  }
427
- async function handleListThreads(res) {
481
+ async function handleListThreads(res, registry) {
428
482
  try {
429
483
  if (!fs.existsSync(THREADS_DIR)) {
430
484
  jsonResponse(res, 200, { threads: [] });
@@ -445,7 +499,7 @@ async function handleListThreads(res) {
445
499
  catch {
446
500
  // skip
447
501
  }
448
- // Read thread config to include projectDir if set
502
+ // Read thread config to include projectDir and executor info
449
503
  const tc = await loadThreadConfig(name);
450
504
  const entry = {
451
505
  name,
@@ -455,6 +509,12 @@ async function handleListThreads(res) {
455
509
  if (tc.projectDir) {
456
510
  entry.projectDir = tc.projectDir;
457
511
  }
512
+ // Include executor info
513
+ const executor = tc.executor || 'thundercat';
514
+ entry.executor = executor;
515
+ if (registry) {
516
+ entry.executorOnline = registry.isOnline(executor);
517
+ }
458
518
  threads.push(entry);
459
519
  }
460
520
  // Sort by last activity descending
@@ -471,6 +531,46 @@ async function handleListThreads(res) {
471
531
  jsonResponse(res, 500, { error: String(err) });
472
532
  }
473
533
  }
534
+ async function handleListExecutors(res, registry) {
535
+ try {
536
+ const executors = registry.listExecutors();
537
+ jsonResponse(res, 200, { executors });
538
+ }
539
+ catch (err) {
540
+ jsonResponse(res, 500, { error: String(err) });
541
+ }
542
+ }
543
+ /**
544
+ * Route a device tool call to a remote executor.
545
+ * The executor executes the tool locally and returns the result.
546
+ */
547
+ async function handleDeviceToolCall(executorId, req, res, registry) {
548
+ let body;
549
+ try {
550
+ const raw = await readBody(req);
551
+ body = JSON.parse(raw);
552
+ }
553
+ catch {
554
+ jsonResponse(res, 400, { error: 'Invalid JSON body' });
555
+ return;
556
+ }
557
+ if (!body.tool) {
558
+ jsonResponse(res, 400, { error: 'Missing tool name' });
559
+ return;
560
+ }
561
+ if (!registry.isOnline(executorId)) {
562
+ jsonResponse(res, 503, { error: `Device "${executorId}" is offline` });
563
+ return;
564
+ }
565
+ try {
566
+ const result = await registry.deviceToolCall(executorId, body.tool, body.args || {});
567
+ jsonResponse(res, 200, result);
568
+ }
569
+ catch (err) {
570
+ const errorMsg = err instanceof Error ? err.message : String(err);
571
+ jsonResponse(res, 500, { error: errorMsg, isError: true });
572
+ }
573
+ }
474
574
  async function handleDeleteThread(threadName, req, res) {
475
575
  const confirm = req.headers['x-confirm'];
476
576
  if (confirm !== 'delete') {
@@ -519,6 +619,60 @@ async function handleDeleteThread(threadName, req, res) {
519
619
  jsonResponse(res, 500, { error: String(err) });
520
620
  }
521
621
  }
622
+ async function handleDeleteMessages(threadName, req, res) {
623
+ const confirm = req.headers['x-confirm'];
624
+ if (confirm !== 'delete') {
625
+ jsonResponse(res, 400, { error: 'Missing X-Confirm: delete header' });
626
+ return;
627
+ }
628
+ let body;
629
+ try {
630
+ const raw = await readBody(req);
631
+ body = JSON.parse(raw);
632
+ }
633
+ catch {
634
+ jsonResponse(res, 400, { error: 'Invalid JSON body' });
635
+ return;
636
+ }
637
+ if (!Array.isArray(body.messageIds) || body.messageIds.length === 0) {
638
+ jsonResponse(res, 400, { error: 'Missing or empty "messageIds" array' });
639
+ return;
640
+ }
641
+ const idsToDelete = new Set(body.messageIds);
642
+ try {
643
+ const filePath = path.join(THREADS_DIR, threadName + '.jsonl');
644
+ if (!fs.existsSync(filePath)) {
645
+ jsonResponse(res, 404, { error: 'Thread not found' });
646
+ return;
647
+ }
648
+ const raw = fs.readFileSync(filePath, 'utf-8');
649
+ const lines = raw.split('\n').filter(l => l.trim());
650
+ const kept = [];
651
+ let deleted = 0;
652
+ for (const line of lines) {
653
+ try {
654
+ const msg = JSON.parse(line);
655
+ if (msg.id && idsToDelete.has(msg.id)) {
656
+ deleted++;
657
+ }
658
+ else {
659
+ kept.push(line);
660
+ }
661
+ }
662
+ catch {
663
+ // Malformed line — keep it
664
+ kept.push(line);
665
+ }
666
+ }
667
+ fs.writeFileSync(filePath, kept.join('\n') + (kept.length > 0 ? '\n' : ''), 'utf-8');
668
+ // Clear in-memory cache so next request reads fresh data
669
+ clearThreadCache(threadName);
670
+ jsonResponse(res, 200, { deleted, remaining: kept.length });
671
+ }
672
+ catch (err) {
673
+ jsonResponse(res, 500, { error: String(err) });
674
+ }
675
+ }
522
676
  async function handleSyncMessages(threadName, req, res) {
523
677
  let body;
524
678
  try {
@@ -606,6 +760,14 @@ async function handleUpdateThreadConfig(threadName, req, res) {
606
760
  updates.projectDir = body.projectDir;
607
761
  if (body.template !== undefined)
608
762
  updates.template = body.template;
763
+ if (body.executor !== undefined)
764
+ updates.executor = body.executor;
765
+ if (body.executorPaths !== undefined)
766
+ updates.executorPaths = body.executorPaths;
767
+ if (body.devices !== undefined)
768
+ updates.devices = body.devices;
769
+ if (body.gitRemoteUrl !== undefined)
770
+ updates.gitRemoteUrl = body.gitRemoteUrl;
609
771
  await saveThreadConfig(threadName, updates);
610
772
  const updated = await loadThreadConfig(threadName);
611
773
  jsonResponse(res, 200, { config: updated });
@@ -839,6 +1001,11 @@ async function handleNotify(req, res) {
839
1001
  export async function startGatewayServer(options) {
840
1002
  const { port, ...pipelineOpts } = options;
841
1003
  let currentApiKeys = options.apiKeys;
1004
+ // Create or use provided executor registry
1005
+ const executorRegistry = options.executorRegistry || new ExecutorRegistry();
1006
+ pipelineOpts.executorRegistry = executorRegistry;
1007
+ // Set up executor WebSocket server
1008
+ const executorWss = new WebSocketServer({ noServer: true });
842
1009
  // Initialize VAPID for push notifications (if configured)
843
1010
  const vapidConfig = options.vapid;
844
1011
  if (vapidConfig) {
@@ -899,6 +1066,22 @@ export async function startGatewayServer(options) {
899
1066
  await handleDeleteThread(params.name, req, res);
900
1067
  return;
901
1068
  }
1069
+ // DELETE /api/thread/:name/messages
1070
+ if (routePath === '/api/thread/:name/messages' && req.method === 'DELETE') {
1071
+ await handleDeleteMessages(params.name, req, res);
1072
+ return;
1073
+ }
1074
+ // GET /api/thread/:name/config — read thread config
1075
+ if (routePath === '/api/thread/:name/config' && req.method === 'GET') {
1076
+ try {
1077
+ const tc = await loadThreadConfig(params.name);
1078
+ jsonResponse(res, 200, tc);
1079
+ }
1080
+ catch (err) {
1081
+ jsonResponse(res, 500, { error: String(err) });
1082
+ }
1083
+ return;
1084
+ }
902
1085
  // PUT /api/thread/:name/config — update thread config (projectDir, template)
903
1086
  if (routePath === '/api/thread/:name/config' && req.method === 'PUT') {
904
1087
  await handleUpdateThreadConfig(params.name, req, res);
@@ -906,7 +1089,12 @@ export async function startGatewayServer(options) {
906
1089
  }
907
1090
  // GET /api/threads
908
1091
  if (routePath === '/api/threads' && req.method === 'GET') {
909
- await handleListThreads(res);
1092
+ await handleListThreads(res, executorRegistry);
1093
+ return;
1094
+ }
1095
+ // GET /api/executors
1096
+ if (routePath === '/api/executors' && req.method === 'GET') {
1097
+ await handleListExecutors(res, executorRegistry);
910
1098
  return;
911
1099
  }
912
1100
  // GET /api/templates — list templates
@@ -924,6 +1112,11 @@ export async function startGatewayServer(options) {
924
1112
  await handleAgentInject(req, res, pipelineOpts);
925
1113
  return;
926
1114
  }
1115
+ // POST /api/device/:executorId/tool — route device tool call to executor
1116
+ if (routePath === '/api/device/:executorId/tool' && req.method === 'POST') {
1117
+ await handleDeviceToolCall(params.executorId, req, res, executorRegistry);
1118
+ return;
1119
+ }
927
1120
  // POST /api/migrate — sync thread + clone repo + set projectDir
928
1121
  if (routePath === '/api/migrate' && req.method === 'POST') {
929
1122
  await handleMigrate(req, res, pipelineOpts);
@@ -954,6 +1147,40 @@ export async function startGatewayServer(options) {
954
1147
  }
955
1148
  }
956
1149
  });
1150
+ // Handle executor WebSocket upgrades on /ws/executor
1151
+ server.on('upgrade', (req, socket, head) => {
1152
+ const url = req.url?.split('?')[0] || '/';
1153
+ if (url !== '/ws/executor')
1154
+ return; // let other handlers (webchat) handle non-executor paths
1155
+ // Authenticate via query param
1156
+ const queryApiKey = new URL(req.url || '/', `http://${req.headers.host}`).searchParams.get('apiKey');
1157
+ if (!queryApiKey || !currentApiKeys.includes(queryApiKey)) {
1158
+ socket.write('HTTP/1.1 401 Unauthorized\r\n\r\n');
1159
+ socket.destroy();
1160
+ return;
1161
+ }
1162
+ executorWss.handleUpgrade(req, socket, head, (ws) => {
1163
+ // Wait for registration message
1164
+ const timeout = setTimeout(() => {
1165
+ ws.close(1008, 'Registration timeout');
1166
+ }, 10_000);
1167
+ ws.once('message', (raw) => {
1168
+ clearTimeout(timeout);
1169
+ try {
1170
+ const data = JSON.parse(raw.toString());
1171
+ if (data.type === 'executor_register') {
1172
+ executorRegistry.register(data, ws);
1173
+ }
1174
+ else {
1175
+ ws.close(1008, 'Expected executor_register message');
1176
+ }
1177
+ }
1178
+ catch {
1179
+ ws.close(1008, 'Invalid registration message');
1180
+ }
1181
+ });
1182
+ });
1183
+ });
957
1184
  return new Promise((resolve, reject) => {
958
1185
  server.on('error', reject);
959
1186
  server.listen(port, () => {
@@ -965,13 +1192,23 @@ export async function startGatewayServer(options) {
965
1192
  port: actualPort,
966
1193
  url,
967
1194
  server,
1195
+ executorRegistry,
968
1196
  updateApiKeys: (newKeys) => {
969
1197
  currentApiKeys = newKeys;
970
1198
  },
1199
+ setBroadcastToThread: (fn) => {
1200
+ pipelineOpts.broadcastToThread = fn;
1201
+ },
971
1202
  close: async () => {
972
1203
  // Abort any in-flight message processing
973
1204
  threadQueues.clear();
974
1205
  threadBusy.clear();
1206
+ executorRegistry.shutdown();
1207
+ // Close executor WebSocket server
1208
+ for (const client of executorWss.clients) {
1209
+ client.close();
1210
+ }
1211
+ executorWss.close();
975
1212
  return new Promise(resolveClose => {
976
1213
  server.close(() => {
977
1214
  clearThreadCache();