@dev-anywhere/proxy 0.2.3 → 0.2.5

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/serve.js CHANGED
@@ -11,10 +11,10 @@ import {
11
11
  decidePtySemanticTransition,
12
12
  extractOscSequences,
13
13
  extractOscSignals
14
- } from "./chunk-OBYEKZWC.js";
14
+ } from "./chunk-Q7AQFYHG.js";
15
15
  import {
16
16
  spawnScript
17
- } from "./chunk-ZUWAB67J.js";
17
+ } from "./chunk-IHUQNJF6.js";
18
18
  import {
19
19
  CLAUDE_PROVIDER,
20
20
  CODEX_PROVIDER,
@@ -35,7 +35,7 @@ import {
35
35
  serializeControl,
36
36
  serializeIpc,
37
37
  serializeWorkerMsg
38
- } from "./chunk-NZZXBVO2.js";
38
+ } from "./chunk-L6J5QCFH.js";
39
39
  import {
40
40
  buildProviderEnv,
41
41
  loadConfig,
@@ -968,7 +968,7 @@ function extractConversationText(msg) {
968
968
  return null;
969
969
  }
970
970
  async function extractTitleAndCwd(filePath) {
971
- return new Promise((resolve5) => {
971
+ return new Promise((resolve3) => {
972
972
  const rl = createInterface({
973
973
  input: createReadStream(filePath, { encoding: "utf-8" }),
974
974
  crlfDelay: Infinity
@@ -996,10 +996,10 @@ async function extractTitleAndCwd(filePath) {
996
996
  }
997
997
  });
998
998
  rl.on("close", () => {
999
- if (!resolved) resolve5({ title, cwd });
1000
- else resolve5({ title, cwd });
999
+ if (!resolved) resolve3({ title, cwd });
1000
+ else resolve3({ title, cwd });
1001
1001
  });
1002
- rl.on("error", () => resolve5({ title, cwd }));
1002
+ rl.on("error", () => resolve3({ title, cwd }));
1003
1003
  });
1004
1004
  }
1005
1005
  async function collectJsonlFiles(root) {
@@ -1021,7 +1021,7 @@ async function collectJsonlFiles(root) {
1021
1021
  return files;
1022
1022
  }
1023
1023
  async function extractCodexTitleAndCwd(filePath) {
1024
- return new Promise((resolve5) => {
1024
+ return new Promise((resolve3) => {
1025
1025
  const rl = createInterface({
1026
1026
  input: createReadStream(filePath, { encoding: "utf-8" }),
1027
1027
  crlfDelay: Infinity
@@ -1045,8 +1045,8 @@ async function extractCodexTitleAndCwd(filePath) {
1045
1045
  } catch {
1046
1046
  }
1047
1047
  });
1048
- rl.on("close", () => resolve5({ id, title, cwd }));
1049
- rl.on("error", () => resolve5({ id, title, cwd }));
1048
+ rl.on("close", () => resolve3({ id, title, cwd }));
1049
+ rl.on("error", () => resolve3({ id, title, cwd }));
1050
1050
  });
1051
1051
  }
1052
1052
  function extractCodexUserText(payload) {
@@ -1598,7 +1598,7 @@ var WorkerRegistry = class {
1598
1598
  }
1599
1599
  args.push("--");
1600
1600
  const providerEnv = this.deps.getProviderEnv();
1601
- const child = spawnScript(new URL("../session-worker", import.meta.url), args, {
1601
+ const child = spawnScript("session-worker", args, {
1602
1602
  logger: serviceLogger,
1603
1603
  env: options?.hook ? { ...providerEnv, DEV_ANYWHERE_HOOK_TOKEN: options.hook.token } : providerEnv
1604
1604
  });
@@ -1611,7 +1611,7 @@ var WorkerRegistry = class {
1611
1611
  return workerPid;
1612
1612
  }
1613
1613
  connect(sessionId, sockPath) {
1614
- return new Promise((resolve5) => {
1614
+ return new Promise((resolve3) => {
1615
1615
  const sock = connect(sockPath);
1616
1616
  sock.on("connect", () => {
1617
1617
  this.sockets.set(sessionId, sock);
@@ -1627,9 +1627,9 @@ var WorkerRegistry = class {
1627
1627
  );
1628
1628
  sock.on("close", () => this.onDisconnect(sessionId));
1629
1629
  sock.on("error", () => this.onDisconnect(sessionId));
1630
- resolve5(sock);
1630
+ resolve3(sock);
1631
1631
  });
1632
- sock.on("error", () => resolve5(null));
1632
+ sock.on("error", () => resolve3(null));
1633
1633
  });
1634
1634
  }
1635
1635
  // 枚举 DATA_DIR 下所有 session 目录,尝试连接存活的 worker.sock;失败则清理 stale socket。
@@ -1959,9 +1959,11 @@ function terminateSessionByOwnership(deps, sessionId) {
1959
1959
  }
1960
1960
 
1961
1961
  // src/serve/clipboard-image-upload.ts
1962
- import { existsSync as existsSync4, mkdirSync, readFileSync as readFileSync4, statSync, writeFileSync } from "fs";
1963
- import { isAbsolute as isAbsolute2, join as join5, relative, resolve } from "path";
1962
+ import { mkdirSync, writeFileSync } from "fs";
1963
+ import { tmpdir } from "os";
1964
+ import { join as join5 } from "path";
1964
1965
  import { nanoid as nanoid3 } from "nanoid";
1966
+ var DEFAULT_DATA_DIR = join5(tmpdir(), "dev-anywhere");
1965
1967
  var MAX_CLIPBOARD_IMAGE_BYTES = 10 * 1024 * 1024;
1966
1968
  var MAX_CLIPBOARD_IMAGE_BASE64_LENGTH = Math.ceil(MAX_CLIPBOARD_IMAGE_BYTES / 3) * 4;
1967
1969
  var IMAGE_EXTENSIONS = /* @__PURE__ */ new Map([
@@ -1970,10 +1972,6 @@ var IMAGE_EXTENSIONS = /* @__PURE__ */ new Map([
1970
1972
  ["image/webp", "webp"],
1971
1973
  ["image/gif", "gif"]
1972
1974
  ]);
1973
- function formatTimestamp(ms) {
1974
- const [date, time = "000000"] = new Date(ms).toISOString().replace(/\.\d{3}Z$/, "").split("T");
1975
- return `${date.replace(/-/g, "")}-${time.replace(/:/g, "")}`;
1976
- }
1977
1975
  function normalizeBase64(input) {
1978
1976
  return input.replace(/^data:[^;]+;base64,/i, "").replace(/\s/g, "");
1979
1977
  }
@@ -1992,54 +1990,6 @@ function decodeBase64Image(dataBase64) {
1992
1990
  }
1993
1991
  return buffer;
1994
1992
  }
1995
- function resolveChildDir(rootPath, ...segments) {
1996
- const root = resolve(rootPath);
1997
- const uploadDir = resolve(root, ...segments);
1998
- const relativePath = relative(root, uploadDir);
1999
- if (!relativePath || relativePath.startsWith("..") || isAbsolute2(relativePath)) {
2000
- throw new Error("\u4F1A\u8BDD\u8DEF\u5F84\u65E0\u6548");
2001
- }
2002
- return uploadDir;
2003
- }
2004
- function resolveSessionClipboardDir(dataDir, sessionId) {
2005
- return resolveChildDir(dataDir, sessionId, "clipboard");
2006
- }
2007
- function normalizeGitignoreLine(line) {
2008
- return line.trim().replace(/^\/+/, "").replace(/\/+$/, "");
2009
- }
2010
- function ensureProjectClipboardIgnored(cwd) {
2011
- const gitignorePath = join5(cwd, ".gitignore");
2012
- if (!existsSync4(gitignorePath)) return;
2013
- try {
2014
- const current = readFileSync4(gitignorePath, "utf-8");
2015
- const alreadyIgnored = current.split(/\r?\n/).some((line) => normalizeGitignoreLine(line) === ".dev-anywhere");
2016
- if (alreadyIgnored) return;
2017
- const separator = current.length > 0 && !current.endsWith("\n") ? "\n" : "";
2018
- writeFileSync(gitignorePath, `${current}${separator}.dev-anywhere/
2019
- `);
2020
- } catch {
2021
- }
2022
- }
2023
- function trySaveProjectClipboardImage(options) {
2024
- if (!options.cwd) return null;
2025
- try {
2026
- const cwd = resolve(options.cwd);
2027
- if (!statSync(cwd).isDirectory()) return null;
2028
- const clipboardRoot = resolve(cwd, ".dev-anywhere", "clipboard");
2029
- const uploadDir = resolveChildDir(clipboardRoot, options.sessionId);
2030
- const path = join5(uploadDir, options.fileName);
2031
- mkdirSync(uploadDir, { recursive: true });
2032
- writeFileSync(path, options.buffer, { mode: 384 });
2033
- ensureProjectClipboardIgnored(cwd);
2034
- return { success: true, path: relative(cwd, path) };
2035
- } catch (err) {
2036
- serviceLogger.warn(
2037
- { sessionId: options.sessionId, cwd: options.cwd, error: String(err) },
2038
- "Project clipboard image write failed; falling back to data dir"
2039
- );
2040
- return null;
2041
- }
2042
- }
2043
1993
  function saveClipboardImageUpload(request, options = {}) {
2044
1994
  const extension = IMAGE_EXTENSIONS.get(request.mimeType);
2045
1995
  if (!extension) {
@@ -2051,20 +2001,11 @@ function saveClipboardImageUpload(request, options = {}) {
2051
2001
  }
2052
2002
  try {
2053
2003
  const buffer = decodeBase64Image(request.dataBase64);
2054
- const now = options.now ?? Date.now;
2055
2004
  const suffix = options.randomSuffix?.() ?? nanoid3(6);
2056
- const fileName = `pasted-${formatTimestamp(now())}-${suffix}.${extension}`;
2057
- const projectResult = trySaveProjectClipboardImage({
2058
- cwd: options.cwd,
2059
- sessionId: request.sessionId,
2060
- fileName,
2061
- buffer
2062
- });
2063
- if (projectResult) return projectResult;
2064
- const dataDir = options.dataDir ?? DATA_DIR;
2065
- const uploadDir = resolveSessionClipboardDir(dataDir, request.sessionId);
2066
- const path = join5(uploadDir, fileName);
2067
- mkdirSync(uploadDir, { recursive: true });
2005
+ const fileName = `paste-${suffix}.${extension}`;
2006
+ const dataDir = options.dataDir ?? DEFAULT_DATA_DIR;
2007
+ const path = join5(dataDir, fileName);
2008
+ mkdirSync(dataDir, { recursive: true });
2068
2009
  writeFileSync(path, buffer, { mode: 384 });
2069
2010
  return { success: true, path };
2070
2011
  } catch (err) {
@@ -2077,8 +2018,8 @@ function saveClipboardImageUpload(request, options = {}) {
2077
2018
  }
2078
2019
 
2079
2020
  // src/serve/file-download.ts
2080
- import { readFileSync as readFileSync5, realpathSync, statSync as statSync2 } from "fs";
2081
- import { extname, isAbsolute as isAbsolute3, resolve as resolve2 } from "path";
2021
+ import { readFileSync as readFileSync4, realpathSync, statSync } from "fs";
2022
+ import { extname, isAbsolute as isAbsolute2, resolve } from "path";
2082
2023
  var MAX_FILE_DOWNLOAD_BYTES = 100 * 1024 * 1024;
2083
2024
  var EXT_MIME_MAP = {
2084
2025
  ".png": "image/png",
@@ -2113,7 +2054,7 @@ function guessMimeType(filePath) {
2113
2054
  return EXT_MIME_MAP[ext] ?? "application/octet-stream";
2114
2055
  }
2115
2056
  function resolveDownloadPath(rawPath, cwd) {
2116
- const candidate = isAbsolute3(rawPath) ? resolve2(rawPath) : resolve2(cwd, rawPath);
2057
+ const candidate = isAbsolute2(rawPath) ? resolve(rawPath) : resolve(cwd, rawPath);
2117
2058
  return realpathSync(candidate);
2118
2059
  }
2119
2060
  function errorCode(err) {
@@ -2125,7 +2066,7 @@ function errorCode(err) {
2125
2066
  function loadFileDownload(request, options) {
2126
2067
  try {
2127
2068
  const resolvedPath = resolveDownloadPath(request.path, options.cwd);
2128
- const stat2 = statSync2(resolvedPath);
2069
+ const stat2 = statSync(resolvedPath);
2129
2070
  if (!stat2.isFile()) {
2130
2071
  return {
2131
2072
  success: false,
@@ -2145,7 +2086,7 @@ function loadFileDownload(request, options) {
2145
2086
  errorCode: ControlErrorCode.UNKNOWN
2146
2087
  };
2147
2088
  }
2148
- const buffer = readFileSync5(resolvedPath);
2089
+ const buffer = readFileSync4(resolvedPath);
2149
2090
  return {
2150
2091
  success: true,
2151
2092
  sessionId: request.sessionId,
@@ -2166,12 +2107,14 @@ function loadFileDownload(request, options) {
2166
2107
  }
2167
2108
 
2168
2109
  // src/serve/file-upload.ts
2169
- import { existsSync as existsSync5, mkdirSync as mkdirSync2, readFileSync as readFileSync6, statSync as statSync3, writeFileSync as writeFileSync2 } from "fs";
2170
- import { basename, isAbsolute as isAbsolute4, join as join6, relative as relative2, resolve as resolve3 } from "path";
2110
+ import { mkdirSync as mkdirSync2, writeFileSync as writeFileSync2 } from "fs";
2111
+ import { tmpdir as tmpdir2 } from "os";
2112
+ import { extname as extname2, join as join6 } from "path";
2171
2113
  import { nanoid as nanoid4 } from "nanoid";
2114
+ var DEFAULT_DATA_DIR2 = join6(tmpdir2(), "dev-anywhere");
2172
2115
  var MAX_FILE_UPLOAD_BYTES = 100 * 1024 * 1024;
2173
2116
  var MAX_FILE_UPLOAD_BASE64_LENGTH = Math.ceil(MAX_FILE_UPLOAD_BYTES / 3) * 4;
2174
- var SAFE_FILENAME_RE = /^[A-Za-z0-9._-]+$/;
2117
+ var SAFE_EXT_RE = /^[A-Za-z0-9]{1,6}$/;
2175
2118
  function normalizeBase642(input) {
2176
2119
  return input.replace(/^data:[^;]+;base64,/i, "").replace(/\s/g, "");
2177
2120
  }
@@ -2190,76 +2133,18 @@ function decodeBase64File(dataBase64) {
2190
2133
  }
2191
2134
  return buffer;
2192
2135
  }
2193
- function sanitizeFileName(fileName, fallbackPrefix, suffix) {
2194
- const base = basename(fileName).trim();
2195
- if (base && SAFE_FILENAME_RE.test(base)) return base;
2196
- const extMatch = base.match(/\.([A-Za-z0-9]{1,6})$/);
2197
- const ext = extMatch ? `.${extMatch[1]}` : "";
2198
- return `${fallbackPrefix}-${suffix}${ext}`;
2199
- }
2200
- function resolveChildDir2(rootPath, ...segments) {
2201
- const root = resolve3(rootPath);
2202
- const target = resolve3(root, ...segments);
2203
- const rel = relative2(root, target);
2204
- if (!rel || rel.startsWith("..") || isAbsolute4(rel)) {
2205
- throw new Error("\u4F1A\u8BDD\u8DEF\u5F84\u65E0\u6548");
2206
- }
2207
- return target;
2208
- }
2209
- function normalizeGitignoreLine2(line) {
2210
- return line.trim().replace(/^\/+/, "").replace(/\/+$/, "");
2211
- }
2212
- function ensureProjectUploadIgnored(cwd) {
2213
- const gitignorePath = join6(cwd, ".gitignore");
2214
- if (!existsSync5(gitignorePath)) return;
2215
- try {
2216
- const current = readFileSync6(gitignorePath, "utf-8");
2217
- const alreadyIgnored = current.split(/\r?\n/).some((line) => normalizeGitignoreLine2(line) === ".dev-anywhere");
2218
- if (alreadyIgnored) return;
2219
- const separator = current.length > 0 && !current.endsWith("\n") ? "\n" : "";
2220
- writeFileSync2(gitignorePath, `${current}${separator}.dev-anywhere/
2221
- `);
2222
- } catch {
2223
- }
2224
- }
2225
- function trySaveProjectUpload(options) {
2226
- if (!options.cwd) return null;
2227
- try {
2228
- const cwd = resolve3(options.cwd);
2229
- if (!statSync3(cwd).isDirectory()) return null;
2230
- const uploadsRoot = resolve3(cwd, ".dev-anywhere", "uploads");
2231
- const uploadDir = resolveChildDir2(uploadsRoot, options.sessionId);
2232
- const path = join6(uploadDir, options.fileName);
2233
- mkdirSync2(uploadDir, { recursive: true });
2234
- writeFileSync2(path, options.buffer, { mode: 384 });
2235
- ensureProjectUploadIgnored(cwd);
2236
- return { success: true, path: relative2(cwd, path) };
2237
- } catch (err) {
2238
- serviceLogger.warn(
2239
- { sessionId: options.sessionId, cwd: options.cwd, error: String(err) },
2240
- "Project upload write failed; falling back to data dir"
2241
- );
2242
- return null;
2243
- }
2136
+ function safeExtension(fileName) {
2137
+ const raw = extname2(fileName).slice(1).toLowerCase();
2138
+ return SAFE_EXT_RE.test(raw) ? `.${raw}` : "";
2244
2139
  }
2245
2140
  async function saveFileUpload(request, options = {}) {
2246
2141
  try {
2247
2142
  const buffer = decodeBase64File(request.dataBase64);
2248
- const now = options.now ?? Date.now;
2249
2143
  const suffix = options.randomSuffix?.() ?? nanoid4(6);
2250
- const stamped = new Date(now()).toISOString().replace(/[-:T.Z]/g, "").slice(0, 14);
2251
- const fileName = sanitizeFileName(request.fileName, `upload-${stamped}`, suffix);
2252
- const projectResult = trySaveProjectUpload({
2253
- cwd: options.cwd,
2254
- sessionId: request.sessionId,
2255
- fileName,
2256
- buffer
2257
- });
2258
- if (projectResult) return projectResult;
2259
- const dataDir = options.dataDir ?? DATA_DIR;
2260
- const uploadDir = resolveChildDir2(dataDir, request.sessionId, "uploads");
2261
- const path = join6(uploadDir, fileName);
2262
- mkdirSync2(uploadDir, { recursive: true });
2144
+ const fileName = `up-${suffix}${safeExtension(request.fileName)}`;
2145
+ const dataDir = options.dataDir ?? DEFAULT_DATA_DIR2;
2146
+ const path = join6(dataDir, fileName);
2147
+ mkdirSync2(dataDir, { recursive: true });
2263
2148
  writeFileSync2(path, buffer, { mode: 384 });
2264
2149
  return { success: true, path };
2265
2150
  } catch (err) {
@@ -2272,16 +2157,16 @@ async function saveFileUpload(request, options = {}) {
2272
2157
  }
2273
2158
 
2274
2159
  // src/serve/image-preview.ts
2275
- import { readFileSync as readFileSync7, realpathSync as realpathSync2, statSync as statSync4 } from "fs";
2276
- import { tmpdir } from "os";
2277
- import { isAbsolute as isAbsolute5, relative as relative3, resolve as resolve4 } from "path";
2160
+ import { readFileSync as readFileSync5, realpathSync as realpathSync2, statSync as statSync2 } from "fs";
2161
+ import { tmpdir as tmpdir3 } from "os";
2162
+ import { isAbsolute as isAbsolute3, relative, resolve as resolve2 } from "path";
2278
2163
  var MAX_IMAGE_PREVIEW_BYTES = 10 * 1024 * 1024;
2279
2164
  function isInsideRoot(realFilePath, realRootPath) {
2280
- const rel = relative3(realRootPath, realFilePath);
2281
- return rel === "" || !rel.startsWith("..") && !isAbsolute5(rel);
2165
+ const rel = relative(realRootPath, realFilePath);
2166
+ return rel === "" || !rel.startsWith("..") && !isAbsolute3(rel);
2282
2167
  }
2283
2168
  function allowedRoots(options) {
2284
- return [options.cwd, options.tmpDir ?? tmpdir(), ...options.previewRoots ?? []].map((root) => root.trim()).filter(Boolean).flatMap((root) => {
2169
+ return [options.cwd, options.tmpDir ?? tmpdir3(), ...options.previewRoots ?? []].map((root) => root.trim()).filter(Boolean).flatMap((root) => {
2285
2170
  try {
2286
2171
  return [realpathSync2(root)];
2287
2172
  } catch {
@@ -2290,7 +2175,7 @@ function allowedRoots(options) {
2290
2175
  });
2291
2176
  }
2292
2177
  function resolvePreviewPath(rawPath, options) {
2293
- const candidate = isAbsolute5(rawPath) ? resolve4(rawPath) : resolve4(options.cwd, rawPath);
2178
+ const candidate = isAbsolute3(rawPath) ? resolve2(rawPath) : resolve2(options.cwd, rawPath);
2294
2179
  const realCandidate = realpathSync2(candidate);
2295
2180
  if (!allowedRoots(options).some((root) => isInsideRoot(realCandidate, root))) {
2296
2181
  throw Object.assign(new Error("\u56FE\u7247\u8DEF\u5F84\u4E0D\u5728\u5141\u8BB8\u9884\u89C8\u7684\u76EE\u5F55\u5185"), {
@@ -2323,7 +2208,7 @@ function errorCode2(err) {
2323
2208
  function loadImagePreview(request, options) {
2324
2209
  try {
2325
2210
  const resolvedPath = resolvePreviewPath(request.path, options);
2326
- const stat2 = statSync4(resolvedPath);
2211
+ const stat2 = statSync2(resolvedPath);
2327
2212
  if (!stat2.isFile()) {
2328
2213
  return {
2329
2214
  success: false,
@@ -2343,7 +2228,7 @@ function loadImagePreview(request, options) {
2343
2228
  errorCode: ControlErrorCode.UNKNOWN
2344
2229
  };
2345
2230
  }
2346
- const buffer = readFileSync7(resolvedPath);
2231
+ const buffer = readFileSync5(resolvedPath);
2347
2232
  const mimeType = detectImageMime(buffer);
2348
2233
  if (!mimeType) {
2349
2234
  return {
@@ -2444,8 +2329,7 @@ var RelayInputHandlers = class {
2444
2329
  onClipboardImageUpload(msg) {
2445
2330
  const { sessionId, requestId } = msg;
2446
2331
  if (!sessionId) return;
2447
- const session = this.deps.sessionManager.getSession(sessionId);
2448
- if (!session) {
2332
+ if (!this.deps.sessionManager.getSession(sessionId)) {
2449
2333
  this.deps.relayConnection.sendRaw(
2450
2334
  serializeControl({
2451
2335
  type: "clipboard_image_upload_response",
@@ -2459,17 +2343,12 @@ var RelayInputHandlers = class {
2459
2343
  serviceLogger.warn({ sessionId }, "Clipboard image upload rejected: session not found");
2460
2344
  return;
2461
2345
  }
2462
- const result = saveClipboardImageUpload(
2463
- {
2464
- sessionId,
2465
- mimeType: msg.mimeType,
2466
- dataBase64: msg.dataBase64,
2467
- fileName: msg.fileName
2468
- },
2469
- {
2470
- cwd: session.cwd
2471
- }
2472
- );
2346
+ const result = saveClipboardImageUpload({
2347
+ sessionId,
2348
+ mimeType: msg.mimeType,
2349
+ dataBase64: msg.dataBase64,
2350
+ fileName: msg.fileName
2351
+ });
2473
2352
  this.deps.relayConnection.sendRaw(
2474
2353
  serializeControl({
2475
2354
  type: "clipboard_image_upload_response",
@@ -2550,10 +2429,7 @@ var RelayInputHandlers = class {
2550
2429
  })
2551
2430
  );
2552
2431
  if (result.success) {
2553
- serviceLogger.info(
2554
- { sessionId, path, size: result.size },
2555
- "File download handled"
2556
- );
2432
+ serviceLogger.info({ sessionId, path, size: result.size }, "File download handled");
2557
2433
  } else {
2558
2434
  serviceLogger.warn(
2559
2435
  { sessionId, path, errorCode: result.errorCode, error: result.error },
@@ -2564,8 +2440,7 @@ var RelayInputHandlers = class {
2564
2440
  async onFileUploadRequest(msg) {
2565
2441
  const { sessionId, requestId, mimeType, dataBase64, fileName } = msg;
2566
2442
  if (!sessionId) return;
2567
- const session = this.deps.sessionManager.getSession(sessionId);
2568
- if (!session) {
2443
+ if (!this.deps.sessionManager.getSession(sessionId)) {
2569
2444
  this.deps.relayConnection.sendRaw(
2570
2445
  serializeControl({
2571
2446
  type: "file_upload_response",
@@ -2579,10 +2454,7 @@ var RelayInputHandlers = class {
2579
2454
  serviceLogger.warn({ sessionId }, "File upload rejected: session not found");
2580
2455
  return;
2581
2456
  }
2582
- const result = await saveFileUpload(
2583
- { sessionId, mimeType, dataBase64, fileName },
2584
- { cwd: session.cwd }
2585
- );
2457
+ const result = await saveFileUpload({ sessionId, mimeType, dataBase64, fileName });
2586
2458
  this.deps.relayConnection.sendRaw(
2587
2459
  serializeControl({
2588
2460
  type: "file_upload_response",
@@ -2793,14 +2665,14 @@ var RelayPermissionHandlers = class {
2793
2665
 
2794
2666
  // src/serve/relay-resource-handlers.ts
2795
2667
  import { homedir as homedir4 } from "os";
2796
- import { accessSync, constants, statSync as statSync5 } from "fs";
2668
+ import { accessSync, constants, statSync as statSync3 } from "fs";
2797
2669
  function errorMessage(err) {
2798
2670
  return err instanceof Error ? err.message : String(err);
2799
2671
  }
2800
2672
  function validateExecutablePath(path) {
2801
2673
  const normalized = path.trim();
2802
2674
  if (!normalized.startsWith("/")) throw new Error("CLI \u8DEF\u5F84\u5FC5\u987B\u662F\u7EDD\u5BF9\u8DEF\u5F84");
2803
- const stat2 = statSync5(normalized);
2675
+ const stat2 = statSync3(normalized);
2804
2676
  if (!stat2.isFile()) throw new Error("CLI \u8DEF\u5F84\u4E0D\u662F\u53EF\u6267\u884C\u6587\u4EF6");
2805
2677
  accessSync(normalized, constants.X_OK);
2806
2678
  return normalized;
@@ -2908,8 +2780,8 @@ var RelayResourceHandlers = class {
2908
2780
  };
2909
2781
 
2910
2782
  // src/serve/relay-session-create-handler.ts
2911
- import { rmSync, statSync as statSync6 } from "fs";
2912
- import { isAbsolute as isAbsolute6 } from "path";
2783
+ import { rmSync, statSync as statSync4 } from "fs";
2784
+ import { isAbsolute as isAbsolute4 } from "path";
2913
2785
  import { nanoid as nanoid5 } from "nanoid";
2914
2786
 
2915
2787
  // src/serve/hosted-pty-registry.ts
@@ -3161,11 +3033,11 @@ function validateSessionCwd(cwd) {
3161
3033
  return { message: "\u8BF7\u8F93\u5165\u5DE5\u4F5C\u76EE\u5F55", code: ControlErrorCode.INVALID_PATH };
3162
3034
  }
3163
3035
  const trimmed = cwd.trim();
3164
- if (!isAbsolute6(trimmed)) {
3036
+ if (!isAbsolute4(trimmed)) {
3165
3037
  return { message: "\u5DE5\u4F5C\u76EE\u5F55\u5FC5\u987B\u662F\u7EDD\u5BF9\u8DEF\u5F84", code: ControlErrorCode.INVALID_PATH };
3166
3038
  }
3167
3039
  try {
3168
- const stat2 = statSync6(trimmed);
3040
+ const stat2 = statSync4(trimmed);
3169
3041
  return stat2.isDirectory() ? null : { message: "\u5DE5\u4F5C\u76EE\u5F55\u4E0D\u662F\u76EE\u5F55", code: ControlErrorCode.PATH_NOT_DIRECTORY };
3170
3042
  } catch (err) {
3171
3043
  return {
@@ -3584,9 +3456,7 @@ var RelayRouter = class {
3584
3456
  if (sid) {
3585
3457
  const status = this.deps.agentStatusRegistry.get(sid);
3586
3458
  const statuses2 = status && this.deps.sessionManager.getSession(sid) ? [{ sessionId: sid, payload: status }] : [];
3587
- this.deps.relaySend(
3588
- serializeControl({ type: "agent_status_response", requestId, statuses: statuses2 })
3589
- );
3459
+ this.deps.relaySend(serializeControl({ type: "agent_status_response", requestId, statuses: statuses2 }));
3590
3460
  serviceLogger.info({ sessionId: sid, count: statuses2.length }, "Agent status snapshot sent");
3591
3461
  return;
3592
3462
  }
@@ -3595,9 +3465,7 @@ var RelayRouter = class {
3595
3465
  if (!this.deps.sessionManager.getSession(sessionId)) continue;
3596
3466
  statuses.push({ sessionId, payload: status });
3597
3467
  }
3598
- this.deps.relaySend(
3599
- serializeControl({ type: "agent_status_response", requestId, statuses })
3600
- );
3468
+ this.deps.relaySend(serializeControl({ type: "agent_status_response", requestId, statuses }));
3601
3469
  serviceLogger.info({ count: statuses.length }, "Agent status snapshot sent");
3602
3470
  }
3603
3471
  onSessionTerminate(msg) {
@@ -3762,11 +3630,11 @@ var PermissionBroker = class {
3762
3630
  if (this.pending.has(request.requestId)) {
3763
3631
  return Promise.resolve(DUPLICATE_DECISION);
3764
3632
  }
3765
- return new Promise((resolve5) => {
3633
+ return new Promise((resolve3) => {
3766
3634
  this.pending.set(request.requestId, {
3767
3635
  ...request,
3768
3636
  source: "hook",
3769
- resolve: resolve5,
3637
+ resolve: resolve3,
3770
3638
  createdAt: Date.now()
3771
3639
  });
3772
3640
  });
@@ -4142,14 +4010,14 @@ function createEventBridge(deps) {
4142
4010
 
4143
4011
  // src/serve/service-files.ts
4144
4012
  import { execSync } from "child_process";
4145
- import { existsSync as existsSync6, readFileSync as readFileSync8, unlinkSync as unlinkSync2 } from "fs";
4013
+ import { existsSync as existsSync4, readFileSync as readFileSync6, unlinkSync as unlinkSync2 } from "fs";
4146
4014
  import { hostname } from "os";
4147
4015
  import { connect as connect2 } from "net";
4148
4016
  function tryConnectSocket(sockPath) {
4149
- return new Promise((resolve5) => {
4017
+ return new Promise((resolve3) => {
4150
4018
  const s = connect2(sockPath);
4151
- s.on("connect", () => resolve5(s));
4152
- s.on("error", () => resolve5(null));
4019
+ s.on("connect", () => resolve3(s));
4020
+ s.on("error", () => resolve3(null));
4153
4021
  });
4154
4022
  }
4155
4023
  function isProcessAlive(pid) {
@@ -4161,7 +4029,7 @@ function isProcessAlive(pid) {
4161
4029
  }
4162
4030
  }
4163
4031
  async function cleanupStaleResources() {
4164
- if (existsSync6(SOCK_PATH)) {
4032
+ if (existsSync4(SOCK_PATH)) {
4165
4033
  const existing = await tryConnectSocket(SOCK_PATH);
4166
4034
  if (existing) {
4167
4035
  existing.destroy();
@@ -4174,8 +4042,8 @@ async function cleanupStaleResources() {
4174
4042
  unlinkSync2(SOCK_PATH);
4175
4043
  serviceLogger.info("Removed stale socket file");
4176
4044
  }
4177
- if (existsSync6(PID_PATH)) {
4178
- const pidStr = readFileSync8(PID_PATH, "utf-8").trim();
4045
+ if (existsSync4(PID_PATH)) {
4046
+ const pidStr = readFileSync6(PID_PATH, "utf-8").trim();
4179
4047
  const pid = parseInt(pidStr, 10);
4180
4048
  if (!isNaN(pid) && isProcessAlive(pid)) {
4181
4049
  const msg = `Another service is already running with PID ${pid}`;
@@ -4507,7 +4375,7 @@ function handleTerminalConnection(socket, deps) {
4507
4375
 
4508
4376
  // src/serve/hook-registry.ts
4509
4377
  import { createHash, randomBytes } from "crypto";
4510
- import { existsSync as existsSync7, mkdirSync as mkdirSync3, readFileSync as readFileSync9, renameSync, writeFileSync as writeFileSync3 } from "fs";
4378
+ import { existsSync as existsSync5, mkdirSync as mkdirSync3, readFileSync as readFileSync7, renameSync, writeFileSync as writeFileSync3 } from "fs";
4511
4379
  import { dirname } from "path";
4512
4380
  import { z } from "zod";
4513
4381
  var PersistedHookSessionBindingSchema = z.object({
@@ -4568,10 +4436,10 @@ var HookRegistry = class {
4568
4436
  }
4569
4437
  }
4570
4438
  load() {
4571
- if (!this.persistPath || !existsSync7(this.persistPath)) return;
4439
+ if (!this.persistPath || !existsSync5(this.persistPath)) return;
4572
4440
  try {
4573
4441
  const parsed = PersistedHookRegistrySchema.parse(
4574
- JSON.parse(readFileSync9(this.persistPath, "utf8"))
4442
+ JSON.parse(readFileSync7(this.persistPath, "utf8"))
4575
4443
  );
4576
4444
  this.bindingsBySession.clear();
4577
4445
  for (const binding of parsed.bindings) {
@@ -4635,7 +4503,7 @@ var HookServer = class {
4635
4503
  this.writeJson(res, 500, { error: "internal_error" });
4636
4504
  });
4637
4505
  });
4638
- return new Promise((resolve5, reject) => {
4506
+ return new Promise((resolve3, reject) => {
4639
4507
  const onError = (err) => {
4640
4508
  this.server?.off("listening", onListening);
4641
4509
  reject(err);
@@ -4643,7 +4511,7 @@ var HookServer = class {
4643
4511
  const onListening = () => {
4644
4512
  this.server?.off("error", onError);
4645
4513
  serviceLogger.info({ host: this.host, port: this.options.port }, "Hook server listening");
4646
- resolve5();
4514
+ resolve3();
4647
4515
  };
4648
4516
  this.server.once("error", onError);
4649
4517
  this.server.once("listening", onListening);
@@ -4654,8 +4522,8 @@ var HookServer = class {
4654
4522
  if (!this.server) return Promise.resolve();
4655
4523
  const server = this.server;
4656
4524
  this.server = null;
4657
- return new Promise((resolve5, reject) => {
4658
- server.close((err) => err ? reject(err) : resolve5());
4525
+ return new Promise((resolve3, reject) => {
4526
+ server.close((err) => err ? reject(err) : resolve3());
4659
4527
  });
4660
4528
  }
4661
4529
  getListeningPort() {
@@ -4769,7 +4637,7 @@ var HookServer = class {
4769
4637
  this.writeJson(res, 200, payload);
4770
4638
  }
4771
4639
  readBody(req) {
4772
- return new Promise((resolve5, reject) => {
4640
+ return new Promise((resolve3, reject) => {
4773
4641
  let body = "";
4774
4642
  let size = 0;
4775
4643
  req.setEncoding("utf8");
@@ -4782,7 +4650,7 @@ var HookServer = class {
4782
4650
  }
4783
4651
  body += chunk;
4784
4652
  });
4785
- req.on("end", () => resolve5(body));
4653
+ req.on("end", () => resolve3(body));
4786
4654
  req.on("error", reject);
4787
4655
  });
4788
4656
  }
@@ -5089,7 +4957,10 @@ async function startService(options) {
5089
4957
  relayConnection.on("connected", () => {
5090
4958
  void controlHandlers.reinitializeOnReconnect().catch((err) => {
5091
4959
  serviceLogger.error(
5092
- { error: err instanceof Error ? err.message : String(err), stack: err instanceof Error ? err.stack : void 0 },
4960
+ {
4961
+ error: err instanceof Error ? err.message : String(err),
4962
+ stack: err instanceof Error ? err.stack : void 0
4963
+ },
5093
4964
  "reinitializeOnReconnect failed: client may see stale state until next manual sync"
5094
4965
  );
5095
4966
  });