@on-mission/sdk 0.1.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.d.ts +20 -0
- package/dist/api.d.ts.map +1 -0
- package/dist/api.js +39 -0
- package/dist/api.js.map +1 -0
- package/dist/auth.d.ts +65 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +45 -0
- package/dist/auth.js.map +1 -0
- package/dist/config.d.ts +39 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +28 -0
- package/dist/config.js.map +1 -0
- package/dist/context.d.ts +24 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +22 -0
- package/dist/context.js.map +1 -0
- package/dist/events.d.ts +62 -0
- package/dist/events.d.ts.map +1 -0
- package/dist/events.js +30 -0
- package/dist/events.js.map +1 -0
- package/dist/http-server.d.ts +51 -0
- package/dist/http-server.d.ts.map +1 -0
- package/dist/http-server.js +163 -0
- package/dist/http-server.js.map +1 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/ingress.d.ts +133 -0
- package/dist/ingress.d.ts.map +1 -0
- package/dist/ingress.js +89 -0
- package/dist/ingress.js.map +1 -0
- package/dist/logging.d.ts +31 -0
- package/dist/logging.d.ts.map +1 -0
- package/dist/logging.js +77 -0
- package/dist/logging.js.map +1 -0
- package/dist/sdk.d.ts +116 -0
- package/dist/sdk.d.ts.map +1 -0
- package/dist/sdk.js +327 -0
- package/dist/sdk.js.map +1 -0
- package/dist/tool-registry.d.ts +29 -0
- package/dist/tool-registry.d.ts.map +1 -0
- package/dist/tool-registry.js +37 -0
- package/dist/tool-registry.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +56 -0
package/dist/sdk.js
ADDED
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mission SDK — Main Entry
|
|
3
|
+
*
|
|
4
|
+
* Creates the SDK instance that a plugin uses to interact with the
|
|
5
|
+
* Mission platform. Communication is HTTP-native:
|
|
6
|
+
*
|
|
7
|
+
* Outbound (Plugin → Mission API):
|
|
8
|
+
* Standard REST calls via the API client.
|
|
9
|
+
*
|
|
10
|
+
* Inbound (Mission API → Plugin):
|
|
11
|
+
* HTTP requests to the plugin's HTTP server, exposed via
|
|
12
|
+
* Daytona Preview URLs.
|
|
13
|
+
*
|
|
14
|
+
* Lifecycle:
|
|
15
|
+
* 1. const mission = createMissionSDK() — create SDK (no connection yet)
|
|
16
|
+
* 2. await mission.connect() — start HTTP server, install logging
|
|
17
|
+
* 3. // auth, config, events are now usable
|
|
18
|
+
* 4. mission.tools.registerAll(handlers) — register tool handlers
|
|
19
|
+
* 5. mission.ingress.on('name', handler) — register ingress handlers
|
|
20
|
+
* 6. mission.onShutdown(() => cleanup()) — register shutdown hooks
|
|
21
|
+
* 7. await mission.ready() — signal readiness, accept traffic
|
|
22
|
+
*
|
|
23
|
+
* See docs/technical-designs/plugin-architecture.md §4 and §6.
|
|
24
|
+
* See docs/technical-designs/daytona-sandbox-runtime.md.
|
|
25
|
+
*/
|
|
26
|
+
import { createApiClient } from './api';
|
|
27
|
+
import { createAuthModule } from './auth';
|
|
28
|
+
import { createConfigModule } from './config';
|
|
29
|
+
import { readContextFromEnv } from './context';
|
|
30
|
+
import { createEventsModule } from './events';
|
|
31
|
+
import { createHttpServer } from './http-server';
|
|
32
|
+
import { createIngressRegistry } from './ingress';
|
|
33
|
+
import { installLogging } from './logging';
|
|
34
|
+
import { createToolRegistry } from './tool-registry';
|
|
35
|
+
// ─── Factory ─────────────────────────────────────────────────────────────────
|
|
36
|
+
/** Interval between keep-alive heartbeats (in ms). */
|
|
37
|
+
const HEARTBEAT_INTERVAL_MS = 10 * 60 * 1000; // 10 minutes
|
|
38
|
+
/** How often to check if the JWT needs refreshing (in ms). */
|
|
39
|
+
const TOKEN_REFRESH_CHECK_MS = 5 * 60 * 1000; // 5 minutes
|
|
40
|
+
/** Refresh the JWT when it has this much time left (in ms). */
|
|
41
|
+
const TOKEN_REFRESH_BUFFER_MS = 15 * 60 * 1000; // 15 minutes before expiry
|
|
42
|
+
/**
|
|
43
|
+
* Create a Mission SDK instance.
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* ```ts
|
|
47
|
+
* import { createMissionSDK } from '@mission/sdk'
|
|
48
|
+
*
|
|
49
|
+
* const mission = createMissionSDK()
|
|
50
|
+
* await mission.connect()
|
|
51
|
+
*
|
|
52
|
+
* const auth = await mission.auth.get()
|
|
53
|
+
* const config = await mission.config.get<MyConfig>(defaults)
|
|
54
|
+
*
|
|
55
|
+
* mission.tools.registerAll(handlers)
|
|
56
|
+
* mission.ingress.on('webhook', handler)
|
|
57
|
+
* mission.onShutdown(() => cleanup())
|
|
58
|
+
*
|
|
59
|
+
* await mission.ready()
|
|
60
|
+
* ```
|
|
61
|
+
*/
|
|
62
|
+
export function createMissionSDK(options) {
|
|
63
|
+
const envContext = readContextFromEnv();
|
|
64
|
+
const context = {
|
|
65
|
+
...envContext,
|
|
66
|
+
...options?.context
|
|
67
|
+
};
|
|
68
|
+
// Port priority: explicit option > env var (in context) > 3000
|
|
69
|
+
const port = options?.port ?? context.pluginPort;
|
|
70
|
+
// Core modules
|
|
71
|
+
const api = createApiClient(context);
|
|
72
|
+
const httpServer = createHttpServer();
|
|
73
|
+
const toolRegistry = createToolRegistry();
|
|
74
|
+
const ingressRegistry = createIngressRegistry(api);
|
|
75
|
+
const shutdownHandlers = [];
|
|
76
|
+
let isShuttingDown = false;
|
|
77
|
+
let heartbeatTimer = null;
|
|
78
|
+
let tokenRefreshTimer = null;
|
|
79
|
+
let shutdownResolve = null;
|
|
80
|
+
// ─── Keep-alive heartbeat ───────────────────────────────────────────
|
|
81
|
+
function startHeartbeat() {
|
|
82
|
+
heartbeatTimer = setInterval(() => {
|
|
83
|
+
// Send heartbeat to Mission API.
|
|
84
|
+
// The API responds by pinging our HTTP server's /_mission/ping
|
|
85
|
+
// endpoint, which resets Daytona's auto-stop timer.
|
|
86
|
+
void api.trpc.plugin.heartbeat.mutate({}).catch((err) => {
|
|
87
|
+
console.error('[SDK] heartbeat failed:', err);
|
|
88
|
+
});
|
|
89
|
+
}, HEARTBEAT_INTERVAL_MS);
|
|
90
|
+
// Don't let the heartbeat timer prevent process exit
|
|
91
|
+
if (heartbeatTimer.unref) {
|
|
92
|
+
heartbeatTimer.unref();
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
function stopHeartbeat() {
|
|
96
|
+
if (heartbeatTimer) {
|
|
97
|
+
clearInterval(heartbeatTimer);
|
|
98
|
+
heartbeatTimer = null;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
// ─── JWT token refresh ────────────────────────────────────────────
|
|
102
|
+
function getTokenExpiry() {
|
|
103
|
+
const token = api.getToken();
|
|
104
|
+
if (!token)
|
|
105
|
+
return null;
|
|
106
|
+
try {
|
|
107
|
+
const payload = JSON.parse(Buffer.from(token.split('.')[1], 'base64').toString());
|
|
108
|
+
return typeof payload.exp === 'number' ? payload.exp * 1000 : null;
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
return null;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
function startTokenRefresh() {
|
|
115
|
+
tokenRefreshTimer = setInterval(async () => {
|
|
116
|
+
const expiry = getTokenExpiry();
|
|
117
|
+
if (!expiry)
|
|
118
|
+
return;
|
|
119
|
+
const timeLeft = expiry - Date.now();
|
|
120
|
+
if (timeLeft > TOKEN_REFRESH_BUFFER_MS)
|
|
121
|
+
return;
|
|
122
|
+
try {
|
|
123
|
+
const result = await api.trpc.plugin.tokenRefresh.mutate({});
|
|
124
|
+
if (!result || typeof result !== 'object' || !('token' in result)) {
|
|
125
|
+
throw new Error('Invalid token refresh response');
|
|
126
|
+
}
|
|
127
|
+
api.setToken(result.token);
|
|
128
|
+
console.error('[SDK] JWT refreshed successfully');
|
|
129
|
+
}
|
|
130
|
+
catch (err) {
|
|
131
|
+
console.error('[SDK] JWT refresh failed:', err);
|
|
132
|
+
}
|
|
133
|
+
}, TOKEN_REFRESH_CHECK_MS);
|
|
134
|
+
if (tokenRefreshTimer.unref) {
|
|
135
|
+
tokenRefreshTimer.unref();
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
function stopTokenRefresh() {
|
|
139
|
+
if (tokenRefreshTimer) {
|
|
140
|
+
clearInterval(tokenRefreshTimer);
|
|
141
|
+
tokenRefreshTimer = null;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
// ─── Graceful shutdown ──────────────────────────────────────────────
|
|
145
|
+
async function handleShutdown() {
|
|
146
|
+
if (isShuttingDown)
|
|
147
|
+
return;
|
|
148
|
+
isShuttingDown = true;
|
|
149
|
+
console.error('[SDK] Shutdown signal received — running cleanup handlers');
|
|
150
|
+
// 1. Stop timers
|
|
151
|
+
stopHeartbeat();
|
|
152
|
+
stopTokenRefresh();
|
|
153
|
+
// 2. Run plugin shutdown handlers
|
|
154
|
+
for (const handler of shutdownHandlers) {
|
|
155
|
+
try {
|
|
156
|
+
await handler();
|
|
157
|
+
}
|
|
158
|
+
catch (err) {
|
|
159
|
+
console.error('[SDK] Shutdown handler error:', err);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
// 3. Stop the HTTP server
|
|
163
|
+
try {
|
|
164
|
+
await httpServer.stop();
|
|
165
|
+
}
|
|
166
|
+
catch (err) {
|
|
167
|
+
console.error('[SDK] Error stopping HTTP server:', err);
|
|
168
|
+
}
|
|
169
|
+
console.error('[SDK] Shutdown complete');
|
|
170
|
+
// 4. Resolve the ready() promise so the process can exit
|
|
171
|
+
if (shutdownResolve) {
|
|
172
|
+
shutdownResolve();
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
// ─── Wire up HTTP server routes ─────────────────────────────────────
|
|
176
|
+
function installRoutes() {
|
|
177
|
+
// Health check
|
|
178
|
+
httpServer.route('GET', '/_mission/health', async () => {
|
|
179
|
+
return {
|
|
180
|
+
status: 200,
|
|
181
|
+
body: JSON.stringify({
|
|
182
|
+
status: 'healthy',
|
|
183
|
+
installationId: context.installationId,
|
|
184
|
+
timestamp: new Date().toISOString()
|
|
185
|
+
})
|
|
186
|
+
};
|
|
187
|
+
});
|
|
188
|
+
// Keep-alive ping (Mission API calls this to reset Daytona auto-stop)
|
|
189
|
+
httpServer.route('GET', '/_mission/ping', async () => {
|
|
190
|
+
return {
|
|
191
|
+
status: 200,
|
|
192
|
+
body: JSON.stringify({ pong: true })
|
|
193
|
+
};
|
|
194
|
+
});
|
|
195
|
+
// Tool calls: POST /_mission/tools/:toolName
|
|
196
|
+
httpServer.route('POST', '/_mission/tools/:toolName', async (req) => {
|
|
197
|
+
const toolName = req.params.toolName;
|
|
198
|
+
let args = {};
|
|
199
|
+
if (req.body) {
|
|
200
|
+
try {
|
|
201
|
+
args = JSON.parse(req.body);
|
|
202
|
+
}
|
|
203
|
+
catch {
|
|
204
|
+
return {
|
|
205
|
+
status: 400,
|
|
206
|
+
body: JSON.stringify({ error: 'Invalid JSON body' })
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
try {
|
|
211
|
+
const result = await toolRegistry.dispatch(toolName, args);
|
|
212
|
+
return {
|
|
213
|
+
status: 200,
|
|
214
|
+
body: JSON.stringify({ result })
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
catch (err) {
|
|
218
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
219
|
+
console.error(`[SDK] Tool call '${toolName}' failed:`, message);
|
|
220
|
+
return {
|
|
221
|
+
status: err instanceof Error && err.message.startsWith('Unknown tool')
|
|
222
|
+
? 404
|
|
223
|
+
: 500,
|
|
224
|
+
body: JSON.stringify({ error: message })
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
});
|
|
228
|
+
// Ingress HTTP endpoints: POST /_ingress/:endpointName
|
|
229
|
+
// (also accepts GET for webhook verification flows like Slack challenge)
|
|
230
|
+
httpServer.route('POST', '/_ingress/:endpointName', async (req) => {
|
|
231
|
+
const endpointName = req.params.endpointName;
|
|
232
|
+
const ingressReq = {
|
|
233
|
+
method: req.method,
|
|
234
|
+
path: req.path,
|
|
235
|
+
headers: req.headers,
|
|
236
|
+
body: req.body,
|
|
237
|
+
query: req.query
|
|
238
|
+
};
|
|
239
|
+
const result = await ingressRegistry.dispatch(endpointName, ingressReq);
|
|
240
|
+
return {
|
|
241
|
+
status: result.status,
|
|
242
|
+
headers: result.headers,
|
|
243
|
+
body: result.body
|
|
244
|
+
};
|
|
245
|
+
});
|
|
246
|
+
httpServer.route('GET', '/_ingress/:endpointName', async (req) => {
|
|
247
|
+
const endpointName = req.params.endpointName;
|
|
248
|
+
const ingressReq = {
|
|
249
|
+
method: req.method,
|
|
250
|
+
path: req.path,
|
|
251
|
+
headers: req.headers,
|
|
252
|
+
body: req.body,
|
|
253
|
+
query: req.query
|
|
254
|
+
};
|
|
255
|
+
const result = await ingressRegistry.dispatch(endpointName, ingressReq);
|
|
256
|
+
return {
|
|
257
|
+
status: result.status,
|
|
258
|
+
headers: result.headers,
|
|
259
|
+
body: result.body
|
|
260
|
+
};
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
// ─── SDK instance ───────────────────────────────────────────────────
|
|
264
|
+
const sdk = {
|
|
265
|
+
context,
|
|
266
|
+
auth: createAuthModule(api),
|
|
267
|
+
config: createConfigModule(api),
|
|
268
|
+
events: createEventsModule(api),
|
|
269
|
+
ingress: ingressRegistry,
|
|
270
|
+
tools: toolRegistry,
|
|
271
|
+
connect: async () => {
|
|
272
|
+
// 1. Install console override for structured logging
|
|
273
|
+
installLogging(api);
|
|
274
|
+
// 2. Install HTTP routes
|
|
275
|
+
installRoutes();
|
|
276
|
+
// 3. Start the HTTP server
|
|
277
|
+
await httpServer.start(port);
|
|
278
|
+
// 4. Start keep-alive heartbeat
|
|
279
|
+
startHeartbeat();
|
|
280
|
+
// 5. Start JWT token refresh timer
|
|
281
|
+
startTokenRefresh();
|
|
282
|
+
console.error(`[SDK] Connected — HTTP server on port ${port}, auth/config/events available`);
|
|
283
|
+
},
|
|
284
|
+
ready: async () => {
|
|
285
|
+
// 1. Signal to the Mission API that we're ready for traffic
|
|
286
|
+
const toolNames = toolRegistry.getToolNames();
|
|
287
|
+
const ingressEndpoints = ingressRegistry.getHttpEndpointNames();
|
|
288
|
+
const streamEndpoints = ingressRegistry.getStreamEndpointNames();
|
|
289
|
+
await api.trpc.plugin.ready.mutate({
|
|
290
|
+
tools: toolNames,
|
|
291
|
+
ingress: ingressEndpoints,
|
|
292
|
+
streams: streamEndpoints,
|
|
293
|
+
port
|
|
294
|
+
});
|
|
295
|
+
console.error(`[SDK] Ready — ${toolNames.length} tools: ${toolNames.join(', ')}`);
|
|
296
|
+
if (ingressEndpoints.length > 0) {
|
|
297
|
+
console.error(`[SDK] Ingress endpoints: ${ingressEndpoints.join(', ')}`);
|
|
298
|
+
}
|
|
299
|
+
if (streamEndpoints.length > 0) {
|
|
300
|
+
console.error(`[SDK] Stream endpoints: ${streamEndpoints.join(', ')}`);
|
|
301
|
+
}
|
|
302
|
+
// 2. Install signal handlers for graceful shutdown
|
|
303
|
+
process.on('SIGTERM', () => {
|
|
304
|
+
handleShutdown().catch(err => {
|
|
305
|
+
console.error('[SDK] Fatal shutdown error:', err);
|
|
306
|
+
process.exit(1);
|
|
307
|
+
});
|
|
308
|
+
});
|
|
309
|
+
process.on('SIGINT', () => {
|
|
310
|
+
handleShutdown().catch(err => {
|
|
311
|
+
console.error('[SDK] Fatal shutdown error:', err);
|
|
312
|
+
process.exit(1);
|
|
313
|
+
});
|
|
314
|
+
});
|
|
315
|
+
console.error('[SDK] Accepting traffic — plugin is live');
|
|
316
|
+
// 3. Keep alive until shutdown signal
|
|
317
|
+
await new Promise(resolve => {
|
|
318
|
+
shutdownResolve = resolve;
|
|
319
|
+
});
|
|
320
|
+
},
|
|
321
|
+
onShutdown: (handler) => {
|
|
322
|
+
shutdownHandlers.push(handler);
|
|
323
|
+
}
|
|
324
|
+
};
|
|
325
|
+
return sdk;
|
|
326
|
+
}
|
|
327
|
+
//# sourceMappingURL=sdk.js.map
|
package/dist/sdk.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sdk.js","sourceRoot":"","sources":["../src/sdk.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool Registry
|
|
3
|
+
*
|
|
4
|
+
* Plugins register their tool handlers here. When the Gateway sends
|
|
5
|
+
* a "tools.call" command, the registry dispatches to the right handler.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* mission.tools.register('gmail_search', async (params) => { ... })
|
|
9
|
+
* mission.tools.registerAll(handlers)
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* A tool handler function. Receives validated params, returns a result.
|
|
13
|
+
* The SDK handles wrapping the result in the gateway response protocol.
|
|
14
|
+
*/
|
|
15
|
+
export type ToolHandler = (params: Record<string, unknown>) => Promise<unknown>;
|
|
16
|
+
export type ToolsModule = {
|
|
17
|
+
/** Register a single tool handler by name. */
|
|
18
|
+
register: (name: string, handler: ToolHandler) => void;
|
|
19
|
+
/** Register multiple tool handlers at once. */
|
|
20
|
+
registerAll: (handlers: Record<string, ToolHandler>) => void;
|
|
21
|
+
};
|
|
22
|
+
export type ToolRegistry = ToolsModule & {
|
|
23
|
+
/** Dispatch a tool call to the registered handler. */
|
|
24
|
+
dispatch: (name: string, params: Record<string, unknown>) => Promise<unknown>;
|
|
25
|
+
/** Get the list of registered tool names. */
|
|
26
|
+
getToolNames: () => string[];
|
|
27
|
+
};
|
|
28
|
+
export declare function createToolRegistry(): ToolRegistry;
|
|
29
|
+
//# sourceMappingURL=tool-registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-registry.d.ts","sourceRoot":"","sources":["../src/tool-registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH;;;GAGG;AACH,MAAM,MAAM,WAAW,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;AAE/E,MAAM,MAAM,WAAW,GAAG;IACxB,8CAA8C;IAC9C,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,KAAK,IAAI,CAAA;IACtD,+CAA+C;IAC/C,WAAW,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,KAAK,IAAI,CAAA;CAC7D,CAAA;AAID,MAAM,MAAM,YAAY,GAAG,WAAW,GAAG;IACvC,sDAAsD;IACtD,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;IAC7E,6CAA6C;IAC7C,YAAY,EAAE,MAAM,MAAM,EAAE,CAAA;CAC7B,CAAA;AAED,wBAAgB,kBAAkB,IAAI,YAAY,CAgCjD"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool Registry
|
|
3
|
+
*
|
|
4
|
+
* Plugins register their tool handlers here. When the Gateway sends
|
|
5
|
+
* a "tools.call" command, the registry dispatches to the right handler.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* mission.tools.register('gmail_search', async (params) => { ... })
|
|
9
|
+
* mission.tools.registerAll(handlers)
|
|
10
|
+
*/
|
|
11
|
+
export function createToolRegistry() {
|
|
12
|
+
const handlers = new Map();
|
|
13
|
+
return {
|
|
14
|
+
register(name, handler) {
|
|
15
|
+
if (handlers.has(name)) {
|
|
16
|
+
console.error(`[Tools] Warning: overwriting handler for '${name}'`);
|
|
17
|
+
}
|
|
18
|
+
handlers.set(name, handler);
|
|
19
|
+
},
|
|
20
|
+
registerAll(map) {
|
|
21
|
+
for (const [name, handler] of Object.entries(map)) {
|
|
22
|
+
handlers.set(name, handler);
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
async dispatch(name, params) {
|
|
26
|
+
const handler = handlers.get(name);
|
|
27
|
+
if (!handler) {
|
|
28
|
+
throw new Error(`Unknown tool: ${name}`);
|
|
29
|
+
}
|
|
30
|
+
return handler(params);
|
|
31
|
+
},
|
|
32
|
+
getToolNames() {
|
|
33
|
+
return Array.from(handlers.keys());
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=tool-registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-registry.js","sourceRoot":"","sources":["../src/tool-registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAwBH,MAAM,UAAU,kBAAkB;IAChC,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAuB,CAAA;IAE/C,OAAO;QACL,QAAQ,CAAC,IAAY,EAAE,OAAoB;YACzC,IAAI,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;gBACvB,OAAO,CAAC,KAAK,CAAC,6CAA6C,IAAI,GAAG,CAAC,CAAA;YACrE,CAAC;YACD,QAAQ,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;QAC7B,CAAC;QAED,WAAW,CAAC,GAAgC;YAC1C,KAAK,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;gBAClD,QAAQ,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;YAC7B,CAAC;QACH,CAAC;QAED,KAAK,CAAC,QAAQ,CACZ,IAAY,EACZ,MAA+B;YAE/B,MAAM,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;YAClC,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,MAAM,IAAI,KAAK,CAAC,iBAAiB,IAAI,EAAE,CAAC,CAAA;YAC1C,CAAC;YACD,OAAO,OAAO,CAAC,MAAM,CAAC,CAAA;QACxB,CAAC;QAED,YAAY;YACV,OAAO,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAA;QACpC,CAAC;KACF,CAAA;AACH,CAAC"}
|