@karlorz/codexhost-cli-darwin-x64 0.13.3-6 → 0.13.3-7

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.
@@ -5,7 +5,7 @@ var __export = (target, all) => {
5
5
  };
6
6
 
7
7
  // packages/console-server/src/main.ts
8
- import path19 from "node:path";
8
+ import path21 from "node:path";
9
9
  import { fileURLToPath } from "node:url";
10
10
 
11
11
  // packages/update-manager/dist/runtime-metadata.js
@@ -891,7 +891,7 @@ function createBackgroundUpdateManager(dependencies = {}) {
891
891
  }
892
892
 
893
893
  // packages/console-server/src/harnesses.ts
894
- import path10 from "node:path";
894
+ import path12 from "node:path";
895
895
 
896
896
  // packages/harness-plugin-files/dist/discovery.js
897
897
  import { readdir as readdir2, realpath as realpath2 } from "node:fs/promises";
@@ -1663,10 +1663,10 @@ function mergeDefs(...defs) {
1663
1663
  function cloneDef(schema) {
1664
1664
  return mergeDefs(schema._zod.def);
1665
1665
  }
1666
- function getElementAtPath(obj, path20) {
1667
- if (!path20)
1666
+ function getElementAtPath(obj, path22) {
1667
+ if (!path22)
1668
1668
  return obj;
1669
- return path20.reduce((acc, key) => acc?.[key], obj);
1669
+ return path22.reduce((acc, key) => acc?.[key], obj);
1670
1670
  }
1671
1671
  function promiseAllObject(promisesObj) {
1672
1672
  const keys = Object.keys(promisesObj);
@@ -2075,11 +2075,11 @@ function explicitlyAborted(x, startIndex = 0) {
2075
2075
  }
2076
2076
  return false;
2077
2077
  }
2078
- function prefixIssues(path20, issues) {
2078
+ function prefixIssues(path22, issues) {
2079
2079
  return issues.map((iss) => {
2080
2080
  var _a3;
2081
2081
  (_a3 = iss).path ?? (_a3.path = []);
2082
- iss.path.unshift(path20);
2082
+ iss.path.unshift(path22);
2083
2083
  return iss;
2084
2084
  });
2085
2085
  }
@@ -2226,16 +2226,16 @@ function flattenError(error51, mapper = (issue2) => issue2.message) {
2226
2226
  }
2227
2227
  function formatError(error51, mapper = (issue2) => issue2.message) {
2228
2228
  const fieldErrors = { _errors: [] };
2229
- const processError = (error52, path20 = []) => {
2229
+ const processError = (error52, path22 = []) => {
2230
2230
  for (const issue2 of error52.issues) {
2231
2231
  if (issue2.code === "invalid_union" && issue2.errors.length) {
2232
- issue2.errors.map((issues) => processError({ issues }, [...path20, ...issue2.path]));
2232
+ issue2.errors.map((issues) => processError({ issues }, [...path22, ...issue2.path]));
2233
2233
  } else if (issue2.code === "invalid_key") {
2234
- processError({ issues: issue2.issues }, [...path20, ...issue2.path]);
2234
+ processError({ issues: issue2.issues }, [...path22, ...issue2.path]);
2235
2235
  } else if (issue2.code === "invalid_element") {
2236
- processError({ issues: issue2.issues }, [...path20, ...issue2.path]);
2236
+ processError({ issues: issue2.issues }, [...path22, ...issue2.path]);
2237
2237
  } else {
2238
- const fullpath = [...path20, ...issue2.path];
2238
+ const fullpath = [...path22, ...issue2.path];
2239
2239
  if (fullpath.length === 0) {
2240
2240
  fieldErrors._errors.push(mapper(issue2));
2241
2241
  } else {
@@ -2262,17 +2262,17 @@ function formatError(error51, mapper = (issue2) => issue2.message) {
2262
2262
  }
2263
2263
  function treeifyError(error51, mapper = (issue2) => issue2.message) {
2264
2264
  const result = { errors: [] };
2265
- const processError = (error52, path20 = []) => {
2265
+ const processError = (error52, path22 = []) => {
2266
2266
  var _a3, _b;
2267
2267
  for (const issue2 of error52.issues) {
2268
2268
  if (issue2.code === "invalid_union" && issue2.errors.length) {
2269
- issue2.errors.map((issues) => processError({ issues }, [...path20, ...issue2.path]));
2269
+ issue2.errors.map((issues) => processError({ issues }, [...path22, ...issue2.path]));
2270
2270
  } else if (issue2.code === "invalid_key") {
2271
- processError({ issues: issue2.issues }, [...path20, ...issue2.path]);
2271
+ processError({ issues: issue2.issues }, [...path22, ...issue2.path]);
2272
2272
  } else if (issue2.code === "invalid_element") {
2273
- processError({ issues: issue2.issues }, [...path20, ...issue2.path]);
2273
+ processError({ issues: issue2.issues }, [...path22, ...issue2.path]);
2274
2274
  } else {
2275
- const fullpath = [...path20, ...issue2.path];
2275
+ const fullpath = [...path22, ...issue2.path];
2276
2276
  if (fullpath.length === 0) {
2277
2277
  result.errors.push(mapper(issue2));
2278
2278
  continue;
@@ -2304,8 +2304,8 @@ function treeifyError(error51, mapper = (issue2) => issue2.message) {
2304
2304
  }
2305
2305
  function toDotPath(_path) {
2306
2306
  const segs = [];
2307
- const path20 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
2308
- for (const seg of path20) {
2307
+ const path22 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
2308
+ for (const seg of path22) {
2309
2309
  if (typeof seg === "number")
2310
2310
  segs.push(`[${seg}]`);
2311
2311
  else if (typeof seg === "symbol")
@@ -14997,13 +14997,13 @@ function resolveRef(ref, ctx) {
14997
14997
  if (!ref.startsWith("#")) {
14998
14998
  throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
14999
14999
  }
15000
- const path20 = ref.slice(1).split("/").filter(Boolean);
15001
- if (path20.length === 0) {
15000
+ const path22 = ref.slice(1).split("/").filter(Boolean);
15001
+ if (path22.length === 0) {
15002
15002
  return ctx.rootSchema;
15003
15003
  }
15004
15004
  const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
15005
- if (path20[0] === defsKey) {
15006
- const key = path20[1];
15005
+ if (path22[0] === defsKey) {
15006
+ const key = path22[1];
15007
15007
  if (!key || !ctx.defs[key]) {
15008
15008
  throw new Error(`Reference not found: ${ref}`);
15009
15009
  }
@@ -15720,6 +15720,8 @@ var CONSOLE_HOST_METHODS = Object.freeze([
15720
15720
  "codexhost/harness/installation",
15721
15721
  "codexhost/harness/launch-settings/get",
15722
15722
  "codexhost/harness/launch-settings/set",
15723
+ "codexhost/harness/grok-computer-use/get",
15724
+ "codexhost/harness/grok-computer-use/set",
15723
15725
  "codexhost/harness/web-ui/open",
15724
15726
  "codexhost/harness/accounts/sources",
15725
15727
  "codexhost/harness/accounts/list",
@@ -16251,7 +16253,9 @@ var harnessInspectionSchema = external_exports.union([
16251
16253
  var harnessInspectParamsSchema = external_exports.object({
16252
16254
  harnessId: harnessIdSchema,
16253
16255
  cwd: nonBlankTextSchema2.max(16384).optional(),
16254
- refresh: external_exports.boolean().optional()
16256
+ refresh: external_exports.boolean().optional(),
16257
+ /** `availability` asks only whether the Harness can run; see `InspectHarnessInput.purpose`. */
16258
+ purpose: external_exports.literal("availability").optional()
16255
16259
  }).strict();
16256
16260
  var harnessWebUiOpenParamsSchema = external_exports.object({
16257
16261
  harnessId: harnessIdSchema
@@ -16425,6 +16429,26 @@ var harnessLaunchSettingsSchema = external_exports.object({
16425
16429
  restartRequired: external_exports.boolean()
16426
16430
  }).strict();
16427
16431
 
16432
+ // packages/shared-contracts/dist/grok-computer-use.js
16433
+ var grokComputerUseGetSchema = external_exports.object({}).strict();
16434
+ var grokComputerUseSetSchema = external_exports.object({
16435
+ enabled: external_exports.boolean().optional(),
16436
+ browser: external_exports.boolean().optional()
16437
+ }).strict().refine((value) => value.enabled !== void 0 || value.browser !== void 0, {
16438
+ message: "Expected enabled or browser"
16439
+ });
16440
+ var grokComputerUseSettingsSchema = external_exports.object({
16441
+ enabled: external_exports.boolean(),
16442
+ available: external_exports.boolean(),
16443
+ unavailableReason: external_exports.string().min(1).max(500).optional(),
16444
+ browser: external_exports.boolean().optional(),
16445
+ browserFilesPresent: external_exports.boolean().optional(),
16446
+ browserAvailable: external_exports.boolean().optional(),
16447
+ browserUnavailableReason: external_exports.string().min(1).max(500).optional(),
16448
+ applyFailed: external_exports.boolean().optional(),
16449
+ applyError: external_exports.string().min(1).max(500).optional()
16450
+ }).strict();
16451
+
16428
16452
  // packages/shared-contracts/dist/harness-installation.js
16429
16453
  var harnessInstallationParamsSchema = external_exports.object({
16430
16454
  harnessId: harnessIdSchema,
@@ -17057,23 +17081,365 @@ var HarnessLaunchSettingsStore = class {
17057
17081
  }
17058
17082
  };
17059
17083
 
17060
- // packages/console-server/src/paths.ts
17084
+ // packages/harness-plugin-files/dist/grok-computer-use.js
17085
+ import { randomUUID as randomUUID3 } from "node:crypto";
17086
+ import { access, mkdir as mkdir5, readFile as readFile5, rename as rename3, rm as rm5, writeFile as writeFile4 } from "node:fs/promises";
17061
17087
  import os2 from "node:os";
17088
+ import path10 from "node:path";
17089
+
17090
+ // packages/harness-plugin-files/dist/grok-computer-use-lock.js
17091
+ import { mkdir as mkdir4, rm as rm4 } from "node:fs/promises";
17062
17092
  import path9 from "node:path";
17093
+ import { setTimeout as delay3 } from "node:timers/promises";
17094
+ async function withGrokComputerUseLock(dataDirectory3, grokHome2, operation) {
17095
+ const locks = [
17096
+ .../* @__PURE__ */ new Set([
17097
+ path9.join(dataDirectory3, ".grok-computer-use.lock"),
17098
+ path9.join(grokHome2, ".codexhost-cua.lock")
17099
+ ])
17100
+ ].sort();
17101
+ const acquired = [];
17102
+ const deadline = Date.now() + 5e3;
17103
+ try {
17104
+ for (const lock of locks) {
17105
+ await mkdir4(path9.dirname(lock), { recursive: true, mode: 448 });
17106
+ for (; ; ) {
17107
+ try {
17108
+ await mkdir4(lock, { mode: 448 });
17109
+ acquired.push(lock);
17110
+ break;
17111
+ } catch (error51) {
17112
+ if (error51.code !== "EEXIST")
17113
+ throw error51;
17114
+ if (Date.now() >= deadline)
17115
+ throw new Error("Grok Computer Use settings are locked");
17116
+ await delay3(25);
17117
+ }
17118
+ }
17119
+ }
17120
+ return await operation();
17121
+ } finally {
17122
+ for (const lock of acquired.reverse())
17123
+ await rm4(lock, { recursive: true });
17124
+ }
17125
+ }
17126
+
17127
+ // packages/harness-plugin-files/dist/grok-computer-use.js
17128
+ var GROK_BROWSER_BINDING_SUPPORTED = false;
17129
+ var PREFERENCE_FILE = "grok-computer-use.json";
17130
+ var TABLE = "[mcp_servers.cua_repl]";
17131
+ var ENV_TABLE = "[mcp_servers.cua_repl.env]";
17132
+ var COMPUTER_UNAVAILABLE = "ChatGPT Desktop Computer Use files were not found. Install ChatGPT.app with Computer Use, then try again.";
17133
+ var BROWSER_FILES_UNAVAILABLE = "ChatGPT Desktop in-app browser files were not found. Update ChatGPT.app, then try again.";
17134
+ var BROWSER_UNSUPPORTED = "ChatGPT Desktop does not authorize Grok to use the in-app browser. The preference is saved as intent until Desktop supports an external Harness.";
17135
+ var APPLY_FAILED = "Could not apply Grok Computer Use settings to Grok config.";
17136
+ var GrokComputerUseError = class extends Error {
17137
+ constructor(message) {
17138
+ super(message);
17139
+ this.name = "GrokComputerUseError";
17140
+ }
17141
+ };
17142
+ function dataDirectory(environment) {
17143
+ return environment.CODEXHOST_DATA_DIR ? path10.resolve(environment.CODEXHOST_DATA_DIR) : path10.join(os2.homedir(), ".codexhost");
17144
+ }
17145
+ function grokHome(environment) {
17146
+ return environment.GROK_HOME ? path10.resolve(environment.GROK_HOME) : path10.join(environment.HOME ?? os2.homedir(), ".grok");
17147
+ }
17148
+ function chatgptApp(environment, platform) {
17149
+ if (environment.CODEXHOST_CHATGPT_APP)
17150
+ return path10.resolve(environment.CODEXHOST_CHATGPT_APP);
17151
+ if (platform === "darwin")
17152
+ return "/Applications/ChatGPT.app";
17153
+ return void 0;
17154
+ }
17155
+ async function isFile(target) {
17156
+ try {
17157
+ await access(target);
17158
+ return true;
17159
+ } catch {
17160
+ return false;
17161
+ }
17162
+ }
17163
+ function isNotFound(error51) {
17164
+ return Boolean(error51 && typeof error51 === "object" && "code" in error51 && error51.code === "ENOENT");
17165
+ }
17166
+ async function writeAtomically(file2, content) {
17167
+ await mkdir5(path10.dirname(file2), { recursive: true, mode: 448 });
17168
+ const temporary = `${file2}.${randomUUID3()}.tmp`;
17169
+ try {
17170
+ await writeFile4(temporary, content, { mode: 384, flag: "wx" });
17171
+ await rename3(temporary, file2);
17172
+ } finally {
17173
+ await rm5(temporary, { force: true });
17174
+ }
17175
+ }
17176
+ function launchPaths(environment, platform) {
17177
+ const app = chatgptApp(environment, platform);
17178
+ if (!app)
17179
+ return void 0;
17180
+ const resources = path10.join(app, "Contents", "Resources");
17181
+ const cuaNode = path10.join(resources, "cua_node");
17182
+ return {
17183
+ node: path10.join(cuaNode, "bin", "node"),
17184
+ cuaRepl: path10.join(cuaNode, "lib", "node_modules", "@oai", "cua-repl", "bin", "cua-repl.mjs"),
17185
+ nodeRepl: path10.join(cuaNode, "bin", "node_repl"),
17186
+ nodeModules: path10.join(cuaNode, "lib", "node_modules"),
17187
+ codexCli: path10.join(resources, "codex-cli", "bin", "codex"),
17188
+ skyApp: path10.join(environment.HOME ?? os2.homedir(), ".codex", "computer-use", "Codex Computer Use.app"),
17189
+ codexHome: path10.join(environment.HOME ?? os2.homedir(), ".codex"),
17190
+ browserDesktop: path10.join(cuaNode, "lib", "node_modules", "@oai", "browser-desktop")
17191
+ };
17192
+ }
17193
+ async function sharedRuntimePresent(launch) {
17194
+ const present = await Promise.all([launch.node, launch.cuaRepl, launch.nodeRepl].map(isFile));
17195
+ return present.every(Boolean);
17196
+ }
17197
+ async function computerFilesPresent(launch) {
17198
+ const present = await Promise.all([isFile(launch.skyApp), isFile(launch.codexCli)]);
17199
+ return present.every(Boolean);
17200
+ }
17201
+ async function browserFilesPresent(launch) {
17202
+ return isFile(path10.join(launch.browserDesktop, "package.json"));
17203
+ }
17204
+ async function discoverGrokComputerUseLaunch(environment = process.env, platform = process.platform) {
17205
+ const launch = launchPaths(environment, platform);
17206
+ if (!launch || !await sharedRuntimePresent(launch))
17207
+ return void 0;
17208
+ return launch;
17209
+ }
17210
+ function tableRange(text, header) {
17211
+ const lines = text.split(/\n/);
17212
+ let start = -1;
17213
+ for (let index = 0; index < lines.length; index += 1) {
17214
+ if (lines[index] === header) {
17215
+ start = index;
17216
+ break;
17217
+ }
17218
+ }
17219
+ if (start < 0)
17220
+ return void 0;
17221
+ let end = lines.length;
17222
+ for (let index = start + 1; index < lines.length; index += 1) {
17223
+ const line = lines[index] ?? "";
17224
+ if (line.startsWith("[") && line.endsWith("]")) {
17225
+ end = index;
17226
+ break;
17227
+ }
17228
+ }
17229
+ return { start, end };
17230
+ }
17231
+ function removeTables(text, headers) {
17232
+ let current = text;
17233
+ for (const header of headers) {
17234
+ const range = tableRange(current, header);
17235
+ if (!range)
17236
+ continue;
17237
+ const lines = current.split(/\n/);
17238
+ lines.splice(range.start, range.end - range.start);
17239
+ current = lines.join("\n");
17240
+ }
17241
+ return current.replace(/\n{3,}/g, "\n\n");
17242
+ }
17243
+ function cuaReplEnabledInToml(text) {
17244
+ const range = tableRange(text, TABLE);
17245
+ if (!range)
17246
+ return false;
17247
+ const body = text.split(/\n/).slice(range.start, range.end);
17248
+ for (const line of body) {
17249
+ if (/^enabled\s*=\s*false\b/u.test(line))
17250
+ return false;
17251
+ if (/^enabled\s*=\s*true\b/u.test(line))
17252
+ return true;
17253
+ }
17254
+ return true;
17255
+ }
17256
+ function inferredSurfaces(text) {
17257
+ if (!cuaReplEnabledInToml(text))
17258
+ return { enabled: false, browser: false };
17259
+ const range = tableRange(text, ENV_TABLE);
17260
+ const body = range ? text.split(/\n/).slice(range.start, range.end).join("\n") : "";
17261
+ const literal2 = /^CUA_REPL_ENABLED_SURFACES\s*=\s*(["'])([^"']*)\1\s*(?:#.*)?$/mu.exec(body);
17262
+ if (!literal2)
17263
+ return { enabled: true, browser: false };
17264
+ const surfaces = new Set(literal2[2]?.split(",").map((surface) => surface.trim()));
17265
+ return { enabled: surfaces.has("computer"), browser: surfaces.has("browser") };
17266
+ }
17267
+ function stanza(launch, state) {
17268
+ const trusted = `${launch.codexHome}:${launch.nodeModules}`;
17269
+ const services = {};
17270
+ if (state.browser)
17271
+ services.browser = "@oai/browser-desktop/service";
17272
+ if (state.enabled)
17273
+ services.sky = "@oai/sky/service";
17274
+ const surfaces = [state.browser ? "browser" : "", state.enabled ? "computer" : ""].filter(Boolean).join(",");
17275
+ const backends = state.browser ? 'BROWSER_USE_AVAILABLE_BACKENDS = "iab"\n' : "";
17276
+ const active = state.enabled || state.browser;
17277
+ return `${TABLE}
17278
+ command = ${JSON.stringify(launch.node)}
17279
+ args = [${JSON.stringify(launch.cuaRepl)}]
17280
+ enabled = ${active ? "true" : "false"}
17281
+ startup_timeout_sec = 120
17282
+
17283
+ ${ENV_TABLE}
17284
+ NODE_REPL_TRUSTED_SERVICES = ${JSON.stringify(JSON.stringify(services))}
17285
+ NODE_REPL_TRUSTED_CODE_PATHS = ${JSON.stringify(trusted)}
17286
+ NODE_REPL_NODE_PATH = ${JSON.stringify(launch.node)}
17287
+ CODEX_HOME = ${JSON.stringify(launch.codexHome)}
17288
+ CUA_REPL_NODE_REPL_PATH = ${JSON.stringify(launch.nodeRepl)}
17289
+ NODE_REPL_NODE_MODULE_DIRS = ${JSON.stringify(launch.nodeModules)}
17290
+ NODE_REPL_NATIVE_PIPE_CONNECT_TIMEOUT_MS = "1000"
17291
+ SKY_CUA_SERVICE_PATH = ${JSON.stringify(launch.skyApp)}
17292
+ CODEX_CLI_PATH = ${JSON.stringify(launch.codexCli)}
17293
+ ${backends}CUA_REPL_ENABLED_SURFACES = ${JSON.stringify(surfaces)}
17294
+ `;
17295
+ }
17296
+ async function readPreference(environment) {
17297
+ try {
17298
+ const document = JSON.parse(await readFile5(path10.join(dataDirectory(environment), PREFERENCE_FILE), "utf8"));
17299
+ return {
17300
+ ...typeof document.enabled === "boolean" ? { enabled: document.enabled } : {},
17301
+ ...typeof document.browser === "boolean" ? { browser: document.browser } : {},
17302
+ ...typeof document.applyError === "string" && document.applyError ? { applyError: document.applyError } : {}
17303
+ };
17304
+ } catch (error51) {
17305
+ if (isNotFound(error51))
17306
+ return void 0;
17307
+ throw new GrokComputerUseError("Could not read Grok Computer Use settings");
17308
+ }
17309
+ }
17310
+ async function writePreference(environment, state) {
17311
+ const document = {
17312
+ ...typeof state.enabled === "boolean" ? { enabled: state.enabled } : {},
17313
+ ...typeof state.browser === "boolean" ? { browser: state.browser } : {},
17314
+ ...state.applyError ? { applyError: state.applyError } : {}
17315
+ };
17316
+ await writeAtomically(path10.join(dataDirectory(environment), PREFERENCE_FILE), `${JSON.stringify(document)}
17317
+ `);
17318
+ }
17319
+ async function readGrokConfig(environment) {
17320
+ try {
17321
+ return await readFile5(path10.join(grokHome(environment), "config.toml"), "utf8");
17322
+ } catch (error51) {
17323
+ if (isNotFound(error51))
17324
+ return "";
17325
+ throw new GrokComputerUseError("Could not read Grok config");
17326
+ }
17327
+ }
17328
+ async function writeGrokConfig(environment, text) {
17329
+ await writeAtomically(path10.join(grokHome(environment), "config.toml"), text.endsWith("\n") ? text : `${text}
17330
+ `);
17331
+ }
17332
+ async function currentState(environment, preference) {
17333
+ const resolved = preference ?? await readPreference(environment);
17334
+ const inferred = resolved?.enabled === void 0 ? inferredSurfaces(await readGrokConfig(environment)) : void 0;
17335
+ return {
17336
+ enabled: resolved?.enabled ?? inferred?.enabled ?? false,
17337
+ browser: resolved ? resolved.browser ?? false : inferred?.browser ?? false,
17338
+ ...resolved?.applyError ? { applyError: resolved.applyError } : {}
17339
+ };
17340
+ }
17341
+ function settingsFrom(state, files) {
17342
+ const bindable = files.browser && GROK_BROWSER_BINDING_SUPPORTED;
17343
+ return {
17344
+ enabled: state.enabled,
17345
+ available: files.computer,
17346
+ ...files.computer ? {} : { unavailableReason: COMPUTER_UNAVAILABLE },
17347
+ browser: state.browser,
17348
+ browserFilesPresent: files.browser,
17349
+ browserAvailable: bindable,
17350
+ ...bindable ? {} : {
17351
+ browserUnavailableReason: files.browser ? BROWSER_UNSUPPORTED : BROWSER_FILES_UNAVAILABLE
17352
+ },
17353
+ ...state.applyError ? { applyFailed: true, applyError: state.applyError } : {}
17354
+ };
17355
+ }
17356
+ async function surfaceFiles(launch) {
17357
+ if (!launch)
17358
+ return { computer: false, browser: false };
17359
+ const [computer, browser] = await Promise.all([
17360
+ computerFilesPresent(launch),
17361
+ browserFilesPresent(launch)
17362
+ ]);
17363
+ return { computer, browser };
17364
+ }
17365
+ async function getGrokComputerUseSettings(environment = process.env, platform = process.platform) {
17366
+ const launch = await discoverGrokComputerUseLaunch(environment, platform);
17367
+ return settingsFrom(await currentState(environment), await surfaceFiles(launch));
17368
+ }
17369
+ async function writeConfigForState(state, launch, files, environment) {
17370
+ const current = await readGrokConfig(environment);
17371
+ const range = tableRange(current, TABLE);
17372
+ const effective = {
17373
+ enabled: state.enabled && files.computer,
17374
+ browser: state.browser && files.browser && GROK_BROWSER_BINDING_SUPPORTED
17375
+ };
17376
+ if (!effective.enabled && !effective.browser && !range)
17377
+ return;
17378
+ if (!launch) {
17379
+ if (!range)
17380
+ return;
17381
+ const lines = current.split(/\n/);
17382
+ const body = lines.slice(range.start, range.end);
17383
+ const replaced = body.map((line) => /^enabled\s*=/u.test(line) ? "enabled = false" : line);
17384
+ if (!replaced.some((line) => /^enabled\s*=/u.test(line))) {
17385
+ replaced.splice(1, 0, "enabled = false");
17386
+ }
17387
+ lines.splice(range.start, range.end - range.start, ...replaced);
17388
+ await writeGrokConfig(environment, lines.join("\n"));
17389
+ return;
17390
+ }
17391
+ const stripped = removeTables(current, [ENV_TABLE, TABLE]).replace(/\s+$/u, "\n");
17392
+ await writeGrokConfig(environment, `${stripped.trimEnd()}
17393
+
17394
+ ${stanza(launch, effective)}`);
17395
+ }
17396
+ async function setGrokComputerUse(update, environment = process.env, platform = process.platform) {
17397
+ return withGrokComputerUseLock(dataDirectory(environment), grokHome(environment), async () => {
17398
+ const launch = await discoverGrokComputerUseLaunch(environment, platform);
17399
+ const files = await surfaceFiles(launch);
17400
+ if (update.enabled && !files.computer) {
17401
+ throw new GrokComputerUseError(COMPUTER_UNAVAILABLE);
17402
+ }
17403
+ if (update.browser && !files.browser) {
17404
+ throw new GrokComputerUseError(BROWSER_FILES_UNAVAILABLE);
17405
+ }
17406
+ const previous = await currentState(environment);
17407
+ const state = {
17408
+ enabled: update.enabled ?? previous.enabled,
17409
+ browser: update.browser ?? previous.browser
17410
+ };
17411
+ try {
17412
+ await writeConfigForState(state, launch, files, environment);
17413
+ await writePreference(environment, state);
17414
+ } catch (error51) {
17415
+ await writeConfigForState(previous, launch, files, environment).catch(() => void 0);
17416
+ const applyError = error51 instanceof GrokComputerUseError ? error51.message : APPLY_FAILED;
17417
+ await writePreference(environment, { ...previous, applyError }).catch(() => void 0);
17418
+ if (error51 instanceof GrokComputerUseError)
17419
+ throw error51;
17420
+ throw new GrokComputerUseError(APPLY_FAILED);
17421
+ }
17422
+ return settingsFrom(state, files);
17423
+ });
17424
+ }
17425
+
17426
+ // packages/console-server/src/paths.ts
17427
+ import os3 from "node:os";
17428
+ import path11 from "node:path";
17063
17429
  var DEFAULT_CONSOLE_PORT = 4399;
17064
17430
  var CONSOLE_PORT_ENV = "CODEXHOST_CONSOLE_PORT";
17065
17431
  var LAUNCHER_EXECUTABLE_ENV = "CODEXHOST_LAUNCHER_EXECUTABLE";
17066
- function dataDirectory(environment = process.env) {
17067
- return environment.CODEXHOST_DATA_DIR ? path9.resolve(environment.CODEXHOST_DATA_DIR) : path9.join(os2.homedir(), ".codexhost");
17432
+ function dataDirectory2(environment = process.env) {
17433
+ return environment.CODEXHOST_DATA_DIR ? path11.resolve(environment.CODEXHOST_DATA_DIR) : path11.join(os3.homedir(), ".codexhost");
17068
17434
  }
17069
17435
  function consolePaths(environment = process.env) {
17070
- const root = dataDirectory(environment);
17436
+ const root = dataDirectory2(environment);
17071
17437
  return {
17072
17438
  dataDirectory: root,
17073
- startupRecordFile: path9.join(root, "diagnostics", "launcher-startup-v1.json"),
17074
- controllerStatusFile: path9.join(root, "diagnostics", "desktop-controller-v1.json"),
17075
- logsDirectory: path9.join(root, "logs"),
17076
- hostDescriptorDirectory: path9.join(root, "console", "hosts")
17439
+ startupRecordFile: path11.join(root, "diagnostics", "launcher-startup-v1.json"),
17440
+ controllerStatusFile: path11.join(root, "diagnostics", "desktop-controller-v1.json"),
17441
+ logsDirectory: path11.join(root, "logs"),
17442
+ hostDescriptorDirectory: path11.join(root, "console", "hosts")
17077
17443
  };
17078
17444
  }
17079
17445
  function consolePort(environment = process.env) {
@@ -17089,10 +17455,10 @@ function consolePort(environment = process.env) {
17089
17455
  // packages/console-server/src/harnesses.ts
17090
17456
  var HARNESS_PLUGIN_DIRECTORY_ENV = "CODEXHOST_PLUGIN_DIRECTORY";
17091
17457
  function harnessPluginRoots(appDirectory2, sourceCheckout, environment = process.env) {
17092
- const bundled = sourceCheckout ? path10.resolve(appDirectory2, "..", "..", "host-runtime", "dist", "plugins") : path10.join(appDirectory2, "plugins");
17458
+ const bundled = sourceCheckout ? path12.resolve(appDirectory2, "..", "..", "host-runtime", "dist", "plugins") : path12.join(appDirectory2, "plugins");
17093
17459
  return [
17094
17460
  bundled,
17095
- environment[HARNESS_PLUGIN_DIRECTORY_ENV] ?? path10.join(dataDirectory(environment), "plugins")
17461
+ environment[HARNESS_PLUGIN_DIRECTORY_ENV] ?? path12.join(dataDirectory2(environment), "plugins")
17096
17462
  ];
17097
17463
  }
17098
17464
  var ConsoleHarnessError = class extends Error {
@@ -17126,7 +17492,8 @@ function createConsoleHarnesses(roots, environment = process.env) {
17126
17492
  launchCommand: manifest.launchCommand === true,
17127
17493
  links: manifest.links ?? null,
17128
17494
  icon,
17129
- launchPath
17495
+ launchPath,
17496
+ ...manifest.id === "grok" ? { computerUse: await getGrokComputerUseSettings(environment) } : {}
17130
17497
  });
17131
17498
  }
17132
17499
  return harnesses.sort(
@@ -17147,17 +17514,27 @@ function createConsoleHarnesses(roots, environment = process.env) {
17147
17514
  } catch (error51) {
17148
17515
  throw new ConsoleHarnessError(400, error51 instanceof Error ? error51.message : String(error51));
17149
17516
  }
17517
+ },
17518
+ async setGrokComputerUse(update) {
17519
+ const harness2 = (await list()).find((candidate) => candidate.id === "grok");
17520
+ if (!harness2) throw new ConsoleHarnessError(404, "Harness 'grok' is not installed");
17521
+ try {
17522
+ const computerUse = await setGrokComputerUse(update, environment);
17523
+ return { ...harness2, computerUse };
17524
+ } catch (error51) {
17525
+ throw new ConsoleHarnessError(400, error51 instanceof Error ? error51.message : String(error51));
17526
+ }
17150
17527
  }
17151
17528
  };
17152
17529
  }
17153
17530
 
17154
17531
  // packages/console-server/src/host-client.ts
17155
- import { readdir as readdir4, readFile as readFile6, rm as rm4 } from "node:fs/promises";
17156
- import path12 from "node:path";
17532
+ import { readdir as readdir4, readFile as readFile7, rm as rm6 } from "node:fs/promises";
17533
+ import path14 from "node:path";
17157
17534
 
17158
17535
  // packages/console-server/src/diagnostics.ts
17159
- import { open as open4, readdir as readdir3, readFile as readFile5, stat as stat3 } from "node:fs/promises";
17160
- import path11 from "node:path";
17536
+ import { open as open4, readdir as readdir3, readFile as readFile6, stat as stat3 } from "node:fs/promises";
17537
+ import path13 from "node:path";
17161
17538
  var MAX_DIAGNOSTIC_FILE_BYTES = 256 * 1024;
17162
17539
  var MAX_LOG_TAIL_BYTES = 256 * 1024;
17163
17540
  var LOG_FILE_PATTERN = /^host-runtime-\d{1,10}\.log(?:\.1)?$/u;
@@ -17165,7 +17542,7 @@ async function readBoundedJson(filePath) {
17165
17542
  try {
17166
17543
  const metadata = await stat3(filePath);
17167
17544
  if (!metadata.isFile() || metadata.size > MAX_DIAGNOSTIC_FILE_BYTES) return null;
17168
- return JSON.parse(await readFile5(filePath, "utf8"));
17545
+ return JSON.parse(await readFile6(filePath, "utf8"));
17169
17546
  } catch {
17170
17547
  return null;
17171
17548
  }
@@ -17238,7 +17615,7 @@ async function listLogFiles(logsDirectory) {
17238
17615
  const entries = await Promise.all(
17239
17616
  names.filter(isLogFileName).map(async (name) => {
17240
17617
  try {
17241
- const metadata = await stat3(path11.join(logsDirectory, name));
17618
+ const metadata = await stat3(path13.join(logsDirectory, name));
17242
17619
  return metadata.isFile() ? { name, size: metadata.size, modifiedAt: metadata.mtimeMs } : null;
17243
17620
  } catch {
17244
17621
  return null;
@@ -17252,7 +17629,7 @@ async function readLogTail(logsDirectory, name, maxBytes = MAX_LOG_TAIL_BYTES) {
17252
17629
  const limit = Math.max(1, Math.min(maxBytes, MAX_LOG_TAIL_BYTES));
17253
17630
  let handle;
17254
17631
  try {
17255
- handle = await open4(path11.join(logsDirectory, name), "r");
17632
+ handle = await open4(path13.join(logsDirectory, name), "r");
17256
17633
  } catch {
17257
17634
  return null;
17258
17635
  }
@@ -17333,14 +17710,14 @@ async function findHost(descriptorDirectory, isAlive = processIsAlive2) {
17333
17710
  }
17334
17711
  const hosts = [];
17335
17712
  for (const name of names.filter((candidate) => DESCRIPTOR_PATTERN.test(candidate))) {
17336
- const filePath = path12.join(descriptorDirectory, name);
17713
+ const filePath = path14.join(descriptorDirectory, name);
17337
17714
  try {
17338
- const text = await readFile6(filePath, "utf8");
17715
+ const text = await readFile7(filePath, "utf8");
17339
17716
  if (text.length > DESCRIPTOR_MAX_BYTES) continue;
17340
17717
  const endpoint = parseDescriptor(JSON.parse(text));
17341
17718
  if (!endpoint) continue;
17342
17719
  if (isAlive(endpoint.pid)) hosts.push(endpoint);
17343
- else await rm4(filePath, { force: true });
17720
+ else await rm6(filePath, { force: true });
17344
17721
  } catch {
17345
17722
  continue;
17346
17723
  }
@@ -17378,12 +17755,12 @@ function createConsoleHostClient(descriptorDirectory, options = {}) {
17378
17755
  // packages/console-server/src/installation.ts
17379
17756
  import { execFile as execFile2 } from "node:child_process";
17380
17757
  import { existsSync } from "node:fs";
17381
- import { readFile as readFile7 } from "node:fs/promises";
17382
- import path13 from "node:path";
17758
+ import { readFile as readFile8 } from "node:fs/promises";
17759
+ import path15 from "node:path";
17383
17760
  async function readDistribution(appDirectory2) {
17384
17761
  try {
17385
17762
  return parseDistributionMetadata(
17386
- JSON.parse(await readFile7(path13.join(appDirectory2, "codexhost-distribution.json"), "utf8"))
17763
+ JSON.parse(await readFile8(path15.join(appDirectory2, "codexhost-distribution.json"), "utf8"))
17387
17764
  );
17388
17765
  } catch (error51) {
17389
17766
  if (error51.code === "ENOENT") return null;
@@ -17391,17 +17768,17 @@ async function readDistribution(appDirectory2) {
17391
17768
  }
17392
17769
  }
17393
17770
  function installedLauncherCandidates(appDirectory2, platform = process.platform) {
17394
- const resourcesRoot = path13.dirname(appDirectory2);
17771
+ const resourcesRoot = path15.dirname(appDirectory2);
17395
17772
  const suffix = platform === "win32" ? ".exe" : "";
17396
- const candidates = [path13.join(resourcesRoot, "bin", `codexhost${suffix}`)];
17397
- if (platform === "darwin" && path13.basename(resourcesRoot) === "Resources") {
17398
- candidates.unshift(path13.join(path13.dirname(resourcesRoot), "MacOS", "codexhost"));
17773
+ const candidates = [path15.join(resourcesRoot, "bin", `codexhost${suffix}`)];
17774
+ if (platform === "darwin" && path15.basename(resourcesRoot) === "Resources") {
17775
+ candidates.unshift(path15.join(path15.dirname(resourcesRoot), "MacOS", "codexhost"));
17399
17776
  }
17400
17777
  return candidates;
17401
17778
  }
17402
17779
  function resolveLauncherExecutable(appDirectory2, environment = process.env, platform = process.platform, exists = existsSync) {
17403
17780
  const configured = environment[LAUNCHER_EXECUTABLE_ENV];
17404
- if (configured && path13.isAbsolute(configured) && exists(configured)) return configured;
17781
+ if (configured && path15.isAbsolute(configured) && exists(configured)) return configured;
17405
17782
  return installedLauncherCandidates(appDirectory2, platform).find(exists) ?? null;
17406
17783
  }
17407
17784
  async function resolveInstallation(appDirectory2, environment = process.env) {
@@ -17443,7 +17820,7 @@ function launchCommand(installation, environment = process.env, action = "launch
17443
17820
  if (installation.distribution?.distribution === "npm") {
17444
17821
  const node = environment.CODEXHOST_NPM_NODE_PATH;
17445
17822
  const wrapper = environment.CODEXHOST_NPM_LAUNCHER_PATH;
17446
- if (node && wrapper && path13.isAbsolute(node) && path13.isAbsolute(wrapper)) {
17823
+ if (node && wrapper && path15.isAbsolute(node) && path15.isAbsolute(wrapper)) {
17447
17824
  return { command: node, args: [wrapper, ...action === "restart" ? [action] : []] };
17448
17825
  }
17449
17826
  return null;
@@ -17454,11 +17831,11 @@ function launchCommand(installation, environment = process.env, action = "launch
17454
17831
  // packages/console-server/src/open.ts
17455
17832
  import { spawn as spawn3 } from "node:child_process";
17456
17833
  import { stat as stat4 } from "node:fs/promises";
17457
- import path18 from "node:path";
17834
+ import path20 from "node:path";
17458
17835
 
17459
17836
  // packages/console-server/src/page.ts
17460
- import { readFile as readFile8 } from "node:fs/promises";
17461
- import path14 from "node:path";
17837
+ import { readFile as readFile9 } from "node:fs/promises";
17838
+ import path16 from "node:path";
17462
17839
  var CONSOLE_PAGE_HTML = `<!doctype html>
17463
17840
  <html lang="en">
17464
17841
  <head>
@@ -17479,14 +17856,14 @@ var MISSING_BUNDLE_SCRIPT = `document.body.textContent = "codexhost console asse
17479
17856
  `;
17480
17857
  function consoleBundleCandidates(appDirectory2) {
17481
17858
  return [
17482
- path14.join(appDirectory2, "console-web.js"),
17483
- path14.resolve(appDirectory2, "..", "..", "renderer-extension", "dist", "console.js")
17859
+ path16.join(appDirectory2, "console-web.js"),
17860
+ path16.resolve(appDirectory2, "..", "..", "renderer-extension", "dist", "console.js")
17484
17861
  ];
17485
17862
  }
17486
17863
  async function loadConsoleBundle(appDirectory2) {
17487
17864
  for (const candidate of consoleBundleCandidates(appDirectory2)) {
17488
17865
  try {
17489
- return await readFile8(candidate, "utf8");
17866
+ return await readFile9(candidate, "utf8");
17490
17867
  } catch {
17491
17868
  continue;
17492
17869
  }
@@ -17610,14 +17987,14 @@ function readAnnouncement(fetcher = fetch) {
17610
17987
  }
17611
17988
 
17612
17989
  // packages/console-server/src/diagnostic-report.ts
17613
- import os3 from "node:os";
17990
+ import os4 from "node:os";
17614
17991
  var ISSUE_REPOSITORY_URL = "https://github.com/karlorz/codex-host";
17615
17992
  var ISSUE_ERROR_CHARS = 800;
17616
17993
  var ISSUE_URL_MAX_LENGTH = 7e3;
17617
17994
  var REPORT_LOG_TAIL_BYTES = 32 * 1024;
17618
17995
  var REPORT_LOG_FILES = 2;
17619
17996
  var REPORT_STARTUP_RECORDS = 5;
17620
- function redactHome(text, home = os3.homedir()) {
17997
+ function redactHome(text, home = os4.homedir()) {
17621
17998
  if (!home || home === "/" || home.length < 3) return text;
17622
17999
  const variants = /* @__PURE__ */ new Set([home, JSON.stringify(home).slice(1, -1)]);
17623
18000
  let result = text;
@@ -17633,7 +18010,7 @@ async function buildDiagnosticReport(input, readTail, now = () => /* @__PURE__ *
17633
18010
  return {
17634
18011
  schemaVersion: 1,
17635
18012
  generatedAt: now().toISOString(),
17636
- platform: { os: process.platform, arch: process.arch, release: os3.release() },
18013
+ platform: { os: process.platform, arch: process.arch, release: os4.release() },
17637
18014
  codexhost: {
17638
18015
  version: input.distribution?.version ?? input.consoleVersion,
17639
18016
  distribution: input.distribution?.distribution ?? null,
@@ -17709,7 +18086,7 @@ function issueUrl(report, home) {
17709
18086
  }
17710
18087
 
17711
18088
  // packages/console-server/src/updates.ts
17712
- import path15 from "node:path";
18089
+ import path17 from "node:path";
17713
18090
  var ERROR_MAX_LENGTH = 500;
17714
18091
  var ConsoleUpdateError = class extends Error {
17715
18092
  constructor(code, message) {
@@ -17742,13 +18119,13 @@ function installationKind(metadata) {
17742
18119
  }
17743
18120
  function absoluteEnvironmentPath(environment, name) {
17744
18121
  const value = environment[name];
17745
- if (!value || !path15.isAbsolute(value)) {
18122
+ if (!value || !path17.isAbsolute(value)) {
17746
18123
  throw new ConsoleUpdateError(
17747
18124
  "unsupported",
17748
18125
  `${name} is unavailable; run 'codexhost console' from the npm command to update`
17749
18126
  );
17750
18127
  }
17751
- return path15.normalize(value);
18128
+ return path17.normalize(value);
17752
18129
  }
17753
18130
  function createConsoleUpdates(options) {
17754
18131
  const environment = options.environment ?? process.env;
@@ -17789,13 +18166,13 @@ function createConsoleUpdates(options) {
17789
18166
  }
17790
18167
  }
17791
18168
  async function prepare(metadata, target, release, onPrepared) {
17792
- const resourcesRoot = path15.dirname(target.appDirectory);
18169
+ const resourcesRoot = path17.dirname(target.appDirectory);
17793
18170
  const common = {
17794
18171
  version: release.version,
17795
18172
  launcherPid: options.processId ?? process.pid,
17796
18173
  launcherExecutable: options.processExecutable ?? process.execPath,
17797
18174
  runtimeDescriptorPath: target.runtimeDescriptorPath,
17798
- updaterExecutable: path15.join(
18175
+ updaterExecutable: path17.join(
17799
18176
  resourcesRoot,
17800
18177
  "libexec",
17801
18178
  platform === "win32" ? "codexhost-updater.exe" : "codexhost-updater"
@@ -17830,13 +18207,13 @@ function createConsoleUpdates(options) {
17830
18207
  if (kind === "windows-installer") {
17831
18208
  return manager.prepareWindowsInstaller({ ...common, artifact, installRoot: resourcesRoot });
17832
18209
  }
17833
- const appPath = path15.dirname(path15.dirname(resourcesRoot));
18210
+ const appPath = path17.dirname(path17.dirname(resourcesRoot));
17834
18211
  return manager.prepareMacOsDmg({ ...common, artifact, appPath });
17835
18212
  }
17836
18213
  return Object.freeze({
17837
18214
  async check(target, signal) {
17838
18215
  const metadata = target.distribution;
17839
- const runtime = metadata ? null : await readRuntimeMetadata(path15.join(target.appDirectory, "main.js"), environment).catch(
18216
+ const runtime = metadata ? null : await readRuntimeMetadata(path17.join(target.appDirectory, "main.js"), environment).catch(
17840
18217
  () => null
17841
18218
  );
17842
18219
  const empty = {
@@ -17887,7 +18264,7 @@ function createConsoleUpdates(options) {
17887
18264
  if (!metadata) {
17888
18265
  throw new ConsoleUpdateError("unsupported", "A source checkout cannot update itself");
17889
18266
  }
17890
- if (!target.runtimeDescriptorPath || !path15.isAbsolute(target.runtimeDescriptorPath)) {
18267
+ if (!target.runtimeDescriptorPath || !path17.isAbsolute(target.runtimeDescriptorPath)) {
17891
18268
  throw new ConsoleUpdateError("unsupported", "The Launcher runtime path is unavailable");
17892
18269
  }
17893
18270
  if (handedOff) {
@@ -17956,20 +18333,20 @@ function createConsoleUpdates(options) {
17956
18333
  }
17957
18334
 
17958
18335
  // packages/console-server/src/live-voice-inject.ts
17959
- import { randomUUID as randomUUID3 } from "node:crypto";
17960
- import { mkdir as mkdir4, readFile as readFile9, rename as rename3, rm as rm5, writeFile as writeFile4 } from "node:fs/promises";
17961
- import path16 from "node:path";
18336
+ import { randomUUID as randomUUID4 } from "node:crypto";
18337
+ import { mkdir as mkdir6, readFile as readFile10, rename as rename4, rm as rm7, writeFile as writeFile5 } from "node:fs/promises";
18338
+ import path18 from "node:path";
17962
18339
  var CPA_LIVE_VOICE_ENV = "CODEXHOST_CPA_LIVE_VOICE";
17963
18340
  var LIVE_VOICE_INJECT_FILE = "live-voice-inject-v1.json";
17964
- function injectPath(dataDirectory2) {
17965
- return path16.join(dataDirectory2, LIVE_VOICE_INJECT_FILE);
18341
+ function injectPath(dataDirectory3) {
18342
+ return path18.join(dataDirectory3, LIVE_VOICE_INJECT_FILE);
17966
18343
  }
17967
- async function readLiveVoiceInjectState(dataDirectory2, environment = process.env) {
18344
+ async function readLiveVoiceInjectState(dataDirectory3, environment = process.env) {
17968
18345
  const env = environment[CPA_LIVE_VOICE_ENV];
17969
18346
  const envOverride = env === "0" || env === "1" ? env : null;
17970
18347
  let inject = true;
17971
18348
  try {
17972
- const parsed = JSON.parse(await readFile9(injectPath(dataDirectory2), "utf8"));
18349
+ const parsed = JSON.parse(await readFile10(injectPath(dataDirectory3), "utf8"));
17973
18350
  inject = parsed.version !== 1 || parsed.inject !== false;
17974
18351
  } catch {
17975
18352
  inject = true;
@@ -17979,18 +18356,18 @@ async function readLiveVoiceInjectState(dataDirectory2, environment = process.en
17979
18356
  if (envOverride === "1") inject = true;
17980
18357
  return { inject, savedInject, envOverride };
17981
18358
  }
17982
- async function writeLiveVoiceInjectFile(dataDirectory2, inject, routes) {
18359
+ async function writeLiveVoiceInjectFile(dataDirectory3, inject, routes) {
17983
18360
  if (!routes) {
17984
18361
  try {
17985
- const saved = JSON.parse(await readFile9(injectPath(dataDirectory2), "utf8"));
18362
+ const saved = JSON.parse(await readFile10(injectPath(dataDirectory3), "utf8"));
17986
18363
  if (saved?.version === 1) routes = voiceRoutesSchema.safeParse(saved.routes).data;
17987
18364
  } catch {
17988
18365
  }
17989
18366
  }
17990
- await mkdir4(dataDirectory2, { recursive: true, mode: 448 });
17991
- const temporaryPath = path16.join(dataDirectory2, `.${LIVE_VOICE_INJECT_FILE}.${randomUUID3()}.tmp`);
18367
+ await mkdir6(dataDirectory3, { recursive: true, mode: 448 });
18368
+ const temporaryPath = path18.join(dataDirectory3, `.${LIVE_VOICE_INJECT_FILE}.${randomUUID4()}.tmp`);
17992
18369
  try {
17993
- await writeFile4(
18370
+ await writeFile5(
17994
18371
  temporaryPath,
17995
18372
  `${JSON.stringify({ version: 1, inject, ...routes ? { routes } : {} }, null, 2)}
17996
18373
  `,
@@ -17999,16 +18376,16 @@ async function writeLiveVoiceInjectFile(dataDirectory2, inject, routes) {
17999
18376
  flag: "wx"
18000
18377
  }
18001
18378
  );
18002
- await rename3(temporaryPath, injectPath(dataDirectory2));
18379
+ await rename4(temporaryPath, injectPath(dataDirectory3));
18003
18380
  } finally {
18004
- await rm5(temporaryPath, { force: true });
18381
+ await rm7(temporaryPath, { force: true });
18005
18382
  }
18006
18383
  }
18007
18384
 
18008
18385
  // packages/console-server/src/voice-settings.ts
18009
18386
  import { createHash as createHash2 } from "node:crypto";
18010
- import { readFile as readFile10 } from "node:fs/promises";
18011
- import path17 from "node:path";
18387
+ import { readFile as readFile11 } from "node:fs/promises";
18388
+ import path19 from "node:path";
18012
18389
  var VoiceSettingsConflict = class extends Error {
18013
18390
  };
18014
18391
  var VoiceSettingsStore = class {
@@ -18022,7 +18399,7 @@ var VoiceSettingsStore = class {
18022
18399
  let document = null;
18023
18400
  try {
18024
18401
  document = JSON.parse(
18025
- await readFile10(path17.join(this.directory, LIVE_VOICE_INJECT_FILE), "utf8")
18402
+ await readFile11(path19.join(this.directory, LIVE_VOICE_INJECT_FILE), "utf8")
18026
18403
  );
18027
18404
  } catch (error51) {
18028
18405
  if (!(error51 instanceof SyntaxError) && error51.code !== "ENOENT")
@@ -18469,6 +18846,22 @@ function startConsoleServer(options) {
18469
18846
  sendJson(response, 200, { harnesses: await options.harnesses.list() });
18470
18847
  return;
18471
18848
  }
18849
+ if (route === "POST /api/harnesses/grok-computer-use") {
18850
+ const parsed = grokComputerUseSetSchema.safeParse(body);
18851
+ if (!parsed.success) {
18852
+ sendJson(response, 400, { error: "Expected { enabled } or { browser }" });
18853
+ return;
18854
+ }
18855
+ try {
18856
+ const harness2 = await options.harnesses.setGrokComputerUse(parsed.data);
18857
+ sendJson(response, 200, { harness: harness2 });
18858
+ } catch (error51) {
18859
+ sendJson(response, error51 instanceof ConsoleHarnessError ? error51.status : 500, {
18860
+ error: error51 instanceof Error ? error51.message : String(error51)
18861
+ });
18862
+ }
18863
+ return;
18864
+ }
18472
18865
  if (route === "POST /api/harnesses/launch-path") {
18473
18866
  const id = body.id;
18474
18867
  const value = body.path;
@@ -18630,7 +19023,7 @@ async function requestShutdown(port) {
18630
19023
  if (!response.ok) throw new Error(`console shutdown failed: HTTP ${response.status}`);
18631
19024
  }
18632
19025
  async function consoleBuildId(entryPath2, environment = process.env) {
18633
- const files = [entryPath2, ...consoleBundleCandidates(path18.dirname(entryPath2))];
19026
+ const files = [entryPath2, ...consoleBundleCandidates(path20.dirname(entryPath2))];
18634
19027
  const parts = [];
18635
19028
  for (const file2 of files) {
18636
19029
  const metadata = await stat4(file2).catch(() => null);
@@ -18638,7 +19031,7 @@ async function consoleBuildId(entryPath2, environment = process.env) {
18638
19031
  }
18639
19032
  const runtime = await readRuntimeMetadata(entryPath2, environment).catch(() => null);
18640
19033
  if (runtime?.distribution === "development") parts.push(runtime.version);
18641
- return JSON.stringify([parts.join("."), dataDirectory(environment)]);
19034
+ return JSON.stringify([parts.join("."), dataDirectory2(environment)]);
18642
19035
  }
18643
19036
  function startDetachedServer(entryPath2, environment) {
18644
19037
  const child = spawn3(process.execPath, [entryPath2, "serve"], {
@@ -18733,7 +19126,7 @@ async function updateFromCommand(appDirectory2, arguments_) {
18733
19126
  var IDLE_TIMEOUT_MS = 30 * 60 * 1e3;
18734
19127
  var HANDOFF_EXIT_DELAY_MS = 500;
18735
19128
  var entryPath = fileURLToPath(import.meta.url);
18736
- var appDirectory = path19.dirname(entryPath);
19129
+ var appDirectory = path21.dirname(entryPath);
18737
19130
  function usage() {
18738
19131
  console.error(
18739
19132
  "usage: console-server open [--no-browser] | console-server ensure | console-server serve | console-server update"