svamp-cli 0.2.118 → 0.2.120

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 (25) hide show
  1. package/bin/skills/loop/SKILL.md +1 -1
  2. package/bin/skills/loop/bin/checklist.mjs +94 -0
  3. package/bin/skills/loop/bin/loop-init.mjs +4 -1
  4. package/bin/skills/loop/bin/stop-gate.mjs +24 -3
  5. package/bin/skills/loop/test/test-checklist.mjs +65 -0
  6. package/dist/{agentCommands-BTkU0PQb.mjs → agentCommands-DIfofhT-.mjs} +4 -4
  7. package/dist/{auth-DimbhOMP.mjs → auth-zcVYRjJ8.mjs} +1 -1
  8. package/dist/cli.mjs +78 -54
  9. package/dist/{commands-Bw2V_awn.mjs → commands-BFpGoTq8.mjs} +1 -1
  10. package/dist/{commands-BJfRk4KT.mjs → commands-BOCpNFZX.mjs} +2 -2
  11. package/dist/{commands-3FsdWpJO.mjs → commands-BYsoZ6Fn.mjs} +2 -2
  12. package/dist/{commands-BEjlVtvS.mjs → commands-CPsUPDnI.mjs} +1 -1
  13. package/dist/{commands-B5rek8XG.mjs → commands-CuY9G_88.mjs} +94 -14
  14. package/dist/{commands-fbQs3jLx.mjs → commands-DOtJfJG7.mjs} +5 -5
  15. package/dist/{fleet-D5dNVJIp.mjs → fleet-CEAB4PS0.mjs} +1 -1
  16. package/dist/{frpc-CdcXdQde.mjs → frpc-DlsBjcRf.mjs} +1 -1
  17. package/dist/{headlessCli-Lk2OU1Gh.mjs → headlessCli-DuY4WQVa.mjs} +2 -2
  18. package/dist/index.mjs +1 -1
  19. package/dist/{package-CxWiFy_P.mjs → package-DS33M8qt.mjs} +1 -1
  20. package/dist/{run-DIoR81Ev.mjs → run-6Pp8yTPw.mjs} +1 -1
  21. package/dist/{run-9C2ogsuu.mjs → run-C4BsPJ_p.mjs} +832 -66
  22. package/dist/{serveCommands-BqApmjmR.mjs → serveCommands-UDH0noeg.mjs} +5 -5
  23. package/dist/{serveManager-XsXnI804.mjs → serveManager-QZooKtI4.mjs} +2 -2
  24. package/dist/{sideband-BHWq1P8E.mjs → sideband-Wfli3n7U.mjs} +1 -1
  25. package/package.json +1 -1
@@ -2,7 +2,7 @@ import { existsSync, readFileSync, writeFileSync } from 'node:fs';
2
2
  import { execSync } from 'node:child_process';
3
3
  import { basename, resolve, join, isAbsolute } from 'node:path';
4
4
  import os from 'node:os';
5
- import { G as normalizeAllowedUser, H as loadSecurityContextConfig, I as resolveSecurityContext, J as buildSecurityContextFromFlags, K as mergeSecurityContexts, c as connectToHypha, L as buildSessionShareUrl, M as computeOutboundHop, n as shortId, N as buildMachineShareUrl } from './run-9C2ogsuu.mjs';
5
+ import { G as formatHandle, H as normalizeAllowedUser, I as loadSecurityContextConfig, J as resolveSecurityContext, K as buildSecurityContextFromFlags, L as mergeSecurityContexts, c as connectToHypha, M as buildSessionShareUrl, N as computeOutboundHop, n as shortId, O as buildMachineShareUrl, P as parseHandle, Q as handleMatchesMetadata } from './run-C4BsPJ_p.mjs';
6
6
  import 'os';
7
7
  import 'fs/promises';
8
8
  import 'fs';
@@ -43,6 +43,10 @@ function resolveDisplayName(meta, directory) {
43
43
  const dirName = dir ? basename(dir) : "";
44
44
  return customTitle || summary || name || dirName || "untitled";
45
45
  }
