@dev-anywhere/proxy 0.1.7 → 0.1.9

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.
@@ -0,0 +1,81 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ loadConfig
4
+ } from "./chunk-DCDXAM76.js";
5
+ import "./chunk-2JUB4LDU.js";
6
+ import "./chunk-QFYI6AMN.js";
7
+
8
+ // src/relay-token.ts
9
+ function toHttpUrl(relayUrl) {
10
+ return relayUrl.replace(/^ws:/i, "http:").replace(/^wss:/i, "https:").replace(/\/$/, "");
11
+ }
12
+ async function runRelayTokenCommand(options) {
13
+ let config;
14
+ try {
15
+ config = loadConfig({ relayName: options.relayName });
16
+ } catch (err) {
17
+ console.error(err instanceof Error ? err.message : String(err));
18
+ process.exit(1);
19
+ }
20
+ const { relayName, relayUrl, relayToken } = config;
21
+ if (!relayUrl) {
22
+ console.error(
23
+ `Relay "${relayName}" has no URL configured. Edit ~/.dev-anywhere/config.json or set RELAY_URL.`
24
+ );
25
+ process.exit(1);
26
+ }
27
+ if (!relayToken) {
28
+ console.error(
29
+ `Relay "${relayName}" has no proxy token configured. The admin endpoint requires one.`
30
+ );
31
+ process.exit(1);
32
+ }
33
+ const adminUrl = `${toHttpUrl(relayUrl)}/api/admin/client-token`;
34
+ let res;
35
+ try {
36
+ res = await fetch(adminUrl, {
37
+ headers: { authorization: `Bearer ${relayToken}` },
38
+ cache: "no-store"
39
+ });
40
+ } catch (err) {
41
+ console.error(`Request to ${adminUrl} failed: ${err instanceof Error ? err.message : err}`);
42
+ process.exit(1);
43
+ }
44
+ if (res.status === 401) {
45
+ console.error(
46
+ `Relay rejected the proxy token (HTTP 401). Verify ~/.dev-anywhere/config.json matches the relay's RELAY_PROXY_TOKEN.`
47
+ );
48
+ process.exit(1);
49
+ }
50
+ if (res.status === 204) {
51
+ const result = { status: "no_client_token" };
52
+ printResult(relayName, relayUrl, result);
53
+ return;
54
+ }
55
+ if (!res.ok) {
56
+ const body = await res.text().catch(() => "");
57
+ console.error(`Unexpected response from relay (HTTP ${res.status}): ${body}`);
58
+ process.exit(1);
59
+ }
60
+ const json = await res.json();
61
+ if (typeof json.clientToken !== "string" || json.clientToken.length === 0) {
62
+ console.error(`Relay returned a malformed payload: ${JSON.stringify(json)}`);
63
+ process.exit(1);
64
+ }
65
+ printResult(relayName, relayUrl, { status: "ok", clientToken: json.clientToken });
66
+ }
67
+ function printResult(relayName, relayUrl, result) {
68
+ const httpBase = toHttpUrl(relayUrl);
69
+ console.log(`Relay: ${relayName} (${relayUrl})`);
70
+ if (result.status === "no_client_token") {
71
+ console.log(`Token: (not configured \u2014 /client endpoint is open)`);
72
+ console.log(`URL: ${httpBase}/`);
73
+ return;
74
+ }
75
+ console.log(`Token: ${result.clientToken}`);
76
+ console.log(`URL: ${httpBase}/?relayToken=${encodeURIComponent(result.clientToken)}`);
77
+ }
78
+ export {
79
+ runRelayTokenCommand
80
+ };
81
+ //# sourceMappingURL=relay-token-Z4JZFPQ5.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/relay-token.ts"],"sourcesContent":["// `dev-anywhere relay token` 实现:用本地 proxyToken 向已配置的 relay\n// 请求当前生效的 client token,避免运维者必须 ssh 到 VPS 读 .env。\nimport { loadConfig } from \"./common/config.js\";\n\ninterface FetchClientTokenResult {\n status: \"ok\" | \"no_client_token\";\n clientToken?: string;\n}\n\nfunction toHttpUrl(relayUrl: string): string {\n return relayUrl.replace(/^ws:/i, \"http:\").replace(/^wss:/i, \"https:\").replace(/\\/$/, \"\");\n}\n\nexport async function runRelayTokenCommand(options: { relayName?: string }): Promise<void> {\n let config: ReturnType<typeof loadConfig>;\n try {\n config = loadConfig({ relayName: options.relayName });\n } catch (err) {\n console.error(err instanceof Error ? err.message : String(err));\n process.exit(1);\n }\n\n const { relayName, relayUrl, relayToken } = config;\n if (!relayUrl) {\n console.error(\n `Relay \"${relayName}\" has no URL configured. Edit ~/.dev-anywhere/config.json or set RELAY_URL.`,\n );\n process.exit(1);\n }\n if (!relayToken) {\n console.error(\n `Relay \"${relayName}\" has no proxy token configured. The admin endpoint requires one.`,\n );\n process.exit(1);\n }\n\n const adminUrl = `${toHttpUrl(relayUrl)}/api/admin/client-token`;\n let res: Response;\n try {\n res = await fetch(adminUrl, {\n headers: { authorization: `Bearer ${relayToken}` },\n cache: \"no-store\",\n });\n } catch (err) {\n console.error(`Request to ${adminUrl} failed: ${err instanceof Error ? err.message : err}`);\n process.exit(1);\n }\n\n if (res.status === 401) {\n console.error(\n `Relay rejected the proxy token (HTTP 401). Verify ~/.dev-anywhere/config.json matches the relay's RELAY_PROXY_TOKEN.`,\n );\n process.exit(1);\n }\n if (res.status === 204) {\n const result: FetchClientTokenResult = { status: \"no_client_token\" };\n printResult(relayName, relayUrl, result);\n return;\n }\n if (!res.ok) {\n const body = await res.text().catch(() => \"\");\n console.error(`Unexpected response from relay (HTTP ${res.status}): ${body}`);\n process.exit(1);\n }\n\n const json = (await res.json()) as { clientToken?: unknown };\n if (typeof json.clientToken !== \"string\" || json.clientToken.length === 0) {\n console.error(`Relay returned a malformed payload: ${JSON.stringify(json)}`);\n process.exit(1);\n }\n printResult(relayName, relayUrl, { status: \"ok\", clientToken: json.clientToken });\n}\n\nfunction printResult(relayName: string, relayUrl: string, result: FetchClientTokenResult): void {\n const httpBase = toHttpUrl(relayUrl);\n console.log(`Relay: ${relayName} (${relayUrl})`);\n if (result.status === \"no_client_token\") {\n console.log(`Token: (not configured — /client endpoint is open)`);\n console.log(`URL: ${httpBase}/`);\n return;\n }\n console.log(`Token: ${result.clientToken}`);\n console.log(`URL: ${httpBase}/?relayToken=${encodeURIComponent(result.clientToken!)}`);\n}\n"],"mappings":";;;;;;;;AASA,SAAS,UAAU,UAA0B;AAC3C,SAAO,SAAS,QAAQ,SAAS,OAAO,EAAE,QAAQ,UAAU,QAAQ,EAAE,QAAQ,OAAO,EAAE;AACzF;AAEA,eAAsB,qBAAqB,SAAgD;AACzF,MAAI;AACJ,MAAI;AACF,aAAS,WAAW,EAAE,WAAW,QAAQ,UAAU,CAAC;AAAA,EACtD,SAAS,KAAK;AACZ,YAAQ,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAC9D,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,EAAE,WAAW,UAAU,WAAW,IAAI;AAC5C,MAAI,CAAC,UAAU;AACb,YAAQ;AAAA,MACN,UAAU,SAAS;AAAA,IACrB;AACA,YAAQ,KAAK,CAAC;AAAA,EAChB;AACA,MAAI,CAAC,YAAY;AACf,YAAQ;AAAA,MACN,UAAU,SAAS;AAAA,IACrB;AACA,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,WAAW,GAAG,UAAU,QAAQ,CAAC;AACvC,MAAI;AACJ,MAAI;AACF,UAAM,MAAM,MAAM,UAAU;AAAA,MAC1B,SAAS,EAAE,eAAe,UAAU,UAAU,GAAG;AAAA,MACjD,OAAO;AAAA,IACT,CAAC;AAAA,EACH,SAAS,KAAK;AACZ,YAAQ,MAAM,cAAc,QAAQ,YAAY,eAAe,QAAQ,IAAI,UAAU,GAAG,EAAE;AAC1F,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,MAAI,IAAI,WAAW,KAAK;AACtB,YAAQ;AAAA,MACN;AAAA,IACF;AACA,YAAQ,KAAK,CAAC;AAAA,EAChB;AACA,MAAI,IAAI,WAAW,KAAK;AACtB,UAAM,SAAiC,EAAE,QAAQ,kBAAkB;AACnE,gBAAY,WAAW,UAAU,MAAM;AACvC;AAAA,EACF;AACA,MAAI,CAAC,IAAI,IAAI;AACX,UAAM,OAAO,MAAM,IAAI,KAAK,EAAE,MAAM,MAAM,EAAE;AAC5C,YAAQ,MAAM,wCAAwC,IAAI,MAAM,MAAM,IAAI,EAAE;AAC5E,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,OAAQ,MAAM,IAAI,KAAK;AAC7B,MAAI,OAAO,KAAK,gBAAgB,YAAY,KAAK,YAAY,WAAW,GAAG;AACzE,YAAQ,MAAM,uCAAuC,KAAK,UAAU,IAAI,CAAC,EAAE;AAC3E,YAAQ,KAAK,CAAC;AAAA,EAChB;AACA,cAAY,WAAW,UAAU,EAAE,QAAQ,MAAM,aAAa,KAAK,YAAY,CAAC;AAClF;AAEA,SAAS,YAAY,WAAmB,UAAkB,QAAsC;AAC9F,QAAM,WAAW,UAAU,QAAQ;AACnC,UAAQ,IAAI,UAAU,SAAS,KAAK,QAAQ,GAAG;AAC/C,MAAI,OAAO,WAAW,mBAAmB;AACvC,YAAQ,IAAI,yDAAoD;AAChE,YAAQ,IAAI,UAAU,QAAQ,GAAG;AACjC;AAAA,EACF;AACA,UAAQ,IAAI,UAAU,OAAO,WAAW,EAAE;AAC1C,UAAQ,IAAI,UAAU,QAAQ,gBAAgB,mBAAmB,OAAO,WAAY,CAAC,EAAE;AACzF;","names":[]}
package/dist/serve.js CHANGED
@@ -5,16 +5,15 @@ import {
5
5
  KnownContentBlockSchema,
6
6
  SeqCounter,
7
7
  StreamJsonEventSchema
8
- } from "./chunk-ODK6N2NP.js";
8
+ } from "./chunk-7XMJMVIL.js";
9
9
  import {
10
10
  createFSM,
11
11
  defineFSM,
12
12
  extractOscSequences,
13
13
  extractOscSignals,
14
- serviceLogger,
15
14
  shouldReleaseApprovalWait,
16
15
  stateAfterApprovalRelease
17
- } from "./chunk-JGGDVMY5.js";
16
+ } from "./chunk-ORZTFYXR.js";
18
17
  import {
19
18
  spawnScript
20
19
  } from "./chunk-ZUWAB67J.js";
