@computesdk/workbench 2.0.0 → 2.0.2
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/bin/workbench.js +272 -105
- package/dist/bin/workbench.js.map +1 -1
- package/dist/index.js +272 -105
- package/dist/index.js.map +1 -1
- package/package.json +13 -13
- package/src/bin/workbench-ts.ts +0 -1
package/dist/index.js
CHANGED
|
@@ -20,10 +20,26 @@ function setSandbox(state, sandbox, provider) {
|
|
|
20
20
|
state.currentSandbox = sandbox;
|
|
21
21
|
state.currentProvider = provider;
|
|
22
22
|
state.sandboxCreatedAt = /* @__PURE__ */ new Date();
|
|
23
|
+
updatePromptIfNeeded(state);
|
|
23
24
|
}
|
|
24
25
|
function clearSandbox(state) {
|
|
25
26
|
state.currentSandbox = null;
|
|
26
27
|
state.sandboxCreatedAt = null;
|
|
28
|
+
updatePromptIfNeeded(state);
|
|
29
|
+
}
|
|
30
|
+
function updatePromptIfNeeded(state) {
|
|
31
|
+
if (state._replServer) {
|
|
32
|
+
const prompt = getPrompt(state);
|
|
33
|
+
state._replServer.setPrompt(prompt);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
function getPrompt(state) {
|
|
37
|
+
if (!state.currentSandbox) {
|
|
38
|
+
return "> ";
|
|
39
|
+
}
|
|
40
|
+
const provider = state.currentProvider || "unknown";
|
|
41
|
+
const sandboxId = state.currentSandbox.sandboxId || "";
|
|
42
|
+
return `${provider}:${sandboxId}> `;
|
|
27
43
|
}
|
|
28
44
|
function hasSandbox(state) {
|
|
29
45
|
return state.currentSandbox !== null;
|
|
@@ -79,6 +95,7 @@ function showWelcome(availableProviders, currentProvider, useDirectMode) {
|
|
|
79
95
|
console.log(c.bold(c.cyan("\n\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557")));
|
|
80
96
|
console.log(c.bold(c.cyan("\u2551 ComputeSDK Workbench \u2551")));
|
|
81
97
|
console.log(c.bold(c.cyan("\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D\n")));
|
|
98
|
+
console.log(c.dim("Prompt shows connection status: > (disconnected) or provider:sandbox> (connected)\n"));
|
|
82
99
|
if (availableProviders.length > 0) {
|
|
83
100
|
const backendProviders = availableProviders.filter((p) => p !== "gateway");
|
|
84
101
|
console.log(`Providers available: ${backendProviders.join(", ")}`);
|
|
@@ -112,7 +129,12 @@ function showInfo(state) {
|
|
|
112
129
|
return;
|
|
113
130
|
}
|
|
114
131
|
console.log("\n" + c.bold("Current Sandbox:"));
|
|
132
|
+
if (state.currentSandbox.sandboxId) {
|
|
133
|
+
console.log(` Sandbox ID: ${c.cyan(state.currentSandbox.sandboxId)}`);
|
|
134
|
+
}
|
|
115
135
|
console.log(` Provider: ${c.green(state.currentProvider || "unknown")}`);
|
|
136
|
+
const modeLabel = state.useDirectMode ? "direct \u{1F517}" : "gateway \u{1F310}";
|
|
137
|
+
console.log(` Mode: ${c.blue(modeLabel)}`);
|
|
116
138
|
console.log(` Created: ${state.sandboxCreatedAt?.toLocaleString() || "unknown"}`);
|
|
117
139
|
console.log(` Uptime: ${formatUptime(state)}`);
|
|
118
140
|
console.log("");
|
|
@@ -209,12 +231,28 @@ ${c.bold("Running Commands:")}
|
|
|
209
231
|
${c.cyan('git.clone("https://github.com/user/repo")')}
|
|
210
232
|
${c.cyan("git.status()")}
|
|
211
233
|
|
|
212
|
-
${c.dim("Filesystem:")}
|
|
234
|
+
${c.dim("Filesystem (via commands):")}
|
|
213
235
|
${c.cyan('ls("/home")')}
|
|
214
236
|
${c.cyan('cat("/etc/hosts")')}
|
|
215
237
|
${c.cyan('rm.rf("/tmp")')} ${c.dim("// Force remove")}
|
|
216
238
|
${c.cyan('rm.auto("/path")')} ${c.dim("// Smart remove")}
|
|
217
239
|
|
|
240
|
+
${c.dim("Filesystem (direct API):")}
|
|
241
|
+
${c.cyan('filesystem.readFile("/etc/hosts")')}
|
|
242
|
+
${c.cyan('filesystem.writeFile("/app/server.js", code)')}
|
|
243
|
+
${c.cyan('filesystem.mkdir("/app")')}
|
|
244
|
+
${c.cyan('filesystem.readdir("/home")')}
|
|
245
|
+
${c.cyan('filesystem.exists("/path")')}
|
|
246
|
+
${c.cyan('filesystem.remove("/file")')}
|
|
247
|
+
|
|
248
|
+
${c.dim("Sandbox Methods:")}
|
|
249
|
+
${c.cyan("getUrl({ port: 3000 })")} ${c.dim("// Get public URL")}
|
|
250
|
+
${c.cyan(`runCode("console.log('hi')", "node")`)}
|
|
251
|
+
${c.cyan("sandboxInfo()")} ${c.dim("// Get sandbox details")}
|
|
252
|
+
${c.cyan("getInstance()")} ${c.dim("// Get native instance")}
|
|
253
|
+
|
|
254
|
+
${c.dim('Note: No need to use "await" - promises are auto-awaited!')}
|
|
255
|
+
|
|
218
256
|
${c.dim("Compute CLI:")}
|
|
219
257
|
${c.cyan("compute.isSetup()")} ${c.dim("// Check if daemon is running")}
|
|
220
258
|
${c.cyan("compute.setup()")} ${c.dim("// Install + start daemon")}
|
|
@@ -244,47 +282,62 @@ function logWarning(message) {
|
|
|
244
282
|
}
|
|
245
283
|
|
|
246
284
|
// src/cli/providers.ts
|
|
285
|
+
import {
|
|
286
|
+
PROVIDER_AUTH as SHARED_PROVIDER_AUTH,
|
|
287
|
+
PROVIDER_NAMES as SHARED_PROVIDER_NAMES,
|
|
288
|
+
getProviderConfigFromEnv
|
|
289
|
+
} from "computesdk";
|
|
247
290
|
var PROVIDER_NAMES = [
|
|
248
291
|
"gateway",
|
|
249
|
-
|
|
250
|
-
"railway",
|
|
251
|
-
"daytona",
|
|
252
|
-
"modal",
|
|
253
|
-
"runloop",
|
|
254
|
-
"vercel",
|
|
255
|
-
"cloudflare",
|
|
256
|
-
"codesandbox",
|
|
257
|
-
"blaxel"
|
|
292
|
+
...SHARED_PROVIDER_NAMES
|
|
258
293
|
];
|
|
259
|
-
var
|
|
260
|
-
gateway: ["COMPUTESDK_API_KEY"],
|
|
261
|
-
|
|
262
|
-
railway: ["RAILWAY_API_KEY", "RAILWAY_PROJECT_ID", "RAILWAY_ENVIRONMENT_ID"],
|
|
263
|
-
daytona: ["DAYTONA_API_KEY"],
|
|
264
|
-
modal: ["MODAL_TOKEN_ID", "MODAL_TOKEN_SECRET"],
|
|
265
|
-
runloop: ["RUNLOOP_API_KEY"],
|
|
266
|
-
vercel: ["VERCEL_TOKEN", "VERCEL_TEAM_ID", "VERCEL_PROJECT_ID"],
|
|
267
|
-
cloudflare: ["CLOUDFLARE_API_TOKEN", "CLOUDFLARE_ACCOUNT_ID"],
|
|
268
|
-
codesandbox: ["CSB_API_KEY"],
|
|
269
|
-
blaxel: ["BL_API_KEY", "BL_WORKSPACE"]
|
|
294
|
+
var PROVIDER_AUTH = {
|
|
295
|
+
gateway: [["COMPUTESDK_API_KEY"]],
|
|
296
|
+
...SHARED_PROVIDER_AUTH
|
|
270
297
|
};
|
|
271
298
|
function getProviderStatus(provider) {
|
|
299
|
+
const authOptions = PROVIDER_AUTH[provider];
|
|
272
300
|
if (typeof process === "undefined") {
|
|
273
301
|
return {
|
|
274
302
|
name: provider,
|
|
275
303
|
isComplete: false,
|
|
276
304
|
present: [],
|
|
277
|
-
missing: [...
|
|
305
|
+
missing: [...authOptions[0]]
|
|
278
306
|
};
|
|
279
307
|
}
|
|
280
|
-
const
|
|
281
|
-
const
|
|
282
|
-
const
|
|
308
|
+
const allVars = new Set(authOptions.flat());
|
|
309
|
+
const presentSet = /* @__PURE__ */ new Set();
|
|
310
|
+
for (const v of allVars) {
|
|
311
|
+
if (process.env?.[v]) presentSet.add(v);
|
|
312
|
+
}
|
|
313
|
+
let bestOption = null;
|
|
314
|
+
for (const option of authOptions) {
|
|
315
|
+
const missing = [];
|
|
316
|
+
let presentCount = 0;
|
|
317
|
+
for (const v of option) {
|
|
318
|
+
if (presentSet.has(v)) {
|
|
319
|
+
presentCount++;
|
|
320
|
+
} else {
|
|
321
|
+
missing.push(v);
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
if (missing.length === 0) {
|
|
325
|
+
return {
|
|
326
|
+
name: provider,
|
|
327
|
+
isComplete: true,
|
|
328
|
+
present: [...presentSet],
|
|
329
|
+
missing: []
|
|
330
|
+
};
|
|
331
|
+
}
|
|
332
|
+
if (!bestOption || presentCount > bestOption.presentCount) {
|
|
333
|
+
bestOption = { presentCount, missing };
|
|
334
|
+
}
|
|
335
|
+
}
|
|
283
336
|
return {
|
|
284
337
|
name: provider,
|
|
285
|
-
isComplete:
|
|
286
|
-
present: [...
|
|
287
|
-
missing: [
|
|
338
|
+
isComplete: false,
|
|
339
|
+
present: [...presentSet],
|
|
340
|
+
missing: bestOption?.missing ?? []
|
|
288
341
|
};
|
|
289
342
|
}
|
|
290
343
|
function getAvailableProviders() {
|
|
@@ -416,47 +469,12 @@ async function loadProvider(providerName) {
|
|
|
416
469
|
}
|
|
417
470
|
}
|
|
418
471
|
function getProviderConfig(providerName) {
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
break;
|
|
424
|
-
case "railway":
|
|
425
|
-
if (process.env.RAILWAY_API_KEY) config.apiKey = process.env.RAILWAY_API_KEY;
|
|
426
|
-
if (process.env.RAILWAY_PROJECT_ID) config.projectId = process.env.RAILWAY_PROJECT_ID;
|
|
427
|
-
if (process.env.RAILWAY_ENVIRONMENT_ID) config.environmentId = process.env.RAILWAY_ENVIRONMENT_ID;
|
|
428
|
-
break;
|
|
429
|
-
case "daytona":
|
|
430
|
-
if (process.env.DAYTONA_API_KEY) config.apiKey = process.env.DAYTONA_API_KEY;
|
|
431
|
-
break;
|
|
432
|
-
case "modal":
|
|
433
|
-
if (process.env.MODAL_TOKEN_ID) config.tokenId = process.env.MODAL_TOKEN_ID;
|
|
434
|
-
if (process.env.MODAL_TOKEN_SECRET) config.tokenSecret = process.env.MODAL_TOKEN_SECRET;
|
|
435
|
-
break;
|
|
436
|
-
case "runloop":
|
|
437
|
-
if (process.env.RUNLOOP_API_KEY) config.apiKey = process.env.RUNLOOP_API_KEY;
|
|
438
|
-
break;
|
|
439
|
-
case "vercel":
|
|
440
|
-
if (process.env.VERCEL_TOKEN) config.token = process.env.VERCEL_TOKEN;
|
|
441
|
-
if (process.env.VERCEL_TEAM_ID) config.teamId = process.env.VERCEL_TEAM_ID;
|
|
442
|
-
if (process.env.VERCEL_PROJECT_ID) config.projectId = process.env.VERCEL_PROJECT_ID;
|
|
443
|
-
break;
|
|
444
|
-
case "cloudflare":
|
|
445
|
-
if (process.env.CLOUDFLARE_API_TOKEN) config.apiToken = process.env.CLOUDFLARE_API_TOKEN;
|
|
446
|
-
if (process.env.CLOUDFLARE_ACCOUNT_ID) config.accountId = process.env.CLOUDFLARE_ACCOUNT_ID;
|
|
447
|
-
break;
|
|
448
|
-
case "codesandbox":
|
|
449
|
-
if (process.env.CSB_API_KEY) config.apiKey = process.env.CSB_API_KEY;
|
|
450
|
-
break;
|
|
451
|
-
case "blaxel":
|
|
452
|
-
if (process.env.BL_API_KEY) config.apiKey = process.env.BL_API_KEY;
|
|
453
|
-
if (process.env.BL_WORKSPACE) config.workspace = process.env.BL_WORKSPACE;
|
|
454
|
-
break;
|
|
455
|
-
case "gateway":
|
|
456
|
-
if (process.env.COMPUTESDK_API_KEY) config.apiKey = process.env.COMPUTESDK_API_KEY;
|
|
457
|
-
break;
|
|
472
|
+
if (providerName === "gateway") {
|
|
473
|
+
const config = {};
|
|
474
|
+
if (process.env.COMPUTESDK_API_KEY) config.apiKey = process.env.COMPUTESDK_API_KEY;
|
|
475
|
+
return config;
|
|
458
476
|
}
|
|
459
|
-
return
|
|
477
|
+
return getProviderConfigFromEnv(providerName);
|
|
460
478
|
}
|
|
461
479
|
|
|
462
480
|
// src/cli/commands.ts
|
|
@@ -630,9 +648,34 @@ async function runCommand(state, command) {
|
|
|
630
648
|
} catch (error) {
|
|
631
649
|
const duration = Date.now() - startTime;
|
|
632
650
|
logError(`Failed ${c.dim(`(${formatDuration(duration)})`)} - ${error instanceof Error ? error.message : String(error)}`);
|
|
651
|
+
if (isStaleConnectionError(error)) {
|
|
652
|
+
clearSandbox(state);
|
|
653
|
+
logWarning("Sandbox connection lost. Next command will create a new sandbox.");
|
|
654
|
+
}
|
|
633
655
|
throw error;
|
|
634
656
|
}
|
|
635
657
|
}
|
|
658
|
+
function isStaleConnectionError(error) {
|
|
659
|
+
if (!(error instanceof Error)) return false;
|
|
660
|
+
const message = error.message.toLowerCase();
|
|
661
|
+
const stalePhrases = [
|
|
662
|
+
"websocket",
|
|
663
|
+
"connection refused",
|
|
664
|
+
"connection reset",
|
|
665
|
+
"connection closed",
|
|
666
|
+
"socket hang up",
|
|
667
|
+
"econnrefused",
|
|
668
|
+
"econnreset",
|
|
669
|
+
"etimedout",
|
|
670
|
+
"not found",
|
|
671
|
+
"sandbox not found",
|
|
672
|
+
"unauthorized",
|
|
673
|
+
"401",
|
|
674
|
+
"403",
|
|
675
|
+
"404"
|
|
676
|
+
];
|
|
677
|
+
return stalePhrases.some((phrase) => message.includes(phrase));
|
|
678
|
+
}
|
|
636
679
|
async function switchProvider(state, mode, providerName) {
|
|
637
680
|
let useDirect = false;
|
|
638
681
|
let actualProvider = mode;
|
|
@@ -788,7 +831,8 @@ import * as path from "path";
|
|
|
788
831
|
import * as os from "os";
|
|
789
832
|
function createREPL(state) {
|
|
790
833
|
const replServer = repl.start({
|
|
791
|
-
prompt: "
|
|
834
|
+
prompt: "> ",
|
|
835
|
+
// Initial prompt, will be updated by state management
|
|
792
836
|
useColors: true,
|
|
793
837
|
terminal: true,
|
|
794
838
|
useGlobal: false,
|
|
@@ -799,6 +843,7 @@ function createREPL(state) {
|
|
|
799
843
|
setupSmartEvaluator(replServer, state);
|
|
800
844
|
setupAutocomplete(replServer, state);
|
|
801
845
|
setupHistory(replServer);
|
|
846
|
+
state._replServer = replServer;
|
|
802
847
|
return replServer;
|
|
803
848
|
}
|
|
804
849
|
function injectCmdContext(replServer) {
|
|
@@ -906,10 +951,94 @@ function injectWorkbenchCommands(replServer, state) {
|
|
|
906
951
|
};
|
|
907
952
|
replServer.context.env = () => showEnv();
|
|
908
953
|
replServer.context.help = showHelp;
|
|
954
|
+
replServer.context.getUrl = async (options) => {
|
|
955
|
+
const sandbox = state.currentSandbox;
|
|
956
|
+
if (!sandbox) {
|
|
957
|
+
throw new Error("No active sandbox. Run a command to auto-create one.");
|
|
958
|
+
}
|
|
959
|
+
return sandbox.getUrl(options);
|
|
960
|
+
};
|
|
961
|
+
replServer.context.sandboxInfo = async () => {
|
|
962
|
+
const sandbox = state.currentSandbox;
|
|
963
|
+
if (!sandbox) {
|
|
964
|
+
throw new Error("No active sandbox. Run a command to auto-create one.");
|
|
965
|
+
}
|
|
966
|
+
return sandbox.getInfo();
|
|
967
|
+
};
|
|
968
|
+
replServer.context.runCode = async (code, runtime) => {
|
|
969
|
+
const sandbox = state.currentSandbox;
|
|
970
|
+
if (!sandbox) {
|
|
971
|
+
throw new Error("No active sandbox. Run a command to auto-create one.");
|
|
972
|
+
}
|
|
973
|
+
return sandbox.runCode(code, runtime);
|
|
974
|
+
};
|
|
975
|
+
replServer.context.filesystem = {
|
|
976
|
+
get readFile() {
|
|
977
|
+
return async (path2) => {
|
|
978
|
+
const sandbox = state.currentSandbox;
|
|
979
|
+
if (!sandbox) {
|
|
980
|
+
throw new Error("No active sandbox. Run a command to auto-create one.");
|
|
981
|
+
}
|
|
982
|
+
return sandbox.filesystem.readFile(path2);
|
|
983
|
+
};
|
|
984
|
+
},
|
|
985
|
+
get writeFile() {
|
|
986
|
+
return async (path2, content) => {
|
|
987
|
+
const sandbox = state.currentSandbox;
|
|
988
|
+
if (!sandbox) {
|
|
989
|
+
throw new Error("No active sandbox. Run a command to auto-create one.");
|
|
990
|
+
}
|
|
991
|
+
return sandbox.filesystem.writeFile(path2, content);
|
|
992
|
+
};
|
|
993
|
+
},
|
|
994
|
+
get mkdir() {
|
|
995
|
+
return async (path2) => {
|
|
996
|
+
const sandbox = state.currentSandbox;
|
|
997
|
+
if (!sandbox) {
|
|
998
|
+
throw new Error("No active sandbox. Run a command to auto-create one.");
|
|
999
|
+
}
|
|
1000
|
+
return sandbox.filesystem.mkdir(path2);
|
|
1001
|
+
};
|
|
1002
|
+
},
|
|
1003
|
+
get readdir() {
|
|
1004
|
+
return async (path2) => {
|
|
1005
|
+
const sandbox = state.currentSandbox;
|
|
1006
|
+
if (!sandbox) {
|
|
1007
|
+
throw new Error("No active sandbox. Run a command to auto-create one.");
|
|
1008
|
+
}
|
|
1009
|
+
return sandbox.filesystem.readdir(path2);
|
|
1010
|
+
};
|
|
1011
|
+
},
|
|
1012
|
+
get exists() {
|
|
1013
|
+
return async (path2) => {
|
|
1014
|
+
const sandbox = state.currentSandbox;
|
|
1015
|
+
if (!sandbox) {
|
|
1016
|
+
throw new Error("No active sandbox. Run a command to auto-create one.");
|
|
1017
|
+
}
|
|
1018
|
+
return sandbox.filesystem.exists(path2);
|
|
1019
|
+
};
|
|
1020
|
+
},
|
|
1021
|
+
get remove() {
|
|
1022
|
+
return async (path2) => {
|
|
1023
|
+
const sandbox = state.currentSandbox;
|
|
1024
|
+
if (!sandbox) {
|
|
1025
|
+
throw new Error("No active sandbox. Run a command to auto-create one.");
|
|
1026
|
+
}
|
|
1027
|
+
return sandbox.filesystem.remove(path2);
|
|
1028
|
+
};
|
|
1029
|
+
}
|
|
1030
|
+
};
|
|
1031
|
+
replServer.context.getInstance = () => {
|
|
1032
|
+
const sandbox = state.currentSandbox;
|
|
1033
|
+
if (!sandbox) {
|
|
1034
|
+
throw new Error("No active sandbox. Run a command to auto-create one.");
|
|
1035
|
+
}
|
|
1036
|
+
return sandbox.getInstance();
|
|
1037
|
+
};
|
|
909
1038
|
}
|
|
910
1039
|
function setupSmartEvaluator(replServer, state) {
|
|
911
1040
|
const originalEval = replServer.eval;
|
|
912
|
-
const workbenchCommands = /* @__PURE__ */ new Set(["help", "providers", "info", "env", "restart", "destroy", "mode", "verbose"]);
|
|
1041
|
+
const workbenchCommands = /* @__PURE__ */ new Set(["help", "providers", "info", "env", "restart", "destroy", "mode", "verbose", "sandboxInfo"]);
|
|
913
1042
|
replServer.eval = function(cmd3, context, filename, callback) {
|
|
914
1043
|
const trimmedCmd = cmd3.trim();
|
|
915
1044
|
const providerMatch = trimmedCmd.match(/^provider(?:\s+(direct|gateway))?\s+(\w+)$/);
|
|
@@ -968,6 +1097,15 @@ function setupSmartEvaluator(replServer, state) {
|
|
|
968
1097
|
}
|
|
969
1098
|
return;
|
|
970
1099
|
}
|
|
1100
|
+
if (result && typeof result.then === "function") {
|
|
1101
|
+
try {
|
|
1102
|
+
const output = await result;
|
|
1103
|
+
callback(null, output);
|
|
1104
|
+
} catch (error) {
|
|
1105
|
+
callback(error, void 0);
|
|
1106
|
+
}
|
|
1107
|
+
return;
|
|
1108
|
+
}
|
|
971
1109
|
callback(null, result);
|
|
972
1110
|
});
|
|
973
1111
|
};
|
|
@@ -986,52 +1124,81 @@ function setupAutocomplete(replServer, state) {
|
|
|
986
1124
|
"help": [],
|
|
987
1125
|
"verbose": [],
|
|
988
1126
|
"exit": [],
|
|
989
|
-
".exit": []
|
|
1127
|
+
".exit": [],
|
|
1128
|
+
// Sandbox methods
|
|
1129
|
+
"getUrl": [],
|
|
1130
|
+
"runCode": [],
|
|
1131
|
+
"sandboxInfo": [],
|
|
1132
|
+
"getInstance": []
|
|
1133
|
+
// Filesystem is an object, so it gets dot notation autocomplete automatically
|
|
990
1134
|
};
|
|
991
1135
|
replServer.completer = function(line, callback) {
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
1136
|
+
try {
|
|
1137
|
+
const trimmed = line.trim();
|
|
1138
|
+
if (!line.includes(" ") && !line.includes(".")) {
|
|
1139
|
+
const commands = Object.keys(workbenchCommands);
|
|
1140
|
+
const hits = commands.filter((cmd3) => cmd3.startsWith(trimmed));
|
|
1141
|
+
if (originalCompleter) {
|
|
1142
|
+
originalCompleter.call(replServer, line, (err, result) => {
|
|
1143
|
+
if (err || !result) {
|
|
1144
|
+
callback(null, [hits, trimmed]);
|
|
1145
|
+
return;
|
|
1146
|
+
}
|
|
1147
|
+
if (!Array.isArray(result) || result.length !== 2) {
|
|
1148
|
+
callback(null, [hits, trimmed]);
|
|
1149
|
+
return;
|
|
1150
|
+
}
|
|
1151
|
+
const [contextHits, partial] = result;
|
|
1152
|
+
if (!Array.isArray(contextHits)) {
|
|
1153
|
+
callback(null, [hits, trimmed]);
|
|
1154
|
+
return;
|
|
1155
|
+
}
|
|
1156
|
+
const allHits = [.../* @__PURE__ */ new Set([...hits, ...contextHits])].sort();
|
|
1157
|
+
const completionPrefix = typeof partial === "string" ? partial : trimmed;
|
|
1158
|
+
callback(null, [allHits, completionPrefix]);
|
|
1159
|
+
});
|
|
1160
|
+
return;
|
|
1161
|
+
}
|
|
1162
|
+
callback(null, [hits.length ? hits : commands, trimmed]);
|
|
1163
|
+
return;
|
|
1164
|
+
}
|
|
1165
|
+
if (line.includes(" ") && !line.includes(".")) {
|
|
1166
|
+
const parts = line.split(" ");
|
|
1167
|
+
const command = parts[0].trim();
|
|
1168
|
+
const partial = parts.slice(1).join(" ").trim();
|
|
1169
|
+
const suggestions = workbenchCommands[command];
|
|
1170
|
+
if (suggestions !== void 0) {
|
|
1171
|
+
if (suggestions.length > 0) {
|
|
1172
|
+
const hits = suggestions.filter((s) => s.startsWith(partial)).map((s) => `${command} ${s}`);
|
|
1173
|
+
callback(null, [hits.length ? hits : suggestions.map((s) => `${command} ${s}`), line]);
|
|
1174
|
+
} else {
|
|
1175
|
+
callback(null, [[], line]);
|
|
1176
|
+
}
|
|
1177
|
+
return;
|
|
1178
|
+
}
|
|
1179
|
+
}
|
|
996
1180
|
if (originalCompleter) {
|
|
997
1181
|
originalCompleter.call(replServer, line, (err, result) => {
|
|
998
1182
|
if (err || !result) {
|
|
999
|
-
callback(null, [
|
|
1183
|
+
callback(null, [[], line]);
|
|
1000
1184
|
return;
|
|
1001
1185
|
}
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
callback(null, [hits, trimmed]);
|
|
1186
|
+
if (!Array.isArray(result) || result.length !== 2) {
|
|
1187
|
+
callback(null, [[], line]);
|
|
1005
1188
|
return;
|
|
1006
1189
|
}
|
|
1007
|
-
const
|
|
1008
|
-
|
|
1190
|
+
const [completions, partial] = result;
|
|
1191
|
+
if (!Array.isArray(completions) || typeof partial !== "string") {
|
|
1192
|
+
callback(null, [[], line]);
|
|
1193
|
+
return;
|
|
1194
|
+
}
|
|
1195
|
+
callback(null, [completions, partial]);
|
|
1009
1196
|
});
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
callback(null, [hits.length ? hits : commands, trimmed]);
|
|
1013
|
-
return;
|
|
1014
|
-
}
|
|
1015
|
-
if (line.includes(" ") && !line.includes(".")) {
|
|
1016
|
-
const parts = line.split(" ");
|
|
1017
|
-
const command = parts[0].trim();
|
|
1018
|
-
const partial = parts.slice(1).join(" ").trim();
|
|
1019
|
-
const suggestions = workbenchCommands[command];
|
|
1020
|
-
if (suggestions && suggestions.length > 0) {
|
|
1021
|
-
const hits = suggestions.filter((s) => s.startsWith(partial)).map((s) => `${command} ${s}`);
|
|
1022
|
-
callback(null, [hits.length ? hits : suggestions.map((s) => `${command} ${s}`), line]);
|
|
1023
|
-
return;
|
|
1197
|
+
} else {
|
|
1198
|
+
callback(null, [[], line]);
|
|
1024
1199
|
}
|
|
1025
|
-
}
|
|
1026
|
-
|
|
1027
|
-
originalCompleter.call(replServer, line, (err, result) => {
|
|
1028
|
-
if (err || !result) {
|
|
1029
|
-
callback(null, [[], line]);
|
|
1030
|
-
return;
|
|
1031
|
-
}
|
|
1032
|
-
callback(null, result);
|
|
1033
|
-
});
|
|
1034
|
-
} else {
|
|
1200
|
+
} catch (error) {
|
|
1201
|
+
console.error("Autocomplete error:", error);
|
|
1035
1202
|
callback(null, [[], line]);
|
|
1036
1203
|
}
|
|
1037
1204
|
};
|