mindwire 0.1.10 → 0.1.13
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/README.md +73 -0
- package/dist/client.d.ts +3 -0
- package/dist/index.cjs +182 -19
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.js +180 -20
- package/dist/index.js.map +1 -1
- package/dist/run.d.ts +8 -4
- package/dist/types.d.ts +53 -5
- package/dist/workspace.d.ts +149 -0
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -32,3 +32,6 @@ export { catalogProviders, catalogProvider, catalogModels, lookupModel, loadCata
|
|
|
32
32
|
export type { CatalogOptions } from "./catalog/index.js";
|
|
33
33
|
export { MindwireError, ApiError, RunFailedError, TimeoutError } from "./errors.js";
|
|
34
34
|
export * from "./types.js";
|
|
35
|
+
export { WorkspaceApi, WorkspaceCollection, ProjectOperationsApi } from "./workspace.js";
|
|
36
|
+
export type { ProjectRequest, ProjectAuth, ProjectOperation, ProjectRemoveRequest } from "./workspace.js";
|
|
37
|
+
export type { WorkspaceRecord, WorkspaceAgent, WorkspaceProject, WorkspaceChat, WorkspaceKind, WorkspaceInput, WorkspaceImport, WorkspaceSnapshot } from "./workspace.js";
|
package/dist/index.js
CHANGED
|
@@ -286,6 +286,8 @@ async function* readSSE(body, signal) {
|
|
|
286
286
|
if (payload !== void 0) yield JSON.parse(payload);
|
|
287
287
|
} finally {
|
|
288
288
|
if (signal) signal.removeEventListener("abort", onAbort);
|
|
289
|
+
await reader.cancel().catch(() => {
|
|
290
|
+
});
|
|
289
291
|
reader.releaseLock();
|
|
290
292
|
}
|
|
291
293
|
}
|
|
@@ -358,7 +360,8 @@ var Run = class _Run {
|
|
|
358
360
|
}
|
|
359
361
|
/** Unified SSE event stream: replay buffer, then live events, then close. */
|
|
360
362
|
async *stream(opts = {}) {
|
|
361
|
-
const
|
|
363
|
+
const cursor = opts.after === void 0 ? "" : `?after=${encodeURIComponent(opts.after)}`;
|
|
364
|
+
const res = await this.http.open("GET", `/runs/${encodeURIComponent(this.id)}/stream${cursor}`, {
|
|
362
365
|
...opts.signal ? { signal: opts.signal } : {}
|
|
363
366
|
});
|
|
364
367
|
for await (const ev of readSSE(res.body, opts.signal)) {
|
|
@@ -409,9 +412,9 @@ var Run = class _Run {
|
|
|
409
412
|
});
|
|
410
413
|
}
|
|
411
414
|
/**
|
|
412
|
-
* Switch the permission mode
|
|
413
|
-
*
|
|
414
|
-
*
|
|
415
|
+
* Switch the live permission mode using a value from the agent's settings schema.
|
|
416
|
+
* Resolves after the harness acknowledges the change; rejects if it cannot apply it.
|
|
417
|
+
* Requires `setPermissionMode`. Codex settings apply on the next turn instead.
|
|
415
418
|
*/
|
|
416
419
|
async setPermissionMode(mode) {
|
|
417
420
|
await this.http.request("POST", `/runs/${encodeURIComponent(this.id)}/set-permission-mode`, {
|
|
@@ -435,6 +438,12 @@ var Run = class _Run {
|
|
|
435
438
|
this.data = await this.http.request("GET", `/runs/${encodeURIComponent(this.id)}`);
|
|
436
439
|
return this.data;
|
|
437
440
|
}
|
|
441
|
+
/** Restore current output once, then follow with `stream({ after: snapshot.sequence })`. */
|
|
442
|
+
async snapshot() {
|
|
443
|
+
const snapshot = await this.http.request("GET", `/runs/${encodeURIComponent(this.id)}/snapshot`);
|
|
444
|
+
this.data = snapshot.run;
|
|
445
|
+
return snapshot;
|
|
446
|
+
}
|
|
438
447
|
/**
|
|
439
448
|
* Consume the event stream to completion. Returns the final run record and the `result`
|
|
440
449
|
* event's summary (if any). Throws {@link RunFailedError} on an `error`/`cancelled` outcome
|
|
@@ -465,8 +474,114 @@ var Run = class _Run {
|
|
|
465
474
|
}
|
|
466
475
|
};
|
|
467
476
|
|
|
477
|
+
// src/workspace.ts
|
|
478
|
+
var ProjectOperationsApi = class {
|
|
479
|
+
constructor(mw) {
|
|
480
|
+
this.mw = mw;
|
|
481
|
+
}
|
|
482
|
+
mw;
|
|
483
|
+
async list(activeOnly = false) {
|
|
484
|
+
const response = await this.mw.http.request("GET", "/workspace/operations", {
|
|
485
|
+
query: { active: activeOnly }
|
|
486
|
+
});
|
|
487
|
+
return response.operations;
|
|
488
|
+
}
|
|
489
|
+
get(id) {
|
|
490
|
+
return this.mw.http.request("GET", `/workspace/operations/${encodeURIComponent(id)}`);
|
|
491
|
+
}
|
|
492
|
+
cancel(id) {
|
|
493
|
+
return this.mw.http.request("POST", `/workspace/operations/${encodeURIComponent(id)}/cancel`);
|
|
494
|
+
}
|
|
495
|
+
retry(id, auth) {
|
|
496
|
+
return this.mw.http.request("POST", `/workspace/operations/${encodeURIComponent(id)}/retry`, { body: { auth } });
|
|
497
|
+
}
|
|
498
|
+
/** The first event is the current snapshot, then live changes. Reconnecting never replays old
|
|
499
|
+
* progress. Breaking the loop/aborting detaches the observer; cancel(id) explicitly stops work.
|
|
500
|
+
*/
|
|
501
|
+
async *watch(id, opts = {}) {
|
|
502
|
+
const controller = new AbortController();
|
|
503
|
+
const abort = () => controller.abort();
|
|
504
|
+
opts.signal?.addEventListener("abort", abort, { once: true });
|
|
505
|
+
if (opts.signal?.aborted) controller.abort();
|
|
506
|
+
try {
|
|
507
|
+
const response = await this.mw.http.open("GET", `/workspace/operations/${encodeURIComponent(id)}/stream`, {
|
|
508
|
+
signal: controller.signal
|
|
509
|
+
});
|
|
510
|
+
let sequence = -1;
|
|
511
|
+
for await (const operation of readSSE(response.body, controller.signal)) {
|
|
512
|
+
if (operation.sequence > sequence) {
|
|
513
|
+
sequence = operation.sequence;
|
|
514
|
+
yield operation;
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
} finally {
|
|
518
|
+
controller.abort();
|
|
519
|
+
opts.signal?.removeEventListener("abort", abort);
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
};
|
|
523
|
+
var WorkspaceCollection = class {
|
|
524
|
+
constructor(mw, kind) {
|
|
525
|
+
this.mw = mw;
|
|
526
|
+
this.kind = kind;
|
|
527
|
+
}
|
|
528
|
+
mw;
|
|
529
|
+
kind;
|
|
530
|
+
/** Create with a stable client-generated ID. For updates, supply the record's last revision. */
|
|
531
|
+
put(id, record, expectedRevision) {
|
|
532
|
+
return this.mw.http.request("PUT", `/workspace/${this.kind}/${encodeURIComponent(id)}`, {
|
|
533
|
+
body: { record, expectedRevision }
|
|
534
|
+
});
|
|
535
|
+
}
|
|
536
|
+
/** Remove membership and dependent chat links. Files and native transcripts are retained.
|
|
537
|
+
* Use deleteChat() for an explicit transcript purge. Running chats reject removal with 409.
|
|
538
|
+
*/
|
|
539
|
+
delete(id, revision) {
|
|
540
|
+
return this.mw.http.request("DELETE", `/workspace/${this.kind}/${encodeURIComponent(id)}`, {
|
|
541
|
+
query: { revision }
|
|
542
|
+
});
|
|
543
|
+
}
|
|
544
|
+
};
|
|
545
|
+
var WorkspaceApi = class {
|
|
546
|
+
constructor(mw) {
|
|
547
|
+
this.mw = mw;
|
|
548
|
+
this.operations = new ProjectOperationsApi(mw);
|
|
549
|
+
this.agents = new WorkspaceCollection(mw, "agents");
|
|
550
|
+
this.projects = new WorkspaceCollection(mw, "projects");
|
|
551
|
+
this.chats = new WorkspaceCollection(mw, "chats");
|
|
552
|
+
}
|
|
553
|
+
mw;
|
|
554
|
+
operations;
|
|
555
|
+
agents;
|
|
556
|
+
projects;
|
|
557
|
+
chats;
|
|
558
|
+
snapshot() {
|
|
559
|
+
return this.mw.http.request("GET", "/workspace");
|
|
560
|
+
}
|
|
561
|
+
/** Start an operation owned by the daemon. The same ID/payload returns the existing operation. */
|
|
562
|
+
createProject(request) {
|
|
563
|
+
return this.mw.http.request("POST", "/workspace/projects", { body: request });
|
|
564
|
+
}
|
|
565
|
+
/** Permanently remove the confirmed project's directory and membership.
|
|
566
|
+
* projects.delete() retains files. Native harness transcripts are not purged.
|
|
567
|
+
*/
|
|
568
|
+
removeProjectFiles(id, request) {
|
|
569
|
+
return this.mw.http.request("POST", `/workspace/projects/${encodeURIComponent(id)}/remove`, { body: request });
|
|
570
|
+
}
|
|
571
|
+
/** Incremental reconciliation. Pass the previous identity to detect a replaced/restored workspace.
|
|
572
|
+
* A 409 requires fetching snapshot() again; never apply a delta to a different registry.
|
|
573
|
+
*/
|
|
574
|
+
changes(since, workspaceId) {
|
|
575
|
+
return this.mw.http.request("GET", "/workspace/changes", { query: { since, workspaceId } });
|
|
576
|
+
}
|
|
577
|
+
/** Import legacy metadata before replacing a local cache. Safe to repeat after interruption. */
|
|
578
|
+
import(records) {
|
|
579
|
+
return this.mw.http.request("POST", "/workspace/import", { body: records });
|
|
580
|
+
}
|
|
581
|
+
};
|
|
582
|
+
|
|
468
583
|
// src/version.ts
|
|
469
|
-
var SDK_VERSION = "0.1.
|
|
584
|
+
var SDK_VERSION = "0.1.13" ;
|
|
470
585
|
|
|
471
586
|
// src/daemon-binary.ts
|
|
472
587
|
function supported(platform, arch) {
|
|
@@ -724,6 +839,8 @@ function remote(baseUrl, opts = {}) {
|
|
|
724
839
|
// src/client.ts
|
|
725
840
|
var handleByTransport = /* @__PURE__ */ new WeakMap();
|
|
726
841
|
var Mindwire = class _Mindwire {
|
|
842
|
+
/** Workspace registry: saved agent profiles, projects and chat relationships. */
|
|
843
|
+
workspace;
|
|
727
844
|
http;
|
|
728
845
|
/** The default agent type applied to agent-scoped calls, if set. */
|
|
729
846
|
defaultAgent;
|
|
@@ -757,6 +874,7 @@ var Mindwire = class _Mindwire {
|
|
|
757
874
|
}
|
|
758
875
|
});
|
|
759
876
|
this.defaultAgent = opts.agent;
|
|
877
|
+
this.workspace = new WorkspaceApi(this);
|
|
760
878
|
this.auth = new AuthApi(this);
|
|
761
879
|
this.prompts = new PromptsApi(this);
|
|
762
880
|
this.mcp = new McpApi(this);
|
|
@@ -777,6 +895,7 @@ var Mindwire = class _Mindwire {
|
|
|
777
895
|
const clone = Object.create(_Mindwire.prototype);
|
|
778
896
|
clone.http = this.http;
|
|
779
897
|
clone.defaultAgent = agent;
|
|
898
|
+
clone.workspace = new WorkspaceApi(clone);
|
|
780
899
|
clone.auth = new AuthApi(clone);
|
|
781
900
|
clone.prompts = new PromptsApi(clone);
|
|
782
901
|
clone.mcp = new McpApi(clone);
|
|
@@ -1299,17 +1418,24 @@ function makeEmit(cfg) {
|
|
|
1299
1418
|
}
|
|
1300
1419
|
};
|
|
1301
1420
|
}
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1421
|
+
async function daemonDirectory(host) {
|
|
1422
|
+
const result = await host.exec(["sh", "-lc", 'printf "<<MW_HOME>>%s<<MW_HOME>>" "$HOME"'], { timeoutSeconds: 15 });
|
|
1423
|
+
const runtimeHome = result.stdout?.match(/<<MW_HOME>>([\s\S]*?)<<MW_HOME>>/)?.[1];
|
|
1424
|
+
if (!runtimeHome?.startsWith("/") || runtimeHome.length > 4096 || /[\x00-\x1f\x7f]/.test(runtimeHome)) {
|
|
1425
|
+
throw new MindwireError("mindwire: cannot resolve the runtime user's home directory");
|
|
1426
|
+
}
|
|
1427
|
+
return runtimeHome.replace(/\/+$/, "") + "/.mindwire";
|
|
1428
|
+
}
|
|
1307
1429
|
async function ensureDaemon(host, cfg) {
|
|
1308
1430
|
const emit2 = makeEmit(cfg);
|
|
1309
|
-
|
|
1431
|
+
let token = cfg.token ?? (await import('crypto')).randomBytes(32).toString("hex");
|
|
1310
1432
|
try {
|
|
1311
1433
|
await waitHostReady(host);
|
|
1312
1434
|
emit2({ phase: "connect", message: "runtime ready" });
|
|
1435
|
+
const directory = await daemonDirectory(host);
|
|
1436
|
+
if (!cfg.token) {
|
|
1437
|
+
token = await readWorkspaceToken(host, directory) ?? token;
|
|
1438
|
+
}
|
|
1313
1439
|
const desired = cfg.desiredVersion ?? SDK_VERSION;
|
|
1314
1440
|
const health = await probeHealth(host, cfg.port, token);
|
|
1315
1441
|
if (health.reachable) {
|
|
@@ -1330,22 +1456,35 @@ async function ensureDaemon(host, cfg) {
|
|
|
1330
1456
|
} else {
|
|
1331
1457
|
emit2({ phase: "probe", message: "no daemon reachable; deploying" });
|
|
1332
1458
|
}
|
|
1333
|
-
await deploy(host, cfg, emit2, token);
|
|
1459
|
+
await deploy(host, cfg, emit2, token, directory);
|
|
1460
|
+
if (!cfg.token) token = await readWorkspaceToken(host, directory) ?? token;
|
|
1334
1461
|
return token;
|
|
1335
1462
|
} catch (err) {
|
|
1336
1463
|
emit2({ phase: "error", message: "ensure failed", error: err instanceof Error ? err.message : String(err) });
|
|
1337
1464
|
throw err;
|
|
1338
1465
|
}
|
|
1339
1466
|
}
|
|
1340
|
-
async function
|
|
1467
|
+
async function readWorkspaceToken(host, directory) {
|
|
1468
|
+
const saved = await host.exec(["sh", "-lc", `cat ${shellQuote(directory + "/daemon.token")} 2>/dev/null || true`], { timeoutSeconds: 15 });
|
|
1469
|
+
const candidate = saved.stdout?.trim();
|
|
1470
|
+
return candidate && candidate.length <= 4096 && /^[\x21-\x7e]+$/.test(candidate) ? candidate : void 0;
|
|
1471
|
+
}
|
|
1472
|
+
async function deploy(host, cfg, emit2, token, directory) {
|
|
1473
|
+
const newPath = directory + "/mindwired.new";
|
|
1474
|
+
const BIN = shellQuote(directory + "/mindwired"), BIN_NEW = shellQuote(newPath);
|
|
1475
|
+
const STATE = shellQuote(directory + "/agent-state.json"), LOG = shellQuote(directory + "/daemon.log");
|
|
1476
|
+
const TOKEN = shellQuote(directory + "/daemon.token");
|
|
1341
1477
|
const arch = await probeArch(host);
|
|
1342
1478
|
const desired = cfg.desiredVersion ?? SDK_VERSION;
|
|
1343
1479
|
let acquire = "";
|
|
1480
|
+
let stagedUpload;
|
|
1344
1481
|
if (cfg.daemonBin) {
|
|
1345
1482
|
const binPath = await resolveLinuxDaemon(cfg.daemonBin, arch);
|
|
1346
1483
|
const bytes = await readBytes(binPath);
|
|
1347
1484
|
emit2({ phase: "upload", message: `uploading daemon (${arch}, ${formatMiB(bytes.length)})`, arch, bytes: bytes.length });
|
|
1348
|
-
await
|
|
1485
|
+
stagedUpload = `${newPath}-${(await import('crypto')).randomUUID()}`;
|
|
1486
|
+
await host.putFile(stagedUpload, bytes, { mode: "0755" });
|
|
1487
|
+
acquire = `mv -f ${shellQuote(stagedUpload)} ${BIN_NEW}`;
|
|
1349
1488
|
} else {
|
|
1350
1489
|
if (!/^[0-9]+\.[0-9]+\.[0-9]+(?:-[0-9A-Za-z.-]+)?$/.test(desired)) {
|
|
1351
1490
|
throw new MindwireError(`mindwire: cannot download daemon for non-release SDK version ${desired}`);
|
|
@@ -1376,25 +1515,46 @@ async function deploy(host, cfg, emit2, token) {
|
|
|
1376
1515
|
}
|
|
1377
1516
|
const script = [
|
|
1378
1517
|
"set -e",
|
|
1379
|
-
`mkdir -p ${
|
|
1518
|
+
`mkdir -p ${shellQuote(directory)}`,
|
|
1519
|
+
// iOS takes this same workspace lock. Unique staging also protects concurrent local uploads.
|
|
1520
|
+
stagedUpload ? `trap ${shellQuote(`rm -f ${shellQuote(stagedUpload)}`)} EXIT` : "",
|
|
1521
|
+
'command -v flock >/dev/null 2>&1 || { echo "MINDWIRE_FAIL flock is required to lock daemon updates"; exit 1; }',
|
|
1522
|
+
`exec 9>${shellQuote(directory + "/daemon-install.lock")}`,
|
|
1523
|
+
'flock -w 360 9 || { echo "MINDWIRE_FAIL another daemon update is still running"; exit 1; }',
|
|
1524
|
+
`mw_token=${shellQuote(token)}`,
|
|
1525
|
+
!cfg.token ? `if [ -s ${TOKEN} ]; then mw_token=$(cat ${TOKEN}); fi` : "",
|
|
1526
|
+
!cfg.forceDeploy ? [
|
|
1527
|
+
`mw_health=$(curl -fsS --max-time 3 -H "Authorization: Bearer $mw_token" http://127.0.0.1:${cfg.port}/healthz 2>/dev/null || true)`,
|
|
1528
|
+
`mw_version=$(printf '%s' "$mw_health" | sed -n 's/.*"version"[[:space:]]*:[[:space:]]*"\\([^" ]*\\)".*/\\1/p')`,
|
|
1529
|
+
`if [ -n "$mw_health" ] && ${cfg.autoUpdate ? `[ "$mw_version" = ${shellQuote(desired)} ]` : "true"}; then echo MINDWIRE_READY; exit 0; fi`
|
|
1530
|
+
].join("\n") : "",
|
|
1380
1531
|
acquire,
|
|
1381
1532
|
// Stop a prior daemon by exact process NAME, never `pkill -f <path>`: this whole script (which
|
|
1382
1533
|
// contains `${BIN}` several times) is the argv of the `bash -lc` shell running it, so a full-cmdline
|
|
1383
1534
|
// match would SIGTERM our own deploying shell before the daemon ever launches. `-x mindwired` matches
|
|
1384
1535
|
// only the daemon's comm (`bash`/`pkill` never match), leaving this shell alive.
|
|
1385
|
-
|
|
1536
|
+
"if command -v pkill >/dev/null 2>&1; then",
|
|
1537
|
+
" pkill -x mindwired 2>/dev/null || true",
|
|
1538
|
+
"else",
|
|
1539
|
+
" for mw_proc in /proc/[0-9]*/comm; do",
|
|
1540
|
+
' IFS= read -r mw_name 2>/dev/null < "$mw_proc" || continue',
|
|
1541
|
+
' [ "$mw_name" = mindwired ] || continue',
|
|
1542
|
+
" mw_pid=${mw_proc#/proc/}; mw_pid=${mw_pid%/comm}",
|
|
1543
|
+
' kill "$mw_pid" 2>/dev/null || true',
|
|
1544
|
+
" done",
|
|
1545
|
+
"fi",
|
|
1386
1546
|
"sleep 0.3",
|
|
1387
1547
|
`mv -f ${BIN_NEW} ${BIN}`,
|
|
1388
1548
|
`chmod +x ${BIN}`,
|
|
1389
1549
|
// Detach so the daemon survives this exec's shell exiting. ADDR=":<port>" binds 0.0.0.0.
|
|
1390
|
-
`setsid nohup env ADDR=":${cfg.port}" AGENT_TYPE
|
|
1550
|
+
`setsid nohup env ADDR=":${cfg.port}" AGENT_TYPE=${shellQuote(cfg.agent)} AGENT_CWD=${shellQuote(cfg.agentCwd)} STATE_PATH=${STATE} DAEMON_TOKEN="$mw_token" ${BIN} > ${LOG} 2>&1 < /dev/null 9>&- &`,
|
|
1391
1551
|
// Health-poll from inside the VM (loopback) and emit a marker — exit codes are unreliable here.
|
|
1392
|
-
`for i in $(seq 1 60); do curl -fsS --max-time 2 -H
|
|
1552
|
+
`for i in $(seq 1 60); do curl -fsS --max-time 2 -H "Authorization: Bearer $mw_token" http://127.0.0.1:${cfg.port}/healthz >/dev/null 2>&1 && { echo MINDWIRE_READY; exit 0; }; sleep 0.25; done`,
|
|
1393
1553
|
"echo MINDWIRE_FAIL",
|
|
1394
1554
|
`tail -n 40 ${LOG} 2>/dev/null || true`
|
|
1395
1555
|
].join("\n");
|
|
1396
1556
|
emit2({ phase: "launch", message: "launching daemon" });
|
|
1397
|
-
const res = await host.exec(["bash", "-lc", script], { timeoutSeconds:
|
|
1557
|
+
const res = await host.exec(["bash", "-lc", script], { timeoutSeconds: 420 });
|
|
1398
1558
|
const out = res.stdout ?? "";
|
|
1399
1559
|
if (!out.includes("MINDWIRE_READY")) {
|
|
1400
1560
|
throw new MindwireError(
|
|
@@ -2299,6 +2459,6 @@ function clearCatalogCache() {
|
|
|
2299
2459
|
inflight = null;
|
|
2300
2460
|
}
|
|
2301
2461
|
|
|
2302
|
-
export { ApiError, AuthApi, ContainerHost, Http, MODELS_DEV_URL, McpApi, Mindwire, MindwireError, NotifyApi, PromptsApi, ProvidersApi, Run, RunFailedError, SDK_VERSION, TimeoutError, catalogModels, catalogProvider, catalogProviders, clearCatalogCache, docker, ensureDaemon, ensureDaemonBinary, loadCatalog, local, lookupModel, oblien, provisionContainer, provisionDocker, provisionOblien, provisionSsh, provisionSshContainer, remote, resolveLinuxDaemon, ssh, startEmbedded };
|
|
2462
|
+
export { ApiError, AuthApi, ContainerHost, Http, MODELS_DEV_URL, McpApi, Mindwire, MindwireError, NotifyApi, ProjectOperationsApi, PromptsApi, ProvidersApi, Run, RunFailedError, SDK_VERSION, TimeoutError, WorkspaceApi, WorkspaceCollection, catalogModels, catalogProvider, catalogProviders, clearCatalogCache, docker, ensureDaemon, ensureDaemonBinary, loadCatalog, local, lookupModel, oblien, provisionContainer, provisionDocker, provisionOblien, provisionSsh, provisionSshContainer, remote, resolveLinuxDaemon, ssh, startEmbedded };
|
|
2303
2463
|
//# sourceMappingURL=index.js.map
|
|
2304
2464
|
//# sourceMappingURL=index.js.map
|