lody 0.77.2 → 0.79.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -60,10 +60,11 @@ import require$$1$5, { Worker as Worker$1 } from "node:worker_threads";
60
60
  import require$$1$6, { fileURLToPath, pathToFileURL } from "node:url";
61
61
  import require$$1$7 from "node:console";
62
62
  import require$$1$8 from "node:dns";
63
- import { C as CodeCollabV2OpenTextRequestSchema, a as CodeCollabV2RefreshTextRequestSchema, b as CodeCollabV2SaveTextRequestSchema, c as CodeCollabV2OpenCurrentDiffRequestSchema, d as CodeCollabV2OpenAllChangesDiffRequestSchema, e as CodeCollabV2OpenTurnDiffRequestSchema, f as CodeCollabV2InitDirectoryRequestSchema, g as CodeCollabV2OpenTextOkSchema, h as CodeCollabV2RefreshTextResponseSchema, i as CodeCollabV2SaveTextResponseSchema, j as CodeCollabV2OpenCurrentDiffResponseSchema, k as CodeCollabV2OpenAllChangesDiffResponseSchema, l as CodeCollabV2OpenTurnDiffResponseSchema, m as CodeCollabV2InitDirectoryOkSchema, n as CodeCollabV2LspUnsupportedSchema, o as CodeCollabV2ErrorSchema, p as CodeCollabV2RpcContentEnvelopeSchema, q as deriveCodeCollabV2ContentKeyId, r as CodeCollabV2ErrorCodeSchema, s as CodeCollabV2RpcResponseSchema, t as deriveCodeCollabV2ContentKeyBytes, u as readCodeCollabFileIndexSignalFromFlock, w as writeCodeCollabFileIndexSignalToFlock, v as writeCodeCollabFileIndexToFlock, x as buildCodeCollabFileIndexState, y as CODE_COLLAB_V2_TEXT_LIMITS, z as CODE_COLLAB_V2_ALL_CHANGES_DIFF_LIMITS, A as computeAllChanges, B as codeCollabFileIndexStatesEqual, D as scanGitDirectoryEntries, E as closeDirectoryQuietly } from "./chunks/directory-handle-BBQKxZ5F.js";
63
+ import { C as CodeCollabV2OpenTextRequestSchema, a as CodeCollabV2RefreshTextRequestSchema, b as CodeCollabV2SaveTextRequestSchema, c as CodeCollabV2OpenCurrentDiffRequestSchema, d as CodeCollabV2OpenAllChangesDiffRequestSchema, e as CodeCollabV2OpenTurnDiffRequestSchema, f as CodeCollabV2InitDirectoryRequestSchema, g as CodeCollabV2OpenTextOkSchema, h as CodeCollabV2RefreshTextResponseSchema, i as CodeCollabV2SaveTextResponseSchema, j as CodeCollabV2OpenCurrentDiffResponseSchema, k as CodeCollabV2OpenAllChangesDiffResponseSchema, l as CodeCollabV2OpenTurnDiffResponseSchema, m as CodeCollabV2InitDirectoryOkSchema, n as CodeCollabV2LspUnsupportedSchema, o as CodeCollabV2ErrorSchema, p as CodeCollabV2RpcContentEnvelopeSchema, q as deriveCodeCollabV2ContentKeyId, r as CodeCollabV2ErrorCodeSchema, s as CodeCollabV2RpcResponseSchema, t as deriveCodeCollabV2ContentKeyBytes, u as readCodeCollabFileIndexSignalFromFlock, w as writeCodeCollabFileIndexSignalToFlock, v as writeCodeCollabFileIndexToFlock, x as buildCodeCollabFileIndexState, y as CODE_COLLAB_V2_TEXT_LIMITS, z as CODE_COLLAB_V2_ALL_CHANGES_DIFF_LIMITS, A as computeAllChanges, B as codeCollabFileIndexStatesEqual, D as scanGitDirectoryEntries, E as closeDirectoryQuietly } from "./chunks/directory-handle-OPjjCl3O.js";
64
64
  import { C as ClientSideConnection, P as PROTOCOL_VERSION, p as packageJson, n as ndJsonStream } from "./chunks/package-qnDHmQq4.js";
65
65
  import { StringDecoder } from "node:string_decoder";
66
66
  import { pipeline, finished } from "node:stream/promises";
67
+ import { r as runtimeManifest } from "./chunks/runtime-manifest-Fr5DEH54.js";
67
68
  import { AsyncLocalStorage as AsyncLocalStorage$1 } from "async_hooks";
68
69
  import { createRequire } from "module";
69
70
  import { c as computeLineCounts, a as countTextLines } from "./chunks/diff-line-counts-bmGB_T-n.js";
@@ -2292,7 +2293,7 @@ Upgrade Node, then re-run: npx lody@latest`;
2292
2293
  return frames;
2293
2294
  };
2294
2295
  }
2295
- const version$8 = "5.38.8";
2296
+ const version$9 = "5.38.8";
2296
2297
  const FeatureFlagError = {
2297
2298
  ERRORS_WHILE_COMPUTING: "errors_while_computing_flags",
2298
2299
  FLAG_MISSING: "flag_missing",
@@ -3470,7 +3471,7 @@ Upgrade Node, then re-run: npx lody@latest`;
3470
3471
  return this.options.fetch ? this.options.fetch(url, options) : fetch(url, options);
3471
3472
  }
3472
3473
  getLibraryVersion() {
3473
- return version$8;
3474
+ return version$9;
3474
3475
  }
3475
3476
  getCustomUserAgent() {
3476
3477
  return `${this.getLibraryId()}/${this.getLibraryVersion()}`;
@@ -4319,7 +4320,7 @@ Upgrade Node, then re-run: npx lody@latest`;
4319
4320
  throw new Error(`Unrecognized ${PLATFORM_ENV_VAR} value: ${JSON.stringify(raw2)} (expected "local" or "cloud")`);
4320
4321
  }
4321
4322
  const name$2 = "lody";
4322
- const version$7 = "0.76.0";
4323
+ const version$8 = "0.76.0";
4323
4324
  const normalizeRuntimeEnv = (value) => {
4324
4325
  switch (value?.toLowerCase()) {
4325
4326
  case "dev":
@@ -4568,6 +4569,11 @@ Upgrade Node, then re-run: npx lody@latest`;
4568
4569
  agentType: "kimi",
4569
4570
  displayName: "Kimi Code"
4570
4571
  },
4572
+ {
4573
+ runtimeName: "grok-build",
4574
+ agentType: "grok",
4575
+ displayName: "Grok"
4576
+ },
4571
4577
  {
4572
4578
  runtimeName: "claude-code",
4573
4579
  agentType: "claude",
@@ -4585,7 +4591,7 @@ Upgrade Node, then re-run: npx lody@latest`;
4585
4591
  return false;
4586
4592
  }
4587
4593
  const record2 = value;
4588
- return (record2.codexPath === void 0 || typeof record2.codexPath === "string") && (record2.claudeCodeExecutable === void 0 || typeof record2.claudeCodeExecutable === "string") && (record2.kimiPath === void 0 || typeof record2.kimiPath === "string");
4594
+ return (record2.codexPath === void 0 || typeof record2.codexPath === "string") && (record2.claudeCodeExecutable === void 0 || typeof record2.claudeCodeExecutable === "string") && (record2.kimiPath === void 0 || typeof record2.kimiPath === "string") && (record2.grokPath === void 0 || typeof record2.grokPath === "string");
4589
4595
  };
4590
4596
  const hasBuiltinRuntimeOverrideValues = (runtimeOverrides) => !!runtimeOverrides && Object.values(runtimeOverrides).some((value) => typeof value === "string" && value.trim().length > 0);
4591
4597
  const getBuiltinRuntimeOverrideSourceVersionSuffix = (runtimeOverrides) => hasBuiltinRuntimeOverrideValues(runtimeOverrides) ? `+override:${JSON.stringify(runtimeOverrides)}` : "";
@@ -4619,6 +4625,7 @@ Upgrade Node, then re-run: npx lody@latest`;
4619
4625
  const CODEX_AUTO_REVIEW_MODE_ID = "agent-auto-review";
4620
4626
  const BUILTIN_DEFAULT_MODE_IDS = {
4621
4627
  kimi: "auto",
4628
+ grok: "agent",
4622
4629
  claude: "auto",
4623
4630
  codex: CODEX_AUTO_REVIEW_MODE_ID
4624
4631
  };
@@ -11243,6 +11250,7 @@ Requirements:
11243
11250
  const WorktreeCleanupScriptConfigSchema = WorktreeSetupScriptConfigSchema;
11244
11251
  _enum$1([
11245
11252
  "kimi",
11253
+ "grok",
11246
11254
  "claude",
11247
11255
  "codex"
11248
11256
  ]);
@@ -11258,7 +11266,8 @@ Requirements:
11258
11266
  const BuiltinRuntimeOverridesSchema = object$1({
11259
11267
  codexPath: string$1().optional(),
11260
11268
  claudeCodeExecutable: string$1().optional(),
11261
- kimiPath: string$1().optional()
11269
+ kimiPath: string$1().optional(),
11270
+ grokPath: string$1().optional()
11262
11271
  }).strict();
11263
11272
  const AcpConfigOptionValueSchema = union$7([
11264
11273
  string$1(),
@@ -14248,32 +14257,16 @@ Requirements:
14248
14257
  }
14249
14258
  }
14250
14259
  },