@@ -24,7 +23,20 @@ import {
24
23
  detectAgentCliStatus
25
24
  } from "./chunk-6O6JTF24.js";
26
25
  import {
27
- CONFIG_PATH,
26
+ createIpcReader,
27
+ createWorkerReader,
28
+ serializeIpc,
29
+ serializeWorkerMsg
30
+ } from "./chunk-U5T7ZYXT.js";
31
+ import {
32
+ buildProviderEnv,
33
+ loadConfig,
34
+ saveAgentCliPath
35
+ } from "./chunk-DCDXAM76.js";
36
+ import {
37
+ serviceLogger
38
+ } from "./chunk-2JUB4LDU.js";
39
+ import {
28
40
  ControlErrorCode,
29
41
  DATA_DIR,
30
42
  DEFAULT_PROXY_PROFILE,
@@ -38,19 +50,14 @@ import {
38
50
  STOPPED_PATH,
39
51
  SessionState,
40
52
  buildMessage,
41
- createIpcReader,
42
- createWorkerReader,
43
- defaultHookPortForProfile,
44
53
  ensureProfileWorkspace,
45
- serializeIpc,
46
- serializeWorkerMsg,
47
54
  sessionPaths,
48
55
  tildify
49
- } from "./chunk-RFBTVZ2X.js";
56
+ } from "./chunk-QFYI6AMN.js";
50
57
 
