runline 0.4.0 → 0.5.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/core/engine.js +139 -7
- package/package.json +2 -1
package/dist/core/engine.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { createRequire } from "node:module";
|
|
1
3
|
import { getQuickJS, shouldInterruptAfterDeadline, } from "quickjs-emscripten";
|
|
2
4
|
import { applyEnvOverrides, updateConnectionConfig } from "../config/loader.js";
|
|
3
5
|
export class ExecutionEngine {
|
|
@@ -215,6 +217,15 @@ function formatError(cause) {
|
|
|
215
217
|
}
|
|
216
218
|
return String(cause);
|
|
217
219
|
}
|
|
220
|
+
// MiniSearch UMD bundle, loaded once and inlined into the sandbox source.
|
|
221
|
+
// UMD assigns to globalThis.MiniSearch when run in a non-CJS / non-AMD env
|
|
222
|
+
// (which QuickJS is), so we just paste the file in and use the global.
|
|
223
|
+
const __minisearchSource = (() => {
|
|
224
|
+
const req = createRequire(import.meta.url);
|
|
225
|
+
const pkg = req.resolve("minisearch/package.json");
|
|
226
|
+
const path = pkg.replace(/package\.json$/, "dist/umd/index.js");
|
|
227
|
+
return readFileSync(path, "utf8");
|
|
228
|
+
})();
|
|
218
229
|
function buildHelpData(plugins) {
|
|
219
230
|
const data = {};
|
|
220
231
|
for (const p of plugins) {
|
|
@@ -223,7 +234,11 @@ function buildHelpData(plugins) {
|
|
|
223
234
|
description: a.description,
|
|
224
235
|
inputs: Object.fromEntries(Object.entries(a.inputSchema ?? {}).map(([k, v]) => [
|
|
225
236
|
k,
|
|
226
|
-
|
|
237
|
+
{
|
|
238
|
+
type: v.type,
|
|
239
|
+
required: !!v.required,
|
|
240
|
+
description: v.description,
|
|
241
|
+
},
|
|
227
242
|
])),
|
|
228
243
|
}));
|
|
229
244
|
}
|
|
@@ -247,15 +262,14 @@ const __fmt = (v) => {
|
|
|
247
262
|
try { return JSON.stringify(v); } catch { return String(v); }
|
|
248
263
|
};
|
|
249
264
|
|
|
265
|
+
// Inlined MiniSearch UMD — attaches MiniSearch to globalThis inside the sandbox.
|
|
266
|
+
${__minisearchSource}
|
|
267
|
+
|
|
250
268
|
const __help = ${JSON.stringify(helpData)};
|
|
251
269
|
|
|
252
270
|
const __makeProxy = (path = []) => new Proxy(() => undefined, {
|
|
253
271
|
get(_t, prop) {
|
|
254
272
|
if (prop === 'then' || typeof prop === 'symbol') return undefined;
|
|
255
|
-
if (prop === 'help') {
|
|
256
|
-
const pluginName = path[0];
|
|
257
|
-
return () => pluginName && __help[pluginName] ? __help[pluginName] : __help;
|
|
258
|
-
}
|
|
259
273
|
return __makeProxy([...path, String(prop)]);
|
|
260
274
|
},
|
|
261
275
|
apply(_t, _this, args) {
|
|
@@ -265,8 +279,126 @@ const __makeProxy = (path = []) => new Proxy(() => undefined, {
|
|
|
265
279
|
.then((raw) => raw === undefined ? undefined : JSON.parse(raw));
|
|
266
280
|
},
|
|
267
281
|
});
|
|
268
|
-
|
|
269
|
-
|
|
282
|
+
|
|
283
|
+
// Flat index of every "plugin.action" path → { plugin, entry }
|
|
284
|
+
const __index = (() => {
|
|
285
|
+
const out = Object.create(null);
|
|
286
|
+
for (const plugin of Object.keys(__help)) {
|
|
287
|
+
for (const e of __help[plugin]) {
|
|
288
|
+
out[plugin + '.' + e.action] = { plugin, entry: e };
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
return out;
|
|
292
|
+
})();
|
|
293
|
+
|
|
294
|
+
const __formatSignature = (plugin, entry) => {
|
|
295
|
+
const fields = Object.entries(entry.inputs || {})
|
|
296
|
+
.map(([k, v]) => k + (v.required ? '' : '?') + ': ' + v.type)
|
|
297
|
+
.join(', ');
|
|
298
|
+
return plugin + '.' + entry.action + (fields ? '({ ' + fields + ' })' : '()');
|
|
299
|
+
};
|
|
300
|
+
|
|
301
|
+
// Build a MiniSearch index over every action path. Indexed at sandbox
|
|
302
|
+
// startup, queried by actions.find().
|
|
303
|
+
const __search = (() => {
|
|
304
|
+
const docs = [];
|
|
305
|
+
for (const path of Object.keys(__index)) {
|
|
306
|
+
const { plugin, entry } = __index[path];
|
|
307
|
+
docs.push({
|
|
308
|
+
id: path,
|
|
309
|
+
path,
|
|
310
|
+
plugin,
|
|
311
|
+
action: entry.action,
|
|
312
|
+
description: entry.description || '',
|
|
313
|
+
});
|
|
314
|
+
}
|
|
315
|
+
const ms = new MiniSearch({
|
|
316
|
+
fields: ['path', 'plugin', 'action', 'description'],
|
|
317
|
+
storeFields: ['path', 'description'],
|
|
318
|
+
searchOptions: {
|
|
319
|
+
prefix: true,
|
|
320
|
+
fuzzy: 0.2,
|
|
321
|
+
boost: { path: 3, action: 2, plugin: 2 },
|
|
322
|
+
},
|
|
323
|
+
});
|
|
324
|
+
ms.addAll(docs);
|
|
325
|
+
return ms;
|
|
326
|
+
})();
|
|
327
|
+
|
|
328
|
+
const __actionsApi = {
|
|
329
|
+
list(plugin) {
|
|
330
|
+
const paths = Object.keys(__index);
|
|
331
|
+
return plugin ? paths.filter((p) => p.startsWith(plugin + '.')) : paths;
|
|
332
|
+
},
|
|
333
|
+
describe(path) {
|
|
334
|
+
const hit = __index[path];
|
|
335
|
+
if (!hit) {
|
|
336
|
+
const near = __actionsApi.find(path, 3);
|
|
337
|
+
const hint = near.length ? ' Did you mean: ' + near.map((n) => n.path).join(', ') + '?' : '';
|
|
338
|
+
throw new Error('Unknown action: ' + path + '.' + hint);
|
|
339
|
+
}
|
|
340
|
+
return {
|
|
341
|
+
path,
|
|
342
|
+
plugin: hit.plugin,
|
|
343
|
+
action: hit.entry.action,
|
|
344
|
+
description: hit.entry.description,
|
|
345
|
+
signature: __formatSignature(hit.plugin, hit.entry),
|
|
346
|
+
inputs: hit.entry.inputs,
|
|
347
|
+
};
|
|
348
|
+
},
|
|
349
|
+
find(query, limit = 5) {
|
|
350
|
+
const q = String(query || '').trim();
|
|
351
|
+
if (!q) return [];
|
|
352
|
+
return __search.search(q).slice(0, limit).map((r) => ({
|
|
353
|
+
path: r.path,
|
|
354
|
+
description: r.description || undefined,
|
|
355
|
+
score: r.score,
|
|
356
|
+
}));
|
|
357
|
+
},
|
|
358
|
+
check(path, args) {
|
|
359
|
+
const hit = __index[path];
|
|
360
|
+
if (!hit) {
|
|
361
|
+
const near = __actionsApi.find(path, 3).map((n) => n.path);
|
|
362
|
+
return { ok: false, error: 'Unknown action: ' + path, suggestions: near };
|
|
363
|
+
}
|
|
364
|
+
const inputs = hit.entry.inputs || {};
|
|
365
|
+
const provided = args && typeof args === 'object' ? args : {};
|
|
366
|
+
const missing = [];
|
|
367
|
+
const unknown = [];
|
|
368
|
+
const typeErrors = [];
|
|
369
|
+
for (const [k, spec] of Object.entries(inputs)) {
|
|
370
|
+
if (spec.required && !(k in provided)) missing.push(k);
|
|
371
|
+
}
|
|
372
|
+
for (const k of Object.keys(provided)) {
|
|
373
|
+
if (!(k in inputs)) unknown.push(k);
|
|
374
|
+
else {
|
|
375
|
+
const expected = inputs[k].type;
|
|
376
|
+
const actual = Array.isArray(provided[k]) ? 'array' : typeof provided[k];
|
|
377
|
+
if (expected !== actual && !(provided[k] === null || provided[k] === undefined)) {
|
|
378
|
+
typeErrors.push({ field: k, expected, actual });
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
return {
|
|
383
|
+
ok: missing.length === 0 && unknown.length === 0 && typeErrors.length === 0,
|
|
384
|
+
missing,
|
|
385
|
+
unknown,
|
|
386
|
+
typeErrors,
|
|
387
|
+
signature: __formatSignature(hit.plugin, hit.entry),
|
|
388
|
+
};
|
|
389
|
+
},
|
|
390
|
+
};
|
|
391
|
+
|
|
392
|
+
// Unknown keys (plugin names) fall through to the call proxy, so
|
|
393
|
+
// actions.github.issue.create(...) keeps working alongside the explicit
|
|
394
|
+
// list/find/describe/check/help helpers.
|
|
395
|
+
const actions = new Proxy(__actionsApi, {
|
|
396
|
+
get(target, prop) {
|
|
397
|
+
if (prop in target || typeof prop === 'symbol') return target[prop];
|
|
398
|
+
return __makeProxy([String(prop)]);
|
|
399
|
+
},
|
|
400
|
+
});
|
|
401
|
+
|
|
270
402
|
${pluginNames.map((n) => `const ${n} = __makeProxy(['${n}']);`).join("\n")}
|
|
271
403
|
|
|
272
404
|
const console = {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "runline",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "Code mode for agents — turn any API or command into a callable action",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -63,6 +63,7 @@
|
|
|
63
63
|
"dependencies": {
|
|
64
64
|
"chalk": "^5.6.2",
|
|
65
65
|
"commander": "^14.0.3",
|
|
66
|
+
"minisearch": "^7.2.0",
|
|
66
67
|
"proper-lockfile": "^4.1.2",
|
|
67
68
|
"quickjs-emscripten": "^0.32.0",
|
|
68
69
|
"rrule": "^2.8.1"
|