14251
- {
14252
- id: "grok-build",
14253
- name: "Grok Build",
14254
- version: "1.0.0",
14255
- description: "xAI's coding agent and CLI",
14256
- icon: "https://cdn.agentclientprotocol.com/registry/v1/latest/grok-build.svg",
14257
- distribution: {
14258
- npx: {
14259
- package: "@xai-official/grok@1.0.0",
14260
- args: [
14261
- "agent",
14262
- "stdio"
14263
- ]
14264
- }
14265
- }
14266
- },
14267
14260
  {
14268
14261
  id: "harn",
14269
14262
  name: "Harn",
14270
- version: "0.10.69",
14263
+ version: "0.10.70",
14271
14264
  description: "Harn runs .harn agent pipelines as a native ACP coding agent over stdio.",
14272
14265
  icon: "https://cdn.agentclientprotocol.com/registry/v1/latest/harn.svg",
14273
14266
  distribution: {
14274
14267
  binary: {
14275
14268
  "darwin-aarch64": {
14276
- archive: "https://github.com/burin-labs/harn/releases/download/v0.10.69/harn-aarch64-apple-darwin.tar.gz",
14269
+ archive: "https://github.com/burin-labs/harn/releases/download/v0.10.70/harn-aarch64-apple-darwin.tar.gz",
14277
14270
  cmd: "./harn",
14278
14271
  args: [
14279
14272
  "serve",
@@ -14281,7 +14274,7 @@ Requirements:
14281
14274
  ]
14282
14275
  },
14283
14276
  "darwin-x86_64": {
14284
- archive: "https://github.com/burin-labs/harn/releases/download/v0.10.69/harn-x86_64-apple-darwin.tar.gz",
14277
+ archive: "https://github.com/burin-labs/harn/releases/download/v0.10.70/harn-x86_64-apple-darwin.tar.gz",
14285
14278
  cmd: "./harn",
14286
14279
  args: [
14287
14280
  "serve",
@@ -14289,7 +14282,7 @@ Requirements:
14289
14282
  ]
14290
14283
  },
14291
14284
  "linux-aarch64": {
14292
- archive: "https://github.com/burin-labs/harn/releases/download/v0.10.69/harn-aarch64-unknown-linux-gnu.tar.gz",
14285
+ archive: "https://github.com/burin-labs/harn/releases/download/v0.10.70/harn-aarch64-unknown-linux-gnu.tar.gz",
14293
14286
  cmd: "./harn",
14294
14287
  args: [
14295
14288
  "serve",
@@ -14297,7 +14290,7 @@ Requirements:
14297
14290
  ]
14298
14291
  },
14299
14292
  "linux-x86_64": {
14300
- archive: "https://github.com/burin-labs/harn/releases/download/v0.10.69/harn-x86_64-unknown-linux-gnu.tar.gz",
14293
+ archive: "https://github.com/burin-labs/harn/releases/download/v0.10.70/harn-x86_64-unknown-linux-gnu.tar.gz",
14301
14294
  cmd: "./harn",
14302
14295
  args: [
14303
14296
  "serve",
@@ -14305,7 +14298,7 @@ Requirements:
14305
14298
  ]
14306
14299
  },
14307
14300
  "windows-x86_64": {
14308
- archive: "https://github.com/burin-labs/harn/releases/download/v0.10.69/harn-x86_64-pc-windows-msvc.zip",
14301
+ archive: "https://github.com/burin-labs/harn/releases/download/v0.10.70/harn-x86_64-pc-windows-msvc.zip",
14309
14302
  cmd: "harn.exe",
14310
14303
  args: [
14311
14304
  "serve",
@@ -23210,10 +23203,18 @@ ${context2.authorReply.trim()}
23210
23203
  const exhaustive = room;
23211
23204
  throw new Error(`Unsupported local data-plane room: ${String(exhaustive)}`);
23212
23205
  }
23206
+ function createUtf8StreamDecoder() {
23207
+ const decoder2 = new TextDecoder("utf-8");
23208
+ return (chunk) => decoder2.decode(chunk, {
23209
+ stream: true
23210
+ });
23211
+ }
23213
23212
  function createJsonLineSplitter(options) {
23213
+ const decodeChunk = createUtf8StreamDecoder();
23214
23214
  let buffer2 = "";
23215
23215
  let discardingOversizedLine = false;
23216
- return (chunk) => {
23216
+ return (input2) => {
23217
+ let chunk = typeof input2 === "string" ? input2 : decodeChunk(input2);
23217
23218
  if (discardingOversizedLine) {
23218
23219
  const newlineIndex2 = chunk.indexOf("\n");
23219
23220
  if (newlineIndex2 < 0) {
@@ -24594,6 +24595,7 @@ ${peerId}`;
24594
24595
  };
24595
24596
  const SUPPORTED_CLI_TYPES = [
24596
24597
  "kimi",
24598
+ "grok",
24597
24599
  "claude",
24598
24600
  "codex"
24599
24601
  ];
@@ -24636,7 +24638,7 @@ ${peerId}`;
24636
24638
  const getSessionIdFromRoomId = (roomId) => isSessionDocRoomId(roomId) ? roomId.slice(SESSION_DOC_PREFIX.length) : null;
24637
24639
  const isMachineDocRoomId = (roomId) => roomId.startsWith(MACHINE_DOC_PREFIX);
24638
24640
  const name$1 = "@lody/cli-cloud";
24639
- const version$6 = "0.77.2";
24641
+ const version$7 = "0.79.0";
24640
24642
  const type$2 = "module";
24641
24643
  const scripts = {
24642
24644
  "dev": "node dev.mjs",
@@ -24653,7 +24655,7 @@ ${peerId}`;
24653
24655
  };
24654
24656
  const pkg = {
24655
24657
  name: name$1,
24656
- version: version$6,
24658
+ version: version$7,
24657
24659
  "private": true,
24658
24660
  type: type$2,
24659
24661
  scripts,
@@ -24789,7 +24791,7 @@ ${peerId}`;
24789
24791
  }
24790
24792
  const runtimeEnv = getRuntimeEnv();
24791
24793
  const apiKey = resolveApiKey();
24792
- const release = `${name$2}@${version$7}`;
24794
+ const release = `${name$2}@${version$8}`;
24793
24795
  const distinctId = resolveDistinctId();
24794
24796
  const errorReportingEnabled = runtimeEnv !== "dev" && !!apiKey;
24795
24797
  let client$1 = null;
@@ -24801,9 +24803,9 @@ ${peerId}`;
24801
24803
  }
24802
24804
  const baseExceptionProps = {
24803
24805
  $lib: "lody-cli",
24804
- $lib_version: version$7,
24806
+ $lib_version: version$8,
24805
24807
  platform: "cli",
24806
- app_version: version$7,
24808
+ app_version: version$8,
24807
24809
  env: runtimeEnv,
24808
24810
  release,
24809
24811
  machine_id: distinctId
@@ -30413,9 +30415,9 @@ ${originalIndentation}`;
30413
30415
  })(common$2);
30414
30416
  return common$2;
30415
30417
  }
30416
- const version$5 = "3.19.0";
30418
+ const version$6 = "3.19.0";
30417
30419
  const require$$2$3 = {
30418
- version: version$5
30420
+ version: version$6
30419
30421
  };
30420
30422
  var transports = {};
30421
30423
  var winstonTransport = {
@@ -110354,6 +110356,14 @@ ${incoming}`).output;
110354
110356
  ]).optional()
110355
110357
  })
110356
110358
  });
110359
+ const CodexSessionTitleSchema = object$1({
110360
+ titleSource: _enum$1([
110361
+ "explicit",
110362
+ "fallback",
110363
+ "unset",
110364
+ "unknown"
110365
+ ])
110366
+ });
110357
110367
  const CodexProposedPlanParamsSchema = object$1({
110358
110368
  schemaVersion: literal$1(1),
110359
110369
  sessionId: string$1(),
@@ -111058,7 +111068,13 @@ ${incoming}`).output;
111058
111068
  });
111059
111069
  }
111060
111070
  handleAgentSessionTitleUpdate(notification) {
111061
- if (!usesAcpProvidedSessionTitle(this.options.agentConfig?.cliType, this.options.agentConfig?.agentType) || notification.update.sessionUpdate !== "session_info_update") {
111071
+ if (notification.update.sessionUpdate !== "session_info_update") {
111072
+ return;
111073
+ }
111074
+ const ownsTitleGeneration = usesAcpProvidedSessionTitle(this.options.agentConfig?.cliType, this.options.agentConfig?.agentType);
111075
+ const codexTitleMeta = this.isCodexAgent() ? CodexSessionTitleSchema.safeParse(notification.update._meta?.codex) : null;
111076
+ const isExplicitCodexTitle = codexTitleMeta?.success === true && codexTitleMeta.data.titleSource === "explicit";
111077
+ if (!ownsTitleGeneration && !isExplicitCodexTitle) {
111062
111078
  return;
111063
111079
  }
111064
111080
  const title2 = typeof notification.update.title === "string" ? notification.update.title.trim() : "";
@@ -111070,6 +111086,17 @@ ${incoming}`).output;
111070
111086
  isCodexAgent() {
111071
111087
  return this.options.agentConfig?.agentType === "codex";
111072
111088
  }
111089
+ getGrokClientIdentifier() {
111090
+ return this.options.agentConfig?.cliType === "builtin" && this.options.agentConfig.agentType === "grok" ? `lody:${this.options.sessionId}` : void 0;
111091
+ }
111092
+ getGrokSessionMeta() {
111093
+ const clientIdentifier = this.getGrokClientIdentifier();
111094
+ return clientIdentifier ? {
111095
+ _meta: {
111096
+ clientIdentifier
111097
+ }
111098
+ } : {};
111099
+ }
111073
111100
  isCurrentAcpSession(acpSessionId) {
111074
111101
  return this.acpSessionId !== null && acpSessionId === this.acpSessionId;
111075
111102
  }
@@ -111087,6 +111114,8 @@ ${incoming}`).output;
111087
111114
  async startSession(stream2, workdir, resumeSessionId, timeoutOptions = {}, startupAbort, resolveSessionStart, forkSessionId, forkSessionTurnId) {
111088
111115
  const connection2 = new ClientSideConnection(() => this, stream2);
111089
111116
  this.connection = connection2;
111117
+ const grokClientIdentifier = this.getGrokClientIdentifier();
111118
+ const grokSessionMeta = this.getGrokSessionMeta();
111090
111119
  this.logger.debug(`[${this.options.sessionId}] Starting ACP client (workdir=${workdir} resumeSessionId=${resumeSessionId ?? "none"} forkSessionId=${forkSessionId ?? "none"})`);
111091
111120
  if (resumeSessionId && forkSessionId) {
111092
111121
  throw new Error("[ACP_SESSION_START_INVALID] resumeSessionId and forkSessionId are exclusive");
@@ -111117,6 +111146,11 @@ ${incoming}`).output;
111117
111146
  try {
111118
111147
  initResponse = await withTimeout$2(withAbort(connection2.initialize({
111119
111148
  protocolVersion: PROTOCOL_VERSION,
111149
+ ...grokClientIdentifier ? {
111150
+ _meta: {
111151
+ clientIdentifier: grokClientIdentifier
111152
+ }
111153
+ } : {},
111120
111154
  clientCapabilities: {
111121
111155
  terminal: this.terminalEnabled,
111122
111156
  plan: {},
@@ -111307,7 +111341,8 @@ ${incoming}`).output;
111307
111341
  const loadResponse = await withTimeout$2(withAbort(connection2.loadSession({
111308
111342
  sessionId: resumeSessionId,
111309
111343
  cwd: workdir,
111310
- mcpServers
111344
+ mcpServers,
111345
+ ...grokSessionMeta
111311
111346
  }), startupAbort), this.logger, "connection.loadSession", this.options.sessionId, ACP_LOAD_SESSION_TIMEOUT_MS);
111312
111347
  const loadDurationMs = performance$1.now() - loadStart;
111313
111348
  sessionResponse = {
@@ -111348,7 +111383,8 @@ ${incoming}`).output;
111348
111383
  const resumeResponse = await withTimeout$2(withAbort(connection2.resumeSession({
111349
111384
  sessionId: resumeSessionId,
111350
111385
  cwd: workdir,
111351
- mcpServers
111386
+ mcpServers,
111387
+ ...grokSessionMeta
111352
111388
  }), startupAbort), this.logger, "connection.resumeSession", this.options.sessionId, ACP_RESUME_SESSION_TIMEOUT_MS);
111353
111389
  const resumeDurationMs = performance$1.now() - resumeStart;
111354
111390
  sessionResponse = {
@@ -111387,7 +111423,8 @@ ${incoming}`).output;
111387
111423
  try {
111388
111424
  sessionResponse = await withTimeout$2(withAbort(connection2.newSession({
111389
111425
  cwd: workdir,
111390
- mcpServers
111426
+ mcpServers,
111427
+ ...grokSessionMeta
111391
111428
  }), startupAbort), this.logger, "connection.newSession", this.options.sessionId, ACP_NEW_SESSION_TIMEOUT_MS);
111392
111429
  } catch (error2) {
111393
111430
  if (isAcpAuthenticationRequired(error2)) {
@@ -111453,7 +111490,8 @@ ${incoming}`).output;
111453
111490
  try {
111454
111491
  return await withTimeout$2(connection2.newSession({
111455
111492
  cwd: workdir,
111456
- mcpServers
111493
+ mcpServers,
111494
+ ...this.getGrokSessionMeta()
111457
111495
  }), this.logger, "connection.newSession.editAndResend", this.options.sessionId, timeoutMs);
111458
111496
  } catch (error2) {
111459
111497
  throw new Error(`[ACP_SESSION_PREPARE_FAILED] ${formatErrorMessage(error2)}`, {
@@ -121105,14 +121143,18 @@ ${error2.message}` : execaMessage;
121105
121143
  highWaterMark
121106
121144
  }));
121107
121145
  }
121108
- const version$4 = "1.4.0";
121146
+ const version$5 = "1.4.0";
121109
121147
  const dependencies$1 = {
121110
121148
  "@openai/codex": "^0.147.0"
121111
121149
  };
121112
121150
  const codexPackageJson = {
121113
- version: version$4,
121151
+ version: version$5,
121114
121152
  dependencies: dependencies$1
121115
121153
  };
121154
+ const version$4 = "0.1.0";
121155
+ const grokPackageJson = {
121156
+ version: version$4
121157
+ };
121116
121158
  const version$3 = "2.1.220";
121117
121159
  const platforms = {
121118
121160
  "darwin-arm64": {
@@ -121263,10 +121305,13 @@ ${error2.message}` : execaMessage;
121263
121305
  const CLAUDE_ACP_ADAPTER_VERSION = packageJson.version;
121264
121306
  const CLAUDE_CODE_RUNTIME_VERSION = claudeSdkManifestJson.version;
121265
121307
  const KIMI_CODE_VERSION = kimiCodePackageJson.version;
121308
+ const GROK_ACP_ADAPTER_VERSION = grokPackageJson.version;
121309
+ const GROK_BUILD_RUNTIME_VERSION = runtimeManifest.officialRuntime.version;
121266
121310
  const KIMI_CODE_MIN_NODE_VERSION = resolveMinimumNodeVersion("@moonshot-ai/kimi-code", kimiCodePackageJson.engines.node);
121267
121311
  const BUILTIN_CODEX_CAPABILITY_SOURCE_VERSION = `builtin-codex-acp:${CODEX_ACP_ADAPTER_VERSION}+codex:${CODEX_RUNTIME_VERSION}`;
121268
121312
  const BUILTIN_CLAUDE_CAPABILITY_SOURCE_VERSION = `builtin-claude-acp:${CLAUDE_ACP_ADAPTER_VERSION}+agent-sdk:${CLAUDE_AGENT_SDK_VERSION}+claude-code:${CLAUDE_CODE_RUNTIME_VERSION}`;
121269
121313
  const BUILTIN_KIMI_CAPABILITY_SOURCE_VERSION = `builtin-kimi:${KIMI_CODE_VERSION}`;
121314
+ const BUILTIN_GROK_CAPABILITY_SOURCE_VERSION = `builtin-grok-acp:${GROK_ACP_ADAPTER_VERSION}+official-grok:${GROK_BUILD_RUNTIME_VERSION}`;
121270
121315
  const RUNTIMES = {
121271
121316
  codex: {
121272
121317
  name: "codex",
@@ -121416,6 +121461,66 @@ ${error2.message}` : execaMessage;
121416
121461
  cmd: "package/dist/main.mjs"
121417
121462
  }
121418
121463
  }
121464
+ },
121465
+ "grok-build": {
121466
+ name: "grok-build",
121467
+ version: GROK_BUILD_RUNTIME_VERSION,
121468
+ platforms: {
121469
+ "darwin-arm64": {
121470
+ fileName: `xai-official-grok-darwin-arm64-${GROK_BUILD_RUNTIME_VERSION}.tar.zst`,
121471
+ sha256: "63aa0a0a95e7a555a372f1a501dcf59151376d7e4d900e24e1c591ff6cc8f818",
121472
+ size: 46222120,
121473
+ compression: "zstd",
121474
+ cmd: "grok",
121475
+ executableSha256: "13c7f4f0b9abb00bf38216302ea4bab31f03e13555e3576620eca1de572a8d21",
121476
+ executableSize: 131817232
121477
+ },
121478
+ "darwin-x64": {
121479
+ fileName: `xai-official-grok-darwin-x64-${GROK_BUILD_RUNTIME_VERSION}.tar.zst`,
121480
+ sha256: "7bf0af43ba1f3dc8e860e7f887b75966ece7bb6102cc7a3b2fb5af275f757c8a",
121481
+ size: 50590131,
121482
+ compression: "zstd",
121483
+ cmd: "grok",
121484
+ executableSha256: "a82210a961deac9f0cb72ec6c334196abf76a587be4593bc59db2deab85ee6dc",
121485
+ executableSize: 147358e3
121486
+ },
121487
+ "linux-arm64": {
121488
+ fileName: `xai-official-grok-linux-arm64-${GROK_BUILD_RUNTIME_VERSION}.tar.zst`,
121489
+ sha256: "c888d404ad218caa251cbdbbd0da5836c807957be5a83fd8ab21b69de93469d9",
121490
+ size: 49704069,
121491
+ compression: "zstd",
121492
+ cmd: "grok",
121493
+ executableSha256: "bb7c51116564a2219f6a49850815060f416918ac407f1f2ba82c53c0b0d4383f",
121494
+ executableSize: 133745832
121495
+ },
121496
+ "linux-x64": {
121497
+ fileName: `xai-official-grok-linux-x64-${GROK_BUILD_RUNTIME_VERSION}.tar.zst`,
121498
+ sha256: "7d0bb4309e634e0ecb63403f35fa468120f5ecf2173feb6518371be1633ecd99",
121499
+ size: 53264623,
121500
+ compression: "zstd",
121501
+ cmd: "grok",
121502
+ executableSha256: "28dbc967a5843dae2374b6834dadbab95354e685c7e5c8dc750b92a4e5fc7c3e",
121503
+ executableSize: 163676672
121504
+ },
121505
+ "win32-arm64": {
121506
+ fileName: `xai-official-grok-win32-arm64-${GROK_BUILD_RUNTIME_VERSION}.tar.zst`,
121507
+ sha256: "c821de276cb1fa835567bd6c5589709e6ba29182d6b0c9ad7c160cc3df91145c",
121508
+ size: 45241480,
121509
+ compression: "zstd",
121510
+ cmd: "grok.exe",
121511
+ executableSha256: "9d41447b6eee77cfb7359b7f50935ae64b4e7b7e7ef56c40e6d203f5660317e1",
121512
+ executableSize: 121471488
121513
+ },
121514
+ "win32-x64": {
121515
+ fileName: `xai-official-grok-win32-x64-${GROK_BUILD_RUNTIME_VERSION}.tar.zst`,
121516
+ sha256: "5d66d3e0c1e54b050c76b77dfc1dadefbf3e909459a31b4361d8307a671c179c",
121517
+ size: 48124303,
121518
+ compression: "zstd",
121519
+ cmd: "grok.exe",
121520
+ executableSha256: "d546dbc995c2ce9ba97c044d6af6b53f8c11c414a6355bf006802d07c572f406",
121521
+ executableSize: 139903488
121522
+ }
121523
+ }
121419
121524
  }
121420
121525
  };
121421
121526
  function sanitizeSegment(segment) {
@@ -122144,6 +122249,9 @@ ${error2.message}` : execaMessage;
122144
122249
  if (input2.agentType === "kimi") {
122145
122250
  return `${BUILTIN_KIMI_CAPABILITY_SOURCE_VERSION}${runtimeOverrideSuffix}`;
122146
122251
  }
122252
+ if (input2.agentType === "grok") {
122253
+ return `${BUILTIN_GROK_CAPABILITY_SOURCE_VERSION}${runtimeOverrideSuffix}`;
122254
+ }
122147
122255
  }
122148
122256
  return `builtin:${input2.agentType}:unknown`;
122149
122257
  }
@@ -122328,6 +122436,24 @@ ${error2.message}` : execaMessage;
122328
122436
  }
122329
122437
  };