51
58
  // src/serve.ts
52
59
  import { createServer as createServer2 } from "net";
53
- import { unlinkSync as unlinkSync3, writeFileSync as writeFileSync6, chmodSync, rmSync as rmSync2 } from "fs";
60
+ import { unlinkSync as unlinkSync3, writeFileSync as writeFileSync5, chmodSync, rmSync as rmSync2 } from "fs";
54
61
 
55
62
  // src/serve/session-manager.ts
56
63
  import { mkdirSync, readFileSync, renameSync, writeFileSync, existsSync } from "fs";
@@ -614,162 +621,9 @@ var RelayConnection = class extends EventEmitter {
614
621
  }
615
622
  };
616
623
 
617
- // src/common/config.ts
618
- import { existsSync as existsSync3, mkdirSync as mkdirSync3, readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "fs";
619
- import { dirname as dirname3, isAbsolute } from "path";
620
- function parsePort(value, source) {
621
- if (!value) return void 0;
622
- const port = Number(value);
623
- if (!Number.isInteger(port) || port < 1 || port > 65535) {
624
- throw new Error(`Invalid ${source}: expected TCP port 1-65535`);
625
- }
626
- return port;
627
- }
628
- function isRecord(value) {
629
- return typeof value === "object" && value !== null && !Array.isArray(value);
630
- }
631
- function validateConfigShape(value) {
632
- if (!isRecord(value) || !isRecord(value.profiles) || !isRecord(value.relays)) {
633
- throw new Error(`Invalid config shape in ${CONFIG_PATH}: expected "profiles" and "relays".`);
634
- }
635
- return value;
636
- }
637
- function readConfigFile() {
638
- if (!existsSync3(CONFIG_PATH)) {
639
- throw new Error(`Dev Anywhere config not found at ${CONFIG_PATH}. Run "dev-anywhere init".`);
640
- }
641
- return validateConfigShape(JSON.parse(readFileSync3(CONFIG_PATH, "utf-8")));
642
- }
643
- function agentCliField(provider) {
644
- return provider === "claude" ? "claudeBin" : "codexBin";
645
- }
646
- function agentCliHistoryField(provider) {
647
- return provider === "claude" ? "claudeBinHistory" : "codexBinHistory";
648
- }
649
- function validateAgentCliPath(path) {
650
- const normalized = path.trim();
651
- if (!normalized) throw new Error("\u8BF7\u8F93\u5165 CLI \u8DEF\u5F84");
652
- if (!isAbsolute(normalized)) throw new Error("CLI \u8DEF\u5F84\u5FC5\u987B\u662F\u7EDD\u5BF9\u8DEF\u5F84");
653
- return normalized;
654
- }
655
- function uniqueAbsolutePaths(paths) {
656
- const seen = /* @__PURE__ */ new Set();
657
- const result = [];
658
- for (const path of paths) {
659
- const normalized = path?.trim();
660
- if (!normalized || !isAbsolute(normalized) || seen.has(normalized)) continue;
661
- seen.add(normalized);
662
- result.push(normalized);
663
- }
664
- return result;
665
- }
666
- function resolveRelayConfig(fromFile, requestedRelayName) {
667
- const profile = fromFile.profiles[PROFILE_NAME];
668
- if (!profile) {
669
- const available = Object.keys(fromFile.profiles).sort();
670
- throw new Error(
671
- `Unknown profile "${PROFILE_NAME}". Available profiles: ${available.length > 0 ? available.join(", ") : "(none)"}`
672
- );
673
- }
674
- const relayName = requestedRelayName?.trim() || profile.relay?.trim();
675
- if (!relayName) {
676
- throw new Error(`Profile "${PROFILE_NAME}" must specify a relay.`);
677
- }
678
- const relay = fromFile.relays[relayName];
679
- if (!relay) {
680
- const available = Object.keys(fromFile.relays).sort();
681
- throw new Error(
682
- `Unknown relay "${relayName}". Available relays: ${available.length > 0 ? available.join(", ") : "(none)"}`
683
- );
684
- }
685
- return {
686
- relayName,
687
- relayNameSource: requestedRelayName?.trim() ? "cli" : "profile",
688
- relay
689
- };
690
- }
691
- function loadConfig(options) {
692
- const fromFile = readConfigFile();
693
- const agentCli = fromFile.agentCli ?? {};
694
- const resolved = resolveRelayConfig(fromFile, options?.relayName);
695
- const claudeBin = process.env.CLAUDE_BIN ?? agentCli.claudeBin;
696
- const codexBin = process.env.CODEX_BIN ?? agentCli.codexBin;
697
- const config = {
698
- profileName: PROFILE_NAME,
699
- relayName: resolved.relayName,
700
- relayUrl: process.env.RELAY_URL ?? resolved.relay.url,
701
- relayToken: process.env.RELAY_PROXY_TOKEN ?? resolved.relay.proxyToken,
702
- hookPort: parsePort(process.env.DEV_ANYWHERE_HOOK_PORT, "DEV_ANYWHERE_HOOK_PORT") ?? defaultHookPortForProfile(PROFILE_NAME),
703
- claudeBin,
704
- codexBin,
705
- previewRoots: uniqueAbsolutePaths(fromFile.previewRoots ?? []),
706
- agentCliSuggestions: {
707
- claude: uniqueAbsolutePaths([
708
- process.env.CLAUDE_BIN,
709
- agentCli.claudeBin,
710
- ...agentCli.claudeBinHistory ?? []
711
- ]),
712
- codex: uniqueAbsolutePaths([
713
- process.env.CODEX_BIN,
714
- agentCli.codexBin,
715
- ...agentCli.codexBinHistory ?? []
716
- ])
717
- },
718
- sources: {
719
- relayName: resolved.relayNameSource,
720
- relayUrl: process.env.RELAY_URL ? "env" : resolved.relay.url ? "file" : "none",
721
- relayToken: process.env.RELAY_PROXY_TOKEN ? "env" : resolved.relay.proxyToken ? "file" : "none",
722
- hookPort: process.env.DEV_ANYWHERE_HOOK_PORT ? "env" : "default",
723
- claudeBin: process.env.CLAUDE_BIN ? "env" : agentCli.claudeBin ? "file" : "none",
724
- codexBin: process.env.CODEX_BIN ? "env" : agentCli.codexBin ? "file" : "none"
725
- }
726
- };
727
- serviceLogger.info(
728
- {
729
- profile: config.profileName,
730
- relayName: config.relayName,
731
- relayNameSource: config.sources.relayName,
732
- relayUrl: config.relayUrl ?? "(unset)",
733
- relayUrlSource: config.sources.relayUrl,
734
- relayTokenSource: config.sources.relayToken,
735
- hookPort: config.hookPort,
736
- hookPortSource: config.sources.hookPort,
737
- claudeBinSource: config.sources.claudeBin,
738
- codexBinSource: config.sources.codexBin
739
- },
740
- "Config loaded"
741
- );
742
- return config;
743
- }
744
- function buildProviderEnv(config, baseEnv = process.env) {
745
- return {
746
- ...baseEnv,
747
- ...config.claudeBin ? { CLAUDE_BIN: config.claudeBin } : {},
748
- ...config.codexBin ? { CODEX_BIN: config.codexBin } : {}
749
- };
750
- }
751
- function updateAgentCliConfig(config, provider, path) {
752
- const field = agentCliField(provider);
753
- const historyField = agentCliHistoryField(provider);
754
- const history = uniqueAbsolutePaths([path, ...config[historyField] ?? []]).slice(0, 8);
755
- return {
756
- ...config,
757
- [field]: path,
758
- [historyField]: history
759
- };
760
- }
761
- function saveAgentCliPath(provider, path) {
762
- const normalized = validateAgentCliPath(path);
763
- const fromFile = readConfigFile();
764
- fromFile.agentCli = updateAgentCliConfig(fromFile.agentCli ?? {}, provider, normalized);
765
- mkdirSync3(dirname3(CONFIG_PATH), { recursive: true });
766
- writeFileSync3(CONFIG_PATH, `${JSON.stringify(fromFile, null, 2)}
767
- `, "utf-8");
768
- }
769
-
770
624
  // src/serve/handlers/control-messages.ts
771
625
  import { readdir as readdir2, mkdir } from "fs/promises";
772
- import { join as join4, isAbsolute as isAbsolute2, normalize } from "path";
626
+ import { join as join4, isAbsolute, normalize } from "path";
773
627
 
774
628
  // src/serve/session-history.ts
775
629
  import { readdir, stat, access, open } from "fs/promises";
@@ -1181,7 +1035,7 @@ function extractCodexUserText(payload) {
1181
1035
  }
1182
1036
 
1183
1037
  // src/serve/command-discovery.ts
1184
- import { readdirSync, readFileSync as readFileSync4 } from "fs";
1038
+ import { readdirSync, readFileSync as readFileSync3 } from "fs";
1185
1039
  import { homedir as homedir3 } from "os";
1186
1040
  import { join as join3 } from "path";
1187
1041
  var REPL_BUILTINS = [
@@ -1257,7 +1111,7 @@ function scanSkillsDir(dirPath, source) {
1257
1111
  for (const name of entries) {
1258
1112
  const skillPath = join3(dirPath, name, "SKILL.md");
1259
1113
  try {
1260
- const content = readFileSync4(skillPath, "utf-8");
1114
+ const content = readFileSync3(skillPath, "utf-8");
1261
1115
  const parsed = parseSkillFrontmatter(content);
1262
1116
  commands.push({
1263
1117
  name: `/${parsed.name ?? name}`,
@@ -1281,7 +1135,7 @@ function scanCommandsDir(dirPath, source) {
1281
1135
  for (const filename of entries) {
1282
1136
  const cmdName = filename.replace(/\.md$/, "");
1283
1137
  try {
1284
- const content = readFileSync4(join3(dirPath, filename), "utf-8");
1138
+ const content = readFileSync3(join3(dirPath, filename), "utf-8");
1285
1139
  const firstLine = content.split("\n")[0].trim();
1286
1140
  commands.push({
1287
1141
  name: `/${cmdName}`,
@@ -1360,7 +1214,7 @@ function classifyPathError(err) {
1360
1214
  // src/serve/handlers/control-messages.ts
1361
1215
  var COMMAND_REFRESH_MS = 6 * 60 * 60 * 1e3;
1362
1216
  function isPathSafe(path) {
1363
- if (!isAbsolute2(path)) return false;
1217
+ if (!isAbsolute(path)) return false;
1364
1218
  const normalized = normalize(path);
1365
1219
  if (normalized.includes("..")) return false;
1366
1220
  return true;
@@ -1656,7 +1510,7 @@ function createControlMessageHandlers(send, sessionManager) {
1656
1510
 
1657
1511
  // src/serve/worker-registry.ts
1658
1512
  import { connect } from "net";
1659
- import { unlinkSync, existsSync as existsSync4, readdirSync as readdirSync2 } from "fs";
1513
+ import { unlinkSync, existsSync as existsSync3, readdirSync as readdirSync2 } from "fs";
1660
1514
  var WorkerRegistry = class {
1661
1515
  constructor(deps) {
1662
1516
  this.deps = deps;
@@ -1741,12 +1595,12 @@ var WorkerRegistry = class {
1741
1595
  }
1742
1596
  // 枚举 DATA_DIR 下所有 session 目录,尝试连接存活的 worker.sock;失败则清理 stale socket。
1743
1597
  async reconnectAll() {
1744
- if (!existsSync4(DATA_DIR)) return;
1598
+ if (!existsSync3(DATA_DIR)) return;
1745
1599
  const dirs = readdirSync2(DATA_DIR, { withFileTypes: true }).filter((d) => d.isDirectory());
1746
1600
  for (const dir of dirs) {
1747
1601
  const sessionId = dir.name;
1748
1602
  const paths = sessionPaths(sessionId);
1749
- if (!existsSync4(paths.workerSock)) continue;
1603
+ if (!existsSync3(paths.workerSock)) continue;
1750
1604
  const sock = await this.connect(sessionId, paths.workerSock);
1751
1605
  if (sock) {
1752
1606
  if (!this.deps.sessionManager.getSession(sessionId)) {
@@ -2061,8 +1915,8 @@ function terminateSessionByOwnership(deps, sessionId) {
2061
1915
  }
2062
1916
 
2063
1917
  // src/serve/clipboard-image-upload.ts
2064
- import { existsSync as existsSync5, mkdirSync as mkdirSync4, readFileSync as readFileSync5, statSync, writeFileSync as writeFileSync4 } from "fs";
2065
- import { isAbsolute as isAbsolute3, join as join5, relative, resolve } from "path";
1918
+ import { existsSync as existsSync4, mkdirSync as mkdirSync3, readFileSync as readFileSync4, statSync, writeFileSync as writeFileSync3 } from "fs";
1919
+ import { isAbsolute as isAbsolute2, join as join5, relative, resolve } from "path";
2066
1920
  import { nanoid as nanoid3 } from "nanoid";
2067
1921
  var MAX_CLIPBOARD_IMAGE_BYTES = 10 * 1024 * 1024;
2068
1922
  var MAX_CLIPBOARD_IMAGE_BASE64_LENGTH = Math.ceil(MAX_CLIPBOARD_IMAGE_BYTES / 3) * 4;
@@ -2098,7 +1952,7 @@ function resolveChildDir(rootPath, ...segments) {
2098
1952
  const root = resolve(rootPath);
2099
1953
  const uploadDir = resolve(root, ...segments);
2100
1954
  const relativePath = relative(root, uploadDir);
2101
- if (!relativePath || relativePath.startsWith("..") || isAbsolute3(relativePath)) {
1955
+ if (!relativePath || relativePath.startsWith("..") || isAbsolute2(relativePath)) {
2102
1956
  throw new Error("\u4F1A\u8BDD\u8DEF\u5F84\u65E0\u6548");
2103
1957
  }
2104
1958
  return uploadDir;
@@ -2111,13 +1965,13 @@ function normalizeGitignoreLine(line) {
2111
1965
  }
2112
1966
  function ensureProjectClipboardIgnored(cwd) {
2113
1967
  const gitignorePath = join5(cwd, ".gitignore");
2114
- if (!existsSync5(gitignorePath)) return;
1968
+ if (!existsSync4(gitignorePath)) return;
2115
1969
  try {
2116
- const current = readFileSync5(gitignorePath, "utf-8");
1970
+ const current = readFileSync4(gitignorePath, "utf-8");
2117
1971
  const alreadyIgnored = current.split(/\r?\n/).some((line) => normalizeGitignoreLine(line) === ".dev-anywhere");
2118
1972
  if (alreadyIgnored) return;
2119
1973
  const separator = current.length > 0 && !current.endsWith("\n") ? "\n" : "";
2120
- writeFileSync4(gitignorePath, `${current}${separator}.dev-anywhere/
1974
+ writeFileSync3(gitignorePath, `${current}${separator}.dev-anywhere/
2121
1975
  `);
2122
1976
  } catch {
2123
1977
  }
@@ -2130,8 +1984,8 @@ function trySaveProjectClipboardImage(options) {
2130
1984
  const clipboardRoot = resolve(cwd, ".dev-anywhere", "clipboard");
2131
1985
  const uploadDir = resolveChildDir(clipboardRoot, options.sessionId);
2132
1986
  const path = join5(uploadDir, options.fileName);
2133
- mkdirSync4(uploadDir, { recursive: true });
2134
- writeFileSync4(path, options.buffer, { mode: 384 });
1987
+ mkdirSync3(uploadDir, { recursive: true });
1988
+ writeFileSync3(path, options.buffer, { mode: 384 });
2135
1989
  ensureProjectClipboardIgnored(cwd);
2136
1990
  return { success: true, path: relative(cwd, path) };
2137
1991
  } catch {
@@ -2163,8 +2017,8 @@ function saveClipboardImageUpload(request, options = {}) {
2163
2017
  const dataDir = options.dataDir ?? DATA_DIR;
2164
2018
  const uploadDir = resolveSessionClipboardDir(dataDir, request.sessionId);
2165
2019
  const path = join5(uploadDir, fileName);
2166
- mkdirSync4(uploadDir, { recursive: true });
2167
- writeFileSync4(path, buffer, { mode: 384 });
2020
+ mkdirSync3(uploadDir, { recursive: true });
2021
+ writeFileSync3(path, buffer, { mode: 384 });
2168
2022
  return { success: true, path };
2169
2023
  } catch (err) {
2170
2024
  return {
@@ -2177,13 +2031,13 @@ function saveClipboardImageUpload(request, options = {}) {
2177
2031
  }
2178
2032
 
2179
2033
  // src/serve/image-preview.ts
2180
- import { readFileSync as readFileSync6, realpathSync, statSync as statSync2 } from "fs";
2034
+ import { readFileSync as readFileSync5, realpathSync, statSync as statSync2 } from "fs";
2181
2035
  import { tmpdir } from "os";
2182
- import { isAbsolute as isAbsolute4, relative as relative2, resolve as resolve2 } from "path";
2036
+ import { isAbsolute as isAbsolute3, relative as relative2, resolve as resolve2 } from "path";
2183
2037
  var MAX_IMAGE_PREVIEW_BYTES = 10 * 1024 * 1024;
2184
2038
  function isInsideRoot(realFilePath, realRootPath) {
2185
2039
  const rel = relative2(realRootPath, realFilePath);
2186
- return rel === "" || !rel.startsWith("..") && !isAbsolute4(rel);
2040
+ return rel === "" || !rel.startsWith("..") && !isAbsolute3(rel);
2187
2041
  }
2188
2042
  function allowedRoots(options) {
2189
2043
  return [options.cwd, options.tmpDir ?? tmpdir(), ...options.previewRoots ?? []].map((root) => root.trim()).filter(Boolean).flatMap((root) => {
@@ -2195,7 +2049,7 @@ function allowedRoots(options) {
2195
2049
  });
2196
2050
  }
2197
2051
  function resolvePreviewPath(rawPath, options) {
2198
- const candidate = isAbsolute4(rawPath) ? resolve2(rawPath) : resolve2(options.cwd, rawPath);
2052
+ const candidate = isAbsolute3(rawPath) ? resolve2(rawPath) : resolve2(options.cwd, rawPath);
2199
2053
  const realCandidate = realpathSync(candidate);
2200
2054
  if (!allowedRoots(options).some((root) => isInsideRoot(realCandidate, root))) {
2201
2055
  throw Object.assign(new Error("\u56FE\u7247\u8DEF\u5F84\u4E0D\u5728\u5141\u8BB8\u9884\u89C8\u7684\u76EE\u5F55\u5185"), {
@@ -2248,7 +2102,7 @@ function loadImagePreview(request, options) {
2248
2102
  errorCode: ControlErrorCode.UNKNOWN
2249
2103
  };
2250
2104
  }
2251
- const buffer = readFileSync6(resolvedPath);
2105
+ const buffer = readFileSync5(resolvedPath);
2252
2106
  const mimeType = detectImageMime(buffer);
2253
2107
  if (!mimeType) {
2254
2108
  return {
@@ -2745,7 +2599,7 @@ var RelayResourceHandlers = class {
2745
2599
 
2746
2600
  // src/serve/relay-session-create-handler.ts
2747
2601
  import { rmSync, statSync as statSync4 } from "fs";
2748
- import { isAbsolute as isAbsolute5 } from "path";
2602
+ import { isAbsolute as isAbsolute4 } from "path";
2749
2603
  import { nanoid as nanoid4 } from "nanoid";
2750
2604
 
2751
2605
  // src/serve/hosted-pty-registry.ts
@@ -3035,7 +2889,7 @@ function validateSessionCwd(cwd) {
3035
2889
  return { message: "\u8BF7\u8F93\u5165\u5DE5\u4F5C\u76EE\u5F55", code: ControlErrorCode.INVALID_PATH };
3036
2890
  }
3037
2891
  const trimmed = cwd.trim();
3038
- if (!isAbsolute5(trimmed)) {
2892
+ if (!isAbsolute4(trimmed)) {
3039
2893
  return { message: "\u5DE5\u4F5C\u76EE\u5F55\u5FC5\u987B\u662F\u7EDD\u5BF9\u8DEF\u5F84", code: ControlErrorCode.INVALID_PATH };
3040
2894
  }
3041
2895
  try {
@@ -3837,7 +3691,7 @@ function touchSessionActivity(sessionManager, relay, sessionId, now = Date.now()
3837
3691
 
3838
3692
  // src/serve/service-files.ts
3839
3693
  import { execSync } from "child_process";
3840
- import { existsSync as existsSync6, readFileSync as readFileSync7, unlinkSync as unlinkSync2 } from "fs";
3694
+ import { existsSync as existsSync5, readFileSync as readFileSync6, unlinkSync as unlinkSync2 } from "fs";
3841
3695
  import { hostname } from "os";
3842
3696
  import { connect as connect2 } from "net";
3843
3697
  function tryConnectSocket(sockPath) {
@@ -3856,7 +3710,7 @@ function isProcessAlive(pid) {
3856
3710
  }
3857
3711
  }
3858
3712
  async function cleanupStaleResources() {
3859
- if (existsSync6(SOCK_PATH)) {
3713
+ if (existsSync5(SOCK_PATH)) {
3860
3714
  const existing = await tryConnectSocket(SOCK_PATH);
3861
3715
  if (existing) {
3862
3716
  existing.destroy();
@@ -3868,8 +3722,8 @@ async function cleanupStaleResources() {
3868
3722
  unlinkSync2(SOCK_PATH);
3869
3723
  serviceLogger.info("Removed stale socket file");
3870
3724
  }
3871
- if (existsSync6(PID_PATH)) {
3872
- const pidStr = readFileSync7(PID_PATH, "utf-8").trim();
3725
+ if (existsSync5(PID_PATH)) {
3726
+ const pidStr = readFileSync6(PID_PATH, "utf-8").trim();
3873
3727
  const pid = parseInt(pidStr, 10);
3874
3728
  if (!isNaN(pid) && isProcessAlive(pid)) {
3875
3729
  const msg = `Another service is already running with PID ${pid}`;
@@ -4244,8 +4098,8 @@ function handleTerminalConnection(socket, deps) {
4244
4098
 
4245
4099
  // src/serve/hook-registry.ts
4246
4100
  import { createHash, randomBytes } from "crypto";
4247
- import { existsSync as existsSync7, mkdirSync as mkdirSync5, readFileSync as readFileSync8, renameSync as renameSync2, writeFileSync as writeFileSync5 } from "fs";
4248
- import { dirname as dirname4 } from "path";
4101
+ import { existsSync as existsSync6, mkdirSync as mkdirSync4, readFileSync as readFileSync7, renameSync as renameSync2, writeFileSync as writeFileSync4 } from "fs";
4102
+ import { dirname as dirname3 } from "path";
4249
4103
  import { z } from "zod";
4250
4104
  var PersistedHookSessionBindingSchema = z.object({
4251
4105
  sessionId: z.string(),
@@ -4305,10 +4159,10 @@ var HookRegistry = class {
4305
4159
  }
4306
4160
  }
4307
4161
  load() {
4308
- if (!this.persistPath || !existsSync7(this.persistPath)) return;
4162
+ if (!this.persistPath || !existsSync6(this.persistPath)) return;
4309
4163
  try {
4310
4164
  const parsed = PersistedHookRegistrySchema.parse(
4311
- JSON.parse(readFileSync8(this.persistPath, "utf8"))
4165
+ JSON.parse(readFileSync7(this.persistPath, "utf8"))
4312
4166
  );
4313
4167
  this.bindingsBySession.clear();
4314
4168
  for (const binding of parsed.bindings) {
@@ -4324,9 +4178,9 @@ var HookRegistry = class {
4324
4178
  save() {
4325
4179
  if (!this.persistPath) return;
4326
4180
  try {
4327
- mkdirSync5(dirname4(this.persistPath), { recursive: true });
4181
+ mkdirSync4(dirname3(this.persistPath), { recursive: true });
4328
4182
  const tmpPath = `${this.persistPath}.${process.pid}.${Date.now()}.tmp`;
4329
- writeFileSync5(
4183
+ writeFileSync4(
4330
4184
  tmpPath,
4331
4185
  JSON.stringify(
4332
4186
  {
@@ -4842,7 +4696,7 @@ async function startService(options) {
4842
4696
  });
4843
4697
  });
4844
4698
  server.listen(SOCK_PATH, () => {
4845
- writeFileSync6(PID_PATH, String(process.pid));
4699
+ writeFileSync5(PID_PATH, String(process.pid));
4846
4700
  chmodSync(SOCK_PATH, 384);
4847
4701
  serviceLogger.info({ pid: process.pid, sock: SOCK_PATH }, "Service started");
4848
4702
  });