46
+ function resolveHandle(meta) {
47
+ const m = meta || {};
48
+ return formatHandle(m.projectName, m.friendlyName);
49
+ }
46
50
  function toMarkdownInline(value) {
47
51
  const escaped = value.replace(/`/g, "\\`");
48
52
  return `\`${escaped}\``;
@@ -52,6 +56,7 @@ function formatSessionStatus(data) {
52
56
  "## Session Status",
53
57
  "",
54
58
  `- Session ID: ${toMarkdownInline(data.sessionId)}`,
59
+ ...data.handle ? [`- Handle: ${toMarkdownInline(data.handle)}`] : [],
55
60
  `- Agent: ${data.flavor}`
56
61
  ];
57
62
  if (data.name) lines.push(`- Title: ${data.name}`);
@@ -89,6 +94,9 @@ const SESSION_RPC_PARAMS = {
89
94
  getLatestMessages: ["beforeSeq", "limit"],
90
95
  sendMessage: ["content", "localId", "meta"],
91
96
  btw: ["question"],
97
+ editMessage: ["messageId", "newText"],
98
+ refineLastReply: ["instruction"],
99
+ undoLastEdit: [],
92
100
  getMetadata: [],
93
101
  updateMetadata: ["newMetadata", "expectedVersion"],
94
102
  updateConfig: ["patch"],
@@ -521,9 +529,16 @@ ${machines.length} machine(s) found.`);
521
529
  await server.disconnect();
522
530
  }
523
531
  }
532
+ function matchByHandle(sessions, partial) {
533
+ const parsed = parseHandle(partial);
534
+ if (!parsed) return [];
535
+ return sessions.filter((s) => handleMatchesMetadata(parsed, s.metadata || {}));
536
+ }
524
537
  function findSessionMatch(sessions, partial) {
525
538
  const exact = sessions.find((s) => s.sessionId === partial);
526
539
  if (exact) return exact;
540
+ const byHandle = matchByHandle(sessions, partial);
541
+ if (byHandle.length === 1) return byHandle[0];
527
542
  const matches = sessions.filter((s) => s.sessionId.startsWith(partial));
528
543
  if (matches.length === 1) return matches[0];
529
544
  return void 0;
@@ -531,6 +546,15 @@ function findSessionMatch(sessions, partial) {
531
546
  function resolveSessionId(sessions, partial) {
532
547
  const exact = sessions.find((s) => s.sessionId === partial);
533
548
  if (exact) return exact;
549
+ const byHandle = matchByHandle(sessions, partial);
550
+ if (byHandle.length === 1) return byHandle[0];
551
+ if (byHandle.length > 1) {
552
+ console.error(`Ambiguous handle "${partial}". Matches:`);
553
+ for (const s of byHandle) {
554
+ console.error(` ${resolveHandle(s.metadata || {}) || s.sessionId} (${s.sessionId})`);
555
+ }
556
+ process.exit(1);
557
+ }
534
558
  const matches = sessions.filter((s) => s.sessionId.startsWith(partial));
535
559
  if (matches.length === 1) return matches[0];
536
560
  if (matches.length === 0) {
@@ -782,10 +806,12 @@ async function sessionList(machineId, opts) {
782
806
  function formatPeerLine(s) {
783
807
  const m = s.metadata || {};
784
808
  const title = resolveDisplayName(m, s.directory);
809
+ const handle = resolveHandle(m);
785
810
  const agent = m.flavor || "claude";
786
811
  const status = s.active ? "\x1B[32mactive\x1B[0m" : "\x1B[90midle\x1B[0m";
787
812
  const dir = m.path || s.directory || "-";
788
- return ` [${s.sessionId.slice(0, 8)}] ${truncate(title, 32)} \u2014 ${status} \xB7 ${agent} \xB7 ${dir}`;
813
+ const label = handle ? `${handle} \xB7 ${truncate(title, 28)}` : truncate(title, 32);
814
+ return ` [${s.sessionId.slice(0, 8)}] ${label} \u2014 ${status} \xB7 ${agent} \xB7 ${dir}`;
789
815
  }
790
816
  async function sessionWhoami(opts) {
791
817
  const currentSessionId = process.env.SVAMP_SESSION_ID;
@@ -828,6 +854,7 @@ async function sessionWhoami(opts) {
828
854
  isCurrent: g === current,
829
855
  sessions: g.sessions.map((s) => ({
830
856
  sessionId: s.sessionId,
857
+ handle: resolveHandle(s.metadata || {}) || null,
831
858
  title: resolveDisplayName(s.metadata || {}, s.directory),
832
859
  agent: s.metadata?.flavor || "claude",
833
860
  active: s.active,
@@ -850,6 +877,10 @@ async function sessionWhoami(opts) {
850
877
  const m = currentSession.metadata || {};
851
878
  lines.push("## This session");
852
879
  lines.push(`- id: ${currentSession.sessionId}`);
880
+ {
881
+ const h = resolveHandle(m);
882
+ if (h) lines.push(`- handle: ${h}`);
883
+ }
853
884
  lines.push(`- topic: ${resolveDisplayName(m, currentSession.directory)}`);
854
885
  lines.push(`- agent: ${m.flavor || "claude"}`);
855
886
  lines.push(`- dir: ${m.path || currentSession.directory || "-"}`);
@@ -888,9 +919,9 @@ async function sessionWhoami(opts) {
888
919
  }
889
920
  lines.push("");
890
921
  lines.push("## Reach a peer");
891
- lines.push("- `svamp session list` \u2014 find a peer's id/title, then:");
892
- lines.push("- `svamp session info <id>` / `svamp session messages <id>` \u2014 inspect before reaching out");
893
- lines.push('- `svamp session send <id> "<msg>"` \u2014 drop a message into a peer\'s inbox');
922
+ lines.push("- `svamp session list` \u2014 find a peer's handle (project:name) or id, then:");
923
+ lines.push("- `svamp session info <handle|id>` / `svamp session messages <handle|id>` \u2014 inspect before reaching out");
924
+ lines.push('- `svamp session send <handle|id> "<msg>"` \u2014 drop a message into a peer\'s inbox (e.g. `send hypha-cloud:brave-otter "\u2026"`)');
894
925
  lines.push('- Reply to an inbox message: `svamp session inbox reply <message-id> "<body>"`');
895
926
  lines.push("- Keep it purposeful: only initiate with a concrete reason, avoid ping-pong loops.");
896
927
  console.log(lines.join("\n"));
@@ -931,6 +962,7 @@ async function listSessionsFromMachines(_server, machines, opts) {
931
962
  ...s,
932
963
  flavor: m.flavor || "claude",
933
964
  name: resolveDisplayName(m, s.directory),
965
+ handle: resolveHandle(m),
934
966
  path: m.path || s.directory || "",
935
967
  host: m.host || s.machineHost || ""
936
968
  };
@@ -938,6 +970,7 @@ async function listSessionsFromMachines(_server, machines, opts) {
938
970
  if (opts?.json) {
939
971
  console.log(formatJson(enriched.map((s) => ({
940
972
  sessionId: s.sessionId,
973
+ handle: s.handle,
941
974
  agent: s.flavor,
942
975
  name: s.name,
943
976
  path: s.path,
@@ -946,17 +979,18 @@ async function listSessionsFromMachines(_server, machines, opts) {
946
979
  directory: s.directory
947
980
  }))));
948
981
  } else {
949
- const header = `${"ID".padEnd(10)} ${"AGENT".padEnd(10)} ${"STATUS".padEnd(9)} ${"TITLE".padEnd(25)} ${"MACHINE".padEnd(18)} ${"DIRECTORY".padEnd(35)}`;
982
+ const header = `${"ID".padEnd(10)} ${"HANDLE".padEnd(24)} ${"AGENT".padEnd(8)} ${"STATUS".padEnd(9)} ${"TITLE".padEnd(22)} ${"MACHINE".padEnd(16)} ${"DIRECTORY".padEnd(30)}`;
950
983
  console.log(header);
951
984
  console.log("-".repeat(header.length));
952
985
  for (const s of enriched) {
953
986
  const id = s.sessionId.slice(0, 8);
954
- const agent = (s.flavor || "claude").padEnd(10);
987
+ const handle = truncate(s.handle || "-", 24).padEnd(24);
988
+ const agent = (s.flavor || "claude").padEnd(8);
955
989
  const status = s.active ? "\x1B[32mactive\x1B[0m " : "\x1B[90minactive\x1B[0m";
956
- const name = truncate(s.name || "-", 25).padEnd(25);
957
- const machine = truncate(s.host || "-", 16).padEnd(18);
958
- const dir = truncate(s.directory || "-", 33).padEnd(35);
959
- console.log(`${id.padEnd(10)} ${agent} ${status} ${name} ${machine} ${dir}`);
990
+ const name = truncate(s.name || "-", 22).padEnd(22);
991
+ const machine = truncate(s.host || "-", 14).padEnd(16);
992
+ const dir = truncate(s.directory || "-", 28).padEnd(30);
993
+ console.log(`${id.padEnd(10)} ${handle} ${agent} ${status} ${name} ${machine} ${dir}`);
960
994
  }
961
995
  }
962
996
  }
@@ -1245,6 +1279,7 @@ async function sessionInfo(sessionId, machineId, opts) {
1245
1279
  sessionId: fullId,
1246
1280
  flavor: metadata.flavor || "claude",
1247
1281
  name: resolveDisplayName(metadata, metadata.path || void 0),
1282
+ handle: resolveHandle(metadata),
1248
1283
  path: metadata.path || "",
1249
1284
  host: metadata.host || "",
1250
1285
  lifecycleState: metadata.lifecycleState || "unknown",
@@ -1311,6 +1346,48 @@ async function sessionMessages(sessionId, machineId, opts) {
1311
1346
  await server.disconnect();
1312
1347
  }
1313
1348
  }
1349
+ async function sessionEditMessage(sessionId, messageId, newText, machineId) {
1350
+ const { server, machine, fullId } = await connectAndResolveSession(sessionId, machineId);
1351
+ try {
1352
+ const res = await machine.sessionRPC(fullId, "editMessage", { messageId, newText });
1353
+ if (res?.success) {
1354
+ console.log("\u2713 Message edited; Claude restarted with the rewritten history.");
1355
+ } else {
1356
+ console.error(`\u2717 Edit failed: ${res?.message || "unknown error"}`);
1357
+ process.exitCode = 1;
1358
+ }
1359
+ } finally {
1360
+ await server.disconnect();
1361
+ }
1362
+ }
1363
+ async function sessionRefineLastReply(sessionId, instruction, machineId) {
1364
+ const { server, machine, fullId } = await connectAndResolveSession(sessionId, machineId);
1365
+ try {
1366
+ const res = await machine.sessionRPC(fullId, "refineLastReply", { instruction });
1367
+ if (res?.success) {
1368
+ console.log("\u2713 Latest reply refined; Claude restarted with the rewritten history.");
1369
+ } else {
1370
+ console.error(`\u2717 Refine failed: ${res?.message || "unknown error"}`);
1371
+ process.exitCode = 1;
1372
+ }
1373
+ } finally {
1374
+ await server.disconnect();
1375
+ }
1376
+ }
1377
+ async function sessionUndoEdit(sessionId, machineId) {
1378
+ const { server, machine, fullId } = await connectAndResolveSession(sessionId, machineId);
1379
+ try {
1380
+ const res = await machine.sessionRPC(fullId, "undoLastEdit", {});
1381
+ if (res?.success) {
1382
+ console.log("\u2713 Last edit reverted; Claude restarted with the pre-edit history.");
1383
+ } else {
1384
+ console.error(`\u2717 Undo failed: ${res?.message || "unknown error"}`);
1385
+ process.exitCode = 1;
1386
+ }
1387
+ } finally {
1388
+ await server.disconnect();
1389
+ }
1390
+ }
1314
1391
  async function sessionApprove(sessionId, requestId, machineId, opts) {
1315
1392
  const { server, machine, fullId } = await connectAndResolveSession(sessionId, machineId);
1316
1393
  try {
@@ -1716,7 +1793,10 @@ async function sendCore(machine, fullId, message, opts) {
1716
1793
  body: message,
1717
1794
  timestamp: Date.now(),
1718
1795
  read: false,
1719
- from: callerSessionId ? `agent:${callerSessionId}` : `cli:${os.userInfo().username}`,
1796
+ // Prefer the sender session's friendly handle (project:name) so the receiver —
1797
+ // and a human watching the exchange — sees who's talking, not an opaque id.
1798
+ // `fromSession` still carries the routable id for reply delivery.
1799
+ from: callerSessionId ? process.env.SVAMP_SESSION_HANDLE || `agent:${callerSessionId}` : `cli:${os.userInfo().username}`,
1720
1800
  ...callerSessionId ? { fromSession: callerSessionId } : {},
1721
1801
  to: fullId,
1722
1802
  subject: opts?.subject,
@@ -2530,7 +2610,7 @@ async function sessionInboxReply(sessionIdPartial, messageId, body, machineId) {
2530
2610
  body,
2531
2611
  timestamp: Date.now(),
2532
2612
  read: false,
2533
- from: `session:${fullId}`,
2613
+ from: process.env.SVAMP_SESSION_HANDLE || `session:${fullId}`,
2534
2614
  fromSession: fullId,
2535
2615
  to: original.fromSession,
2536
2616
  subject: original.subject ? `Re: ${original.subject}` : void 0,
@@ -2555,4 +2635,4 @@ async function sessionInboxClear(sessionIdPartial, machineId, opts) {
2555
2635
  }
2556
2636
  }
2557
2637
 
2558
- export { collectAssistantResponse, connectAndGetMachine, connectAndResolveSession, createWorktree, generateWorktreeName, machineExec, machineInfo, machineLs, machineShare, parseShareArg, queryCore, renderMessage, resolveSessionId, sendCore, sessionApprove, sessionArchive, sessionAttach, sessionDelete, sessionDeny, sessionInboxClear, sessionInboxList, sessionInboxRead, sessionInboxReply, sessionInboxSend, sessionInfo, sessionList, sessionLoopCancel, sessionLoopStart, sessionLoopStatus, sessionMachines, sessionMessages, sessionQuery, sessionResume, sessionSend, sessionShare, sessionSpawn, sessionSupervise, sessionUnsupervise, sessionWait, sessionWhoami, snapshotLatestSeq, validateSendOptions, wiseAskCli };
2638
+ export { collectAssistantResponse, connectAndGetMachine, connectAndResolveSession, createWorktree, generateWorktreeName, machineExec, machineInfo, machineLs, machineShare, parseShareArg, queryCore, renderMessage, resolveSessionId, sendCore, sessionApprove, sessionArchive, sessionAttach, sessionDelete, sessionDeny, sessionEditMessage, sessionInboxClear, sessionInboxList, sessionInboxRead, sessionInboxReply, sessionInboxSend, sessionInfo, sessionList, sessionLoopCancel, sessionLoopStart, sessionLoopStatus, sessionMachines, sessionMessages, sessionQuery, sessionRefineLastReply, sessionResume, sessionSend, sessionShare, sessionSpawn, sessionSupervise, sessionUndoEdit, sessionUnsupervise, sessionWait, sessionWhoami, snapshotLatestSeq, validateSendOptions, wiseAskCli };
@@ -58,7 +58,7 @@ async function serviceExpose(args) {
58
58
  process.exit(1);
59
59
  }
60
60
  if (foreground) {
61
- const { runFrpcTunnel } = await import('./frpc-CdcXdQde.mjs');
61
+ const { runFrpcTunnel } = await import('./frpc-DlsBjcRf.mjs');
62
62
  await runFrpcTunnel(name, ports, void 0, {
63
63
  group,
64
64
  groupKey,
@@ -68,7 +68,7 @@ async function serviceExpose(args) {
68
68
  });
69
69
  return;
70
70
  }
71
- const { connectAndGetMachine } = await import('./commands-B5rek8XG.mjs');
71
+ const { connectAndGetMachine } = await import('./commands-CuY9G_88.mjs');
72
72
  const { server, machine } = await connectAndGetMachine();
73
73
  try {
74
74
  const status = await machine.tunnelStart({
@@ -123,7 +123,7 @@ async function serviceServe(args) {
123
123
  };
124
124
  process.on("SIGINT", cleanup);
125
125
  process.on("SIGTERM", cleanup);
126
- const { runFrpcTunnel } = await import('./frpc-CdcXdQde.mjs');
126
+ const { runFrpcTunnel } = await import('./frpc-DlsBjcRf.mjs');
127
127
  await runFrpcTunnel(name, [caddyPort]);
128
128
  } catch (err) {
129
129
  console.error(`Error serving directory: ${err.message}`);
@@ -132,7 +132,7 @@ async function serviceServe(args) {
132
132
  }
133
133
  async function serviceList(_args) {
134
134
  try {
135
- const { connectAndGetMachine } = await import('./commands-B5rek8XG.mjs');
135
+ const { connectAndGetMachine } = await import('./commands-CuY9G_88.mjs');
136
136
  const { server, machine } = await connectAndGetMachine();
137
137
  try {
138
138
  const tunnels = await machine.tunnelList({});
@@ -161,7 +161,7 @@ async function serviceDelete(args) {
161
161
  process.exit(1);
162
162
  }
163
163
  try {
164
- const { connectAndGetMachine } = await import('./commands-B5rek8XG.mjs');
164
+ const { connectAndGetMachine } = await import('./commands-CuY9G_88.mjs');
165
165
  const { server, machine } = await connectAndGetMachine();
166
166
  try {
167
167
  await machine.tunnelStop({ name });
@@ -1,7 +1,7 @@
1
1
  import { existsSync, readFileSync } from 'node:fs';
2
2
  import { join } from 'node:path';
3
3
  import os from 'node:os';
4
- import { c as connectToHypha } from './run-9C2ogsuu.mjs';
4
+ import { c as connectToHypha } from './run-C4BsPJ_p.mjs';
5
5
  import { PINNED_CLAUDE_CODE_VERSION } from './pinnedClaudeCode-HydRNEt7.mjs';
6
6
  import 'os';
7
7
  import 'fs/promises';
@@ -3,7 +3,7 @@ import { mkdirSync, writeFileSync, unlinkSync, existsSync, chmodSync, readFileSy
3
3
  import { join } from 'path';
4
4
  import { homedir, platform, arch } from 'os';
5
5
  import { createHash, randomUUID } from 'crypto';
6
- import { h as getFrpsSubdomainHost, i as getFrpsServerPort, j as getFrpsServerAddr } from './run-9C2ogsuu.mjs';
6
+ import { h as getFrpsSubdomainHost, i as getFrpsServerPort, j as getFrpsServerAddr } from './run-C4BsPJ_p.mjs';
7
7
  import 'fs/promises';
8
8
  import 'url';
9
9
  import 'node:crypto';
@@ -1,5 +1,5 @@
1
- import { F as resolveModel, O as describeMisconfiguration, P as buildMachineDeps } from './run-9C2ogsuu.mjs';
2
- import { handleRealtimeEvent, initMachineVoiceSession } from './sideband-BHWq1P8E.mjs';
1
+ import { F as resolveModel, T as describeMisconfiguration, U as buildMachineDeps } from './run-C4BsPJ_p.mjs';
2
+ import { handleRealtimeEvent, initMachineVoiceSession } from './sideband-Wfli3n7U.mjs';
3
3
  import { WebSocket } from 'ws';
4
4
  import { execSync, spawn } from 'child_process';
5
5
  import 'os';
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- export { c as connectToHypha, a as createSessionStore, d as daemonStatus, g as getHyphaServerUrl, r as registerMachineService, s as startDaemon, b as stopDaemon } from './run-9C2ogsuu.mjs';
1
+ export { c as connectToHypha, a as createSessionStore, d as daemonStatus, g as getHyphaServerUrl, r as registerMachineService, s as startDaemon, b as stopDaemon } from './run-C4BsPJ_p.mjs';
2
2
  import 'os';
3
3
  import 'fs/promises';
4
4
  import 'fs';
@@ -1,5 +1,5 @@
1
1
  var name = "svamp-cli";
2
- var version = "0.2.118";
2
+ var version = "0.2.120";
3
3
  var description = "Svamp CLI — AI workspace daemon on Hypha Cloud";
4
4
  var author = "Amun AI AB";
5
5
  var license = "SEE LICENSE IN LICENSE";
@@ -1,4 +1,4 @@
1
- import{createRequire as _pkgrollCR}from"node:module";const require=_pkgrollCR(import.meta.url);import { n as shortId, c as connectToHypha, a as createSessionStore, r as registerMachineService, Q as generateHookSettings } from './run-9C2ogsuu.mjs';
1
+ import{createRequire as _pkgrollCR}from"node:module";const require=_pkgrollCR(import.meta.url);import { n as shortId, c as connectToHypha, a as createSessionStore, r as registerMachineService, V as generateHookSettings } from './run-C4BsPJ_p.mjs';
2
2
  import os from 'node:os';
3
3
  import { resolve, join } from 'node:path';
4
4
  import { existsSync, readFileSync, watch } from 'node:fs';