122330
122438
  }
122439
+ if (input2.agentType === "grok") {
122440
+ const overridePath2 = trimRuntimeOverride(input2.runtimeOverrides?.grokPath);
122441
+ const grokPath = overridePath2 ?? await getManagedAgentRuntimeManager().ensureRuntime("grok-build", {
122442
+ onProgress: input2.onManagedRuntimeProgress,
122443
+ signal: input2.signal
122444
+ });
122445
+ return {
122446
+ command: process.execPath,
122447
+ args: [
122448
+ ...resolveCliAdapterEntry("grok-acp"),
122449
+ ...input2.extraArgs ?? []
122450
+ ],
122451
+ env: {
122452
+ GROK_PATH: grokPath,
122453
+ GROK_DISABLE_AUTOUPDATER: "1"
122454
+ }
122455
+ };
122456
+ }
122331
122457
  const overridePath = trimRuntimeOverride(input2.runtimeOverrides?.claudeCodeExecutable);
122332
122458
  const claudePath = overridePath ?? await getManagedAgentRuntimeManager().ensureRuntime("claude-code", {
122333
122459
  onProgress: input2.onManagedRuntimeProgress,
@@ -122375,6 +122501,24 @@ ${error2.message}` : execaMessage;
122375
122501
  ]
122376
122502
  };
122377
122503
  }
122504
+ if (input2.agentType === "grok") {
122505
+ if (input2.action === "status") return null;
122506
+ const overridePath2 = trimRuntimeOverride(input2.runtimeOverrides?.grokPath);
122507
+ const grokPath = overridePath2 ?? await getManagedAgentRuntimeManager().ensureRuntime("grok-build", {
122508
+ onProgress: input2.onManagedRuntimeProgress,
122509
+ signal: input2.signal
122510
+ });
122511
+ return {
122512
+ command: grokPath,
122513
+ args: [
122514
+ "login",
122515
+ "--device-auth"
122516
+ ],
122517
+ env: {
122518
+ GROK_DISABLE_AUTOUPDATER: "1"
122519
+ }
122520
+ };
122521
+ }
122378
122522
  const overridePath = trimRuntimeOverride(input2.runtimeOverrides?.claudeCodeExecutable);
122379
122523
  const claudePath = overridePath ?? await getManagedAgentRuntimeManager().ensureRuntime("claude-code", {
122380
122524
  onProgress: input2.onManagedRuntimeProgress,
@@ -123371,6 +123515,42 @@ ${fallbackStderrTail}` : errorMessage2;
123371
123515
  windowsHide: true
123372
123516
  });
123373
123517
  };
