@spencer-kit/coder-studio 0.3.3 → 0.3.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.
@@ -863,11 +863,11 @@ function resolveSpawnArgv(argv, deps = {}) {
863
863
  return [];
864
864
  }
865
865
  const restArgs = argv.slice(1);
866
- const readFileSync8 = deps.readFileSync ?? ((file) => fs2.readFileSync(file, "utf8"));
867
- const existsSync9 = deps.existsSync ?? fs2.existsSync;
866
+ const readFileSync9 = deps.readFileSync ?? ((file) => fs2.readFileSync(file, "utf8"));
867
+ const existsSync10 = deps.existsSync ?? fs2.existsSync;
868
868
  const pathEnv = deps.pathEnv ?? process.env.Path ?? process.env.PATH ?? "";
869
869
  const pathExt = deps.pathExt ?? process.env.PATHEXT ?? DEFAULT_PATHEXT;
870
- const resolved = resolveExecutablePath(command, pathEnv, pathExt, existsSync9);
870
+ const resolved = resolveExecutablePath(command, pathEnv, pathExt, existsSync10);
871
871
  if (!resolved) {
872
872
  return [...argv];
873
873
  }
@@ -878,7 +878,7 @@ function resolveSpawnArgv(argv, deps = {}) {
878
878
  if (ext === ".cmd" || ext === ".bat") {
879
879
  let content;
880
880
  try {
881
- content = readFileSync8(resolved);
881
+ content = readFileSync9(resolved);
882
882
  } catch {
883
883
  return ["cmd.exe", "/d", "/s", "/c", resolved, ...restArgs];
884
884
  }
@@ -916,17 +916,17 @@ function expandShimVars(value, dp0Dir) {
916
916
  function parsePathExt(pathExt) {
917
917
  return pathExt.split(";").map((entry) => entry.trim().toLowerCase()).filter((entry) => entry.length > 0);
918
918
  }
919
- function resolveExecutablePath(command, pathEnv, pathExt, existsSync9) {
919
+ function resolveExecutablePath(command, pathEnv, pathExt, existsSync10) {
920
920
  const hasExt = path2.win32.extname(command).length > 0;
921
921
  const extensions = parsePathExt(pathExt);
922
922
  if (path2.win32.isAbsolute(command)) {
923
- if (existsSync9(command)) {
923
+ if (existsSync10(command)) {
924
924
  return command;
925
925
  }
926
926
  if (!hasExt) {
927
927
  for (const ext of extensions) {
928
928
  const candidate = command + ext;
929
- if (existsSync9(candidate)) {
929
+ if (existsSync10(candidate)) {
930
930
  return candidate;
931
931
  }
932
932
  }
@@ -937,14 +937,14 @@ function resolveExecutablePath(command, pathEnv, pathExt, existsSync9) {
937
937
  for (const dir of dirs) {
938
938
  if (hasExt) {
939
939
  const candidate = path2.win32.join(dir, command);
940
- if (existsSync9(candidate)) {
940
+ if (existsSync10(candidate)) {
941
941
  return candidate;
942
942
  }
943
943
  continue;
944
944
  }
945
945
  for (const ext of extensions) {
946
946
  const candidate = path2.win32.join(dir, command + ext);
947
- if (existsSync9(candidate)) {
947
+ if (existsSync10(candidate)) {
948
948
  return candidate;
949
949
  }
950
950
  }
@@ -2107,6 +2107,157 @@ var init_command_check = __esm({
2107
2107
  }
2108
2108
  });
2109
2109
 
2110
+ // packages/server/src/provider-runtime/e2e-provider-mock.ts
2111
+ import { chmodSync, existsSync as existsSync6, mkdirSync as mkdirSync3, readFileSync as readFileSync5, writeFileSync as writeFileSync3 } from "node:fs";
2112
+ import { dirname as dirname4, join as join3 } from "node:path";
2113
+ function createE2EProviderMockOverrides(env = process.env) {
2114
+ const statePath = env.CODER_STUDIO_E2E_PROVIDER_STATE_PATH;
2115
+ if (!statePath) {
2116
+ return null;
2117
+ }
2118
+ const binDir = env.CODER_STUDIO_E2E_PROVIDER_BIN_DIR;
2119
+ const debugLogPath = env.CODER_STUDIO_E2E_PROVIDER_DEBUG_LOG_PATH;
2120
+ appendDebugLog(debugLogPath, `init statePath=${statePath} binDir=${binDir ?? ""}`);
2121
+ const commandExists = async (command) => {
2122
+ const state = readMockState(statePath);
2123
+ const override = state.commands?.[command];
2124
+ appendDebugLog(
2125
+ debugLogPath,
2126
+ `commandExists ${command} override=${String(override)} state=${JSON.stringify(state.commands ?? {})}`
2127
+ );
2128
+ if (typeof override === "boolean") {
2129
+ return override;
2130
+ }
2131
+ return checkCommandAvailable(command);
2132
+ };
2133
+ const runCommand2 = async (file, args, options) => {
2134
+ const providerId = getInstallProviderId(file, args);
2135
+ appendDebugLog(
2136
+ debugLogPath,
2137
+ `runCommand ${file} ${args.join(" ")} provider=${providerId ?? "none"}`
2138
+ );
2139
+ if (!providerId) {
2140
+ return runCommandAsString(file, args, options);
2141
+ }
2142
+ const state = readMockState(statePath);
2143
+ const behavior = state.installBehavior?.[providerId];
2144
+ appendDebugLog(
2145
+ debugLogPath,
2146
+ `behavior ${providerId} ${JSON.stringify(behavior)} state=${JSON.stringify(state)}`
2147
+ );
2148
+ if (!behavior) {
2149
+ return runCommandAsString(file, args, options);
2150
+ }
2151
+ if (behavior.result === "success") {
2152
+ writeMockState(statePath, (draft) => {
2153
+ draft.commands ??= {};
2154
+ draft.commands[providerId] = true;
2155
+ });
2156
+ if (binDir) {
2157
+ ensureProviderCommand(binDir, providerId);
2158
+ }
2159
+ appendDebugLog(debugLogPath, `install success ${providerId}`);
2160
+ return {
2161
+ stdout: `installed ${providerId}`,
2162
+ stderr: ""
2163
+ };
2164
+ }
2165
+ const message = behavior.message ?? (behavior.result === "permission_denied" ? "permission denied" : "command not found");
2166
+ throw Object.assign(new Error(message), {
2167
+ exitCode: 1,
2168
+ stdout: "",
2169
+ stderr: message
2170
+ });
2171
+ };
2172
+ return {
2173
+ commandExists,
2174
+ runCommand: runCommand2
2175
+ };
2176
+ }
2177
+ function getInstallProviderId(file, args) {
2178
+ if (file !== "npm" || args.length !== 3) {
2179
+ return null;
2180
+ }
2181
+ if (args[0] !== "install" || args[1] !== "-g") {
2182
+ return null;
2183
+ }
2184
+ const packageName = args[2];
2185
+ if (packageName === PROVIDER_INSTALL_PACKAGES.claude) {
2186
+ return "claude";
2187
+ }
2188
+ if (packageName === PROVIDER_INSTALL_PACKAGES.codex) {
2189
+ return "codex";
2190
+ }
2191
+ return null;
2192
+ }
2193
+ function readMockState(statePath) {
2194
+ if (!existsSync6(statePath)) {
2195
+ return {};
2196
+ }
2197
+ const raw = readFileSync5(statePath, "utf8");
2198
+ if (!raw.trim()) {
2199
+ return {};
2200
+ }
2201
+ try {
2202
+ return JSON.parse(raw);
2203
+ } catch (error) {
2204
+ throw new Error(
2205
+ `Invalid provider mock state at ${statePath}: ${error instanceof Error ? error.message : String(error)}`
2206
+ );
2207
+ }
2208
+ }
2209
+ function writeMockState(statePath, updater) {
2210
+ const nextState = readMockState(statePath);
2211
+ updater(nextState);
2212
+ mkdirSync3(dirname4(statePath), { recursive: true });
2213
+ writeFileSync3(statePath, JSON.stringify(nextState, null, 2));
2214
+ return nextState;
2215
+ }
2216
+ function ensureProviderCommand(binDir, providerId) {
2217
+ mkdirSync3(binDir, { recursive: true });
2218
+ const scriptPath = join3(binDir, providerId);
2219
+ writeFileSync3(scriptPath, PROVIDER_COMMAND_SCRIPTS[providerId], "utf8");
2220
+ chmodSync(scriptPath, 493);
2221
+ }
2222
+ function appendDebugLog(path10, line) {
2223
+ if (!path10) {
2224
+ return;
2225
+ }
2226
+ mkdirSync3(dirname4(path10), { recursive: true });
2227
+ writeFileSync3(path10, `${line}
2228
+ `, { flag: "a" });
2229
+ }
2230
+ var PROVIDER_INSTALL_PACKAGES, PROVIDER_COMMAND_SCRIPTS;
2231
+ var init_e2e_provider_mock = __esm({
2232
+ "packages/server/src/provider-runtime/e2e-provider-mock.ts"() {
2233
+ "use strict";
2234
+ init_command_check();
2235
+ init_command_runner();
2236
+ PROVIDER_INSTALL_PACKAGES = {
2237
+ claude: "@anthropic-ai/claude-code",
2238
+ codex: "@openai/codex"
2239
+ };
2240
+ PROVIDER_COMMAND_SCRIPTS = {
2241
+ claude: `#!/usr/bin/env bash
2242
+ set -euo pipefail
2243
+ trap 'exit 0' TERM INT
2244
+ printf 'Mock Claude ready\\n'
2245
+ while true; do
2246
+ sleep 1
2247
+ done
2248
+ `,
2249
+ codex: `#!/usr/bin/env bash
2250
+ set -euo pipefail
2251
+ trap 'exit 0' TERM INT
2252
+ printf 'Session ID: abcdef-123456\\n> '
2253
+ while true; do
2254
+ sleep 1
2255
+ done
2256
+ `
2257
+ };
2258
+ }
2259
+ });
2260
+
2110
2261
  // packages/server/src/provider-runtime/install-manager.ts
2111
2262
  import { randomUUID as randomUUID2 } from "node:crypto";
2112
2263
  function getErrorDetails(error) {
@@ -3589,8 +3740,8 @@ var init_database = __esm({
3589
3740
 
3590
3741
  // packages/server/src/storage/db.ts
3591
3742
  import { DatabaseSync } from "node:sqlite";
3592
- import { readFileSync as readFileSync5 } from "fs";
3593
- import { join as join3 } from "path";
3743
+ import { readFileSync as readFileSync6 } from "fs";
3744
+ import { join as join4 } from "path";
3594
3745
  function normalizeSql(sql) {
3595
3746
  return (sql ?? "").replace(/\s+/g, " ").trim();
3596
3747
  }
@@ -3737,8 +3888,8 @@ var init_db = __esm({
3737
3888
  "packages/server/src/storage/db.ts"() {
3738
3889
  "use strict";
3739
3890
  init_database();
3740
- SCHEMA_PATH = join3(import.meta.dirname, "migrations", "001_init.sql");
3741
- SCHEMA_SQL = readFileSync5(SCHEMA_PATH, "utf-8");
3891
+ SCHEMA_PATH = join4(import.meta.dirname, "migrations", "001_init.sql");
3892
+ SCHEMA_SQL = readFileSync6(SCHEMA_PATH, "utf-8");
3742
3893
  LEGACY_TABLES = ["hook_registrations", "_migrations"];
3743
3894
  LEGACY_SESSION_COLUMNS = ["resume_id", "transcript_path"];
3744
3895
  EXPECTED_SCHEMA_ENTRIES = buildExpectedSchemaEntries();
@@ -4670,6 +4821,7 @@ function parseFetchUpdatedRefs(stderr) {
4670
4821
  }
4671
4822
  async function runGitCheckout(cwd, ref, options) {
4672
4823
  const args = ["checkout"];
4824
+ const formatCheckoutError = (error, fallbackMessage) => error instanceof GitError ? error.stderr.trim() || error.message || fallbackMessage : fallbackMessage;
4673
4825
  let isRemoteRef = false;
4674
4826
  try {
4675
4827
  const { stdout: remoteList } = await runGit(cwd, ["remote"]);
@@ -4681,15 +4833,22 @@ async function runGitCheckout(cwd, ref, options) {
4681
4833
  if (isRemoteRef && !options?.createBranch) {
4682
4834
  const remoteSeparatorIndex = ref.indexOf("/");
4683
4835
  const branchName = remoteSeparatorIndex >= 0 ? ref.slice(remoteSeparatorIndex + 1) : ref;
4684
- args.push("-b", branchName, ref);
4836
+ try {
4837
+ await runGit(cwd, ["show-ref", "--verify", "--quiet", `refs/heads/${branchName}`]);
4838
+ const { stdout, stderr } = await runGit(cwd, ["checkout", branchName]);
4839
+ const message = stdout || stderr || `Checkout to ${branchName} completed`;
4840
+ return { success: true, message, branch: branchName };
4841
+ } catch {
4842
+ args.push("-b", branchName, ref);
4843
+ }
4685
4844
  try {
4686
4845
  const { stdout, stderr } = await runGit(cwd, args);
4687
4846
  const message = stdout || stderr || `Checkout to ${ref} completed`;
4688
4847
  return { success: true, message, branch: branchName };
4689
- } catch {
4848
+ } catch (error) {
4690
4849
  return {
4691
4850
  success: false,
4692
- message: `Failed to checkout remote branch '${ref}'`
4851
+ message: formatCheckoutError(error, `Failed to checkout remote branch '${ref}'`)
4693
4852
  };
4694
4853
  }
4695
4854
  } else {
@@ -4703,10 +4862,10 @@ async function runGitCheckout(cwd, ref, options) {
4703
4862
  const branch = branchMatch?.[1] ?? ref;
4704
4863
  const message = stdout || stderr || `Checkout to ${ref} completed`;
4705
4864
  return { success: true, message, branch };
4706
- } catch {
4865
+ } catch (error) {
4707
4866
  return {
4708
4867
  success: false,
4709
- message: `Failed to checkout '${ref}'`
4868
+ message: formatCheckoutError(error, `Failed to checkout '${ref}'`)
4710
4869
  };
4711
4870
  }
4712
4871
  }
@@ -4721,23 +4880,42 @@ async function runGitCreateBranch(cwd, branchName, options) {
4721
4880
  }
4722
4881
  async function runGitListBranches(cwd) {
4723
4882
  const { stdout: localOutput } = await runGit(cwd, ["branch", "--list"]);
4883
+ const { stdout: localVerboseOutput } = await runGit(cwd, ["branch", "--list", "-vv"]);
4724
4884
  const { stdout: remoteOutput } = await runGit(cwd, ["branch", "-r"]);
4725
4885
  const branches = [];
4726
4886
  let current = "";
4887
+ const linkedWorktreePathsByBranch = /* @__PURE__ */ new Map();
4888
+ const localVerboseLines = localVerboseOutput.split("\n").filter((line) => line.trim());
4889
+ for (const line of localVerboseLines) {
4890
+ const normalizedLine = line.replace(/^[*+ ]\s+/, "");
4891
+ const branchMatch = normalizedLine.match(/^([^\s]+)\s+/);
4892
+ const worktreeMatch = line.match(/\((.+?)\)\s/);
4893
+ if (!branchMatch?.[1] || !worktreeMatch?.[1]) {
4894
+ continue;
4895
+ }
4896
+ const worktreePath = worktreeMatch[1];
4897
+ if (worktreePath.startsWith("/") || worktreePath.startsWith("~")) {
4898
+ linkedWorktreePathsByBranch.set(branchMatch[1], worktreePath);
4899
+ }
4900
+ }
4727
4901
  const localLines = localOutput.split("\n").filter((line) => line.trim());
4728
4902
  for (const line of localLines) {
4729
4903
  const isCurrent = line.startsWith("*");
4730
- const name = line.replace(/^\*?\s+/, "").trim();
4904
+ const name = line.replace(/^[*+ ]\s+/, "").trim();
4731
4905
  if (name.startsWith("(HEAD detached")) {
4732
4906
  if (isCurrent) {
4733
4907
  current = "";
4734
4908
  }
4735
4909
  continue;
4736
4910
  }
4911
+ if (linkedWorktreePathsByBranch.has(name) && !isCurrent) {
4912
+ continue;
4913
+ }
4737
4914
  branches.push({
4738
4915
  name,
4739
4916
  isRemote: false,
4740
- isCurrent
4917
+ isCurrent,
4918
+ linkedWorktreePath: linkedWorktreePathsByBranch.get(name)
4741
4919
  });
4742
4920
  if (isCurrent) {
4743
4921
  current = name;
@@ -5186,7 +5364,7 @@ var init_context_builder = __esm({
5186
5364
  });
5187
5365
 
5188
5366
  // packages/server/src/terminal/pty-host.ts
5189
- import { chmodSync, existsSync as existsSync6, statSync } from "node:fs";
5367
+ import { chmodSync as chmodSync2, existsSync as existsSync7, statSync } from "node:fs";
5190
5368
  import { createRequire } from "node:module";
5191
5369
  import path6 from "node:path";
5192
5370
  function ensureNodePtySpawnHelperExecutable(deps = {}) {
@@ -5196,9 +5374,9 @@ function ensureNodePtySpawnHelperExecutable(deps = {}) {
5196
5374
  }
5197
5375
  const arch = deps.arch ?? process.arch;
5198
5376
  const resolve4 = deps.resolve ?? ((id) => require2.resolve(id));
5199
- const fileExists = deps.existsSync ?? existsSync6;
5377
+ const fileExists = deps.existsSync ?? existsSync7;
5200
5378
  const stat7 = deps.statSync ?? statSync;
5201
- const chmod = deps.chmodSync ?? chmodSync;
5379
+ const chmod = deps.chmodSync ?? chmodSync2;
5202
5380
  let packageJsonPath;
5203
5381
  try {
5204
5382
  packageJsonPath = resolve4(NODE_PTY_PKG);
@@ -7268,9 +7446,9 @@ var init_validator = __esm({
7268
7446
  });
7269
7447
 
7270
7448
  // packages/server/src/fs/gitignore.ts
7271
- import { existsSync as existsSync7, readFileSync as readFileSync6 } from "fs";
7449
+ import { existsSync as existsSync8, readFileSync as readFileSync7 } from "fs";
7272
7450
  import ignore from "ignore";
7273
- import { join as join4, relative as relative3 } from "path";
7451
+ import { join as join5, relative as relative3 } from "path";
7274
7452
  function normalizePath(path10) {
7275
7453
  return path10.replace(/\\/g, "/");
7276
7454
  }
@@ -7290,26 +7468,26 @@ function isIgnoredByGitignore(ig, path10) {
7290
7468
  return ig.ignores(path10) || ig.ignores(`${path10}/`);
7291
7469
  }
7292
7470
  function createGitignoreFilter(rootPath, dirPath) {
7293
- const gitignorePath = join4(rootPath, ".gitignore");
7294
- if (!existsSync7(gitignorePath)) {
7471
+ const gitignorePath = join5(rootPath, ".gitignore");
7472
+ if (!existsSync8(gitignorePath)) {
7295
7473
  return (name) => !isDefaultTreeIgnored(name);
7296
7474
  }
7297
- const gitignoreContent = readFileSync6(gitignorePath, "utf-8");
7475
+ const gitignoreContent = readFileSync7(gitignorePath, "utf-8");
7298
7476
  const ig = ignore().add(gitignoreContent);
7299
7477
  return (name) => {
7300
7478
  if (isAlwaysTreeIgnored(name)) {
7301
7479
  return false;
7302
7480
  }
7303
- const relativePath = relativeToRoot(rootPath, join4(dirPath, name));
7481
+ const relativePath = relativeToRoot(rootPath, join5(dirPath, name));
7304
7482
  return !isIgnoredByGitignore(ig, relativePath);
7305
7483
  };
7306
7484
  }
7307
7485
  function createWatcherIgnoreFilter(rootPath) {
7308
- const gitignorePath = join4(rootPath, ".gitignore");
7309
- if (!existsSync7(gitignorePath)) {
7486
+ const gitignorePath = join5(rootPath, ".gitignore");
7487
+ if (!existsSync8(gitignorePath)) {
7310
7488
  return (path10) => DEFAULT_WATCHER_IGNORED_PATTERNS.some((p) => p.test(normalizePath(path10)));
7311
7489
  }
7312
- const gitignoreContent = readFileSync6(gitignorePath, "utf-8");
7490
+ const gitignoreContent = readFileSync7(gitignorePath, "utf-8");
7313
7491
  const ig = ignore().add(gitignoreContent);
7314
7492
  return (path10) => {
7315
7493
  const normalizedPath = normalizePath(path10);
@@ -7436,6 +7614,11 @@ var init_manager4 = __esm({
7436
7614
  new WorkspaceWatcher(workspaceId, rootPath, this.deps.broadcaster)
7437
7615
  );
7438
7616
  }
7617
+ hydrateWatchers() {
7618
+ for (const workspace of this.list()) {
7619
+ this.startWatcher(workspace.id, workspace.path);
7620
+ }
7621
+ }
7439
7622
  updateUiState(workspaceId, uiState) {
7440
7623
  const workspace = this.get(workspaceId);
7441
7624
  if (!workspace) {
@@ -8240,8 +8423,12 @@ var init_client = __esm({
8240
8423
  evictedBytesSinceLastWarn = 0;
8241
8424
  lastStreamBufferWarnAt = 0;
8242
8425
  logger;
8426
+ markAlive() {
8427
+ this.isAlive = true;
8428
+ }
8243
8429
  setupSocketHandlers() {
8244
8430
  this.socket.on("message", (data, isBinary) => {
8431
+ this.markAlive();
8245
8432
  if (isBinary) {
8246
8433
  this.messageHandler?.(data);
8247
8434
  return;
@@ -8260,7 +8447,7 @@ var init_client = __esm({
8260
8447
  this.closeHandler?.();
8261
8448
  });
8262
8449
  this.socket.on("pong", () => {
8263
- this.isAlive = true;
8450
+ this.markAlive();
8264
8451
  });
8265
8452
  }
8266
8453
  /**
@@ -8770,6 +8957,10 @@ var init_hub = __esm({
8770
8957
  */
8771
8958
  pingAll() {
8772
8959
  for (const client of this.clients.values()) {
8960
+ if (!client.alive) {
8961
+ client.close(1011, "keepalive_timeout");
8962
+ continue;
8963
+ }
8773
8964
  client.ping();
8774
8965
  }
8775
8966
  }
@@ -8911,7 +9102,7 @@ var init_hub = __esm({
8911
9102
  // packages/server/src/commands/workspace.ts
8912
9103
  import { readdir as readdir2 } from "node:fs/promises";
8913
9104
  import { homedir as homedir3 } from "node:os";
8914
- import { join as join5 } from "node:path";
9105
+ import { join as join6 } from "node:path";
8915
9106
  import { z as z6 } from "zod";
8916
9107
  var init_workspace = __esm({
8917
9108
  "packages/server/src/commands/workspace.ts"() {
@@ -8930,11 +9121,11 @@ var init_workspace = __esm({
8930
9121
  const entries = await readdir2(basePath, { withFileTypes: true });
8931
9122
  const directories = entries.filter((entry) => entry.isDirectory()).map((entry) => ({
8932
9123
  name: entry.name,
8933
- path: join5(basePath, entry.name)
9124
+ path: join6(basePath, entry.name)
8934
9125
  })).sort((a, b) => a.name.localeCompare(b.name));
8935
9126
  return {
8936
9127
  currentPath: basePath,
8937
- parentPath: basePath !== "/" ? join5(basePath, "..") : null,
9128
+ parentPath: basePath !== "/" ? join6(basePath, "..") : null,
8938
9129
  directories
8939
9130
  };
8940
9131
  }
@@ -9028,6 +9219,18 @@ var init_workspace_activity = __esm({
9028
9219
  }
9029
9220
  });
9030
9221
 
9222
+ // packages/server/src/commands/connection.ts
9223
+ import { z as z8 } from "zod";
9224
+ var init_connection = __esm({
9225
+ "packages/server/src/commands/connection.ts"() {
9226
+ "use strict";
9227
+ init_dispatch();
9228
+ registerCommand("connection.probe", z8.object({}).default({}), async () => {
9229
+ return { ok: true };
9230
+ });
9231
+ }
9232
+ });
9233
+
9031
9234
  // packages/server/src/provider-runtime/runtime-status.ts
9032
9235
  function canAutoInstall(provider, platform, missingCommands, missingPrerequisites, availableCommands) {
9033
9236
  const strategies = provider.install.strategies[platform] ?? [];
@@ -9122,7 +9325,7 @@ var init_runtime_status = __esm({
9122
9325
  });
9123
9326
 
9124
9327
  // packages/server/src/commands/session.ts
9125
- import { z as z8 } from "zod";
9328
+ import { z as z9 } from "zod";
9126
9329
  function getProviderFromRegistry(providerId, registry) {
9127
9330
  return registry.find((provider) => provider.id === providerId);
9128
9331
  }
@@ -9133,8 +9336,8 @@ var init_session = __esm({
9133
9336
  init_dispatch();
9134
9337
  registerCommand(
9135
9338
  "session.list",
9136
- z8.object({
9137
- workspaceId: z8.string()
9339
+ z9.object({
9340
+ workspaceId: z9.string()
9138
9341
  }),
9139
9342
  async (args, ctx) => {
9140
9343
  return ctx.sessionMgr.getForWorkspace(args.workspaceId);
@@ -9142,10 +9345,10 @@ var init_session = __esm({
9142
9345
  );
9143
9346
  registerCommand(
9144
9347
  "session.create",
9145
- z8.object({
9146
- workspaceId: z8.string(),
9147
- providerId: z8.string(),
9148
- draft: z8.string().optional()
9348
+ z9.object({
9349
+ workspaceId: z9.string(),
9350
+ providerId: z9.string(),
9351
+ draft: z9.string().optional()
9149
9352
  }),
9150
9353
  async (args, ctx) => {
9151
9354
  const workspace = ctx.workspaceMgr.get(args.workspaceId);
@@ -9179,8 +9382,8 @@ var init_session = __esm({
9179
9382
  );
9180
9383
  registerCommand(
9181
9384
  "session.stop",
9182
- z8.object({
9183
- sessionId: z8.string()
9385
+ z9.object({
9386
+ sessionId: z9.string()
9184
9387
  }),
9185
9388
  async (args, ctx) => {
9186
9389
  await ctx.sessionMgr.stop(args.sessionId);
@@ -9188,8 +9391,8 @@ var init_session = __esm({
9188
9391
  );
9189
9392
  registerCommand(
9190
9393
  "session.remove",
9191
- z8.object({
9192
- sessionId: z8.string()
9394
+ z9.object({
9395
+ sessionId: z9.string()
9193
9396
  }),
9194
9397
  async (args, ctx) => {
9195
9398
  const session = ctx.sessionMgr.get(args.sessionId);
@@ -9207,9 +9410,9 @@ var init_session = __esm({
9207
9410
 
9208
9411
  // packages/server/src/fs/tree.ts
9209
9412
  import { readdir as readdir3, stat as stat6 } from "fs/promises";
9210
- import { join as join6, relative as relative4 } from "path";
9413
+ import { join as join7, relative as relative4 } from "path";
9211
9414
  async function readTree(rootPath, subdir) {
9212
- const targetPath = subdir ? join6(rootPath, subdir) : rootPath;
9415
+ const targetPath = subdir ? join7(rootPath, subdir) : rootPath;
9213
9416
  const filter = createGitignoreFilter(rootPath, targetPath);
9214
9417
  const entries = await readdir3(targetPath, { withFileTypes: true });
9215
9418
  const nodes = [];
@@ -9217,7 +9420,7 @@ async function readTree(rootPath, subdir) {
9217
9420
  if (!filter(entry.name)) {
9218
9421
  continue;
9219
9422
  }
9220
- const fullPath = join6(targetPath, entry.name);
9423
+ const fullPath = join7(targetPath, entry.name);
9221
9424
  const relPath = relative4(rootPath, fullPath);
9222
9425
  if (entry.isDirectory()) {
9223
9426
  nodes.push({
@@ -9261,7 +9464,7 @@ async function searchFiles(rootPath, query, limit = 10) {
9261
9464
  const filteredEntries = entries.filter((entry) => filter(entry.name));
9262
9465
  filteredEntries.sort((a, b) => a.name.localeCompare(b.name));
9263
9466
  for (const entry of filteredEntries) {
9264
- const fullPath = join6(dirPath, entry.name);
9467
+ const fullPath = join7(dirPath, entry.name);
9265
9468
  const relPath = relative4(rootPath, fullPath);
9266
9469
  if (entry.isDirectory()) {
9267
9470
  await walk(fullPath);
@@ -9354,7 +9557,7 @@ var init_tree = __esm({
9354
9557
  });
9355
9558
 
9356
9559
  // packages/server/src/commands/file.ts
9357
- import { z as z9 } from "zod";
9560
+ import { z as z10 } from "zod";
9358
9561
  var init_file = __esm({
9359
9562
  "packages/server/src/commands/file.ts"() {
9360
9563
  "use strict";
@@ -9363,9 +9566,9 @@ var init_file = __esm({
9363
9566
  init_dispatch();
9364
9567
  registerCommand(
9365
9568
  "file.readTree",
9366
- z9.object({
9367
- workspaceId: z9.string(),
9368
- subPath: z9.string().optional()
9569
+ z10.object({
9570
+ workspaceId: z10.string(),
9571
+ subPath: z10.string().optional()
9369
9572
  }),
9370
9573
  async (args, ctx) => {
9371
9574
  const workspace = ctx.workspaceMgr.get(args.workspaceId);
@@ -9377,10 +9580,10 @@ var init_file = __esm({
9377
9580
  );
9378
9581
  registerCommand(
9379
9582
  "file.search",
9380
- z9.object({
9381
- workspaceId: z9.string(),
9382
- query: z9.string(),
9383
- limit: z9.number().int().positive().max(50).optional()
9583
+ z10.object({
9584
+ workspaceId: z10.string(),
9585
+ query: z10.string(),
9586
+ limit: z10.number().int().positive().max(50).optional()
9384
9587
  }),
9385
9588
  async (args, ctx) => {
9386
9589
  const workspace = ctx.workspaceMgr.get(args.workspaceId);
@@ -9392,9 +9595,9 @@ var init_file = __esm({
9392
9595
  );
9393
9596
  registerCommand(
9394
9597
  "file.read",
9395
- z9.object({
9396
- workspaceId: z9.string(),
9397
- path: z9.string()
9598
+ z10.object({
9599
+ workspaceId: z10.string(),
9600
+ path: z10.string()
9398
9601
  }),
9399
9602
  async (args, ctx) => {
9400
9603
  const workspace = ctx.workspaceMgr.get(args.workspaceId);
@@ -9406,9 +9609,9 @@ var init_file = __esm({
9406
9609
  );
9407
9610
  registerCommand(
9408
9611
  "file.create",
9409
- z9.object({
9410
- workspaceId: z9.string(),
9411
- path: z9.string()
9612
+ z10.object({
9613
+ workspaceId: z10.string(),
9614
+ path: z10.string()
9412
9615
  }),
9413
9616
  async (args, ctx) => {
9414
9617
  const workspace = ctx.workspaceMgr.get(args.workspaceId);
@@ -9426,9 +9629,9 @@ var init_file = __esm({
9426
9629
  );
9427
9630
  registerCommand(
9428
9631
  "file.mkdir",
9429
- z9.object({
9430
- workspaceId: z9.string(),
9431
- path: z9.string()
9632
+ z10.object({
9633
+ workspaceId: z10.string(),
9634
+ path: z10.string()
9432
9635
  }),
9433
9636
  async (args, ctx) => {
9434
9637
  const workspace = ctx.workspaceMgr.get(args.workspaceId);
@@ -9446,9 +9649,9 @@ var init_file = __esm({
9446
9649
  );
9447
9650
  registerCommand(
9448
9651
  "file.delete",
9449
- z9.object({
9450
- workspaceId: z9.string(),
9451
- path: z9.string()
9652
+ z10.object({
9653
+ workspaceId: z10.string(),
9654
+ path: z10.string()
9452
9655
  }),
9453
9656
  async (args, ctx) => {
9454
9657
  const workspace = ctx.workspaceMgr.get(args.workspaceId);
@@ -9466,11 +9669,11 @@ var init_file = __esm({
9466
9669
  );
9467
9670
  registerCommand(
9468
9671
  "file.write",
9469
- z9.object({
9470
- workspaceId: z9.string(),
9471
- path: z9.string(),
9472
- content: z9.string(),
9473
- baseHash: z9.string().optional()
9672
+ z10.object({
9673
+ workspaceId: z10.string(),
9674
+ path: z10.string(),
9675
+ content: z10.string(),
9676
+ baseHash: z10.string().optional()
9474
9677
  // For conflict detection
9475
9678
  }),
9476
9679
  async (args, ctx) => {
@@ -9561,7 +9764,7 @@ var init_git_events = __esm({
9561
9764
  });
9562
9765
 
9563
9766
  // packages/server/src/commands/git.ts
9564
- import { z as z10 } from "zod";
9767
+ import { z as z11 } from "zod";
9565
9768
  async function runGitNetworkOperation(ctx, workspaceId, op) {
9566
9769
  if (!ctx.autoFetch?.runExclusive) {
9567
9770
  return op();
@@ -9576,16 +9779,16 @@ var init_git2 = __esm({
9576
9779
  init_diff();
9577
9780
  init_dispatch();
9578
9781
  init_git_events();
9579
- gitHttpAuthSchema = z10.object({
9580
- username: z10.string(),
9581
- password: z10.string()
9782
+ gitHttpAuthSchema = z11.object({
9783
+ username: z11.string(),
9784
+ password: z11.string()
9582
9785
  });
9583
- gitCommitRevisionSchema = z10.string().regex(/^[0-9a-fA-F]{7,64}$/, "Invalid git commit revision");
9786
+ gitCommitRevisionSchema = z11.string().regex(/^[0-9a-fA-F]{7,64}$/, "Invalid git commit revision");
9584
9787
  GIT_BACKGROUND_FETCH_TIMEOUT_MS = 30 * 1e3;
9585
9788
  registerCommand(
9586
9789
  "git.status",
9587
- z10.object({
9588
- workspaceId: z10.string()
9790
+ z11.object({
9791
+ workspaceId: z11.string()
9589
9792
  }),
9590
9793
  async (args, ctx) => {
9591
9794
  const workspace = ctx.workspaceMgr.get(args.workspaceId);
@@ -9597,9 +9800,9 @@ var init_git2 = __esm({
9597
9800
  );
9598
9801
  registerCommand(
9599
9802
  "git.stage",
9600
- z10.object({
9601
- workspaceId: z10.string(),
9602
- paths: z10.array(z10.string())
9803
+ z11.object({
9804
+ workspaceId: z11.string(),
9805
+ paths: z11.array(z11.string())
9603
9806
  }),
9604
9807
  async (args, ctx) => {
9605
9808
  const workspace = ctx.workspaceMgr.get(args.workspaceId);
@@ -9613,10 +9816,10 @@ var init_git2 = __esm({
9613
9816
  );
9614
9817
  registerCommand(
9615
9818
  "git.diff",
9616
- z10.object({
9617
- workspaceId: z10.string(),
9618
- path: z10.string(),
9619
- staged: z10.boolean().optional()
9819
+ z11.object({
9820
+ workspaceId: z11.string(),
9821
+ path: z11.string(),
9822
+ staged: z11.boolean().optional()
9620
9823
  }),
9621
9824
  async (args, ctx) => {
9622
9825
  const workspace = ctx.workspaceMgr.get(args.workspaceId);
@@ -9630,9 +9833,9 @@ var init_git2 = __esm({
9630
9833
  );
9631
9834
  registerCommand(
9632
9835
  "git.log",
9633
- z10.object({
9634
- workspaceId: z10.string(),
9635
- limit: z10.number().int().min(1).max(50).optional()
9836
+ z11.object({
9837
+ workspaceId: z11.string(),
9838
+ limit: z11.number().int().min(1).max(50).optional()
9636
9839
  }),
9637
9840
  async (args, ctx) => {
9638
9841
  const workspace = ctx.workspaceMgr.get(args.workspaceId);
@@ -9646,8 +9849,8 @@ var init_git2 = __esm({
9646
9849
  );
9647
9850
  registerCommand(
9648
9851
  "git.show",
9649
- z10.object({
9650
- workspaceId: z10.string(),
9852
+ z11.object({
9853
+ workspaceId: z11.string(),
9651
9854
  sha: gitCommitRevisionSchema
9652
9855
  }),
9653
9856
  async (args, ctx) => {
@@ -9662,9 +9865,9 @@ var init_git2 = __esm({
9662
9865
  );
9663
9866
  registerCommand(
9664
9867
  "git.unstage",
9665
- z10.object({
9666
- workspaceId: z10.string(),
9667
- paths: z10.array(z10.string())
9868
+ z11.object({
9869
+ workspaceId: z11.string(),
9870
+ paths: z11.array(z11.string())
9668
9871
  }),
9669
9872
  async (args, ctx) => {
9670
9873
  const workspace = ctx.workspaceMgr.get(args.workspaceId);
@@ -9678,9 +9881,9 @@ var init_git2 = __esm({
9678
9881
  );
9679
9882
  registerCommand(
9680
9883
  "git.discard",
9681
- z10.object({
9682
- workspaceId: z10.string(),
9683
- paths: z10.array(z10.string())
9884
+ z11.object({
9885
+ workspaceId: z11.string(),
9886
+ paths: z11.array(z11.string())
9684
9887
  }),
9685
9888
  async (args, ctx) => {
9686
9889
  const workspace = ctx.workspaceMgr.get(args.workspaceId);
@@ -9696,9 +9899,9 @@ var init_git2 = __esm({
9696
9899
  );
9697
9900
  registerCommand(
9698
9901
  "git.commit",
9699
- z10.object({
9700
- workspaceId: z10.string(),
9701
- message: z10.string()
9902
+ z11.object({
9903
+ workspaceId: z11.string(),
9904
+ message: z11.string()
9702
9905
  }),
9703
9906
  async (args, ctx) => {
9704
9907
  const workspace = ctx.workspaceMgr.get(args.workspaceId);
@@ -9715,11 +9918,11 @@ var init_git2 = __esm({
9715
9918
  );
9716
9919
  registerCommand(
9717
9920
  "git.push",
9718
- z10.object({
9719
- workspaceId: z10.string(),
9720
- remote: z10.string().optional(),
9721
- branch: z10.string().optional(),
9722
- force: z10.boolean().optional(),
9921
+ z11.object({
9922
+ workspaceId: z11.string(),
9923
+ remote: z11.string().optional(),
9924
+ branch: z11.string().optional(),
9925
+ force: z11.boolean().optional(),
9723
9926
  auth: gitHttpAuthSchema.optional()
9724
9927
  }),
9725
9928
  async (args, ctx) => {
@@ -9746,10 +9949,10 @@ var init_git2 = __esm({
9746
9949
  );
9747
9950
  registerCommand(
9748
9951
  "git.pull",
9749
- z10.object({
9750
- workspaceId: z10.string(),
9751
- remote: z10.string().optional(),
9752
- branch: z10.string().optional(),
9952
+ z11.object({
9953
+ workspaceId: z11.string(),
9954
+ remote: z11.string().optional(),
9955
+ branch: z11.string().optional(),
9753
9956
  auth: gitHttpAuthSchema.optional()
9754
9957
  }),
9755
9958
  async (args, ctx) => {
@@ -9777,12 +9980,12 @@ var init_git2 = __esm({
9777
9980
  );
9778
9981
  registerCommand(
9779
9982
  "git.fetch",
9780
- z10.object({
9781
- workspaceId: z10.string(),
9782
- remote: z10.string().optional(),
9783
- prune: z10.boolean().optional(),
9983
+ z11.object({
9984
+ workspaceId: z11.string(),
9985
+ remote: z11.string().optional(),
9986
+ prune: z11.boolean().optional(),
9784
9987
  auth: gitHttpAuthSchema.optional(),
9785
- background: z10.boolean().optional()
9988
+ background: z11.boolean().optional()
9786
9989
  }),
9787
9990
  async (args, ctx, clientId) => {
9788
9991
  const workspace = ctx.workspaceMgr.get(args.workspaceId);
@@ -9811,10 +10014,10 @@ var init_git2 = __esm({
9811
10014
  );
9812
10015
  registerCommand(
9813
10016
  "git.checkout",
9814
- z10.object({
9815
- workspaceId: z10.string(),
9816
- ref: z10.string(),
9817
- createBranch: z10.boolean().optional()
10017
+ z11.object({
10018
+ workspaceId: z11.string(),
10019
+ ref: z11.string(),
10020
+ createBranch: z11.boolean().optional()
9818
10021
  }),
9819
10022
  async (args, ctx) => {
9820
10023
  const workspace = ctx.workspaceMgr.get(args.workspaceId);
@@ -9836,10 +10039,10 @@ var init_git2 = __esm({
9836
10039
  );
9837
10040
  registerCommand(
9838
10041
  "git.branch",
9839
- z10.object({
9840
- workspaceId: z10.string(),
9841
- name: z10.string(),
9842
- startPoint: z10.string().optional()
10042
+ z11.object({
10043
+ workspaceId: z11.string(),
10044
+ name: z11.string(),
10045
+ startPoint: z11.string().optional()
9843
10046
  }),
9844
10047
  async (args, ctx) => {
9845
10048
  const workspace = ctx.workspaceMgr.get(args.workspaceId);
@@ -9858,8 +10061,8 @@ var init_git2 = __esm({
9858
10061
  );
9859
10062
  registerCommand(
9860
10063
  "git.branches",
9861
- z10.object({
9862
- workspaceId: z10.string()
10064
+ z11.object({
10065
+ workspaceId: z11.string()
9863
10066
  }),
9864
10067
  async (args, ctx) => {
9865
10068
  const workspace = ctx.workspaceMgr.get(args.workspaceId);
@@ -9873,37 +10076,37 @@ var init_git2 = __esm({
9873
10076
  });
9874
10077
 
9875
10078
  // packages/server/src/config/config-io.ts
9876
- import { existsSync as existsSync8, mkdirSync as mkdirSync3, readFileSync as readFileSync7, renameSync, writeFileSync as writeFileSync3 } from "node:fs";
10079
+ import { existsSync as existsSync9, mkdirSync as mkdirSync4, readFileSync as readFileSync8, renameSync, writeFileSync as writeFileSync4 } from "node:fs";
9877
10080
  import { homedir as homedir4 } from "node:os";
9878
- import { basename as basename3, dirname as dirname4, join as join7 } from "node:path";
10081
+ import { basename as basename3, dirname as dirname5, join as join8 } from "node:path";
9879
10082
  function resolveConfigPath(configType) {
9880
10083
  if (configType === "codex") {
9881
10084
  const testHome = process.env.CODER_STUDIO_CODEX_HOME;
9882
10085
  if (testHome && testHome.trim()) {
9883
- return join7(testHome, "config.toml");
10086
+ return join8(testHome, "config.toml");
9884
10087
  }
9885
10088
  const codexHome = process.env.CODEX_HOME;
9886
10089
  if (codexHome && codexHome.trim()) {
9887
- return join7(codexHome, "config.toml");
10090
+ return join8(codexHome, "config.toml");
9888
10091
  }
9889
- return join7(homedir4(), ".codex", "config.toml");
10092
+ return join8(homedir4(), ".codex", "config.toml");
9890
10093
  }
9891
10094
  if (configType === "claude") {
9892
10095
  const testHome = process.env.CODER_STUDIO_CLAUDE_HOME;
9893
10096
  if (testHome && testHome.trim()) {
9894
- return join7(testHome, "settings.json");
10097
+ return join8(testHome, "settings.json");
9895
10098
  }
9896
- return join7(homedir4(), ".claude", "settings.json");
10099
+ return join8(homedir4(), ".claude", "settings.json");
9897
10100
  }
9898
10101
  throw new Error(`Unknown config type: ${configType}`);
9899
10102
  }
9900
10103
  function readConfigFile(configType) {
9901
10104
  const configPath = resolveConfigPath(configType);
9902
- if (!existsSync8(configPath)) {
10105
+ if (!existsSync9(configPath)) {
9903
10106
  return { configPath, content: "", exists: false };
9904
10107
  }
9905
10108
  try {
9906
- const content = readFileSync7(configPath, "utf-8");
10109
+ const content = readFileSync8(configPath, "utf-8");
9907
10110
  return { configPath, content, exists: true };
9908
10111
  } catch {
9909
10112
  return { configPath, content: "", exists: false };
@@ -9912,16 +10115,16 @@ function readConfigFile(configType) {
9912
10115
  function writeConfigFile(configType, content) {
9913
10116
  try {
9914
10117
  const configPath = resolveConfigPath(configType);
9915
- const parentDir = dirname4(configPath);
9916
- if (!existsSync8(parentDir)) {
9917
- mkdirSync3(parentDir, { recursive: true });
10118
+ const parentDir = dirname5(configPath);
10119
+ if (!existsSync9(parentDir)) {
10120
+ mkdirSync4(parentDir, { recursive: true });
9918
10121
  }
9919
10122
  let backupPath = null;
9920
- if (existsSync8(configPath)) {
10123
+ if (existsSync9(configPath)) {
9921
10124
  backupPath = createBackup(configPath);
9922
10125
  }
9923
10126
  const tempPath = `${configPath}.tmp`;
9924
- writeFileSync3(tempPath, content, "utf-8");
10127
+ writeFileSync4(tempPath, content, "utf-8");
9925
10128
  renameSync(tempPath, configPath);
9926
10129
  return { success: true, backupPath };
9927
10130
  } catch (error) {
@@ -9933,13 +10136,13 @@ function writeConfigFile(configType, content) {
9933
10136
  }
9934
10137
  }
9935
10138
  function createBackup(filePath) {
9936
- const original = readFileSync7(filePath, "utf-8");
10139
+ const original = readFileSync8(filePath, "utf-8");
9937
10140
  const ext = filePath.split(".").pop() ?? "";
9938
10141
  const base = basename3(filePath, `.${ext}`);
9939
- const dir = dirname4(filePath);
10142
+ const dir = dirname5(filePath);
9940
10143
  const ts = formatTimestamp(/* @__PURE__ */ new Date());
9941
- const backupPath = join7(dir, `${base}.bak.${ts}.${ext}`);
9942
- writeFileSync3(backupPath, original, "utf-8");
10144
+ const backupPath = join8(dir, `${base}.bak.${ts}.${ext}`);
10145
+ writeFileSync4(backupPath, original, "utf-8");
9943
10146
  return backupPath;
9944
10147
  }
9945
10148
  function formatTimestamp(d) {
@@ -9953,7 +10156,7 @@ var init_config_io = __esm({
9953
10156
  });
9954
10157
 
9955
10158
  // packages/server/src/commands/settings.ts
9956
- import { z as z11 } from "zod";
10159
+ import { z as z12 } from "zod";
9957
10160
  function flattenSettings(obj, prefix = "") {
9958
10161
  const result = {};
9959
10162
  for (const [key, value] of Object.entries(obj)) {
@@ -9976,27 +10179,28 @@ var init_settings2 = __esm({
9976
10179
  init_provider_config_repo();
9977
10180
  init_settings();
9978
10181
  init_dispatch();
9979
- SettingsSchema = z11.object({
9980
- defaultProviderId: z11.string().optional(),
9981
- notifications: z11.object({
9982
- enabled: z11.boolean().optional(),
9983
- soundEnabled: z11.boolean().optional(),
10182
+ SettingsSchema = z12.object({
10183
+ defaultProviderId: z12.string().optional(),
10184
+ notifications: z12.object({
10185
+ enabled: z12.boolean().optional(),
10186
+ soundEnabled: z12.boolean().optional(),
9984
10187
  // Legacy field — accepted for backward compat with older clients but
9985
10188
  // no longer surfaced in the UI. The web client now picks the channel
9986
10189
  // automatically based on workspace focus + page visibility.
9987
- onlyWhenBackgrounded: z11.boolean().optional()
10190
+ onlyWhenBackgrounded: z12.boolean().optional()
9988
10191
  }).optional(),
9989
- supervisor: z11.object({
9990
- evaluationTimeoutSec: z11.number().int().min(1).max(MAX_SUPERVISOR_EVALUATION_TIMEOUT_SEC).default(DEFAULT_SUPERVISOR_EVALUATION_TIMEOUT_SEC).optional()
10192
+ supervisor: z12.object({
10193
+ evaluationTimeoutSec: z12.number().int().min(1).max(MAX_SUPERVISOR_EVALUATION_TIMEOUT_SEC).default(DEFAULT_SUPERVISOR_EVALUATION_TIMEOUT_SEC).optional()
9991
10194
  }).optional(),
9992
- appearance: z11.object({
9993
- theme: z11.enum(["dark"]).optional(),
9994
- terminalRenderer: z11.enum(["standard", "compatibility"]).optional(),
9995
- locale: z11.enum(["zh", "en"]).optional()
10195
+ appearance: z12.object({
10196
+ theme: z12.enum(["dark"]).optional(),
10197
+ terminalRenderer: z12.enum(["standard", "compatibility"]).optional(),
10198
+ terminalCopyOnSelect: z12.boolean().optional(),
10199
+ locale: z12.enum(["zh", "en"]).optional()
9996
10200
  }).optional(),
9997
10201
  providers: ProviderSettingsSchema.optional()
9998
10202
  });
9999
- registerCommand("settings.get", z11.object({}), async (_args, ctx) => {
10203
+ registerCommand("settings.get", z12.object({}), async (_args, ctx) => {
10000
10204
  const row = ctx.db.prepare("SELECT key, value FROM user_settings").all();
10001
10205
  const settings = {};
10002
10206
  for (const { key, value } of row) {
@@ -10029,7 +10233,7 @@ var init_settings2 = __esm({
10029
10233
  });
10030
10234
  registerCommand(
10031
10235
  "settings.update",
10032
- z11.object({
10236
+ z12.object({
10033
10237
  settings: SettingsSchema
10034
10238
  }),
10035
10239
  async (args, ctx) => {
@@ -10061,10 +10265,10 @@ var init_settings2 = __esm({
10061
10265
  );
10062
10266
  registerCommand(
10063
10267
  "settings.previewCommand",
10064
- z11.object({
10065
- providerId: z11.string(),
10268
+ z12.object({
10269
+ providerId: z12.string(),
10066
10270
  config: ProviderLaunchConfigInputSchema,
10067
- workspacePath: z11.string().optional()
10271
+ workspacePath: z12.string().optional()
10068
10272
  }),
10069
10273
  async (args, ctx) => {
10070
10274
  const provider = ctx.providerRegistry.find((item) => item.id === args.providerId);
@@ -10085,8 +10289,8 @@ var init_settings2 = __esm({
10085
10289
  );
10086
10290
  registerCommand(
10087
10291
  "settings.readConfigFile",
10088
- z11.object({
10089
- configType: z11.enum(["codex", "claude"])
10292
+ z12.object({
10293
+ configType: z12.enum(["codex", "claude"])
10090
10294
  }),
10091
10295
  async (args) => {
10092
10296
  const result = readConfigFile(args.configType);
@@ -10095,9 +10299,9 @@ var init_settings2 = __esm({
10095
10299
  );
10096
10300
  registerCommand(
10097
10301
  "settings.writeConfigFile",
10098
- z11.object({
10099
- configType: z11.enum(["codex", "claude"]),
10100
- content: z11.string()
10302
+ z12.object({
10303
+ configType: z12.enum(["codex", "claude"]),
10304
+ content: z12.string()
10101
10305
  }),
10102
10306
  async (args) => {
10103
10307
  const result = writeConfigFile(args.configType, args.content);
@@ -10108,19 +10312,19 @@ var init_settings2 = __esm({
10108
10312
  });
10109
10313
 
10110
10314
  // packages/server/src/commands/provider.ts
10111
- import { z as z12 } from "zod";
10315
+ import { z as z13 } from "zod";
10112
10316
  var init_provider = __esm({
10113
10317
  "packages/server/src/commands/provider.ts"() {
10114
10318
  "use strict";
10115
10319
  init_runtime_status();
10116
10320
  init_dispatch();
10117
- registerCommand("provider.runtimeStatus", z12.object({}), async (_args, ctx) => {
10321
+ registerCommand("provider.runtimeStatus", z13.object({}), async (_args, ctx) => {
10118
10322
  return buildProviderRuntimeStatus(ctx.providerRegistry, ctx.providerRuntimeDeps);
10119
10323
  });
10120
10324
  registerCommand(
10121
10325
  "provider.install.start",
10122
- z12.object({
10123
- providerId: z12.string()
10326
+ z13.object({
10327
+ providerId: z13.string()
10124
10328
  }),
10125
10329
  async (args, ctx) => {
10126
10330
  if (!ctx.providerInstallMgr) {
@@ -10134,8 +10338,8 @@ var init_provider = __esm({
10134
10338
  );
10135
10339
  registerCommand(
10136
10340
  "provider.install.get",
10137
- z12.object({
10138
- jobId: z12.string()
10341
+ z13.object({
10342
+ jobId: z13.string()
10139
10343
  }),
10140
10344
  async (args, ctx) => {
10141
10345
  if (!ctx.providerInstallMgr) {
@@ -10158,29 +10362,29 @@ var init_provider = __esm({
10158
10362
  });
10159
10363
 
10160
10364
  // packages/server/src/commands/supervisor.ts
10161
- import { z as z13 } from "zod";
10365
+ import { z as z14 } from "zod";
10162
10366
  var supervisorObjectiveSchema, createSupervisorSchema, updateSupervisorSchema, sessionIdSchema, supervisorIdSchema;
10163
10367
  var init_supervisor2 = __esm({
10164
10368
  "packages/server/src/commands/supervisor.ts"() {
10165
10369
  "use strict";
10166
10370
  init_dispatch();
10167
- supervisorObjectiveSchema = z13.string().trim().min(1).max(4e3);
10168
- createSupervisorSchema = z13.object({
10169
- sessionId: z13.string(),
10170
- workspaceId: z13.string(),
10371
+ supervisorObjectiveSchema = z14.string().trim().min(1).max(4e3);
10372
+ createSupervisorSchema = z14.object({
10373
+ sessionId: z14.string(),
10374
+ workspaceId: z14.string(),
10171
10375
  objective: supervisorObjectiveSchema,
10172
- evaluatorProviderId: z13.string()
10376
+ evaluatorProviderId: z14.string()
10173
10377
  }).strict();
10174
- updateSupervisorSchema = z13.object({
10175
- id: z13.string(),
10378
+ updateSupervisorSchema = z14.object({
10379
+ id: z14.string(),
10176
10380
  objective: supervisorObjectiveSchema.optional(),
10177
- evaluatorProviderId: z13.string().optional()
10381
+ evaluatorProviderId: z14.string().optional()
10178
10382
  }).strict().refine(
10179
10383
  (input) => input.objective !== void 0 || input.evaluatorProviderId !== void 0,
10180
10384
  "objective or evaluatorProviderId is required"
10181
10385
  );
10182
- sessionIdSchema = z13.object({ sessionId: z13.string() });
10183
- supervisorIdSchema = z13.object({ id: z13.string() });
10386
+ sessionIdSchema = z14.object({ sessionId: z14.string() });
10387
+ supervisorIdSchema = z14.object({ id: z14.string() });
10184
10388
  registerCommand("supervisor.create", createSupervisorSchema, async (args, ctx) => {
10185
10389
  return {
10186
10390
  supervisor: await ctx.supervisorMgr.create({
@@ -10358,7 +10562,7 @@ var init_worktree = __esm({
10358
10562
 
10359
10563
  // packages/server/src/commands/worktree.ts
10360
10564
  import path9 from "node:path";
10361
- import { z as z14 } from "zod";
10565
+ import { z as z15 } from "zod";
10362
10566
  async function findRelatedWorkspaceIds(ctx, workspacePath) {
10363
10567
  const targetCommonDir = await getGitCommonDirPath(workspacePath);
10364
10568
  const relatedWorkspaceIds = await Promise.all(
@@ -10391,7 +10595,7 @@ var init_worktree2 = __esm({
10391
10595
  init_worktree();
10392
10596
  init_dispatch();
10393
10597
  init_git_events();
10394
- registerCommand("worktree.list", z14.object({ workspaceId: z14.string() }), async (args, ctx) => {
10598
+ registerCommand("worktree.list", z15.object({ workspaceId: z15.string() }), async (args, ctx) => {
10395
10599
  const workspace = ctx.workspaceMgr.get(args.workspaceId);
10396
10600
  if (!workspace) {
10397
10601
  throw { code: "workspace_not_found", message: `Workspace not found: ${args.workspaceId}` };
@@ -10400,7 +10604,7 @@ var init_worktree2 = __esm({
10400
10604
  });
10401
10605
  registerCommand(
10402
10606
  "worktree.status",
10403
- z14.object({ workspaceId: z14.string(), worktreePath: z14.string() }),
10607
+ z15.object({ workspaceId: z15.string(), worktreePath: z15.string() }),
10404
10608
  async (args, ctx) => {
10405
10609
  const workspace = ctx.workspaceMgr.get(args.workspaceId);
10406
10610
  if (!workspace) {
@@ -10412,10 +10616,10 @@ var init_worktree2 = __esm({
10412
10616
  );
10413
10617
  registerCommand(
10414
10618
  "worktree.diff",
10415
- z14.object({
10416
- workspaceId: z14.string(),
10417
- worktreePath: z14.string(),
10418
- staged: z14.boolean().optional().default(false)
10619
+ z15.object({
10620
+ workspaceId: z15.string(),
10621
+ worktreePath: z15.string(),
10622
+ staged: z15.boolean().optional().default(false)
10419
10623
  }),
10420
10624
  async (args, ctx) => {
10421
10625
  const workspace = ctx.workspaceMgr.get(args.workspaceId);
@@ -10428,7 +10632,7 @@ var init_worktree2 = __esm({
10428
10632
  );
10429
10633
  registerCommand(
10430
10634
  "worktree.tree",
10431
- z14.object({ workspaceId: z14.string(), worktreePath: z14.string() }),
10635
+ z15.object({ workspaceId: z15.string(), worktreePath: z15.string() }),
10432
10636
  async (args, ctx) => {
10433
10637
  const workspace = ctx.workspaceMgr.get(args.workspaceId);
10434
10638
  if (!workspace) {
@@ -10440,10 +10644,10 @@ var init_worktree2 = __esm({
10440
10644
  );
10441
10645
  registerCommand(
10442
10646
  "worktree.create",
10443
- z14.object({
10444
- workspaceId: z14.string(),
10445
- branch: z14.string(),
10446
- path: z14.string()
10647
+ z15.object({
10648
+ workspaceId: z15.string(),
10649
+ branch: z15.string(),
10650
+ path: z15.string()
10447
10651
  }),
10448
10652
  async (args, ctx) => {
10449
10653
  const workspace = ctx.workspaceMgr.get(args.workspaceId);
@@ -10458,10 +10662,10 @@ var init_worktree2 = __esm({
10458
10662
  );
10459
10663
  registerCommand(
10460
10664
  "worktree.remove",
10461
- z14.object({
10462
- workspaceId: z14.string(),
10463
- worktreePath: z14.string(),
10464
- force: z14.boolean().optional().default(false)
10665
+ z15.object({
10666
+ workspaceId: z15.string(),
10667
+ worktreePath: z15.string(),
10668
+ force: z15.boolean().optional().default(false)
10465
10669
  }),
10466
10670
  async (args, ctx) => {
10467
10671
  const workspace = ctx.workspaceMgr.get(args.workspaceId);
@@ -10485,7 +10689,7 @@ var init_worktree2 = __esm({
10485
10689
  });
10486
10690
 
10487
10691
  // packages/server/src/commands/fencing.ts
10488
- import { z as z15 } from "zod";
10692
+ import { z as z16 } from "zod";
10489
10693
  function createMockFencingRequest() {
10490
10694
  return {
10491
10695
  ip: "127.0.0.1",
@@ -10498,9 +10702,9 @@ var init_fencing2 = __esm({
10498
10702
  init_dispatch();
10499
10703
  registerCommand(
10500
10704
  "fencing.request",
10501
- z15.object({
10502
- workspaceId: z15.string(),
10503
- tabId: z15.string()
10705
+ z16.object({
10706
+ workspaceId: z16.string(),
10707
+ tabId: z16.string()
10504
10708
  }),
10505
10709
  async (args, ctx, clientId) => {
10506
10710
  return ctx.fencingMgr.requestControl(
@@ -10513,7 +10717,7 @@ var init_fencing2 = __esm({
10513
10717
  );
10514
10718
  registerCommand(
10515
10719
  "fencing.heartbeat",
10516
- z15.object({ workspaceId: z15.string() }),
10720
+ z16.object({ workspaceId: z16.string() }),
10517
10721
  async (args, ctx, clientId) => {
10518
10722
  const success = ctx.fencingMgr.heartbeat(args.workspaceId, clientId);
10519
10723
  return { success };
@@ -10521,13 +10725,13 @@ var init_fencing2 = __esm({
10521
10725
  );
10522
10726
  registerCommand(
10523
10727
  "fencing.release",
10524
- z15.object({ workspaceId: z15.string() }),
10728
+ z16.object({ workspaceId: z16.string() }),
10525
10729
  async (args, ctx, clientId) => {
10526
10730
  ctx.fencingMgr.release(args.workspaceId, clientId);
10527
10731
  return {};
10528
10732
  }
10529
10733
  );
10530
- registerCommand("fencing.status", z15.object({ workspaceId: z15.string() }), async (args, ctx) => {
10734
+ registerCommand("fencing.status", z16.object({ workspaceId: z16.string() }), async (args, ctx) => {
10531
10735
  const controller = ctx.fencingMgr.getController(args.workspaceId);
10532
10736
  const isUnresponsive = ctx.fencingMgr.isControllerUnresponsive(args.workspaceId);
10533
10737
  return {
@@ -10538,9 +10742,9 @@ var init_fencing2 = __esm({
10538
10742
  });
10539
10743
  registerCommand(
10540
10744
  "fencing.takeover",
10541
- z15.object({
10542
- workspaceId: z15.string(),
10543
- tabId: z15.string()
10745
+ z16.object({
10746
+ workspaceId: z16.string(),
10747
+ tabId: z16.string()
10544
10748
  }),
10545
10749
  async (args, ctx, clientId) => {
10546
10750
  return ctx.fencingMgr.forceTakeover(
@@ -10560,6 +10764,7 @@ var init_commands = __esm({
10560
10764
  "use strict";
10561
10765
  init_workspace();
10562
10766
  init_workspace_activity();
10767
+ init_connection();
10563
10768
  init_session();
10564
10769
  init_terminal();
10565
10770
  init_file();
@@ -10643,6 +10848,7 @@ async function createServer(configOverrides) {
10643
10848
  (err) => console.warn("[uploads] cascade cleanup failed", { wsId: workspaceId, err })
10644
10849
  )
10645
10850
  });
10851
+ workspaceMgr.hydrateWatchers();
10646
10852
  const authSessionRepo = new AuthSessionRepo(db);
10647
10853
  const authLoginBlockRepo = new AuthLoginBlockRepo(db);
10648
10854
  const app = await buildFastifyApp({
@@ -10682,10 +10888,13 @@ async function createServer(configOverrides) {
10682
10888
  });
10683
10889
  await sessionMgr.hydrate();
10684
10890
  await supervisorMgr.hydrate();
10685
- const providerRuntimeDeps = {};
10891
+ const providerMockOverrides = createE2EProviderMockOverrides();
10892
+ const providerRuntimeDeps = providerMockOverrides ? {
10893
+ commandExists: providerMockOverrides.commandExists
10894
+ } : {};
10686
10895
  const providerInstallMgr = new ProviderInstallManager(providerRegistry, {
10687
10896
  ...providerRuntimeDeps,
10688
- runCommand: runCommandAsString
10897
+ runCommand: providerMockOverrides?.runCommand ?? runCommandAsString
10689
10898
  });
10690
10899
  commandContext = {
10691
10900
  workspaceMgr,
@@ -10724,11 +10933,16 @@ async function createServer(configOverrides) {
10724
10933
  );
10725
10934
  }, STARTUP_GC_DELAY_MS);
10726
10935
  gcTimer.unref();
10936
+ const wsKeepaliveTimer = setInterval(() => {
10937
+ wsHub.pingAll();
10938
+ }, WS_KEEPALIVE_INTERVAL_MS);
10939
+ wsKeepaliveTimer.unref();
10727
10940
  let stopped = false;
10728
10941
  const stopServer = async () => {
10729
10942
  if (stopped) return;
10730
10943
  stopped = true;
10731
10944
  clearTimeout(gcTimer);
10945
+ clearInterval(wsKeepaliveTimer);
10732
10946
  await app.close();
10733
10947
  autoFetch.stop();
10734
10948
  supervisorMgr.stop();
@@ -10844,6 +11058,7 @@ function createSessionDatabase(db) {
10844
11058
  }
10845
11059
  };
10846
11060
  }
11061
+ var WS_KEEPALIVE_INTERVAL_MS;
10847
11062
  var init_server = __esm({
10848
11063
  async "packages/server/src/server.ts"() {
10849
11064
  "use strict";
@@ -10855,6 +11070,7 @@ var init_server = __esm({
10855
11070
  init_config();
10856
11071
  init_auto_fetch();
10857
11072
  init_command_runner();
11073
+ init_e2e_provider_mock();
10858
11074
  init_install_manager();
10859
11075
  init_manager();
10860
11076
  init_db();
@@ -10875,6 +11091,7 @@ var init_server = __esm({
10875
11091
  init_fencing();
10876
11092
  init_hub();
10877
11093
  init_commands();
11094
+ WS_KEEPALIVE_INTERVAL_MS = 15e3;
10878
11095
  if (isDirectExecution(import.meta.url)) {
10879
11096
  const server = await createServer();
10880
11097
  process.on("SIGINT", async () => {