@spencer-kit/coder-studio 0.4.2 → 0.4.4

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/esm/bin.mjs CHANGED
@@ -953,10 +953,10 @@ function resolveSpawnArgv(argv, deps = {}) {
953
953
  }
954
954
  const restArgs = argv.slice(1);
955
955
  const readFileSync10 = deps.readFileSync ?? ((file) => fs2.readFileSync(file, "utf8"));
956
- const existsSync15 = deps.existsSync ?? fs2.existsSync;
956
+ const existsSync16 = deps.existsSync ?? fs2.existsSync;
957
957
  const pathEnv = deps.pathEnv ?? process.env.Path ?? process.env.PATH ?? "";
958
958
  const pathExt = deps.pathExt ?? process.env.PATHEXT ?? DEFAULT_PATHEXT;
959
- const resolved = resolveExecutablePath(command, pathEnv, pathExt, existsSync15);
959
+ const resolved = resolveExecutablePath(command, pathEnv, pathExt, existsSync16);
960
960
  if (!resolved) {
961
961
  return [...argv];
962
962
  }
@@ -1005,17 +1005,17 @@ function expandShimVars(value, dp0Dir) {
1005
1005
  function parsePathExt(pathExt) {
1006
1006
  return pathExt.split(";").map((entry) => entry.trim().toLowerCase()).filter((entry) => entry.length > 0);
1007
1007
  }
1008
- function resolveExecutablePath(command, pathEnv, pathExt, existsSync15) {
1008
+ function resolveExecutablePath(command, pathEnv, pathExt, existsSync16) {
1009
1009
  const hasExt = path3.win32.extname(command).length > 0;
1010
1010
  const extensions = parsePathExt(pathExt);
1011
1011
  if (path3.win32.isAbsolute(command)) {
1012
- if (existsSync15(command)) {
1012
+ if (existsSync16(command)) {
1013
1013
  return command;
1014
1014
  }
1015
1015
  if (!hasExt) {
1016
1016
  for (const ext of extensions) {
1017
1017
  const candidate = command + ext;
1018
- if (existsSync15(candidate)) {
1018
+ if (existsSync16(candidate)) {
1019
1019
  return candidate;
1020
1020
  }
1021
1021
  }
@@ -1026,14 +1026,14 @@ function resolveExecutablePath(command, pathEnv, pathExt, existsSync15) {
1026
1026
  for (const dir of dirs) {
1027
1027
  if (hasExt) {
1028
1028
  const candidate = path3.win32.join(dir, command);
1029
- if (existsSync15(candidate)) {
1029
+ if (existsSync16(candidate)) {
1030
1030
  return candidate;
1031
1031
  }
1032
1032
  continue;
1033
1033
  }
1034
1034
  for (const ext of extensions) {
1035
1035
  const candidate = path3.win32.join(dir, command + ext);
1036
- if (existsSync15(candidate)) {
1036
+ if (existsSync16(candidate)) {
1037
1037
  return candidate;
1038
1038
  }
1039
1039
  }
@@ -2554,12 +2554,12 @@ async function ensureSafeUploadDir(rootDir, targetDir2) {
2554
2554
  await mkdir3(resolvedRoot, { recursive: true });
2555
2555
  await assertDirectorySegmentSafe(resolvedRoot);
2556
2556
  }
2557
- const relative3 = path7.relative(resolvedRoot, resolvedTarget);
2558
- if (!relative3) {
2557
+ const relative4 = path7.relative(resolvedRoot, resolvedTarget);
2558
+ if (!relative4) {
2559
2559
  return;
2560
2560
  }
2561
2561
  let current = resolvedRoot;
2562
- for (const segment of relative3.split(path7.sep)) {
2562
+ for (const segment of relative4.split(path7.sep)) {
2563
2563
  current = path7.join(current, segment);
2564
2564
  try {
2565
2565
  await assertDirectorySegmentSafe(current);
@@ -8077,7 +8077,7 @@ function ensureNodePtySpawnHelperExecutable(deps = {}) {
8077
8077
  const arch = deps.arch ?? process.arch;
8078
8078
  const resolve4 = deps.resolve ?? ((id) => require4.resolve(id));
8079
8079
  const fileExists = deps.existsSync ?? existsSync6;
8080
- const stat9 = deps.statSync ?? statSync;
8080
+ const stat10 = deps.statSync ?? statSync;
8081
8081
  const chmod = deps.chmodSync ?? chmodSync2;
8082
8082
  let packageJsonPath;
8083
8083
  try {
@@ -8095,7 +8095,7 @@ function ensureNodePtySpawnHelperExecutable(deps = {}) {
8095
8095
  if (!fileExists(helperPath)) {
8096
8096
  return;
8097
8097
  }
8098
- const currentMode = stat9(helperPath).mode;
8098
+ const currentMode = stat10(helperPath).mode;
8099
8099
  const executableMode = currentMode | 73;
8100
8100
  if (executableMode === currentMode) {
8101
8101
  return;
@@ -8301,13 +8301,19 @@ import { spawn as spawn3 } from "node:child_process";
8301
8301
  function buildPrompt(context, mode) {
8302
8302
  if (mode === "decompose") {
8303
8303
  return [
8304
- "You are an autonomous supervisor for a target-scoped software task.",
8304
+ "You are an autonomous planner-supervisor for this target-scoped software task.",
8305
+ "Your purpose is to drive the work from objective to high-quality delivery with minimal babysitting.",
8306
+ 'Do not optimize for merely reaching "done"; optimize for a result that is correct, verified, coherent, and not obviously low-quality or rushed.',
8305
8307
  "Your first job is to decompose the target into a supervision structure before evaluation begins.",
8306
8308
  "",
8307
8309
  "Return JSON only.",
8308
8310
  "No prose before or after the JSON.",
8309
8311
  "",
8310
8312
  "Decomposition policy:",
8313
+ "- Create an execution plan, not just a task list.",
8314
+ "- Break the objective into the smallest reasonable set of milestones that maximize clarity, reduce uncertainty, and preserve steady forward progress.",
8315
+ "- Order milestones by dependency, risk reduction, and delivery leverage.",
8316
+ "- Prefer a plan structure that makes execution easier, verification clearer, and replanning cheaper.",
8311
8317
  "- Do not ask the user any questions.",
8312
8318
  "- Do not ask for clarification, confirmation, or approval.",
8313
8319
  "- Do not propose options for the user to choose from.",
@@ -8321,6 +8327,30 @@ function buildPrompt(context, mode) {
8321
8327
  "- Each item must be concrete, milestone-sized, and useful for subsequent evaluation.",
8322
8328
  "- Do not leave the structure empty.",
8323
8329
  "",
8330
+ "Decomposition principles:",
8331
+ "- Prefer milestones that produce a concrete artifact, observable behavior change, test result, or verification result.",
8332
+ "- Make dependencies explicit.",
8333
+ "- Separate implementation, verification, integration, and cleanup when that improves delivery reliability.",
8334
+ "- If a step is too vague to verify independently, split it further.",
8335
+ "- Prefer plans that keep the agent moving with minimal ambiguity between milestones.",
8336
+ "- Use stage-based planning by default unless there are clearly independent deliverables that justify subtargets.",
8337
+ "- Build the plan so it can recover from failed attempts: prefer decompositions that allow narrowing scope, isolating failures, checking assumptions, and restoring a working baseline when needed.",
8338
+ "- Keep the decomposition practical for execution, not merely neat on paper.",
8339
+ "",
8340
+ "Planning quality bar:",
8341
+ "- Prefer fewer, stronger milestones over many thin or vague ones.",
8342
+ "- Every item should imply a concrete deliverable and observable acceptance criteria.",
8343
+ '- Avoid vague items such as "improve", "clean up", or "refactor" unless tied to a specific delivery or verification target.',
8344
+ "- Include quality and verification checkpoints where they materially improve the final result.",
8345
+ "- Do not decompose in a way that encourages superficial completion.",
8346
+ "",
8347
+ "Planning boundary:",
8348
+ "- You are responsible for execution structure, sequencing, quality control, and verification structure.",
8349
+ "- Do not hard-code unnecessary implementation detail too early.",
8350
+ "- If multiple implementation paths exist, prefer a plan that keeps execution adaptable until evidence makes one path clearly better.",
8351
+ "- Do not hide assumptions inside the plan.",
8352
+ "- Do not create a brittle plan that depends on perfect execution.",
8353
+ "",
8324
8354
  "Item requirements:",
8325
8355
  '- Each item must include "id", "kind", "title", "objective", "deliverable", "acceptanceCriteria", and "status".',
8326
8356
  '- "kind" must match the selected decompositionMode: all "stage" or all "subtarget".',
@@ -8353,8 +8383,13 @@ function buildPrompt(context, mode) {
8353
8383
  ].join("\n");
8354
8384
  }
8355
8385
  const lines = [
8356
- "You are an autonomous supervisor for a target-scoped software task.",
8357
- "Your job is to keep the agent moving toward the objective until the objective is complete.",
8386
+ "You are an autonomous planner-supervisor for this target-scoped software task.",
8387
+ "Your purpose is to drive the work from objective to high-quality delivery with minimal babysitting.",
8388
+ 'Do not optimize for merely reaching "done"; optimize for a result that is correct, verified, coherent, and not obviously low-quality or rushed.',
8389
+ "Act as an autonomous execution supervisor.",
8390
+ "Your job is to keep the agent moving toward the objective, maintain delivery quality, detect low-yield paths early, and redirect work when needed.",
8391
+ "Do not passively observe progress; actively steer it toward successful, high-quality completion.",
8392
+ "Drive execution through the supervised agent rather than by independently performing the work yourself.",
8358
8393
  "",
8359
8394
  "Return JSON only.",
8360
8395
  "No prose before or after the JSON.",
@@ -8385,7 +8420,12 @@ function buildPrompt(context, mode) {
8385
8420
  '- When advancing to the next item, mark the previous item as "done" and set activeItemId to the next item explicitly.',
8386
8421
  "- If the active item is blocked, give guidance that is most likely to unblock it.",
8387
8422
  "- If the active item is obsolete, explain the reason briefly and move to the next useful item.",
8388
- "- If the agent appears stuck or repeated the same action, give a different concrete next action.",
8423
+ "- If the current path is low-yield, brittle, repetitive, or producing low-quality output, redirect early.",
8424
+ "- Diagnose stalls precisely: implementation failure, verification failure, environment failure, scope misframing, weak solution quality, or missing evidence.",
8425
+ "- Choose the next action that most improves objective-level progress, not merely the most local continuation.",
8426
+ "- Do not repeat the same tactic after failure unless new evidence justifies retrying it.",
8427
+ "- Maintain commitment to the objective, not blind commitment to the current tactic.",
8428
+ "- Replan locally when needed, but keep the overall execution coherent and objective-driven.",
8389
8429
  "- Do not rewrite the decomposition structure during normal evaluation cycles.",
8390
8430
  "",
8391
8431
  "Allowed statuses:",
@@ -8410,6 +8450,21 @@ function buildPrompt(context, mode) {
8410
8450
  "- If implementation is needed, point to the likely area, behavior, or file/module based on available evidence.",
8411
8451
  "- If the agent asked a question, answer it directly in the guidance and continue with a concrete next action.",
8412
8452
  "",
8453
+ "Delivery quality bar:",
8454
+ "- Do not accept shallow, brittle, or obviously rushed solutions.",
8455
+ "- Do not optimize for the smallest change if it leads to poor maintainability, weak verification, or fragile behavior.",
8456
+ "- Prefer solutions that are robust, coherent with the existing codebase, and likely to hold up beyond the happy path.",
8457
+ "- Require appropriate verification for the kind of work being done.",
8458
+ "- Consider edge cases, integration impact, regressions, and maintainability where relevant.",
8459
+ "- If a solution technically works but is low-quality, incomplete, poorly verified, or obviously a shortcut, treat the milestone as not yet complete.",
8460
+ "- Do not let superficial progress masquerade as real delivery.",
8461
+ "",
8462
+ "Completion standard:",
8463
+ "- A milestone is complete only when its deliverable and acceptanceCriteria are supported by observable evidence and the result meets a reasonable quality bar.",
8464
+ "- The objective is complete only when the final result is implemented, verified, and not obviously compromised in quality.",
8465
+ "- Do not mark work complete merely because code was changed, a command passed once, or a minimal patch exists.",
8466
+ "- Optimize for finished, verified, and defensible delivery.",
8467
+ "",
8413
8468
  "Evaluation policy:",
8414
8469
  "- Update progress incrementally against the existing decomposition.",
8415
8470
  "- Use itemUpdates to reflect evidence-backed status changes only.",
@@ -14894,20 +14949,260 @@ var init_session2 = __esm({
14894
14949
  }
14895
14950
  });
14896
14951
 
14952
+ // packages/server/src/fs/content-search.ts
14953
+ import { spawn as spawn5 } from "child_process";
14954
+ import { existsSync as existsSync8 } from "fs";
14955
+ import { readdir as readdir4, readFile as readFile4, stat as stat8 } from "fs/promises";
14956
+ import { basename as basename2, join as join10, relative as relative2 } from "path";
14957
+ import { createInterface } from "readline";
14958
+ async function searchFileContents(rootPath, options) {
14959
+ const query = options.query.trim();
14960
+ if (!query) {
14961
+ return {
14962
+ files: [],
14963
+ totalMatchCount: 0,
14964
+ hasMoreFiles: false,
14965
+ truncatedMatchFileCount: 0
14966
+ };
14967
+ }
14968
+ const result = await searchWithRipgrep(rootPath, query, options.maxFiles).catch(
14969
+ async (error) => {
14970
+ if (error.code === "ENOENT") {
14971
+ return searchWithNode(rootPath, query, options.maxFiles);
14972
+ }
14973
+ throw error;
14974
+ }
14975
+ );
14976
+ return finalizeResults(result, options.maxFiles, options.maxMatchesPerFile);
14977
+ }
14978
+ async function searchWithRipgrep(rootPath, query, maxFiles) {
14979
+ const hasGitignore = existsSync8(join10(rootPath, ".gitignore"));
14980
+ const args = [
14981
+ "--json",
14982
+ "--line-number",
14983
+ "--column",
14984
+ "--fixed-strings",
14985
+ "--sort",
14986
+ "path",
14987
+ "--with-filename",
14988
+ "--glob",
14989
+ "!**/.git/**",
14990
+ "--glob",
14991
+ "!**/node_modules/**"
14992
+ ];
14993
+ if (hasGitignore) {
14994
+ args.push("--hidden");
14995
+ args.push("--no-require-git");
14996
+ }
14997
+ args.push(query, ".");
14998
+ return new Promise((resolve4, reject) => {
14999
+ const child = spawn5("rg", args, { cwd: rootPath, stdio: ["ignore", "pipe", "pipe"] });
15000
+ const stdout = createInterface({ input: child.stdout });
15001
+ const files = /* @__PURE__ */ new Map();
15002
+ let totalMatchCount = 0;
15003
+ let hasMoreFiles = false;
15004
+ let stderr = "";
15005
+ stdout.on("line", (line) => {
15006
+ if (!line.trim()) {
15007
+ return;
15008
+ }
15009
+ const event = JSON.parse(line);
15010
+ if (event.type !== "match") {
15011
+ return;
15012
+ }
15013
+ const rawPath = event.data?.path?.text;
15014
+ if (!rawPath) {
15015
+ return;
15016
+ }
15017
+ const relativePath = normalizeRelativePath(relative2(rootPath, join10(rootPath, rawPath)));
15018
+ const preview = (event.data?.lines?.text ?? "").replace(/\r?\n$/, "");
15019
+ const lineNumber = event.data?.line_number ?? 1;
15020
+ const submatches = event.data?.submatches ?? [];
15021
+ totalMatchCount += submatches.length;
15022
+ if (!files.has(relativePath) && files.size >= maxFiles) {
15023
+ hasMoreFiles = true;
15024
+ return;
15025
+ }
15026
+ for (const submatch of submatches) {
15027
+ pushMatch(files, relativePath, {
15028
+ line: lineNumber,
15029
+ column: byteOffsetToColumn(preview, submatch.start),
15030
+ endColumn: byteOffsetToColumn(preview, submatch.end),
15031
+ preview,
15032
+ previewColumnStart: byteOffsetToColumn(preview, submatch.start),
15033
+ previewColumnEnd: byteOffsetToColumn(preview, submatch.end)
15034
+ });
15035
+ }
15036
+ });
15037
+ child.stderr.on("data", (chunk) => {
15038
+ stderr += chunk.toString();
15039
+ });
15040
+ child.on("error", (error) => {
15041
+ void stdout.close();
15042
+ reject(error);
15043
+ });
15044
+ child.on("close", (code) => {
15045
+ void stdout.close();
15046
+ if (code === 0 || code === 1) {
15047
+ resolve4({
15048
+ files: sortAccumulators(files),
15049
+ totalMatchCount,
15050
+ hasMoreFiles
15051
+ });
15052
+ return;
15053
+ }
15054
+ reject(
15055
+ Object.assign(new Error(stderr || `rg exited with code ${code ?? "unknown"}`), { code })
15056
+ );
15057
+ });
15058
+ });
15059
+ }
15060
+ async function searchWithNode(rootPath, query, maxFiles) {
15061
+ const files = /* @__PURE__ */ new Map();
15062
+ let totalMatchCount = 0;
15063
+ let hasMoreFiles = false;
15064
+ async function walk(dirPath) {
15065
+ const filter = createGitignoreFilter(rootPath, dirPath);
15066
+ const entries = await readdir4(dirPath, { withFileTypes: true });
15067
+ const filteredEntries = entries.filter((entry) => filter(entry.name));
15068
+ filteredEntries.sort((a, b) => a.name.localeCompare(b.name));
15069
+ for (const entry of filteredEntries) {
15070
+ const fullPath = join10(dirPath, entry.name);
15071
+ if (entry.isDirectory()) {
15072
+ await walk(fullPath);
15073
+ continue;
15074
+ }
15075
+ if (!entry.isFile()) {
15076
+ continue;
15077
+ }
15078
+ const fileStat = await stat8(fullPath);
15079
+ if (fileStat.size > FALLBACK_MAX_FILE_BYTES) {
15080
+ continue;
15081
+ }
15082
+ const buffer = await readFile4(fullPath);
15083
+ if (isBinaryFile(buffer)) {
15084
+ continue;
15085
+ }
15086
+ const relativePath = normalizeRelativePath(relative2(rootPath, fullPath));
15087
+ const file = collectMatchesFromText(relativePath, buffer.toString("utf-8"), query);
15088
+ if (!file) {
15089
+ continue;
15090
+ }
15091
+ totalMatchCount += file.matchCount;
15092
+ if (files.size >= maxFiles) {
15093
+ hasMoreFiles = true;
15094
+ continue;
15095
+ }
15096
+ files.set(relativePath, file);
15097
+ }
15098
+ }
15099
+ await walk(rootPath);
15100
+ return {
15101
+ files: sortAccumulators(files),
15102
+ totalMatchCount,
15103
+ hasMoreFiles
15104
+ };
15105
+ }
15106
+ function collectMatchesFromText(relativePath, content, query) {
15107
+ const file = {
15108
+ path: relativePath,
15109
+ name: basename2(relativePath),
15110
+ matches: [],
15111
+ matchCount: 0
15112
+ };
15113
+ const lines = content.split(/\r?\n/);
15114
+ for (let lineIndex = 0; lineIndex < lines.length; lineIndex += 1) {
15115
+ const preview = lines[lineIndex] ?? "";
15116
+ if (!preview) {
15117
+ continue;
15118
+ }
15119
+ let fromIndex = 0;
15120
+ while (fromIndex <= preview.length) {
15121
+ const matchIndex = preview.indexOf(query, fromIndex);
15122
+ if (matchIndex === -1) {
15123
+ break;
15124
+ }
15125
+ const startColumn = matchIndex + 1;
15126
+ const endColumn = startColumn + query.length;
15127
+ file.matches.push({
15128
+ line: lineIndex + 1,
15129
+ column: startColumn,
15130
+ endColumn,
15131
+ preview,
15132
+ previewColumnStart: startColumn,
15133
+ previewColumnEnd: endColumn
15134
+ });
15135
+ file.matchCount += 1;
15136
+ fromIndex = matchIndex + Math.max(query.length, 1);
15137
+ }
15138
+ }
15139
+ return file.matchCount > 0 ? file : null;
15140
+ }
15141
+ function pushMatch(files, relativePath, match) {
15142
+ let file = files.get(relativePath);
15143
+ if (!file) {
15144
+ file = {
15145
+ path: relativePath,
15146
+ name: basename2(relativePath),
15147
+ matches: [],
15148
+ matchCount: 0
15149
+ };
15150
+ files.set(relativePath, file);
15151
+ }
15152
+ file.matches.push(match);
15153
+ file.matchCount += 1;
15154
+ }
15155
+ function sortAccumulators(files) {
15156
+ return Array.from(files.values()).sort((a, b) => a.path.localeCompare(b.path));
15157
+ }
15158
+ function finalizeResults(result, maxFiles, maxMatchesPerFile) {
15159
+ const visibleFiles = result.files.slice(0, maxFiles).map((file) => ({
15160
+ path: file.path,
15161
+ name: file.name,
15162
+ matchCount: file.matchCount,
15163
+ hasMoreMatches: file.matchCount > maxMatchesPerFile,
15164
+ matches: file.matches.slice(0, maxMatchesPerFile)
15165
+ }));
15166
+ return {
15167
+ files: visibleFiles,
15168
+ totalMatchCount: result.totalMatchCount,
15169
+ hasMoreFiles: result.hasMoreFiles || result.files.length > maxFiles,
15170
+ truncatedMatchFileCount: visibleFiles.filter((file) => file.hasMoreMatches).length
15171
+ };
15172
+ }
15173
+ function normalizeRelativePath(path14) {
15174
+ return path14.replace(/\\/g, "/");
15175
+ }
15176
+ function byteOffsetToColumn(preview, byteOffset) {
15177
+ return Buffer.from(preview, "utf8").subarray(0, byteOffset).toString("utf8").length + 1;
15178
+ }
15179
+ function isBinaryFile(buffer) {
15180
+ const sample = buffer.subarray(0, 8e3);
15181
+ return sample.includes(0);
15182
+ }
15183
+ var FALLBACK_MAX_FILE_BYTES;
15184
+ var init_content_search = __esm({
15185
+ "packages/server/src/fs/content-search.ts"() {
15186
+ "use strict";
15187
+ init_gitignore();
15188
+ FALLBACK_MAX_FILE_BYTES = 1e6;
15189
+ }
15190
+ });
15191
+
14897
15192
  // packages/server/src/fs/tree.ts
14898
- import { readdir as readdir4, stat as stat8 } from "fs/promises";
14899
- import { join as join10, relative as relative2 } from "path";
15193
+ import { readdir as readdir5, stat as stat9 } from "fs/promises";
15194
+ import { join as join11, relative as relative3 } from "path";
14900
15195
  async function readTree(rootPath, subdir) {
14901
- const targetPath = subdir ? join10(rootPath, subdir) : rootPath;
15196
+ const targetPath = subdir ? join11(rootPath, subdir) : rootPath;
14902
15197
  const filter = createTreeVisibilityFilter();
14903
- const entries = await readdir4(targetPath, { withFileTypes: true });
15198
+ const entries = await readdir5(targetPath, { withFileTypes: true });
14904
15199
  const nodes = [];
14905
15200
  for (const entry of entries) {
14906
15201
  if (!filter(entry.name)) {
14907
15202
  continue;
14908
15203
  }
14909
- const fullPath = join10(targetPath, entry.name);
14910
- const relPath = relative2(rootPath, fullPath);
15204
+ const fullPath = join11(targetPath, entry.name);
15205
+ const relPath = relative3(rootPath, fullPath);
14911
15206
  if (entry.isDirectory()) {
14912
15207
  nodes.push({
14913
15208
  name: entry.name,
@@ -14917,7 +15212,7 @@ async function readTree(rootPath, subdir) {
14917
15212
  // Not loaded yet - client will request on expand
14918
15213
  });
14919
15214
  } else if (entry.isFile()) {
14920
- const stats = await stat8(fullPath);
15215
+ const stats = await stat9(fullPath);
14921
15216
  nodes.push({
14922
15217
  name: entry.name,
14923
15218
  path: relPath,
@@ -14946,18 +15241,18 @@ async function searchFiles(rootPath, query, limit = 10) {
14946
15241
  const matches = [];
14947
15242
  async function walk(dirPath) {
14948
15243
  const filter = createGitignoreFilter(rootPath, dirPath);
14949
- const entries = await readdir4(dirPath, { withFileTypes: true });
15244
+ const entries = await readdir5(dirPath, { withFileTypes: true });
14950
15245
  const filteredEntries = entries.filter((entry) => filter(entry.name));
14951
15246
  filteredEntries.sort((a, b) => a.name.localeCompare(b.name));
14952
15247
  for (const entry of filteredEntries) {
14953
- const fullPath = join10(dirPath, entry.name);
14954
- const relPath = relative2(rootPath, fullPath);
15248
+ const fullPath = join11(dirPath, entry.name);
15249
+ const relPath = relative3(rootPath, fullPath);
14955
15250
  if (entry.isDirectory()) {
14956
15251
  await walk(fullPath);
14957
15252
  continue;
14958
15253
  }
14959
15254
  if (entry.isFile()) {
14960
- const rank = scoreFilenameMatch(entry.name, normalizedQuery);
15255
+ const rank = scoreFileMatch(relPath, entry.name, normalizedQuery);
14961
15256
  if (rank === null) {
14962
15257
  continue;
14963
15258
  }
@@ -14986,7 +15281,7 @@ async function searchFiles(rootPath, query, limit = 10) {
14986
15281
  }
14987
15282
  return a.path.toLowerCase().localeCompare(b.path.toLowerCase());
14988
15283
  }).slice(0, limit)) {
14989
- const stats = await stat8(match.fullPath);
15284
+ const stats = await stat9(match.fullPath);
14990
15285
  files.push({
14991
15286
  name: match.name,
14992
15287
  path: match.path,
@@ -14997,6 +15292,13 @@ async function searchFiles(rootPath, query, limit = 10) {
14997
15292
  }
14998
15293
  return { files };
14999
15294
  }
15295
+ function scoreFileMatch(path14, name, query) {
15296
+ const filenameRank = scoreFilenameMatch(name, query);
15297
+ if (filenameRank !== null) {
15298
+ return filenameRank;
15299
+ }
15300
+ return scorePathMatch(path14, query);
15301
+ }
15000
15302
  function scoreFilenameMatch(name, query) {
15001
15303
  const normalizedName = name.toLowerCase();
15002
15304
  const baseName = normalizedName.replace(/\.[^.]+$/, "");
@@ -15023,6 +15325,22 @@ function scoreFilenameMatch(name, query) {
15023
15325
  }
15024
15326
  return null;
15025
15327
  }
15328
+ function scorePathMatch(path14, query) {
15329
+ const normalizedPath = path14.toLowerCase();
15330
+ if (normalizedPath === query) {
15331
+ return 7;
15332
+ }
15333
+ if (normalizedPath.startsWith(query)) {
15334
+ return 8;
15335
+ }
15336
+ if (normalizedPath.includes(query)) {
15337
+ return 9;
15338
+ }
15339
+ if (isSubsequence(query, normalizedPath)) {
15340
+ return 10;
15341
+ }
15342
+ return null;
15343
+ }
15026
15344
  function isSubsequence(query, candidate) {
15027
15345
  let index = 0;
15028
15346
  for (const char of candidate) {
@@ -15047,6 +15365,7 @@ import { z as z13 } from "zod";
15047
15365
  var init_file = __esm({
15048
15366
  "packages/server/src/commands/file.ts"() {
15049
15367
  "use strict";
15368
+ init_content_search();
15050
15369
  init_file_io();
15051
15370
  init_tree();
15052
15371
  init_dispatch();
@@ -15079,6 +15398,26 @@ var init_file = __esm({
15079
15398
  return searchFiles(workspace.path, args.query, args.limit ?? 10);
15080
15399
  }
15081
15400
  );
15401
+ registerCommand(
15402
+ "file.searchContent",
15403
+ z13.object({
15404
+ workspaceId: z13.string(),
15405
+ query: z13.string(),
15406
+ maxFiles: z13.number().int().positive().max(100),
15407
+ maxMatchesPerFile: z13.number().int().positive().max(100)
15408
+ }),
15409
+ async (args, ctx) => {
15410
+ const workspace = ctx.workspaceMgr.get(args.workspaceId);
15411
+ if (!workspace) {
15412
+ throw { code: "workspace_not_found", message: `Workspace not found: ${args.workspaceId}` };
15413
+ }
15414
+ return searchFileContents(workspace.path, {
15415
+ query: args.query,
15416
+ maxFiles: args.maxFiles,
15417
+ maxMatchesPerFile: args.maxMatchesPerFile
15418
+ });
15419
+ }
15420
+ );
15082
15421
  registerCommand(
15083
15422
  "file.read",
15084
15423
  z13.object({
@@ -15201,7 +15540,7 @@ var init_file = __esm({
15201
15540
  });
15202
15541
 
15203
15542
  // packages/server/src/git/diff.ts
15204
- import { mkdtemp as mkdtemp3, readFile as readFile4, rm as rm6 } from "fs/promises";
15543
+ import { mkdtemp as mkdtemp3, readFile as readFile5, rm as rm6 } from "fs/promises";
15205
15544
  import os3 from "os";
15206
15545
  import path11 from "path";
15207
15546
  async function isTrackedPath(cwd, filePath) {
@@ -15241,7 +15580,7 @@ async function getUntrackedFileDiff(cwd, filePath) {
15241
15580
  }
15242
15581
  async function pathExists(cwd, filePath) {
15243
15582
  try {
15244
- await readFile4(resolveSafe(cwd, filePath));
15583
+ await readFile5(resolveSafe(cwd, filePath));
15245
15584
  return true;
15246
15585
  } catch {
15247
15586
  return false;
@@ -15249,7 +15588,7 @@ async function pathExists(cwd, filePath) {
15249
15588
  }
15250
15589
  async function readTextAtRevision(cwd, revision, filePath) {
15251
15590
  if (revision === "WORKTREE") {
15252
- return readFile4(resolveSafe(cwd, filePath), "utf-8");
15591
+ return readFile5(resolveSafe(cwd, filePath), "utf-8");
15253
15592
  }
15254
15593
  try {
15255
15594
  const gitSpec = revision === "INDEX" ? `:${filePath}` : `${revision}:${filePath}`;
@@ -15667,33 +16006,33 @@ var init_git2 = __esm({
15667
16006
  });
15668
16007
 
15669
16008
  // packages/server/src/config/config-io.ts
15670
- import { existsSync as existsSync8, mkdirSync as mkdirSync7, readFileSync as readFileSync7, renameSync as renameSync2, writeFileSync as writeFileSync5 } from "node:fs";
16009
+ import { existsSync as existsSync9, mkdirSync as mkdirSync7, readFileSync as readFileSync7, renameSync as renameSync2, writeFileSync as writeFileSync5 } from "node:fs";
15671
16010
  import { homedir as homedir3 } from "node:os";
15672
- import { basename as basename2, dirname as dirname7, join as join11 } from "node:path";
16011
+ import { basename as basename3, dirname as dirname7, join as join12 } from "node:path";
15673
16012
  function resolveConfigPath(configType) {
15674
16013
  if (configType === "codex") {
15675
16014
  const testHome = process.env.CODER_STUDIO_CODEX_HOME;
15676
16015
  if (testHome && testHome.trim()) {
15677
- return join11(testHome, "config.toml");
16016
+ return join12(testHome, "config.toml");
15678
16017
  }
15679
16018
  const codexHome = process.env.CODEX_HOME;
15680
16019
  if (codexHome && codexHome.trim()) {
15681
- return join11(codexHome, "config.toml");
16020
+ return join12(codexHome, "config.toml");
15682
16021
  }
15683
- return join11(homedir3(), ".codex", "config.toml");
16022
+ return join12(homedir3(), ".codex", "config.toml");
15684
16023
  }
15685
16024
  if (configType === "claude") {
15686
16025
  const testHome = process.env.CODER_STUDIO_CLAUDE_HOME;
15687
16026
  if (testHome && testHome.trim()) {
15688
- return join11(testHome, "settings.json");
16027
+ return join12(testHome, "settings.json");
15689
16028
  }
15690
- return join11(homedir3(), ".claude", "settings.json");
16029
+ return join12(homedir3(), ".claude", "settings.json");
15691
16030
  }
15692
16031
  throw new Error(`Unknown config type: ${configType}`);
15693
16032
  }
15694
16033
  function readConfigFile(configType) {
15695
16034
  const configPath = resolveConfigPath(configType);
15696
- if (!existsSync8(configPath)) {
16035
+ if (!existsSync9(configPath)) {
15697
16036
  return { configPath, content: "", exists: false };
15698
16037
  }
15699
16038
  try {
@@ -15707,11 +16046,11 @@ function writeConfigFile(configType, content) {
15707
16046
  try {
15708
16047
  const configPath = resolveConfigPath(configType);
15709
16048
  const parentDir = dirname7(configPath);
15710
- if (!existsSync8(parentDir)) {
16049
+ if (!existsSync9(parentDir)) {
15711
16050
  mkdirSync7(parentDir, { recursive: true });
15712
16051
  }
15713
16052
  let backupPath = null;
15714
- if (existsSync8(configPath)) {
16053
+ if (existsSync9(configPath)) {
15715
16054
  backupPath = createBackup(configPath);
15716
16055
  }
15717
16056
  const tempPath = `${configPath}.tmp`;
@@ -15729,10 +16068,10 @@ function writeConfigFile(configType, content) {
15729
16068
  function createBackup(filePath) {
15730
16069
  const original = readFileSync7(filePath, "utf-8");
15731
16070
  const ext = filePath.split(".").pop() ?? "";
15732
- const base = basename2(filePath, `.${ext}`);
16071
+ const base = basename3(filePath, `.${ext}`);
15733
16072
  const dir = dirname7(filePath);
15734
16073
  const ts = formatTimestamp(/* @__PURE__ */ new Date());
15735
- const backupPath = join11(dir, `${base}.bak.${ts}.${ext}`);
16074
+ const backupPath = join12(dir, `${base}.bak.${ts}.${ext}`);
15736
16075
  writeFileSync5(backupPath, original, "utf-8");
15737
16076
  return backupPath;
15738
16077
  }
@@ -17092,12 +17431,12 @@ var init_commands = __esm({
17092
17431
  // packages/server/src/server.ts
17093
17432
  import { mkdtempSync, rmSync as rmSync2 } from "node:fs";
17094
17433
  import { tmpdir } from "node:os";
17095
- import { join as join12 } from "node:path";
17434
+ import { join as join13 } from "node:path";
17096
17435
  async function createServer(configOverrides) {
17097
17436
  const config = parseServerConfig(configOverrides);
17098
17437
  const configuredStateDir = resolveConfiguredStateDir(config);
17099
17438
  const shouldCleanupStateRoot = configuredStateDir === IN_MEMORY_STATE_DIR;
17100
- const stateRoot = shouldCleanupStateRoot ? mkdtempSync(join12(tmpdir(), "coder-studio-state-")) : configuredStateDir;
17439
+ const stateRoot = shouldCleanupStateRoot ? mkdtempSync(join13(tmpdir(), "coder-studio-state-")) : configuredStateDir;
17101
17440
  ensureStateDir(config);
17102
17441
  const eventBus = new EventBus();
17103
17442
  const activationMgr = new ActivationManager();
@@ -17107,10 +17446,10 @@ async function createServer(configOverrides) {
17107
17446
  let commandContext;
17108
17447
  let lspMgr = null;
17109
17448
  const terminalRepo = new TerminalRepo({
17110
- filePath: join12(stateRoot, "state", "terminals.json")
17449
+ filePath: join13(stateRoot, "state", "terminals.json")
17111
17450
  });
17112
17451
  const sessionRepo = new SessionRepo({
17113
- filePath: join12(stateRoot, "state", "sessions.json")
17452
+ filePath: join13(stateRoot, "state", "sessions.json")
17114
17453
  });
17115
17454
  const terminalMgr = new TerminalManager({
17116
17455
  ptyHost: createPtyHost(),
@@ -17118,10 +17457,10 @@ async function createServer(configOverrides) {
17118
17457
  db: terminalRepo
17119
17458
  });
17120
17459
  const settingsRepo = new SettingsRepo({
17121
- filePath: join12(stateRoot, "state", "settings.json")
17460
+ filePath: join13(stateRoot, "state", "settings.json")
17122
17461
  });
17123
17462
  const updateStateRepo = new UpdateStateRepo({
17124
- filePath: join12(stateRoot, "state", "update-state.json"),
17463
+ filePath: join13(stateRoot, "state", "update-state.json"),
17125
17464
  currentVersion: config.appVersion ?? "0.0.0"
17126
17465
  });
17127
17466
  const autoFetch = new AutoFetchScheduler({
@@ -17154,10 +17493,10 @@ async function createServer(configOverrides) {
17154
17493
  }
17155
17494
  });
17156
17495
  const providerConfigRepo = new ProviderConfigRepo({
17157
- filePath: join12(stateRoot, "state", "provider-configs.json")
17496
+ filePath: join13(stateRoot, "state", "provider-configs.json")
17158
17497
  });
17159
17498
  const workspaceRepo = new WorkspaceRepo({
17160
- filePath: join12(stateRoot, "state", "workspaces.json")
17499
+ filePath: join13(stateRoot, "state", "workspaces.json")
17161
17500
  });
17162
17501
  const sessionMgr = new SessionManager({
17163
17502
  terminalMgr,
@@ -17192,10 +17531,10 @@ async function createServer(configOverrides) {
17192
17531
  )
17193
17532
  });
17194
17533
  const authSessionRepo = new AuthSessionRepo({
17195
- filePath: join12(stateRoot, "state", "auth-sessions.json")
17534
+ filePath: join13(stateRoot, "state", "auth-sessions.json")
17196
17535
  });
17197
17536
  const authLoginBlockRepo = new AuthLoginBlockRepo({
17198
- filePath: join12(stateRoot, "state", "auth-login-blocks.json")
17537
+ filePath: join13(stateRoot, "state", "auth-login-blocks.json")
17199
17538
  });
17200
17539
  const app = await buildFastifyApp({
17201
17540
  wsHub,
@@ -17270,7 +17609,7 @@ async function createServer(configOverrides) {
17270
17609
  ...config.update,
17271
17610
  currentVersion: config.appVersion ?? "0.0.0"
17272
17611
  },
17273
- updateWorkerLogFilePath: join12(stateRoot, "logs", "update-worker.log"),
17612
+ updateWorkerLogFilePath: join13(stateRoot, "logs", "update-worker.log"),
17274
17613
  countRunningTerminals: () => terminalMgr.getAll().filter((terminal) => terminal.alive).length,
17275
17614
  countRunningSessions: () => sessionMgr.getAll().filter((session) => session.state === "starting" || session.state === "running").length,
17276
17615
  countActiveSupervisors: () => supervisorMgr?.countActive() ?? 0
@@ -17492,28 +17831,28 @@ var init_src4 = __esm({
17492
17831
  });
17493
17832
 
17494
17833
  // packages/cli/src/cli.ts
17495
- import { existsSync as existsSync14 } from "fs";
17496
- import { dirname as dirname10, join as join17 } from "path";
17834
+ import { existsSync as existsSync15 } from "fs";
17835
+ import { dirname as dirname10, join as join18 } from "path";
17497
17836
  import { fileURLToPath as fileURLToPath5 } from "url";
17498
17837
 
17499
17838
  // packages/cli/src/auth-control.ts
17500
17839
  await init_src4();
17501
- import { join as join14 } from "node:path";
17840
+ import { join as join15 } from "node:path";
17502
17841
 
17503
17842
  // packages/cli/src/config-store.ts
17504
17843
  init_state_paths();
17505
- import { existsSync as existsSync9, mkdirSync as mkdirSync8, readFileSync as readFileSync8, writeFileSync as writeFileSync6 } from "fs";
17844
+ import { existsSync as existsSync10, mkdirSync as mkdirSync8, readFileSync as readFileSync8, writeFileSync as writeFileSync6 } from "fs";
17506
17845
  import { homedir as homedir4 } from "os";
17507
- import { join as join13 } from "path";
17846
+ import { join as join14 } from "path";
17508
17847
  function getCliConfigPath() {
17509
- return join13(homedir4(), ".coder-studio", "config.json");
17848
+ return join14(homedir4(), ".coder-studio", "config.json");
17510
17849
  }
17511
17850
  function normalizeLegacyDataDir(input2) {
17512
17851
  return normalizeLegacyStateDir(input2);
17513
17852
  }
17514
17853
  function readCliConfig() {
17515
17854
  const path14 = getCliConfigPath();
17516
- if (!existsSync9(path14)) {
17855
+ if (!existsSync10(path14)) {
17517
17856
  return null;
17518
17857
  }
17519
17858
  try {
@@ -17533,14 +17872,14 @@ function readCliConfig() {
17533
17872
  }
17534
17873
  function writeCliConfig(config) {
17535
17874
  const path14 = getCliConfigPath();
17536
- const dir = join13(homedir4(), ".coder-studio");
17875
+ const dir = join14(homedir4(), ".coder-studio");
17537
17876
  const normalizedConfig = {
17538
17877
  ...config.host !== void 0 ? { host: config.host } : {},
17539
17878
  ...config.port !== void 0 && config.port > 0 ? { port: config.port } : {},
17540
17879
  ...config.stateDir !== void 0 ? { stateDir: normalizeStateDir(config.stateDir) } : {},
17541
17880
  ...config.password !== void 0 ? { password: config.password } : {}
17542
17881
  };
17543
- if (!existsSync9(dir)) {
17882
+ if (!existsSync10(dir)) {
17544
17883
  mkdirSync8(dir, { recursive: true });
17545
17884
  }
17546
17885
  writeFileSync6(path14, JSON.stringify(normalizedConfig, null, 2), "utf-8");
@@ -17555,7 +17894,7 @@ function resolveStateDir() {
17555
17894
  }
17556
17895
  async function listAuthBlocks(now = Date.now()) {
17557
17896
  const repo = new AuthLoginBlockRepo({
17558
- filePath: join14(resolveStateDir(), "state", "auth-login-blocks.json")
17897
+ filePath: join15(resolveStateDir(), "state", "auth-login-blocks.json")
17559
17898
  });
17560
17899
  return repo.listActiveBlocks(now).map((record) => ({
17561
17900
  ip: record.ip,
@@ -17567,13 +17906,13 @@ async function listAuthBlocks(now = Date.now()) {
17567
17906
  }
17568
17907
  async function clearAuthBlockByIp(ip) {
17569
17908
  const repo = new AuthLoginBlockRepo({
17570
- filePath: join14(resolveStateDir(), "state", "auth-login-blocks.json")
17909
+ filePath: join15(resolveStateDir(), "state", "auth-login-blocks.json")
17571
17910
  });
17572
17911
  return repo.delete(ip);
17573
17912
  }
17574
17913
 
17575
17914
  // packages/cli/src/browser.ts
17576
- import { spawn as spawn5 } from "node:child_process";
17915
+ import { spawn as spawn6 } from "node:child_process";
17577
17916
  function getOpenCommand(url) {
17578
17917
  switch (process.platform) {
17579
17918
  case "darwin":
@@ -17587,7 +17926,7 @@ function getOpenCommand(url) {
17587
17926
  async function openBrowser(url) {
17588
17927
  const { command, args } = getOpenCommand(url);
17589
17928
  await new Promise((resolve4, reject) => {
17590
- const child = spawn5(command, args, {
17929
+ const child = spawn6(command, args, {
17591
17930
  detached: true,
17592
17931
  stdio: "ignore",
17593
17932
  windowsHide: true
@@ -17601,12 +17940,12 @@ async function openBrowser(url) {
17601
17940
  }
17602
17941
 
17603
17942
  // packages/cli/src/log-excerpt.ts
17604
- import { closeSync, existsSync as existsSync10, openSync, readSync, statSync as statSync2 } from "fs";
17943
+ import { closeSync, existsSync as existsSync11, openSync, readSync, statSync as statSync2 } from "fs";
17605
17944
  var DEFAULT_MAX_LINES = 40;
17606
17945
  var DEFAULT_MAX_CHARS = 4e3;
17607
17946
  var DEFAULT_MAX_BYTES = 16 * 1024;
17608
17947
  var getFileSize = (path14) => {
17609
- if (!existsSync10(path14)) {
17948
+ if (!existsSync11(path14)) {
17610
17949
  return 0;
17611
17950
  }
17612
17951
  try {
@@ -17621,7 +17960,7 @@ var readLogExcerpt = (path14, {
17621
17960
  maxLines = DEFAULT_MAX_LINES,
17622
17961
  maxChars = DEFAULT_MAX_CHARS
17623
17962
  } = {}) => {
17624
- if (!existsSync10(path14)) {
17963
+ if (!existsSync11(path14)) {
17625
17964
  return null;
17626
17965
  }
17627
17966
  const fileSize = getFileSize(path14);
@@ -17700,12 +18039,12 @@ function assertSupportedNodeVersion(version = process.versions.node) {
17700
18039
  }
17701
18040
 
17702
18041
  // packages/cli/src/package-manifest.ts
17703
- import { existsSync as existsSync11, readFileSync as readFileSync9 } from "fs";
18042
+ import { existsSync as existsSync12, readFileSync as readFileSync9 } from "fs";
17704
18043
  function resolveCliPackageManifestUrl(importMetaUrl) {
17705
18044
  const manifestUrl = [
17706
18045
  new URL("../package.json", importMetaUrl),
17707
18046
  new URL("../../package.json", importMetaUrl)
17708
- ].find((candidate) => existsSync11(candidate));
18047
+ ].find((candidate) => existsSync12(candidate));
17709
18048
  if (!manifestUrl) {
17710
18049
  throw new Error("Unable to locate CLI package.json");
17711
18050
  }
@@ -17928,7 +18267,7 @@ function parseArgs(argv) {
17928
18267
  init_runtime();
17929
18268
  import { mkdirSync as mkdirSync9 } from "fs";
17930
18269
  import { homedir as homedir5 } from "os";
17931
- import { join as join15 } from "path";
18270
+ import { join as join16 } from "path";
17932
18271
  var MANAGED_SERVER_NAME = "coder-studio-server";
17933
18272
  var PM2_RESTART_DELAY_MS = 2e3;
17934
18273
  var PM2_MIN_UPTIME = "5s";
@@ -18099,6 +18438,28 @@ var waitForManagedServerDeletion = async (pm2, waitMs) => {
18099
18438
  }
18100
18439
  throw new Error(`Timed out waiting for the managed server to stop after ${waitMs}ms.`);
18101
18440
  };
18441
+ var isMissingProcessError = (error) => Boolean(
18442
+ error && typeof error === "object" && "code" in error && error.code === "ESRCH"
18443
+ );
18444
+ var waitForProcessExit = async (pid, waitMs) => {
18445
+ const deadline = Date.now() + waitMs;
18446
+ while (Date.now() <= deadline) {
18447
+ try {
18448
+ process.kill(pid, 0);
18449
+ } catch (error) {
18450
+ if (isMissingProcessError(error)) {
18451
+ return;
18452
+ }
18453
+ throw error;
18454
+ }
18455
+ const remainingMs = deadline - Date.now();
18456
+ if (remainingMs <= 0) {
18457
+ break;
18458
+ }
18459
+ await sleep(Math.min(STARTUP_POLL_INTERVAL_MS, remainingMs));
18460
+ }
18461
+ throw new Error(`Timed out waiting for the managed server pid ${pid} to exit after ${waitMs}ms.`);
18462
+ };
18102
18463
  var deleteManagedServerInSession = async (pm2, {
18103
18464
  ignoreMissing = false
18104
18465
  } = {}) => {
@@ -18106,24 +18467,32 @@ var deleteManagedServerInSession = async (pm2, {
18106
18467
  if (processes.length === 0) {
18107
18468
  return false;
18108
18469
  }
18470
+ const previousPid = processes[0]?.pid;
18471
+ const deadline = Date.now() + PM2_DELETE_WAIT_MS;
18109
18472
  try {
18110
18473
  await removeManagedServer(pm2);
18111
18474
  } catch (error) {
18112
18475
  if (ignoreMissing && isMissingManagedServerError(error)) {
18113
- await waitForManagedServerDeletion(pm2, PM2_DELETE_WAIT_MS);
18476
+ await waitForManagedServerDeletion(pm2, Math.max(0, deadline - Date.now()));
18477
+ if (typeof previousPid === "number" && previousPid > 0) {
18478
+ await waitForProcessExit(previousPid, Math.max(0, deadline - Date.now()));
18479
+ }
18114
18480
  return false;
18115
18481
  }
18116
18482
  throw error;
18117
18483
  }
18118
- await waitForManagedServerDeletion(pm2, PM2_DELETE_WAIT_MS);
18484
+ await waitForManagedServerDeletion(pm2, Math.max(0, deadline - Date.now()));
18485
+ if (typeof previousPid === "number" && previousPid > 0) {
18486
+ await waitForProcessExit(previousPid, Math.max(0, deadline - Date.now()));
18487
+ }
18119
18488
  return true;
18120
18489
  };
18121
18490
  var ensureLogDirectory = () => {
18122
- mkdirSync9(join15(homedir5(), ".coder-studio", "logs"), { recursive: true });
18491
+ mkdirSync9(join16(homedir5(), ".coder-studio", "logs"), { recursive: true });
18123
18492
  };
18124
18493
  var getLogPaths = () => ({
18125
- outFile: join15(homedir5(), ".coder-studio", "logs", "server.out.log"),
18126
- errFile: join15(homedir5(), ".coder-studio", "logs", "server.err.log")
18494
+ outFile: join16(homedir5(), ".coder-studio", "logs", "server.out.log"),
18495
+ errFile: join16(homedir5(), ".coder-studio", "logs", "server.err.log")
18127
18496
  });
18128
18497
  var captureStartupLogOffsets = () => {
18129
18498
  const { outFile, errFile } = getLogPaths();
@@ -18251,12 +18620,12 @@ var getManagedServerStatus = async () => withPm2Connection(async (pm2) => {
18251
18620
 
18252
18621
  // packages/cli/src/prompts.ts
18253
18622
  import { stdin as input, stdout as output } from "node:process";
18254
- import { createInterface } from "node:readline/promises";
18623
+ import { createInterface as createInterface2 } from "node:readline/promises";
18255
18624
  function isInteractiveSession() {
18256
18625
  return Boolean(input.isTTY && output.isTTY);
18257
18626
  }
18258
18627
  async function confirmYesNo(prompt) {
18259
- const rl = createInterface({ input, output });
18628
+ const rl = createInterface2({ input, output });
18260
18629
  try {
18261
18630
  const answer = (await rl.question(prompt)).trim().toLowerCase();
18262
18631
  return answer === "y" || answer === "yes";
@@ -18311,7 +18680,7 @@ import { mkdirSync as mkdirSync10 } from "fs";
18311
18680
  import { fileURLToPath as fileURLToPath4 } from "url";
18312
18681
 
18313
18682
  // packages/cli/src/embed.ts
18314
- import { existsSync as existsSync12 } from "fs";
18683
+ import { existsSync as existsSync13 } from "fs";
18315
18684
  import { dirname as dirname8, resolve as resolve3 } from "path";
18316
18685
  import { fileURLToPath as fileURLToPath2 } from "url";
18317
18686
  var __filename = fileURLToPath2(import.meta.url);
@@ -18321,20 +18690,20 @@ function getStaticAssetsDir() {
18321
18690
  return WEB_ASSETS_DIR;
18322
18691
  }
18323
18692
  function hasWebAssets() {
18324
- return existsSync12(WEB_ASSETS_DIR);
18693
+ return existsSync13(WEB_ASSETS_DIR);
18325
18694
  }
18326
18695
 
18327
18696
  // packages/cli/src/update-runtime.ts
18328
- import { existsSync as existsSync13 } from "node:fs";
18329
- import { dirname as dirname9, join as join16 } from "node:path";
18697
+ import { existsSync as existsSync14 } from "node:fs";
18698
+ import { dirname as dirname9, join as join17 } from "node:path";
18330
18699
  import { fileURLToPath as fileURLToPath3 } from "node:url";
18331
18700
  function resolveWorkerEntryPath(importMetaUrl) {
18332
18701
  const currentDir = dirname9(fileURLToPath3(importMetaUrl));
18333
18702
  const candidates = [
18334
- join16(currentDir, "update-worker.mjs"),
18335
- join16(currentDir, "../src/update-worker.ts")
18703
+ join17(currentDir, "update-worker.mjs"),
18704
+ join17(currentDir, "../src/update-worker.ts")
18336
18705
  ];
18337
- return candidates.find((candidate) => existsSync13(candidate));
18706
+ return candidates.find((candidate) => existsSync14(candidate));
18338
18707
  }
18339
18708
  function getUpdateRuntimeInfo(importMetaUrl) {
18340
18709
  const workerEntryPath = resolveWorkerEntryPath(importMetaUrl);
@@ -18561,11 +18930,11 @@ function resolveManagedScriptPath() {
18561
18930
  const currentFile = fileURLToPath5(import.meta.url);
18562
18931
  const currentDir = dirname10(currentFile);
18563
18932
  const candidates = [
18564
- join17(currentDir, "server-runner.js"),
18565
- join17(currentDir, "server-runner.mjs"),
18566
- join17(currentDir, "../src/server-runner.ts")
18933
+ join18(currentDir, "server-runner.js"),
18934
+ join18(currentDir, "server-runner.mjs"),
18935
+ join18(currentDir, "../src/server-runner.ts")
18567
18936
  ];
18568
- const scriptPath = candidates.find((candidate) => existsSync14(candidate));
18937
+ const scriptPath = candidates.find((candidate) => existsSync15(candidate));
18569
18938
  if (!scriptPath) {
18570
18939
  throw new Error("Unable to locate the managed server entry script");
18571
18940
  }