123518
+ const CodexConfigOverrideSchema = record$1(string$1(), unknown());
123519
+ function prepareCodexHomeEnv(options, baseEnv) {
123520
+ const isBuiltinCodex = options.cliType === "builtin" && options.agentType === "codex";
123521
+ const isTitleAgentCodexRun = isBuiltinCodex && baseEnv.LODY_TITLE_AGENT === "1";
123522
+ const shouldUseWorkdirCodexHome = isBuiltinCodex && !baseEnv.CODEX_HOME && (baseEnv.LODY_E2E === "1" || isTitleAgentCodexRun);
123523
+ return {
123524
+ env: shouldUseWorkdirCodexHome ? {
123525
+ ...baseEnv,
123526
+ CODEX_HOME: path__default$1.join(options.workdir, ".codex")
123527
+ } : baseEnv,
123528
+ isTitleAgentCodexRun,
123529
+ shouldUseWorkdirCodexHome
123530
+ };
123531
+ }
123532
+ function withTitleAgentCodexConfig(env2) {
123533
+ const existingConfig = env2.CODEX_CONFIG ? CodexConfigOverrideSchema.parse(JSON.parse(env2.CODEX_CONFIG)) : {};
123534
+ return {
123535
+ ...env2,
123536
+ CODEX_CONFIG: JSON.stringify({
123537
+ ...existingConfig,
123538
+ project_doc_max_bytes: 0,
123539
+ include_environment_context: false,
123540
+ skills: {
123541
+ include_instructions: false,
123542
+ bundled: {
123543
+ enabled: false
123544
+ }
123545
+ }
123546
+ })
123547
+ };
123548
+ }
123549
+ function copyTitleAgentCodexConfig(sourcePath, destinationPath) {
123550
+ if (fs.existsSync(sourcePath)) {
123551
+ fs.copyFileSync(sourcePath, destinationPath);
123552
+ }
123553
+ }
123374
123554
  const startLocalAcpAgent = async (options) => {
123375
123555
  options.signal?.throwIfAborted();
123376
123556
  const launch = await resolveACPProcessLaunchAsync({
@@ -123395,47 +123575,46 @@ ${fallbackStderrTail}` : errorMessage2;
123395
123575
  isResume: false
123396
123576
  };
123397
123577
  const baseEnv = withoutElectronBootstrapCredentials(options.env ?? process.env);
123398
- const shouldUseWorkdirCodexHome = options.cliType === "builtin" && options.agentType === "codex" && !baseEnv.CODEX_HOME && (baseEnv.LODY_E2E === "1" || baseEnv.LODY_TITLE_AGENT === "1");
123399
- const env2 = shouldUseWorkdirCodexHome ? {
123400
- ...baseEnv,
123401
- CODEX_HOME: path__default$1.join(options.workdir, ".codex")
123402
- } : baseEnv;
123578
+ const { env: env2, isTitleAgentCodexRun, shouldUseWorkdirCodexHome } = prepareCodexHomeEnv(options, baseEnv);
123403
123579
  const loginShellEnv = await getLoginShellEnv();
123404
- const envWithAcpStartup = withoutElectronBootstrapCredentials(withLodyNpmCacheForNpx(launch.command, withDefaultAcpPathEntries(mergeACPProcessEnv(launch, mergeLoginShellEnv(env2, loginShellEnv)), options.agentType)));
123580
+ const mergedStartupEnv = withoutElectronBootstrapCredentials(withLodyNpmCacheForNpx(launch.command, withDefaultAcpPathEntries(mergeACPProcessEnv(launch, mergeLoginShellEnv(env2, loginShellEnv)), options.agentType)));
123581
+ const envWithAcpStartup = isTitleAgentCodexRun ? withTitleAgentCodexConfig(mergedStartupEnv) : mergedStartupEnv;
123405
123582
  const keepCodexHome = env2.LODY_KEEP_CODEX_HOME === "1";
123406
123583
  const defaultCodexHome = path__default$1.join(os__default$1.homedir(), ".codex");
123407
123584
  const defaultAuthPath = path__default$1.join(defaultCodexHome, "auth.json");
123585
+ const defaultConfigPath = path__default$1.join(defaultCodexHome, "config.toml");
123408
123586
  const localAuthPath = env2.CODEX_HOME ? path__default$1.join(env2.CODEX_HOME, "auth.json") : null;
123409
- const isTitleAgentRun = baseEnv.LODY_TITLE_AGENT === "1";
123410
- const TITLE_AGENT_CODEX_CONFIG_TOML = `project_doc_max_bytes = 0
123411
- include_environment_context = false
123412
-
123413
- [skills]
123414
- include_instructions = false
123415
-
123416
- [skills.bundled]
123417
- enabled = false
123418
- `;
123587
+ const localConfigPath = env2.CODEX_HOME ? path__default$1.join(env2.CODEX_HOME, "config.toml") : null;
123419
123588
  let lastStderrTail = "";
123420
123589
  const attemptStart = async (attemptArgs, startupTimeouts) => {
123421
123590
  options.signal?.throwIfAborted();
123422
123591
  lastStderrTail = "";
123423
- let copiedAuth = false;
123424
123592
  if (shouldUseWorkdirCodexHome) {
123425
123593
  fs.mkdirSync(env2.CODEX_HOME, {
123426
123594
  recursive: true
123427
123595
  });
123428
- if (isTitleAgentRun) {
123429
- fs.writeFileSync(path__default$1.join(env2.CODEX_HOME, "config.toml"), TITLE_AGENT_CODEX_CONFIG_TOML);
123596
+ if (isTitleAgentCodexRun && localConfigPath && fs.existsSync(defaultConfigPath)) {
123597
+ copyTitleAgentCodexConfig(defaultConfigPath, localConfigPath);
123430
123598
  }
123431
123599
  if (localAuthPath && fs.existsSync(defaultAuthPath) && !fs.existsSync(localAuthPath)) {
123432
123600
  try {
123433
123601
  fs.copyFileSync(defaultAuthPath, localAuthPath);
123434
- copiedAuth = true;
123435
123602
  } catch {
123436
123603
  }
123437
123604
  }
123438
123605
  }
123606
+ const cleanupCodexHome = () => {
123607
+ if (!shouldUseWorkdirCodexHome || !env2.CODEX_HOME || keepCodexHome) {
123608
+ return;
123609
+ }
123610
+ try {
123611
+ fs.rmSync(env2.CODEX_HOME, {
123612
+ recursive: true,
123613
+ force: true
123614
+ });
123615
+ } catch {
123616
+ }
123617
+ };
123439
123618
  captureAcpSpawnStarted(spawnAnalyticsProps);
123440
123619
  let agentProcess;
123441
123620
  try {
@@ -123451,12 +123630,15 @@ enabled = false
123451
123630
  spawnImpl: options.spawnImpl
123452
123631
  });
123453
123632
  } catch (error2) {
123633
+ cleanupCodexHome();
123454
123634
  captureAcpSpawnFailed({
123455
123635
  ...spawnAnalyticsProps,
123456
123636
  reason: classifyCliSpawnReason(error2)
123457
123637
  });
123458
123638
  throw error2;
123459
123639
  }
123640
+ agentProcess.once("exit", cleanupCodexHome);
123641
+ agentProcess.once("error", cleanupCodexHome);
123460
123642
  options.logger.debug(`[acp-startup] spawned ACP process (cliType=${options.cliType} agentType=${options.agentType} workdir=${options.workdir})`);
123461
123643
  const stderrStream = agentProcess.stderr;
123462
123644
  let stderrTail = "";
@@ -123494,24 +123676,6 @@ enabled = false
123494
123676
  ],
123495
123677
  getStderrTail: () => stderrTail
123496
123678
  });
123497
- if (shouldUseWorkdirCodexHome && env2.CODEX_HOME && !keepCodexHome) {
123498
- const cleanup = () => {
123499
- try {
123500
- if (copiedAuth && localAuthPath) {
123501
- fs.rmSync(localAuthPath, {
123502
- force: true
123503
- });
123504
- }
123505
- fs.rmSync(env2.CODEX_HOME, {
123506
- recursive: true,
123507
- force: true
123508
- });
123509
- } catch {
123510
- }
123511
- };
123512
- agentProcess.once("exit", cleanup);
123513
- agentProcess.once("error", cleanup);
123514
- }
123515
123679
  if (!agentProcess.stdout) {
123516
123680
  throw new Error("Agent process stdout is not available");
123517
123681
  }
@@ -123696,6 +123860,9 @@ enabled = false
123696
123860
  if (agentType === "codex") {
123697
123861
  return url.hostname === "auth.openai.com" && (url.pathname.startsWith("/codex/device") || url.pathname.startsWith("/oauth/authorize"));
123698
123862
  }
123863
+ if (agentType === "grok") {
123864
+ return hasDomain(url.hostname, "accounts.x.ai") && (url.pathname.startsWith("/oauth2/device") || url.pathname.startsWith("/device"));
123865
+ }
123699
123866
  return hasDomain(url.hostname, "kimi.com") && url.pathname.startsWith("/code/authorize_device");
123700
123867
  }
123701
123868
  function findAuthorizationUrl(agentType, output) {
@@ -123765,6 +123932,18 @@ enabled = false
123765
123932
  ]
123766
123933
  }
123767
123934
  ],
123935
+ grok: [
123936
+ {
123937
+ id: "xai-device-login",
123938
+ name: "xAI",
123939
+ description: "Sign in with an xAI account",
123940
+ type: "terminal",
123941
+ args: [
123942
+ "login",
123943
+ "--device-auth"
123944
+ ]
123945
+ }
123946
+ ],
123768
123947
  claude: [
123769
123948
  {
123770
123949
  id: "claude-ai-login",
@@ -123811,7 +123990,7 @@ enabled = false
123811
123990
  status: "unknown"
123812
123991
  };
123813
123992
  }
123814
- if (options.agentType === "kimi" || options.agentType === "codex") {
123993
+ if (options.agentType === "kimi" || options.agentType === "grok" || options.agentType === "codex") {
123815
123994
  return {
123816
123995
  status: "unknown"
123817
123996
  };
@@ -124318,7 +124497,7 @@ enabled = false
124318
124497
  options.logger.debug(`[title-generator] Skipping unavailable title config option ${key2}=${String(value)}`);
124319
124498
  }
124320
124499
  }
124321
- const extractTitleChunkFromNotification = (notification) => {
124500
+ const extractTitleChunkFromNotification = (notification, agentType) => {
124322
124501
  const update2 = notification.update;
124323
124502
  if (update2.sessionUpdate !== "agent_message_chunk") {
124324
124503
  return null;
@@ -124328,6 +124507,12 @@ enabled = false
124328
124507
  return null;
124329
124508
  }
124330
124509
  const codexMeta = update2._meta?.["codex"];
124510
+ if (agentType === "codex") {
124511
+ if (!codexMeta || typeof codexMeta !== "object" || !("phase" in codexMeta) || codexMeta.phase !== "final_answer") {
124512
+ return null;
124513
+ }
124514
+ return content.text;
124515
+ }
124331
124516
  if (codexMeta && typeof codexMeta === "object" && "phase" in codexMeta && codexMeta.phase !== "final_answer") {
124332
124517
  return null;
124333
124518
  }
@@ -124342,6 +124527,32 @@ enabled = false
124342
124527
  if (!withoutMarkdown) return null;
124343
124528
  return withoutMarkdown.slice(0, 80);
124344
124529
  };
124530
+ const looksLikeProviderControlPayload = (candidate) => {
124531
+ const trimmed2 = candidate.trim();
124532
+ if (/^\{\s*['"]?(?:type|status|error)['"]?\s*:/i.test(trimmed2) || /["']type["']\s*:\s*["'](?:error|warning)["']/i.test(trimmed2) || /\binvalid_request_error\b/i.test(trimmed2) || /^HTTP\s+[45]\d\d\b/i.test(trimmed2) || /^(?:internal server error|bad request|too many requests)\s*(?:[:({-]|$)/i.test(trimmed2) || /^(?:error|warning|failed|failure)\s*(?:[:{]|\[)/i.test(trimmed2)) {
124533
+ return true;
124534
+ }
124535
+ try {
124536
+ const parsed = JSON.parse(trimmed2);
124537
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
124538
+ return false;
124539
+ }
124540
+ const record2 = parsed;
124541
+ return record2.type === "error" || record2.type === "warning" || typeof record2.status === "number" && record2.status >= 400 || typeof record2.error === "string" || typeof record2.error === "object" && record2.error !== null;
124542
+ } catch {
124543
+ return false;
124544
+ }
124545
+ };
124546
+ const sanitizeGeneratedTitle = (candidate) => {
124547
+ if (!candidate) {
124548
+ return null;
124549
+ }
124550
+ const withoutInternalInstructions = sanitizeLodyInternalInstructions(candidate);
124551
+ if (!withoutInternalInstructions || looksLikeProviderControlPayload(withoutInternalInstructions)) {
124552
+ return null;
124553
+ }
124554
+ return sanitizeTitle(withoutInternalInstructions);
124555
+ };
124345
124556
  const ensureWorkdirIsGitRepo = async (workdir, logger2) => {
124346
124557
  const isGitRepo = async () => {
124347
124558
  try {
@@ -124392,13 +124603,8 @@ enabled = false
124392
124603
  }
124393
124604
  };
124394
124605
  const generateTitleIsolated = async (options) => {
124395
- const workdir = path__default$1.join(os__default$1.tmpdir(), "lody-title-agent");
124396
- fs.mkdirSync(workdir, {
124397
- recursive: true
124398
- });
124399
- if (options.agentType === "codex" && !await ensureWorkdirIsGitRepo(workdir, options.logger)) {
124400
- return sanitizeTitle(options.taskPrompt);
124401
- }
124606
+ const fallbackTitle = sanitizeGeneratedTitle(options.taskPrompt);
124607
+ const workdir = fs.mkdtempSync(path__default$1.join(os__default$1.tmpdir(), "lody-title-agent-"));
124402
124608
  const sleep2 = (ms2) => new Promise((resolve2) => setTimeout(resolve2, ms2));
124403
124609
  const tryGenerateWithArgs = async (extraArgs) => {
124404
124610
  let collectedText = "";
@@ -124419,7 +124625,7 @@ enabled = false
124419
124625
  terminalManager: noopTerminalManager,
124420
124626
  terminalEnabled: false,
124421
124627
  onUpdateMessage: (msg) => {
124422
- const text = extractTitleChunkFromNotification(msg);
124628
+ const text = extractTitleChunkFromNotification(msg, options.agentType);
124423
124629
  if (text) {
124424
124630
  collectedText += text;
124425
124631
  }
@@ -124454,16 +124660,16 @@ enabled = false
124454
124660
  while (Date.now() < deadline && collectedText.trim() === "") {
124455
124661
  await sleep2(100);
124456
124662
  }
124457
- const fromStream = sanitizeTitle(collectedText);
124663
+ const fromStream = sanitizeGeneratedTitle(collectedText);
124458
124664
  if (fromStream) {
124459
124665
  return fromStream;
124460
124666
  }
124461
- const rawTitle = extractTextFromAgentResponse(response2) ?? options.taskPrompt;
124462
- const sanitized = sanitizeTitle(rawTitle);
124667
+ const rawTitle = extractTextFromAgentResponse(response2);
124668
+ const sanitized = sanitizeGeneratedTitle(rawTitle);
124463
124669
  if (sanitized) {
124464
124670
  return sanitized;
124465
124671
  }
124466
- return sanitizeTitle(options.taskPrompt);
124672
+ return fallbackTitle;
124467
124673
  } finally {
124468
124674
  await shutdownLocalAcpAgent({
124469
124675
  agentProcess,
@@ -124474,20 +124680,26 @@ enabled = false
124474
124680
  });
124475
124681
  }
124476
124682
  };
124477
- let lastError = null;
124478
124683
  try {
124479
- const title2 = await tryGenerateWithArgs([]);
124480
- if (title2) {
124481
- return title2;
124684
+ if (options.agentType === "codex" && !await ensureWorkdirIsGitRepo(workdir, options.logger)) {
124685
+ return fallbackTitle;
124686
+ }
124687
+ try {
124688
+ return await tryGenerateWithArgs([]) ?? fallbackTitle;
124689
+ } catch (error2) {
124690
+ options.logger.debug("Failed to generate title with args:", error2);
124691
+ return fallbackTitle;
124692
+ }
124693
+ } finally {
124694
+ try {
124695
+ fs.rmSync(workdir, {
124696
+ recursive: true,
124697
+ force: true
124698
+ });
124699
+ } catch (error2) {
124700
+ options.logger.debug(`[title-generator] Failed to remove temporary workdir ${workdir}: ${formatErrorMessage(error2)}`);
124482
124701
  }
124483
- } catch (error2) {
124484
- options.logger.debug("Failed to generate title with args:", error2);
124485
- lastError = error2;
124486
- }
124487
- if (lastError) {
124488
- throw lastError;
124489
124702
  }
124490
- return null;
124491
124703
  };
124492
124704
  const titleToBranchName = (title2) => {
124493
124705
  if (!title2 || typeof title2 !== "string") {
@@ -129381,10 +129593,20 @@ The postId is ${normalizedFeedbackPostId}. Use the feedback-progress-reporter sk
129381
129593
  this.captureStatusChanged(options.sessionId, "idle", void 0, "turn_failed");
129382
129594
  }
129383
129595
  formatMemoryPressureFailureMessage(result) {
129384
- const availableMb = Math.round(result.availableMemoryBytes / 1024 / 1024);
129385
- const thresholdMb = Math.round(result.thresholdBytes / 1024 / 1024);
129386
- const commitText = result.availableCommitBytes !== void 0 && (result.pressureReason === "commit" || result.pressureReason === "physical_and_commit") && result.commitThresholdBytes !== void 0 ? ` Commit headroom is ${Math.round(result.availableCommitBytes / 1024 / 1024)}MB (threshold: ${Math.round(result.commitThresholdBytes / 1024 / 1024)}MB).` : "";
129387
- return `The machine is under memory pressure (${availableMb}MB available, ${thresholdMb}MB required to start a turn). The turn was not started; free memory and retry.${commitText}`;
129596
+ if (result.pressureReason === "darwin_pressure_critical") {
129597
+ return "The machine is at critical memory pressure \u2014 macOS is reclaiming memory and terminating processes to keep up. The turn was not started; free memory and retry.";
129598
+ }
129599
+ const mb = (bytes) => `${Math.round(bytes / 1024 / 1024)}MB`;
129600
+ const availableMb = mb(result.availableMemoryBytes);
129601
+ const marginMb = mb(result.thresholdBytes);
129602
+ const commitText = result.availableCommitBytes !== void 0 && (result.pressureReason === "commit" || result.pressureReason === "physical_and_commit") && result.commitThresholdBytes !== void 0 ? ` Commit headroom is ${mb(result.availableCommitBytes)} (safety margin: ${mb(result.commitThresholdBytes)}).` : "";
129603
+ const cgroup = result.cgroup;
129604
+ if (cgroup) {
129605
+ const hostText = result.hostAvailableBytes !== void 0 ? `host available ${mb(result.hostAvailableBytes)}, ` : "";
129606
+ const stallText = cgroup.psiSomeAvg10 !== null ? `stalled ${cgroup.psiSomeAvg10}% of the last 10s on reclaim` : "PSI unavailable; hard headroom is below the floor";
129607
+ return `The machine is under memory pressure and ${stallText}. cgroup ${cgroup.path}: ${mb(cgroup.currentBytes)} of ${mb(cgroup.maxBytes)} used, ${mb(cgroup.hardHeadroomBytes)} unused plus ${mb(cgroup.reclaimableBytes)} reclaimable cache/slab; ${hostText}safety margin ${marginMb}. The turn was not started; free memory and retry.${commitText}`;
129608
+ }
129609
+ return `The machine is under memory pressure (${availableMb} available, safety margin ${marginMb}). The turn was not started; free memory and retry.${commitText}`;
129388
129610
  }
129389
129611
  recordKnownChatFailureAndHaltEffect(options) {
129390
129612
  return this.tryPromise(() => this.recordKnownChatFailure(options)).pipe(flatMap$2(() => fail(new SessionTurnHalted({
@@ -146288,7 +146510,8 @@ ${edit.newString}` : edit.newString;
146288
146510
  }
146289
146511
  const LEGACY_BUILTIN_AGENT_TYPES = /* @__PURE__ */ new Set([
146290
146512
  "claude",
146291
- "codex"
146513
+ "codex",
146514
+ "grok"
146292
146515
  ]);
146293
146516
  function inferAgentConfigCliType(agentType) {
146294
146517
  const normalized = normalizeCliValue(agentType)?.toLowerCase();
@@ -160410,7 +160633,7 @@ ${escapeHtmlScriptContent(VISUAL_ANNOTATION_INSPECTOR_BROWSER_SCRIPT)}
160410
160633
  pendingProcessLifecycleAction = null;
160411
160634
  store = new SessionTransientStore();
160412
160635
  sessionActivePresence;
160413
- titleGenerationInFlight = /* @__PURE__ */ new Set();
160636
+ titleGenerationInFlight = /* @__PURE__ */ new Map();
160414
160637
  archiveWatchHandle = null;
160415
160638
  archiveInFlight = /* @__PURE__ */ new Set();
160416
160639
  deleteWatchHandle = null;
@@ -165925,18 +166148,23 @@ ${escapeHtmlScriptContent(VISUAL_ANNOTATION_INSPECTOR_BROWSER_SCRIPT)}
165925
166148
  if (usesAcpProvidedSessionTitle(cliType, agentType)) {
165926
166149
  return;
165927
166150
  }
165928
- if (this.titleGenerationInFlight.has(sessionId)) {
166151
+ const existingGeneration = this.titleGenerationInFlight.get(sessionId);
166152
+ if (existingGeneration) {
166153
+ try {
166154
+ await existingGeneration;
166155
+ } catch (error2) {
166156
+ this.logger.debug(`[${sessionId}] Existing session title generation failed: ${formatErrorMessage(error2)}`);
166157
+ }
165929
166158
  return;
165930
166159
  }
165931
- this.titleGenerationInFlight.add(sessionId);
165932
- try {
166160
+ const generation = (async () => {
165933
166161
  const sessionDoc = await this.workspaceDocument.getOrCreateSessionDoc(sessionId);
165934
166162
  const meta = await sessionDoc.getMetaState();
165935
166163
  const existingTitle = meta?.title?.trim();
165936
166164
  const canOverwriteExistingTitle = meta?.titleSource === "draft";
165937
166165
  if (existingTitle && !canOverwriteExistingTitle) {
165938
166166
  this.logger.debug(`[${sessionId}] Skipping session title generation because title already set: ${existingTitle}`);
165939
- return;
166167
+ return meta?.titleSource === "generated" ? existingTitle : null;
165940
166168
  }
165941
166169
  this.logger.debug(`[${sessionId}] Generating session title because title is missing`);
165942
166170
  const resolvedTitleConfig = titleConfig ?? await this.resolveTitleConfig(sessionId, meta?.agentConfigId);
@@ -165952,20 +166180,27 @@ ${escapeHtmlScriptContent(VISUAL_ANNOTATION_INSPECTOR_BROWSER_SCRIPT)}
165952
166180
  });
165953
166181
  if (!title2) {
165954
166182
  this.logger.debug(`[${sessionId}] Session title generation returned empty result`);
165955
- return;
166183
+ return null;
165956
166184
  }
165957
166185
  const applied = await sessionDoc.setTitleIfSourceIn(title2, "generated", [
165958
166186
  "draft"
165959
166187
  ]);
165960
166188
  if (!applied) {
165961
166189
  this.logger.debug(`[${sessionId}] Skipping generated title because title changed while generation was in flight`);
165962
- return;
166190
+ } else {
166191
+ this.logger.debug(`[${sessionId}] Session title stored in metadata: ${title2}`);
165963
166192
  }
165964
- this.logger.debug(`[${sessionId}] Session title stored in metadata: ${title2}`);
166193
+ return title2;
166194
+ })();
166195
+ this.titleGenerationInFlight.set(sessionId, generation);
166196
+ try {
166197
+ await generation;
165965
166198
  } catch (error2) {
165966
166199
  this.logger.debug(`[${sessionId}] Failed to generate/store session title: ${formatErrorMessage(error2)}`);
165967
166200
  } finally {
165968
- this.titleGenerationInFlight.delete(sessionId);
166201
+ if (this.titleGenerationInFlight.get(sessionId) === generation) {
166202
+ this.titleGenerationInFlight.delete(sessionId);
166203
+ }
165969
166204
  }
165970
166205
  }
165971
166206
  async startSessionDispatchWatcher() {
@@ -166380,11 +166615,14 @@ ${escapeHtmlScriptContent(VISUAL_ANNOTATION_INSPECTOR_BROWSER_SCRIPT)}
166380
166615
  let metaCustomAcp;
166381
166616
  let metaRuntimeOverrides;
166382
166617
  let metaAgentConfigId;
166618
+ let reusableTitlePromise;
166383
166619
  try {
166384
166620
  const sessionDoc = await this.workspaceDocument.getOrCreateSessionDoc(sessionId);
166385
166621
  const meta = await sessionDoc.getMetaState();
166386
166622
  metaBranchName = meta?.branchName?.trim() || null;
166387
166623
  metaAgentConfigId = meta?.agentConfigId;
166624
+ const generatedMetaTitle = meta?.titleSource === "generated" ? meta.title?.trim() : "";
166625
+ reusableTitlePromise = generatedMetaTitle ? Promise.resolve(generatedMetaTitle) : this.titleGenerationInFlight.get(sessionId);
166388
166626
  const agentConfig = metaAgentConfigId ? await this.workspaceDocument.getAgentConfigById(metaAgentConfigId) : null;
166389
166627
  const legacyLaunchConfig = await readLegacySessionLaunchConfig({
166390
166628
  repo: this.workspaceDocument.repo,
@@ -166403,7 +166641,7 @@ ${escapeHtmlScriptContent(VISUAL_ANNOTATION_INSPECTOR_BROWSER_SCRIPT)}
166403
166641
  this.logger.debug(`[${sessionId}] Failed to read session meta before branch rename: ${formatErrorMessage(error2)}`);
166404
166642
  }
166405
166643
  const resolvedTitleConfig = titleConfig ?? await this.resolveTitleConfig(sessionId, metaAgentConfigId);
166406
- const branchName = await this.generateBranchNameWithTimeout(cliType, agentType, trimmedPrompt, env2, 2e4, resolvedTitleConfig, metaCustomAcp, metaRuntimeOverrides);
166644
+ const branchName = await this.generateBranchNameWithTimeout(cliType, agentType, trimmedPrompt, env2, 2e4, resolvedTitleConfig, metaCustomAcp, metaRuntimeOverrides, reusableTitlePromise);
166407
166645
  if (!branchName) {
166408
166646
  this.logger.debug(`[${sessionId}] Skipping branch rename: name generation timed out`);
166409
166647
  return;
@@ -166433,13 +166671,13 @@ ${escapeHtmlScriptContent(VISUAL_ANNOTATION_INSPECTOR_BROWSER_SCRIPT)}
166433
166671
  this.logger.debug(`[${sessionId}] Failed to rename branch: ${formatErrorMessage(error2)}`);
166434
166672
  }
166435
166673
  }
166436
- async generateBranchNameWithTimeout(cliType, agentType, taskPrompt, env2, timeoutMs, titleConfig, customAcp, runtimeOverrides) {
166674
+ async generateBranchNameWithTimeout(cliType, agentType, taskPrompt, env2, timeoutMs, titleConfig, customAcp, runtimeOverrides, reusableTitlePromise) {
166437
166675
  let timeoutHandle = null;
166438
166676
  const timeoutPromise = new Promise((resolve2) => {
166439
166677
  timeoutHandle = setTimeout(() => resolve2(null), timeoutMs);
166440
166678
  });
166441
166679
  const namePromise = (async () => {
166442
- const title2 = await generateTitleIsolated({
166680
+ const title2 = reusableTitlePromise ? await reusableTitlePromise : await generateTitleIsolated({
166443
166681
  cliType,
166444
166682
  agentType,
166445
166683
  customAcp,
@@ -166940,15 +167178,28 @@ ${escapeHtmlScriptContent(VISUAL_ANNOTATION_INSPECTOR_BROWSER_SCRIPT)}
166940
167178
  }
166941
167179
  const execFileAsync = promisify$1(execFile$1);
166942
167180
  const MEMORY_PROBE_TIMEOUT_MS = 1e3;
167181
+ const DARWIN_PRESSURE_NORMAL = 1;
167182
+ const DARWIN_PRESSURE_WARNING = 2;
167183
+ const DARWIN_PRESSURE_CRITICAL = 4;
166943
167184
  async function getMemoryPressureSnapshot() {
166944
- const windowsStatus = await getWindowsMemoryStatus();
167185
+ const [windowsStatus, darwinPressureLevel] = await Promise.all([
167186
+ getWindowsMemoryStatus(),
167187
+ getDarwinMemoryPressureLevel()
167188
+ ]);
166945
167189
  const systemAvailable = await getSystemAvailableMemoryBytes(windowsStatus);
166946
- const cgroupAvailable = getCgroupAvailableMemoryBytes();
166947
- const availableMemoryBytes = cgroupAvailable !== null ? Math.min(systemAvailable, cgroupAvailable) : systemAvailable;
167190
+ const cgroup = readCgroupMemoryState();
167191
+ const availableMemoryBytes = cgroup !== null ? Math.min(systemAvailable, cgroup.hardHeadroomBytes + cgroup.reclaimableBytes) : systemAvailable;
166948
167192
  const effectiveMemoryLimitBytes = getEffectiveMemoryLimitBytes();
166949
167193
  return {
166950
167194
  availableMemoryBytes,
166951
167195
  effectiveMemoryLimitBytes,
167196
+ ...darwinPressureLevel !== null ? {
167197
+ memoryPressureLevel: darwinPressureLevel
167198
+ } : {},
167199
+ ...cgroup !== null ? {
167200
+ cgroup,
167201
+ hostAvailableBytes: systemAvailable
167202
+ } : {},
166952
167203
  ...windowsStatus ? {
166953
167204
  availableCommitBytes: windowsStatus.availableCommitBytes,
166954
167205
  commitLimitBytes: windowsStatus.commitLimitBytes,
@@ -166958,7 +167209,7 @@ ${escapeHtmlScriptContent(VISUAL_ANNOTATION_INSPECTOR_BROWSER_SCRIPT)}
166958
167209
  }
166959
167210
  function getEffectiveMemoryLimitBytes() {
166960
167211
  const totalMem = os__default$1.totalmem();
166961
- const cgroupMax = getCgroupMemoryMaxBytes();
167212
+ const cgroupMax = findTightestCgroupLimit()?.maxBytes ?? null;
166962
167213
  if (cgroupMax !== null) {
166963
167214
  return Math.min(totalMem, cgroupMax);
166964
167215
  }
@@ -167031,6 +167282,34 @@ $mem | ConvertTo-Json -Compress
167031
167282
  return null;
167032
167283
  }
167033
167284
  }
167285
+ async function getDarwinMemoryPressureLevel() {
167286
+ if (process.platform !== "darwin") {
167287
+ return null;
167288
+ }
167289
+ try {
167290
+ const { stdout } = await execFileAsync("sysctl", [
167291
+ "-n",
167292
+ "kern.memorystatus_vm_pressure_level"
167293
+ ], {
167294
+ encoding: "utf8",
167295
+ timeout: MEMORY_PROBE_TIMEOUT_MS
167296
+ });
167297
+ return parseDarwinPressureLevel(String(stdout ?? ""));
167298
+ } catch {
167299
+ return null;
167300
+ }
167301
+ }
167302
+ function parseDarwinPressureLevel(raw2) {
167303
+ const trimmed2 = raw2.trim();
167304
+ if (!/^\d+$/.test(trimmed2)) {
167305
+ return null;
167306
+ }
167307
+ const value = Number.parseInt(trimmed2, 10);
167308
+ if (value === DARWIN_PRESSURE_NORMAL || value === DARWIN_PRESSURE_WARNING || value === DARWIN_PRESSURE_CRITICAL) {
167309
+ return value;
167310
+ }
167311
+ return null;
167312
+ }
167034
167313
  async function getDarwinAvailableMemoryBytes() {
167035
167314
  if (process.platform !== "darwin") {
167036
167315
  return null;
@@ -167078,23 +167357,20 @@ $mem | ConvertTo-Json -Compress
167078
167357
  const availablePages = freePages + speculativePages + purgeablePages + reclaimableCachedPages;
167079
167358
  return availablePages * pageSize;
167080
167359
  }
167081
- function getCgroupMemoryMaxBytes() {
167360
+ function findTightestCgroupLimit() {
167082
167361
  try {
167083
167362
  const cgroupPath = readSelfCgroupPath();
167084
167363
  if (cgroupPath === null) return null;
167085
167364
  let tightest = null;
167086
167365
  let current2 = cgroupPath;
167087
167366
  for (let depth = 0; depth < 20; depth++) {
167088
- const memMaxPath = `/sys/fs/cgroup${current2 === "/" ? "" : current2}/memory.max`;
167089
- const raw2 = readFileSafe(memMaxPath);
167090
- if (raw2 !== null) {
167091
- const trimmed2 = raw2.trim();
167092
- if (trimmed2 !== "max") {
167093
- const value = parseInt(trimmed2, 10);
167094
- if (Number.isFinite(value) && value > 0) {
167095
- tightest = tightest === null ? value : Math.min(tightest, value);
167096
- }
167097
- }
167367
+ const prefix = `/sys/fs/cgroup${current2 === "/" ? "" : current2}`;
167368
+ const value = parseCgroupLimit(readFileSafe(`${prefix}/memory.max`));
167369
+ if (value !== null && (tightest === null || value < tightest.maxBytes)) {
167370
+ tightest = {
167371
+ prefix,
167372
+ maxBytes: value
167373
+ };
167098
167374
  }
167099
167375
  if (current2 === "/" || current2 === "") break;
167100
167376
  const parent = current2.substring(0, current2.lastIndexOf("/")) || "/";
@@ -167106,42 +167382,72 @@ $mem | ConvertTo-Json -Compress
167106
167382
  return null;
167107
167383
  }
167108
167384
  }
167109
- function getCgroupAvailableMemoryBytes() {
167110
- try {
167111
- const cgroupPath = readSelfCgroupPath();
167112
- if (cgroupPath === null) return null;
167113
- let tightestMax = null;
167114
- let tightestPath = null;
167115
- let current2 = cgroupPath;
167116
- for (let depth = 0; depth < 20; depth++) {
167117
- const prefix = `/sys/fs/cgroup${current2 === "/" ? "" : current2}`;
167118
- const raw2 = readFileSafe(`${prefix}/memory.max`);
167119
- if (raw2 !== null) {
167120
- const trimmed2 = raw2.trim();
167121
- if (trimmed2 !== "max") {
167122
- const value = parseInt(trimmed2, 10);
167123
- if (Number.isFinite(value) && value > 0) {
167124
- if (tightestMax === null || value < tightestMax) {
167125
- tightestMax = value;
167126
- tightestPath = prefix;
167127
- }
167128
- }
167129
- }
167130
- }
167131
- if (current2 === "/" || current2 === "") break;
167132
- const parent = current2.substring(0, current2.lastIndexOf("/")) || "/";
167133
- if (parent === current2) break;
167134
- current2 = parent;
167385
+ function parseCgroupLimit(raw2) {
167386
+ if (raw2 === null) return null;
167387
+ const trimmed2 = raw2.trim();
167388
+ if (trimmed2 === "max") return null;
167389
+ const value = parseInt(trimmed2, 10);
167390
+ return Number.isFinite(value) && value > 0 ? value : null;
167391
+ }
167392
+ function readCgroupMemoryState() {
167393
+ const limit2 = findTightestCgroupLimit();
167394
+ if (limit2 === null) return null;
167395
+ const currentRaw = readFileSafe(`${limit2.prefix}/memory.current`);
167396
+ if (currentRaw === null) return null;
167397
+ const currentBytes = parseInt(currentRaw.trim(), 10);
167398
+ if (!Number.isFinite(currentBytes)) return null;
167399
+ const stat2 = parseCgroupMemoryStat(readFileSafe(`${limit2.prefix}/memory.stat`) ?? "");
167400
+ return {
167401
+ path: limit2.prefix,
167402
+ maxBytes: limit2.maxBytes,
167403
+ highBytes: parseCgroupLimit(readFileSafe(`${limit2.prefix}/memory.high`)),
167404
+ currentBytes,
167405
+ hardHeadroomBytes: Math.max(0, limit2.maxBytes - currentBytes),
167406
+ reclaimableBytes: computeCgroupReclaimableBytes(stat2),
167407
+ stat: stat2,
167408
+ psiSomeAvg10: parseCgroupPressureSomeAvg10(readFileSafe(`${limit2.prefix}/memory.pressure`) ?? ""),
167409
+ events: parseCgroupMemoryEvents(readFileSafe(`${limit2.prefix}/memory.events`) ?? "")
167410
+ };
167411
+ }
167412
+ function parseCgroupMemoryStat(raw2) {
167413
+ const values = /* @__PURE__ */ new Map();
167414
+ for (const line3 of raw2.split("\n")) {
167415
+ const match5 = line3.trim().match(/^([a-z_]+)\s+(\d+)$/);
167416
+ if (match5?.[1] && match5[2]) {
167417
+ values.set(match5[1], parseInt(match5[2], 10));
167135
167418
  }
167136
- if (tightestMax === null || tightestPath === null) return null;
167137
- const currentRaw = readFileSafe(`${tightestPath}/memory.current`);
167138
- if (currentRaw === null) return null;
167139
- const currentUsage = parseInt(currentRaw.trim(), 10);
167140
- if (!Number.isFinite(currentUsage)) return null;
167141
- return Math.max(0, tightestMax - currentUsage);
167142
- } catch {
167143
- return null;
167144
167419
  }
167420
+ return {
167421
+ inactiveFileBytes: values.get("inactive_file") ?? 0,
167422
+ activeFileBytes: values.get("active_file") ?? 0,
167423
+ slabReclaimableBytes: values.get("slab_reclaimable") ?? 0,
167424
+ dirtyBytes: (values.get("file_dirty") ?? 0) + (values.get("file_writeback") ?? 0)
167425
+ };
167426
+ }
167427
+ function computeCgroupReclaimableBytes(stat2) {
167428
+ const cleanInactiveFile = Math.max(0, stat2.inactiveFileBytes - stat2.dirtyBytes);
167429
+ return cleanInactiveFile + Math.floor(stat2.slabReclaimableBytes / 2);
167430
+ }
167431
+ function parseCgroupPressureSomeAvg10(raw2) {
167432
+ const match5 = raw2.match(/^some\s+avg10=([\d.]+)/m);
167433
+ if (!match5?.[1]) return null;
167434
+ const value = Number.parseFloat(match5[1]);
167435
+ return Number.isFinite(value) ? value : null;
167436
+ }
167437
+ function parseCgroupMemoryEvents(raw2) {
167438
+ const read = (key2) => {
167439
+ const match5 = raw2.match(new RegExp(`^${key2}\\s+(\\d+)$`, "m"));
167440
+ if (!match5?.[1]) return null;
167441
+ const value = parseInt(match5[1], 10);
167442
+ return Number.isFinite(value) ? value : null;
167443
+ };
167444
+ const high = read("high");
167445
+ const max2 = read("max");
167446
+ if (high === null || max2 === null) return null;
167447
+ return {
167448
+ high,
167449
+ max: max2
167450
+ };
167145
167451
  }
167146
167452
  function readSelfCgroupPath() {
167147
167453
  try {
@@ -167170,6 +167476,11 @@ $mem | ConvertTo-Json -Compress
167170
167476
  const GIB = 1024 * 1024 * 1024;
167171
167477
  const WINDOWS_COMMIT_THRESHOLD_FLOOR_BYTES = 512 * 1024 * 1024;
167172
167478
  const WINDOWS_COMMIT_THRESHOLD_CEILING_BYTES = 2 * GIB;
167479
+ const DEFAULT_MAX_EVICTIONS_PER_CALL = 3;
167480
+ const DEFAULT_PRESSURE_RECHECK_ATTEMPTS = 2;
167481
+ const DEFAULT_PRESSURE_RECHECK_DELAY_MS = 500;
167482
+ const DEFAULT_PSI_STALL_AVG10 = 10;
167483
+ const DEFAULT_CGROUP_HARD_FLOOR_BYTES = 128 * 1024 * 1024;
167173
167484
  function defaultMemoryThresholdBytes() {
167174
167485
  const tenPercent = Math.floor(getEffectiveMemoryLimitBytes() * 0.1);
167175
167486
  return Math.max(GIB, Math.min(4 * GIB, tenPercent));
@@ -167179,16 +167490,83 @@ $mem | ConvertTo-Json -Compress
167179
167490
  idleTimeoutMs: readEnvNumber$1("LODY_SESSION_GC_IDLE_TIMEOUT_MS", 20 * 60 * 1e3),
167180
167491
  sweepIntervalMs: readEnvNumber$1("LODY_SESSION_GC_SWEEP_INTERVAL_MS", 60 * 1e3),
167181
167492
  enabled: process.env.LODY_SESSION_GC_ENABLED !== "false",
167182
- memoryThresholdBytes: readEnvNumber$1("LODY_SESSION_GC_MEMORY_THRESHOLD_BYTES", defaultMemoryThresholdBytes())
167493
+ memoryThresholdBytes: readEnvNumber$1("LODY_SESSION_GC_MEMORY_THRESHOLD_BYTES", defaultMemoryThresholdBytes()),
167494
+ maxEvictionsPerCall: readEnvNumber$1("LODY_SESSION_GC_MAX_EVICTIONS_PER_CALL", DEFAULT_MAX_EVICTIONS_PER_CALL),
167495
+ pressureRecheckAttempts: readEnvNumber$1("LODY_SESSION_GC_PRESSURE_RECHECK_ATTEMPTS", DEFAULT_PRESSURE_RECHECK_ATTEMPTS),
167496
+ pressureRecheckDelayMs: readEnvNumber$1("LODY_SESSION_GC_PRESSURE_RECHECK_DELAY_MS", DEFAULT_PRESSURE_RECHECK_DELAY_MS)
167183
167497
  };
167184
167498
  }
167185
167499
  function getWindowsCommitThresholdBytes(memoryThresholdBytes) {
167186
167500
  return Math.max(WINDOWS_COMMIT_THRESHOLD_FLOOR_BYTES, Math.min(WINDOWS_COMMIT_THRESHOLD_CEILING_BYTES, memoryThresholdBytes));
167187
167501
  }
167502
+ function evaluateMemoryPressure(snapshot, thresholds2) {
167503
+ if (thresholds2.platform === "darwin") {
167504
+ if (snapshot.memoryPressureLevel === DARWIN_PRESSURE_CRITICAL) {
167505
+ return {
167506
+ evict: true,
167507
+ block: true,
167508
+ reason: "darwin_pressure_critical"
167509
+ };
167510
+ }
167511
+ if (snapshot.memoryPressureLevel === DARWIN_PRESSURE_WARNING) {
167512
+ return {
167513
+ evict: true,
167514
+ block: false,
167515
+ reason: "darwin_pressure_warning"
167516
+ };
167517
+ }
167518
+ return {
167519
+ evict: false,
167520
+ block: false,
167521
+ reason: null
167522
+ };
167523
+ }
167524
+ const commitPressure = snapshot.availableCommitBytes !== void 0 && snapshot.availableCommitBytes < thresholds2.commitThresholdBytes;
167525
+ const cgroup = snapshot.cgroup;
167526
+ if (cgroup) {
167527
+ const hostLow = snapshot.hostAvailableBytes !== void 0 && snapshot.hostAvailableBytes < thresholds2.thresholdBytes;
167528
+ const cgroupLow = cgroup.hardHeadroomBytes + cgroup.reclaimableBytes < thresholds2.thresholdBytes;
167529
+ const stalled = cgroup.psiSomeAvg10 !== null ? cgroup.psiSomeAvg10 >= thresholds2.psiStallAvg10 : cgroup.hardHeadroomBytes < thresholds2.cgroupHardFloorBytes;
167530
+ if (hostLow || cgroupLow && stalled) {
167531
+ return {
167532
+ evict: true,
167533
+ block: true,
167534
+ reason: stalled ? "cgroup_stalled" : "physical"
167535
+ };
167536
+ }
167537
+ if (cgroupLow) {
167538
+ return {
167539
+ evict: true,
167540
+ block: false,
167541
+ reason: "cgroup_low_headroom"
167542
+ };
167543
+ }
167544
+ if (commitPressure) {
167545
+ return {
167546
+ evict: true,
167547
+ block: true,
167548
+ reason: "commit"
167549
+ };
167550
+ }
167551
+ return {
167552
+ evict: false,
167553
+ block: false,
167554
+ reason: null
167555
+ };
167556
+ }
167557
+ const physicalPressure = snapshot.availableMemoryBytes < thresholds2.thresholdBytes;
167558
+ const reason = physicalPressure && commitPressure ? "physical_and_commit" : physicalPressure ? "physical" : commitPressure ? "commit" : null;
167559
+ return {
167560
+ evict: reason !== null,
167561
+ block: reason !== null,
167562
+ reason
167563
+ };
167564
+ }
167188
167565
  class SessionGCManager {
167189
- constructor(config2, deps) {
167566
+ constructor(config2, deps, platform2 = process.platform) {
167190
167567
  this.config = config2;
167191
167568
  this.deps = deps;
167569
+ this.platform = platform2;
167192
167570
  }
167193
167571
  sweepInterval = null;
167194
167572
  start() {
@@ -167196,7 +167574,8 @@ $mem | ConvertTo-Json -Compress
167196
167574
  this.deps.logger.debug("[GC] Session GC is disabled");
167197
167575
  return;
167198
167576
  }
167199
- this.deps.logger.debug(`[GC] Starting session GC (interval=${this.config.sweepIntervalMs}ms, idleTimeout=${this.config.idleTimeoutMs}ms, memoryThreshold=${Math.round(this.config.memoryThresholdBytes / 1024 / 1024)}MB)`);
167577
+ const pressureSignal = this.platform === "darwin" ? "kern.memorystatus_vm_pressure_level" : `available<${Math.round(this.config.memoryThresholdBytes / 1024 / 1024)}MB`;
167578
+ this.deps.logger.debug(`[GC] Starting session GC (interval=${this.config.sweepIntervalMs}ms, idleTimeout=${this.config.idleTimeoutMs}ms, pressureSignal=${pressureSignal}, maxEvictionsPerCall=${this.config.maxEvictionsPerCall})`);
167200
167579
  this.sweepInterval = setInterval(() => void this.sweep(), this.config.sweepIntervalMs);
167201
167580
  }
167202
167581
  stop() {
@@ -167236,48 +167615,39 @@ $mem | ConvertTo-Json -Compress
167236
167615
  async evictForMemoryPressure(excludeSessionId) {
167237
167616
  const thresholdBytes = this.config.memoryThresholdBytes;
167238
167617
  const commitThresholdBytes = getWindowsCommitThresholdBytes(thresholdBytes);
167618
+ const thresholds2 = {
167619
+ platform: this.platform,
167620
+ thresholdBytes,
167621
+ commitThresholdBytes,
167622
+ psiStallAvg10: DEFAULT_PSI_STALL_AVG10,
167623
+ cgroupHardFloorBytes: DEFAULT_CGROUP_HARD_FLOOR_BYTES
167624
+ };
167239
167625
  let memorySnapshot = await this.deps.memoryPressure.getLatest();
167240
- let availableMemory = memorySnapshot.availableMemoryBytes;
167241
- let pressureReason = this.getPressureReason(memorySnapshot, thresholdBytes, commitThresholdBytes);
167242
- if (!this.config.enabled) {
167243
- return {
167244
- availableMemoryBytes: availableMemory,
167245
- thresholdBytes,
167246
- hadMemoryPressure: false,
167247
- stillUnderPressure: false,
167248
- evictedSessionIds: [],
167249
- pressureReason: null,
167250
- ...memorySnapshot.availableCommitBytes !== void 0 ? {
167251
- availableCommitBytes: memorySnapshot.availableCommitBytes,
167252
- commitThresholdBytes,
167253
- commitLimitBytes: memorySnapshot.commitLimitBytes,
167254
- committedBytes: memorySnapshot.committedBytes
167255
- } : {}
167256
- };
167257
- }
167258
- if (pressureReason === null) {
167259
- return {
167260
- availableMemoryBytes: availableMemory,
167626
+ let verdict = evaluateMemoryPressure(memorySnapshot, thresholds2);
167627
+ if (this.config.enabled && verdict.evict) {
167628
+ memorySnapshot = await this.deps.memoryPressure.refresh();
167629
+ verdict = evaluateMemoryPressure(memorySnapshot, thresholds2);
167630
+ }
167631
+ if (!this.config.enabled || !verdict.evict) {
167632
+ return this.buildEvictionResult({
167633
+ snapshot: memorySnapshot,
167261
167634
  thresholdBytes,
167635
+ commitThresholdBytes,
167262
167636
  hadMemoryPressure: false,
167263
- stillUnderPressure: false,
167264
- evictedSessionIds: [],
167265
- pressureReason: null,
167266
- ...memorySnapshot.availableCommitBytes !== void 0 ? {
167267
- availableCommitBytes: memorySnapshot.availableCommitBytes,
167268
- commitThresholdBytes,
167269
- commitLimitBytes: memorySnapshot.commitLimitBytes,
167270
- committedBytes: memorySnapshot.committedBytes
167271
- } : {}
167272
- };
167637
+ verdict: this.config.enabled ? verdict : {
167638
+ evict: false,
167639
+ block: false,
167640
+ reason: null
167641
+ },
167642
+ evictedSessionIds: []
167643
+ });
167273
167644
  }
167274
- const commitText = memorySnapshot.availableCommitBytes !== void 0 ? `, commit headroom ${Math.round(memorySnapshot.availableCommitBytes / 1024 / 1024)}MB (threshold: ${Math.round(commitThresholdBytes / 1024 / 1024)}MB)` : "";
167275
- this.deps.logger.debug(`[GC] Memory pressure detected: ${Math.round(availableMemory / 1024 / 1024)}MB available (threshold: ${Math.round(thresholdBytes / 1024 / 1024)}MB)${commitText}`);
167645
+ this.deps.logger.debug(`[GC] Memory pressure detected (${verdict.reason}): ${this.describeMemoryState(memorySnapshot, thresholdBytes, commitThresholdBytes)}`);
167276
167646
  const sessions = this.getSessionsWithIdleTime();
167277
167647
  sessions.sort((a, b) => b.idleMs - a.idleMs);
167278
167648
  const evictedSessionIds = [];
167279
167649
  for (const { sessionId, idleMs } of sessions) {
167280
- if (pressureReason === null) {
167650
+ if (!verdict.evict || evictedSessionIds.length >= this.config.maxEvictionsPerCall) {
167281
167651
  break;
167282
167652
  }
167283
167653
  if (excludeSessionId && sessionId === excludeSessionId) {
@@ -167294,46 +167664,78 @@ $mem | ConvertTo-Json -Compress
167294
167664
  await this.deps.cleanSession(sessionId);
167295
167665
  evictedSessionIds.push(sessionId);
167296
167666
  memorySnapshot = await this.deps.memoryPressure.refresh();
167297
- availableMemory = memorySnapshot.availableMemoryBytes;
167298
- pressureReason = this.getPressureReason(memorySnapshot, thresholdBytes, commitThresholdBytes);
167667
+ verdict = evaluateMemoryPressure(memorySnapshot, thresholds2);
167299
167668
  } catch (error2) {
167300
167669
  this.deps.logger.error(`[GC] Failed to evict session ${sessionId}: ${formatErrorMessage(error2)}`);
167301
167670
  }
167302
167671
  }
167303
- const stillUnderPressure = pressureReason !== null;
167672
+ for (let attempt = 0; verdict.block && attempt < this.config.pressureRecheckAttempts; attempt++) {
167673
+ await this.sleep(this.config.pressureRecheckDelayMs);
167674
+ memorySnapshot = await this.deps.memoryPressure.refresh();
167675
+ verdict = evaluateMemoryPressure(memorySnapshot, thresholds2);
167676
+ if (!verdict.block) {
167677
+ this.deps.logger.debug(`[GC] Memory pressure cleared on recheck ${attempt + 1}: ${this.describeMemoryState(memorySnapshot, thresholdBytes, commitThresholdBytes)}`);
167678
+ }
167679
+ }
167680
+ const availableMemory = memorySnapshot.availableMemoryBytes;
167681
+ const stillUnderPressure = verdict.block;
167304
167682
  if (evictedSessionIds.length > 0) {
167305
167683
  this.deps.logger.debug(`[GC] Memory pressure eviction complete: evicted ${evictedSessionIds.length} sessions, available memory now ${Math.round(availableMemory / 1024 / 1024)}MB`);
167306
167684
  } else if (stillUnderPressure) {
167307
167685
  this.deps.logger.debug("[GC] Memory pressure persists but no idle sessions were eligible for eviction");
167308
167686
  }
167309
- return {
167310
- availableMemoryBytes: availableMemory,
167687
+ return this.buildEvictionResult({
167688
+ snapshot: memorySnapshot,
167311
167689
  thresholdBytes,
167690
+ commitThresholdBytes,
167312
167691
  hadMemoryPressure: true,
167313
- stillUnderPressure,
167314
- evictedSessionIds,
167315
- pressureReason,
167316
- ...memorySnapshot.availableCommitBytes !== void 0 ? {
167317
- availableCommitBytes: memorySnapshot.availableCommitBytes,
167692
+ verdict,
167693
+ evictedSessionIds
167694
+ });
167695
+ }
167696
+ buildEvictionResult(options) {
167697
+ const { snapshot, thresholdBytes, commitThresholdBytes, verdict } = options;
167698
+ return {
167699
+ availableMemoryBytes: snapshot.availableMemoryBytes,
167700
+ thresholdBytes,
167701
+ hadMemoryPressure: options.hadMemoryPressure,
167702
+ stillUnderPressure: verdict.block,
167703
+ evictedSessionIds: options.evictedSessionIds,
167704
+ pressureReason: verdict.reason,
167705
+ ...snapshot.memoryPressureLevel !== void 0 ? {
167706
+ memoryPressureLevel: snapshot.memoryPressureLevel
167707
+ } : {},
167708
+ ...snapshot.cgroup !== void 0 ? {
167709
+ cgroup: snapshot.cgroup
167710
+ } : {},
167711
+ ...snapshot.hostAvailableBytes !== void 0 ? {
167712
+ hostAvailableBytes: snapshot.hostAvailableBytes
167713
+ } : {},
167714
+ ...snapshot.availableCommitBytes !== void 0 ? {
167715
+ availableCommitBytes: snapshot.availableCommitBytes,
167318
167716
  commitThresholdBytes,
167319
- commitLimitBytes: memorySnapshot.commitLimitBytes,
167320
- committedBytes: memorySnapshot.committedBytes
167717
+ commitLimitBytes: snapshot.commitLimitBytes,
167718
+ committedBytes: snapshot.committedBytes
167321
167719
  } : {}
167322
167720
  };
167323
167721
  }
167324
- getPressureReason(snapshot, thresholdBytes, commitThresholdBytes) {
167325
- const physicalPressure = snapshot.availableMemoryBytes < thresholdBytes;
167326
- const commitPressure = snapshot.availableCommitBytes !== void 0 && snapshot.availableCommitBytes < commitThresholdBytes;
167327
- if (physicalPressure && commitPressure) {
167328
- return "physical_and_commit";
167329
- }
167330
- if (physicalPressure) {
167331
- return "physical";
167722
+ sleep(ms2) {
167723
+ if (this.deps.sleep) return this.deps.sleep(ms2);
167724
+ return new Promise((resolve2) => {
167725
+ setTimeout(resolve2, ms2).unref?.();
167726
+ });
167727
+ }
167728
+ describeMemoryState(snapshot, thresholdBytes, commitThresholdBytes) {
167729
+ if (snapshot.memoryPressureLevel !== void 0) {
167730
+ return `kernel pressure level ${snapshot.memoryPressureLevel}`;
167332
167731
  }
167333
- if (commitPressure) {
167334
- return "commit";
167732
+ const cgroup = snapshot.cgroup;
167733
+ if (cgroup) {
167734
+ const mb = (bytes) => Math.round(bytes / 1024 / 1024);
167735
+ return `cgroup ${cgroup.path}: hard headroom ${mb(cgroup.hardHeadroomBytes)}MB + reclaimable ${mb(cgroup.reclaimableBytes)}MB (of ${mb(cgroup.stat.activeFileBytes)}MB active file cache not counted), host available ${snapshot.hostAvailableBytes !== void 0 ? mb(snapshot.hostAvailableBytes) : "?"}MB, PSI some avg10 ${cgroup.psiSomeAvg10 ?? "?"}, threshold ${mb(thresholdBytes)}MB`;
167335
167736
  }
167336
- return null;
167737
+ const commitText = snapshot.availableCommitBytes !== void 0 ? `, commit headroom ${Math.round(snapshot.availableCommitBytes / 1024 / 1024)}MB (threshold: ${Math.round(commitThresholdBytes / 1024 / 1024)}MB)` : "";
167738
+ return `${Math.round(snapshot.availableMemoryBytes / 1024 / 1024)}MB available (threshold: ${Math.round(thresholdBytes / 1024 / 1024)}MB)${commitText}`;
167337
167739
  }
167338
167740
  async getIdleCandidates() {
167339
167741
  const sessions = this.getSessionsWithIdleTime();
@@ -178064,13 +178466,14 @@ export PATH=${toSingleQuotedShellString(ghShimBinDir)}:"$PATH"
178064
178466
  await removeStaleUnixSocket(socketPath, "local_terminal_socket_in_use");
178065
178467
  const server = net.createServer((socket) => {
178066
178468
  let buffer2 = "";
178469
+ const decodeChunk = createUtf8StreamDecoder();
178067
178470
  const state2 = createTerminalSocketState();
178068
178471
  activeClientSockets$1.add(socket);
178069
178472
  const unsubscribe = config2.terminalPtyService.onEvent((event) => {
178070
178473
  publishTerminalEvent(socket, state2, event);
178071
178474
  });
178072
178475
  socket.on("data", (chunk) => {
178073
- buffer2 += chunk.toString("utf8");
178476
+ buffer2 += decodeChunk(chunk);
178074
178477
  if (buffer2.length > MAX_BUFFER_BYTES) {
178075
178478
  send(socket, {
178076
178479
  type: "error",
@@ -178228,7 +178631,7 @@ export PATH=${toSingleQuotedShellString(ghShimBinDir)}:"$PATH"
178228
178631
  });
178229
178632
  }
178230
178633
  });
178231
- socket.on("data", (chunk) => splitLines(chunk.toString("utf8")));
178634
+ socket.on("data", (chunk) => splitLines(chunk));
178232
178635
  socket.setTimeout(CONNECTION_IDLE_TIMEOUT_MS, () => {
178233
178636
  config2.logger.debug(`[loro-data-plane] connection ${connectionId} idle; dropping`);
178234
178637
  socket.destroy();
@@ -185404,10 +185807,11 @@ Shutting down gracefully${reason}...`);
185404
185807
  function logCliDetectionResults(logger2, availability) {
185405
185808
  logger2.debug("Local agent auth detection results:");
185406
185809
  logger2.debug(`kimi: ${availability.kimi || "not found"}`);
185810
+ logger2.debug(`grok: ${availability.grok || "not found"}`);
185407
185811
  logger2.debug(`claude: ${availability.claude || "not found"}`);
185408
185812
  logger2.debug(`codex: ${availability.codex || "not found"}`);
185409
185813
  }
185410
- const startCommand = new Command("start").description("Start agent service in native mode").option("--machine-name <name>", "Machine name to register (defaults to hostname)").option("--cli-types <types...>", "Specify CLI types to register: `kimi`, `claude`, or `codex`", (value, previous) => {
185814
+ const startCommand = new Command("start").description("Start agent service in native mode").option("--machine-name <name>", "Machine name to register (defaults to hostname)").option("--cli-types <types...>", "Specify CLI types to register: `kimi`, `grok`, `claude`, or `codex`", (value, previous) => {
185411
185815
  if (!previous) {
185412
185816
  return [
185413
185817
  value
@@ -185435,7 +185839,7 @@ Shutting down gracefully${reason}...`);
185435
185839
  });
185436
185840
  scrubLocalSupervisorCapabilityEnv();
185437
185841
  await traceAsync(logger2, "startup.process_resource_profile", void 0, async () => normalizeCurrentProcessResourceProfile(logger2));
185438
- for (const diagnostic of getRuntimeDiagnostics(version$7)) {
185842
+ for (const diagnostic of getRuntimeDiagnostics(version$8)) {
185439
185843
  logger2.info(diagnostic);
185440
185844
  }
185441
185845
  if (options.heartbeatLog) {
@@ -185498,6 +185902,7 @@ Shutting down gracefully${reason}...`);
185498
185902
  const cliDetectionStartedAt = Date.now();
185499
185903
  const cliAvailability = {
185500
185904
  kimi: "managed-runtime",
185905
+ grok: "managed-runtime",
185501
185906
  claude: checkClaude(),
185502
185907
  codex: checkCodex()
185503
185908
  };
@@ -185505,6 +185910,7 @@ Shutting down gracefully${reason}...`);
185505
185910
  logCliDetectionResults(logger2, cliAvailability);
185506
185911
  captureAgentServiceEvent("agent_service_cli_detection", {
185507
185912
  kimi_available: true,
185913
+ grok_available: true,
185508
185914
  claude_available: Boolean(cliAvailability.claude),
185509
185915
  codex_available: Boolean(cliAvailability.codex)
185510
185916
  });
@@ -185515,7 +185921,7 @@ Shutting down gracefully${reason}...`);
185515
185921
  availability: cliAvailability
185516
185922
  });
185517
185923
  if (cliSelection.invalid.length > 0) {
185518
- logger2.error(`Unknown CLI types: ${cliSelection.invalid.join(", ")}. Supported values: kimi, claude, codex.`);
185924
+ logger2.error(`Unknown CLI types: ${cliSelection.invalid.join(", ")}. Supported values: kimi, grok, claude, codex.`);
185519
185925
  process.exit(1);
185520
185926
  }
185521
185927
  if (cliSelection.missing.length > 0) {
@@ -213310,7 +213716,7 @@ ${page}${helpTipBottom}${choiceDescription}${ansiEscapes.cursorHide}`;
213310
213716
  data = createReviewBundleSnapshot(bundle);
213311
213717
  }
213312
213718
  const { injectReviewSnapshot } = await import("./chunks/index-VoI6Ds2-.js");
213313
- const { resolveReviewViewerTemplate } = await import("./chunks/review-viewer-C1f8pVKg.js").then(async (m) => {
213719
+ const { resolveReviewViewerTemplate } = await import("./chunks/review-viewer--d2HZGpO.js").then(async (m) => {
213314
213720
  await m.__tla;
213315
213721
  return m;
213316
213722
  });
@@ -214508,6 +214914,76 @@ ${result.stdout ?? ""}`;
214508
214914
  return null;
214509
214915
  }
214510
214916
  }
214917
+ function planDaemonAuthPreflight(input2) {
214918
+ const { existingAuth, validation: validation2, interactive } = input2;
214919
+ const login = (reason) => interactive ? {
214920
+ action: "login",
214921
+ reason
214922
+ } : {
214923
+ action: "abort",
214924
+ reason: "login_required_non_interactive",
214925
+ message: reason === "credentials_rejected" ? "This machine is no longer signed in to Lody." : "This machine is not connected to Lody yet."
214926
+ };
214927
+ if (!existingAuth || !validation2) {
214928
+ return login("missing_credentials");
214929
+ }
214930
+ if (validation2.valid) {
214931
+ return {
214932
+ action: "proceed",
214933
+ user: validation2.user
214934
+ };
214935
+ }
214936
+ if (isTokenValidationUnavailable(validation2)) {
214937
+ return {
214938
+ action: "abort",
214939
+ reason: "backend_unreachable",
214940
+ message: validation2.error ?? validation2.reason
214941
+ };
214942
+ }
214943
+ return login("credentials_rejected");
214944
+ }
214945
+ async function ensureDaemonBackendAuth(options) {
214946
+ const { authClient, logger: logger2, machineName } = options;
214947
+ const interactive = options.interactive ?? process.stdout.isTTY === true;
214948
+ const existingAuth = authClient.getAuthInfo();
214949
+ logger2.info("Checking the connection to Lody\u2026");
214950
+ const validation2 = existingAuth ? await authClient.validateToken(existingAuth.token) : null;
214951
+ const plan = planDaemonAuthPreflight({
214952
+ existingAuth,
214953
+ validation: validation2,
214954
+ interactive
214955
+ });
214956
+ if (plan.action === "abort") {
214957
+ return {
214958
+ status: "failed",
214959
+ reason: plan.reason,
214960
+ message: plan.reason === "backend_unreachable" ? `Could not reach Lody to verify this machine's credentials: ${plan.message}` : plan.message
214961
+ };
214962
+ }
214963
+ if (plan.action === "proceed") {
214964
+ logger2.success(`${chalk.green("\u2713")} Connected as ${chalk.cyan(plan.user.name || plan.user.email)}`);
214965
+ return {
214966
+ status: "authenticated",
214967
+ user: plan.user
214968
+ };
214969
+ }
214970
+ logger2.info(plan.reason === "credentials_rejected" ? "This machine is no longer signed in to Lody. Sign in again to connect it." : "This machine is not connected to Lody yet. Sign in to connect it.");
214971
+ const loginResult = await performLogin(authClient, logger2, {
214972
+ machineName
214973
+ });
214974
+ if (!loginResult.success) {
214975
+ return {
214976
+ status: "failed",
214977
+ reason: "login_failed",
214978
+ message: `Login failed: ${loginResult.error}`
214979
+ };
214980
+ }
214981
+ logger2.success(`${chalk.green("\u2713")} Connected as ${chalk.cyan(loginResult.user.name || loginResult.user.email)}`);
214982
+ return {
214983
+ status: "authenticated",
214984
+ user: loginResult.user
214985
+ };
214986
+ }
214511
214987
  function buildDaemonStartPassthroughArgs(options, unknownArgs) {
214512
214988
  const sanitized = [];
214513
214989
  for (let index = 0; index < unknownArgs.length; index += 1) {
@@ -214661,6 +215137,20 @@ ${result.stdout ?? ""}`;
214661
215137
  }
214662
215138
  }
214663
215139
  }
215140
+ function daemonAuthFailureHint(reason) {
215141
+ switch (reason) {
215142
+ case "backend_unreachable":
215143
+ return `Retry once the connection is back, or start anyway with ${chalk.yellow("--skip-auth-check")}.`;
215144
+ case "login_required_non_interactive":
215145
+ return `Run ${chalk.yellow("lody login")} from a terminal, or pass ${chalk.yellow("--auth <cli_token>")}.`;
215146
+ case "login_failed":
215147
+ return `Run ${chalk.yellow("lody login")} and retry.`;
215148
+ default: {
215149
+ const unreachable = reason;
215150
+ return unreachable;
215151
+ }
215152
+ }
215153
+ }
214664
215154
  function printStartTips() {
214665
215155
  console.log(`Use ${chalk.yellow("lody daemon status")} to check status`);
214666
215156
  console.log(`Use ${chalk.yellow("lody daemon stop")} to stop`);
@@ -214681,7 +215171,7 @@ ${result.stdout ?? ""}`;
214681
215171
  }
214682
215172
  return false;
214683
215173
  }
214684
- const daemonCommand = new Command("daemon").description("Run lody as a background daemon service").addCommand(new Command("start").description("Start lody daemon in the background").option("--auth <credential>", "Connect with a CLI API key or machine connection token").option("--machine-name <name>", "Machine name to register (defaults to hostname)").allowUnknownOption(true).action(async (options, cmd) => {
215174
+ const daemonCommand = new Command("daemon").description("Run lody as a background daemon service").addCommand(new Command("start").description("Start lody daemon in the background").option("--auth <credential>", "Connect with a CLI API key or machine connection token").option("--machine-name <name>", "Machine name to register (defaults to hostname)").option("--skip-auth-check", "Skip the backend connectivity and sign-in check before entering daemon mode").allowUnknownOption(true).action(async (options, cmd) => {
214685
215175
  const readiness = await checkDaemonStartReadiness();
214686
215176
  if (await reportDaemonStartBlocked(readiness, {
214687
215177
  restart: false
@@ -214689,20 +215179,46 @@ ${result.stdout ?? ""}`;
214689
215179
  return;
214690
215180
  }
214691
215181
  const passthroughArgs = buildDaemonStartPassthroughArgs(options, cmd.args);
214692
- if (options.auth) {
215182
+ const platformKind = getCliPlatformKind();
215183
+ if (platformKind === "local" && options.auth) {
215184
+ console.error("--auth is not available on the local platform.");
215185
+ await exitDaemonCommand(1);
215186
+ return;
215187
+ }
215188
+ if (platformKind === "cloud" && (options.auth || !options.skipAuthCheck)) {
214693
215189
  createHybridLogger({
214694
215190
  level: "info"
214695
215191
  });
214696
215192
  const logger2 = getLogger("daemon");
214697
215193
  const authClient = new AuthClient(logger2);
214698
- const loginResult = await performLoginWithAuthCredential(authClient, logger2, {
214699
- credential: options.auth,
214700
- machineName: options.machineName
214701
- });
214702
- if (!loginResult.success) {
214703
- console.error(loginResult.error);
214704
- await exitDaemonCommand(1);
214705
- return;
215194
+ if (options.auth) {
215195
+ const loginResult = await performLoginWithAuthCredential(authClient, logger2, {
215196
+ credential: options.auth,
215197
+ machineName: options.machineName
215198
+ });
215199
+ if (!loginResult.success) {
215200
+ captureDaemonEvent("daemon_start_failed", {
215201
+ reason_code: "auth_credential"
215202
+ });
215203
+ console.error(loginResult.error);
215204
+ await exitDaemonCommand(1);
215205
+ return;
215206
+ }
215207
+ } else {
215208
+ const preflight = await ensureDaemonBackendAuth({
215209
+ authClient,
215210
+ logger: logger2,
215211
+ machineName: options.machineName
215212
+ });
215213
+ if (preflight.status === "failed") {
215214
+ captureDaemonEvent("daemon_start_failed", {
215215
+ reason_code: preflight.reason
215216
+ });
215217
+ console.error(preflight.message);
215218
+ console.error(daemonAuthFailureHint(preflight.reason));
215219
+ await exitDaemonCommand(1);
215220
+ return;
215221
+ }
214706
215222
  }
214707
215223
  }
214708
215224
  captureDaemonEvent("daemon_start_requested");
@@ -214886,9 +215402,9 @@ ${result.stdout ?? ""}`;
214886
215402
  const passthroughArgs = cmd.args;
214887
215403
  captureDaemonEvent("daemon_restart_requested");
214888
215404
  const runningProbeHealth = await fetchLocalProbeHealth();
214889
- const versionMismatchHealth = runningProbeHealth && runningProbeHealth.cliVersion !== version$7 ? runningProbeHealth : null;
215405
+ const versionMismatchHealth = runningProbeHealth && runningProbeHealth.cliVersion !== version$8 ? runningProbeHealth : null;
214890
215406
  if (versionMismatchHealth) {
214891
- console.log(`Running daemon uses lody v${versionMismatchHealth.cliVersion}; current CLI is v${version$7}. Restarting with current CLI.`);
215407
+ console.log(`Running daemon uses lody v${versionMismatchHealth.cliVersion}; current CLI is v${version$8}. Restarting with current CLI.`);
214892
215408
  }
214893
215409
  const stopResult = await stopDaemonProcess();
214894
215410
  captureDaemonEvent("daemon_stop_result", {
@@ -215095,7 +215611,7 @@ ${result.stdout ?? ""}`;
215095
215611
  });
215096
215612
  logger2.info(`Daemon watchdog started (PID ${process.pid})`);
215097
215613
  await normalizeCurrentProcessResourceProfile(logger2);
215098
- for (const diagnostic of getRuntimeDiagnostics(version$7)) {
215614
+ for (const diagnostic of getRuntimeDiagnostics(version$8)) {
215099
215615
  logger2.info(diagnostic);
215100
215616
  }
215101
215617
  const passthroughArgs = cmd.args;
@@ -233492,7 +234008,7 @@ ${result.stdout ?? ""}`;
233492
234008
  cliToken: auth.token,
233493
234009
  source: "mcp",
233494
234010
  feedback: args2.feedback,
233495
- cliVersion: version$7
234011
+ cliVersion: version$8
233496
234012
  }));
233497
234013
  } catch (error2) {
233498
234014
  return mcpErrorResult(error2);
@@ -234214,7 +234730,7 @@ ${lines2.join("\n")}` : ""}${suffix}`);
234214
234730
  cliToken: auth.token,
234215
234731
  source: "cli",
234216
234732
  feedback,
234217
- cliVersion: version$7
234733
+ cliVersion: version$8
234218
234734
  });
234219
234735
  if (options.json) {
234220
234736
  printJson(result);
@@ -234298,7 +234814,7 @@ ${lines2.join("\n")}` : ""}${suffix}`);
234298
234814
  logger: getLogger("http-transport")
234299
234815
  });
234300
234816
  program = new Command();
234301
- program.name("lody").description("Lody Agent CLI tool for managing remote command execution").version(version$7, "-v, --version", "display version number").enablePositionalOptions();
234817
+ program.name("lody").description("Lody Agent CLI tool for managing remote command execution").version(version$8, "-v, --version", "display version number").enablePositionalOptions();
234302
234818
  program.addCommand(loginCommand);
234303
234819
  program.addCommand(logoutCommand);
234304
234820
  program.addCommand(startCommand);