lody 0.101.1 → 0.103.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
@@ -13,7 +13,7 @@ import crypto__default, { createHash as createHash$1, randomUUID as randomUUID$1
13
13
  import os__default, { homedir, userInfo, cpus } from "node:os";
14
14
  import * as path from "node:path";
15
15
  import path__default, { posix as posix$1, basename, win32, join as join$2, resolve, relative as relative$1, dirname as dirname$1, isAbsolute as isAbsolute$2, sep as sep$1, delimiter, normalize } from "node:path";
16
- import { _ as _coercedNumber, Z as ZodNumber, o as object, s as string$1, l as literal$1, b as boolean, a as _enum, n as number$4, d as discriminatedUnion, c as array$2, r as record$3, u as unknown, e as union$7, f as custom$1, g as ZodObject, h as ZodLiteral, j as json$1, p as preprocess, i as ZodError, k as safeParse, m as ZodOptional, q as ZodNullable, t as ZodPipe, v as ZodUnion, w as ZodArray, x as ZodNever, y as ZodDiscriminatedUnion, z as _instanceof, A as uuid, N as NEVER, B as _null, C as lazy, D as looseObject, E as intersection, F as optional$1, G as datetime, H as url, I as any, J as toJSONSchema, K as date, L as email, M as never$1, O as xor } from "./chunks/schemas-9JpFbIUJ.js";
16
+ import { _ as _coercedNumber, Z as ZodNumber, o as object, s as string$1, l as literal$1, b as boolean, a as _enum, n as number$4, d as discriminatedUnion, c as array$2, r as record$3, u as unknown, e as union$7, f as custom$1, g as ZodObject, h as ZodLiteral, j as json$1, p as preprocess, i as ZodError, k as safeParse, m as ZodOptional, q as ZodNullable, t as ZodPipe, v as ZodUnion, w as ZodArray, x as ZodNever, y as ZodDiscriminatedUnion, z as _instanceof, A as uuid, N as NEVER, B as _null, C as looseObject, D as lazy, E as intersection, F as optional$1, G as datetime, H as url, I as any, J as toJSONSchema, K as date, L as email, M as xor, O as never$1 } from "./chunks/schemas-WuyisFi9.js";
17
17
  import require$$0$4, { EventEmitter as EventEmitter$1, once as once$1 } from "node:events";
18
18
  import require$$1$2, { execFile, spawn as spawn$1, execFileSync } from "node:child_process";
19
19
  import process$2 from "node:process";
@@ -37,7 +37,7 @@ import fs__default$2, { readFile, readdir, rm, mkdir as mkdir$1, mkdtemp, chmod,
37
37
  import zlib__default, { gzip, gunzip as gunzip$1, gunzipSync, brotliDecompressSync } from "node:zlib";
38
38
  import require$$1$8, { exec, execFile as execFile$1, spawn as spawn$2 } from "child_process";
39
39
  import { c as createPlanModeConfigOption, L as LODY_PLAN_MODE_CONFIG_ID } from "./chunks/plan-mode-D0D5cnMs.js";
40
- import { D as DEEPSEEK_HARNESS_PERMISSION_MODES, a as DEEPSEEK_HARNESS_AGENT_PRESETS, A as ACP_EXTENSION_DSH_CAPABILITY_SOURCE_VERSION, c as createDeepSeekHarnessProfileFiles, b as DEEPSEEK_HARNESS_PROFILE_NAME, d as DEEPSEEK_HARNESS_PROFILE_FILENAMES, e as ACP_EXTENSION_DSH_QUERY_PATH_ENV, f as ACP_EXTENSION_DSH_SESSION_ROOT_ENV, g as createDeepSeekHarnessNpxSpecifiers, h as DEEPSEEK_HARNESS_DEFAULT_SESSION_COMPRESSION, i as DEEPSEEK_HARNESS_VERSION, j as DEEPSEEK_HARNESS_BASE_URL_ENV, R as RequestError$1, C as ClientSideConnection, P as PROTOCOL_VERSION, n as ndJsonStream, k as client$2, m as methods$1 } from "./chunks/acp-w0Ug9k0u.js";
40
+ import { D as DEEPSEEK_HARNESS_PERMISSION_MODES, a as DEEPSEEK_HARNESS_AGENT_PRESETS, A as ACP_EXTENSION_DSH_CAPABILITY_SOURCE_VERSION, c as createDeepSeekHarnessProfileFiles, b as DEEPSEEK_HARNESS_PROFILE_NAME, d as DEEPSEEK_HARNESS_PROFILE_FILENAMES, e as ACP_EXTENSION_DSH_QUERY_PATH_ENV, f as ACP_EXTENSION_DSH_SESSION_ROOT_ENV, g as createDeepSeekHarnessNpxSpecifiers, h as DEEPSEEK_HARNESS_DEFAULT_SESSION_COMPRESSION, i as DEEPSEEK_HARNESS_VERSION, j as DEEPSEEK_HARNESS_BASE_URL_ENV, R as RequestError$1, C as ClientSideConnection, P as PROTOCOL_VERSION, n as ndJsonStream, k as client$2, m as methods$1 } from "./chunks/acp-BzvviK-N.js";
41
41
  import { i as isLodySubagentProgress, a as isLodySubagentSnapshot, b as isLodySubagentEvent, c as isLodySubagentOutput, L as LODY_EXTENSION_METHODS, M as MAX_USAGE_SCOPE_ID_LENGTH, n as normalizeLodyExtensionMethod, d as LODY_SUBAGENT_EVENT_METHOD } from "./chunks/subagent-events-BJ9JwZva.js";
42
42
  import { i as imports, _ as __wbg_set_wasm$1, r as rawWasm, L as LoroDoc, E as EphemeralStoreWasm, U as UndoManager, a as isValidContainerId, c as callPendingEvents$3, b as LoroTree, d as LoroText, e as LoroMovableList, f as LoroList, g as LoroMap, V as VersionVector, h as __vite__initWasm, j as decodeImportBlobMeta } from "./chunks/loro_wasm_bg-DIxpLA2J.js";
43
43
  import { performance as performance$1 } from "perf_hooks";
@@ -62,17 +62,18 @@ import require$$1$4, { Worker as Worker$1 } from "node:worker_threads";
62
62
  import require$$1$5, { fileURLToPath, pathToFileURL } from "node:url";
63
63
  import require$$1$6 from "node:console";
64
64
  import require$$1$7 from "node:dns";
65
- import { C as CodeCollabV2FileIndexRequestSchema, a as CodeCollabV2OpenTextRequestSchema, b as CodeCollabV2RefreshTextRequestSchema, c as CodeCollabV2SaveTextRequestSchema, d as CodeCollabV2OpenCurrentDiffRequestSchema, e as CodeCollabV2OpenAllChangesDiffRequestSchema, f as CodeCollabV2OpenTurnDiffRequestSchema, g as CodeCollabV2InitDirectoryRequestSchema, h as CodeCollabV2FileIndexSnapshotSchema, i as CodeCollabV2OpenTextOkSchema, j as CodeCollabV2RefreshTextResponseSchema, k as CodeCollabV2SaveTextResponseSchema, l as CodeCollabV2OpenCurrentDiffResponseSchema, m as CodeCollabV2OpenAllChangesDiffResponseSchema, n as CodeCollabV2OpenTurnDiffResponseSchema, o as CodeCollabV2InitDirectoryOkSchema, p as CodeCollabV2LspUnsupportedSchema, q as CodeCollabV2ErrorSchema, r as CodeCollabV2RpcContentEnvelopeSchema, s as deriveCodeCollabV2ContentKeyId, t as CodeCollabV2ErrorCodeSchema, u as CodeCollabV2RpcResponseSchema, v as deriveCodeCollabV2ContentKeyBytes, w as readCodeCollabFileIndexSignalFromFlock, x as writeCodeCollabFileIndexSignalToFlock, y as writeCodeCollabFileIndexToFlock, z as buildCodeCollabFileIndexState, A as CODE_COLLAB_V2_TEXT_LIMITS, B as CODE_COLLAB_V2_ALL_CHANGES_DIFF_LIMITS, D as computeAllChanges, E as codeCollabFileIndexStatesEqual, F as scanGitDirectoryEntries, G as closeDirectoryQuietly } from "./chunks/directory-handle-CjQk33eZ.js";
65
+ import { C as CodeCollabV2FileIndexRequestSchema, a as CodeCollabV2OpenTextRequestSchema, b as CodeCollabV2RefreshTextRequestSchema, c as CodeCollabV2SaveTextRequestSchema, d as CodeCollabV2OpenCurrentDiffRequestSchema, e as CodeCollabV2OpenAllChangesDiffRequestSchema, f as CodeCollabV2OpenTurnDiffRequestSchema, g as CodeCollabV2InitDirectoryRequestSchema, h as CodeCollabV2FileIndexSnapshotSchema, i as CodeCollabV2OpenTextOkSchema, j as CodeCollabV2RefreshTextResponseSchema, k as CodeCollabV2SaveTextResponseSchema, l as CodeCollabV2OpenCurrentDiffResponseSchema, m as CodeCollabV2OpenAllChangesDiffResponseSchema, n as CodeCollabV2OpenTurnDiffResponseSchema, o as CodeCollabV2InitDirectoryOkSchema, p as CodeCollabV2LspUnsupportedSchema, q as CodeCollabV2ErrorSchema, r as CodeCollabV2RpcContentEnvelopeSchema, s as deriveCodeCollabV2ContentKeyId, t as CodeCollabV2ErrorCodeSchema, u as CodeCollabV2RpcResponseSchema, v as deriveCodeCollabV2ContentKeyBytes, w as readCodeCollabFileIndexSignalFromFlock, x as writeCodeCollabFileIndexSignalToFlock, y as writeCodeCollabFileIndexToFlock, z as buildCodeCollabFileIndexState, A as CODE_COLLAB_V2_TEXT_LIMITS, B as CODE_COLLAB_V2_ALL_CHANGES_DIFF_LIMITS, D as computeAllChanges, E as codeCollabFileIndexStatesEqual, F as scanGitDirectoryEntries, G as closeDirectoryQuietly } from "./chunks/directory-handle-CtdCjbNh.js";
66
66
  import { finished, pipeline } from "node:stream/promises";
67
67
  import { StringDecoder } from "node:string_decoder";
68
68
  import { p as packageJson } from "./chunks/package-BoOO46ct.js";
69
+ import { L as LODY_TOOL_NAMES } from "./chunks/session-DyqwlJbY.js";
69
70
  import { AsyncLocalStorage as AsyncLocalStorage$1 } from "async_hooks";
70
71
  import { createRequire } from "module";
71
72
  import { c as computeLineCounts, a as countTextLines } from "./chunks/diff-line-counts-DDGc5P-T.js";
72
73
  import { r as runDiffWorkerTask } from "./chunks/diff-worker-task-MZsLArT5.js";
73
74
  import { C as CODE_COLLAB_IGNORED_DIRECTORY_NAMES, p as parseWorkspaceWatchChildMessage } from "./chunks/workspace-watch-protocol-POg9Lpeq.js";
74
75
  import { Resolver } from "node:dns/promises";
75
- import { C as CloudflaredError } from "./chunks/cloudflared-native-BPe7OSUZ.js";
76
+ import { C as CloudflaredError } from "./chunks/cloudflared-native-DbUToPHH.js";
76
77
  import { setTimeout as setTimeout$1 } from "node:timers/promises";
77
78
  import { createRequire as createRequire$1 } from "node:module";
78
79
  import v8 from "node:v8";
@@ -4316,7 +4317,7 @@ function resolvePlatformKind(raw2) {
4316
4317
  }
4317
4318
  const name$3 = "lody";
4318
4319
  const name$2 = "@lody/cli-cloud";
4319
- const version$d = "0.101.1";
4320
+ const version$d = "0.103.0";
4320
4321
  const type = "module";
4321
4322
  const scripts = { "dev": "node dev.mjs", "dev:staging": "LODY_ENV=staging NODE_ENV=production node dev.mjs", "build": "node build.mjs", "prepare:publish": "node prepare-publish.js", "test": "node --test pnpm-runner.test.mjs vite-config.test.mjs" };
4322
4323
  const devDependencies = { "dotenv": "^16.6.1", "vite": "^7.0.0", "vite-plugin-wasm": "catalog:" };
@@ -4511,7 +4512,7 @@ async function getOrCreateStableMachineIdAsync() {
4511
4512
  if (machineId) return machineId;
4512
4513
  return createMachineId(crypto__default.randomUUID());
4513
4514
  }
4514
- function isRecord$g(value) {
4515
+ function isRecord$h(value) {
4515
4516
  return typeof value === "object" && value !== null;
4516
4517
  }
4517
4518
  const LODY_CLAUDE_TASK_LIFECYCLE_RAW_INPUT_KEY = "lodyClaudeTaskLifecycle";
@@ -4571,7 +4572,7 @@ const LodyTaskMetaSchema = object({
4571
4572
  skipTranscript: boolean().optional()
4572
4573
  });
4573
4574
  const parseLodyTaskMeta = (meta) => {
4574
- if (!isRecord$g(meta) || !isRecord$g(meta.lody)) return null;
4575
+ if (!isRecord$h(meta) || !isRecord$h(meta.lody)) return null;
4575
4576
  const parsed = LodyTaskMetaSchema.safeParse(meta.lody.task);
4576
4577
  if (!parsed.success) return null;
4577
4578
  const task = parsed.data;
@@ -4595,9 +4596,9 @@ const parseLodyTaskMeta = (meta) => {
4595
4596
  };
4596
4597
  };
4597
4598
  const parseSubagentTaskWire = (rawInput) => {
4598
- if (!isRecord$g(rawInput)) return null;
4599
+ if (!isRecord$h(rawInput)) return null;
4599
4600
  const carrier = rawInput[LODY_SUBAGENT_TASK_LIFECYCLE_RAW_INPUT_KEY] ?? rawInput[LODY_CLAUDE_TASK_LIFECYCLE_RAW_INPUT_KEY];
4600
- if (!isRecord$g(carrier)) return null;
4601
+ if (!isRecord$h(carrier)) return null;
4601
4602
  const parsed = SubagentTaskPayloadSchema.safeParse(carrier);
4602
4603
  return parsed.success ? parsed.data : null;
4603
4604
  };
@@ -4611,9 +4612,6 @@ const mergeSubagentTaskPayload = (prev, incoming) => {
4611
4612
  }
4612
4613
  return merged;
4613
4614
  };
4614
- const LODY_TOOL_NAMES = {
4615
- imageGeneration: "ImageGeneration"
4616
- };
4617
4615
  const MANAGED_BUILTIN_RUNTIMES = [
4618
4616
  { runtimeName: "kimi-code", agentType: "kimi", displayName: "Kimi Code" },
4619
4617
  { runtimeName: "grok-build", agentType: "grok", displayName: "Grok" },
@@ -5288,7 +5286,7 @@ const MESSAGE_TEXT_SPAN_KINDS = [
5288
5286
  ];
5289
5287
  const MAX_MESSAGE_TEXT_SPAN_MARK_LENGTH = 16;
5290
5288
  const SPAN_KINDS = new Set(MESSAGE_TEXT_SPAN_KINDS);
5291
- const isRecord$f = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
5289
+ const isRecord$g = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
5292
5290
  const isTextOffset = (value) => typeof value === "number" && Number.isInteger(value) && value >= 0;
5293
5291
  const isOffset = isTextOffset;
5294
5292
  const dropOverlappingRanges = (ranges) => {
@@ -5306,7 +5304,7 @@ const sanitizeMessageTextSpans = (text, spans) => {
5306
5304
  if (!Array.isArray(spans) || spans.length === 0) return void 0;
5307
5305
  const candidates = [];
5308
5306
  for (const span2 of spans) {
5309
- if (!isRecord$f(span2)) continue;
5307
+ if (!isRecord$g(span2)) continue;
5310
5308
  const { start: start2, end: end2, kind: kind2, label: label2, target, mark: mark2 } = span2;
5311
5309
  if (!isOffset(start2) || !isOffset(end2)) continue;
5312
5310
  if (end2 <= start2 || end2 > text.length) continue;
@@ -5331,7 +5329,7 @@ const reanchorMessageTextSpansForTrim = (originalText, trimmedText, spans) => {
5331
5329
  const leading = originalText.length - originalText.trimStart().length;
5332
5330
  if (leading === 0) return sanitizeMessageTextSpans(trimmedText, spans);
5333
5331
  const shifted = spans.map(
5334
- (span2) => isRecord$f(span2) && isOffset(span2.start) && isOffset(span2.end) ? { ...span2, start: span2.start - leading, end: span2.end - leading } : span2
5332
+ (span2) => isRecord$g(span2) && isOffset(span2.start) && isOffset(span2.end) ? { ...span2, start: span2.start - leading, end: span2.end - leading } : span2
5335
5333
  );
5336
5334
  return sanitizeMessageTextSpans(trimmedText, shifted);
5337
5335
  };
@@ -5516,12 +5514,12 @@ function resolveBaseBranchPreference(options) {
5516
5514
  const isMcpTransport = (value) => value === "stdio" || value === "http";
5517
5515
  const ENV_VAR_NAME_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
5518
5516
  const ENV_VAR_PATTERN = /\$\{([A-Za-z_][A-Za-z0-9_]*)\}/g;
5519
- const isRecord$e = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
5520
- const isStringRecord$2 = (value) => isRecord$e(value) && Object.values(value).every((entry) => typeof entry === "string");
5517
+ const isRecord$f = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
5518
+ const isStringRecord$2 = (value) => isRecord$f(value) && Object.values(value).every((entry) => typeof entry === "string");
5521
5519
  const isStringArray = (value) => Array.isArray(value) && value.every((entry) => typeof entry === "string");
5522
5520
  const isOptionalString = (value) => value === void 0 || typeof value === "string";
5523
5521
  const isMcpConnectionSpec = (value) => {
5524
- if (!isRecord$e(value) || !isMcpTransport(value.transport)) {
5522
+ if (!isRecord$f(value) || !isMcpTransport(value.transport)) {
5525
5523
  return false;
5526
5524
  }
5527
5525
  if (value.transport === "stdio") {
@@ -5530,7 +5528,7 @@ const isMcpConnectionSpec = (value) => {
5530
5528
  return typeof value.url === "string" && isOptionalString(value.bearerToken) && (value.headers === void 0 || isStringRecord$2(value.headers));
5531
5529
  };
5532
5530
  const isWorkspaceMcpServerMeta = (value) => {
5533
- if (!isRecord$e(value) || typeof value.id !== "string" || value.id.trim().length === 0 || typeof value.name !== "string" || value.name.trim().length === 0 || !isMcpTransport(value.transport) || typeof value.createdAt !== "number" || !Number.isFinite(value.createdAt) || typeof value.updatedAt !== "number" || !Number.isFinite(value.updatedAt) || value.description !== void 0 && typeof value.description !== "string" || value.enabledByDefault !== void 0 && typeof value.enabledByDefault !== "boolean" || value.createdBy !== void 0 && typeof value.createdBy !== "string") {
5531
+ if (!isRecord$f(value) || typeof value.id !== "string" || value.id.trim().length === 0 || typeof value.name !== "string" || value.name.trim().length === 0 || !isMcpTransport(value.transport) || typeof value.createdAt !== "number" || !Number.isFinite(value.createdAt) || typeof value.updatedAt !== "number" || !Number.isFinite(value.updatedAt) || value.description !== void 0 && typeof value.description !== "string" || value.enabledByDefault !== void 0 && typeof value.enabledByDefault !== "boolean" || value.createdBy !== void 0 && typeof value.createdBy !== "string") {
5534
5532
  return false;
5535
5533
  }
5536
5534
  return value.connection === void 0 || isMcpConnectionSpec(value.connection) && value.connection.transport === value.transport;
@@ -8338,7 +8336,7 @@ const MessageContentSchema = union$7([NonSystemNoticeMessageContentSchema, Syste
8338
8336
  });
8339
8337
  const LEGACY_DEFAULT_BRANCH = "main";
8340
8338
  const LEGACY_BUILTIN_CLI_TYPES = /* @__PURE__ */ new Set(["claude", "codex"]);
8341
- function isRecord$d(value) {
8339
+ function isRecord$e(value) {
8342
8340
  return typeof value === "object" && value !== null;
8343
8341
  }
8344
8342
  function getTrimmedString(value) {
@@ -8355,7 +8353,7 @@ function isAgentConfigCliTypeString(value) {
8355
8353
  return value === "builtin" || value === "registry" || value === "custom";
8356
8354
  }
8357
8355
  function normalizeLegacyProjectRef(value) {
8358
- if (!isRecord$d(value)) {
8356
+ if (!isRecord$e(value)) {
8359
8357
  return value;
8360
8358
  }
8361
8359
  const kind2 = value.kind;
@@ -8369,13 +8367,13 @@ function normalizeLegacyProjectRef(value) {
8369
8367
  normalized.branch = existingBranch;
8370
8368
  } else {
8371
8369
  const legacyBranchFromString = getTrimmedString(legacyProject);
8372
- const legacyBranchFromObject = isRecord$d(legacyProject) ? getTrimmedString(legacyProject.branch) ?? getTrimmedString(legacyProject.project) : void 0;
8370
+ const legacyBranchFromObject = isRecord$e(legacyProject) ? getTrimmedString(legacyProject.branch) ?? getTrimmedString(legacyProject.project) : void 0;
8373
8371
  const resolvedBranch = legacyBranchFromString ?? legacyBranchFromObject;
8374
8372
  if (resolvedBranch) {
8375
8373
  normalized.branch = resolvedBranch;
8376
8374
  }
8377
8375
  }
8378
- if (isRecord$d(legacyProject)) {
8376
+ if (isRecord$e(legacyProject)) {
8379
8377
  if (kind2 === "github" && !getTrimmedString(normalized.repoFullName)) {
8380
8378
  const repoFullName = getTrimmedString(legacyProject.repoFullName);
8381
8379
  if (repoFullName) {
@@ -8410,7 +8408,7 @@ function normalizeLegacySessionProject(message) {
8410
8408
  const normalized = { ...message };
8411
8409
  normalized.project = normalizeLegacyProjectRef(normalized.project);
8412
8410
  const currentProject = normalized.project;
8413
- const projectRecord = isRecord$d(currentProject) ? currentProject : void 0;
8411
+ const projectRecord = isRecord$e(currentProject) ? currentProject : void 0;
8414
8412
  const explicitBranch = getTrimmedString(normalized.branch) ?? getTrimmedString(currentProject) ?? (projectRecord ? getTrimmedString(projectRecord.branch) ?? getTrimmedString(projectRecord.project) : void 0);
8415
8413
  const repoFullName = (projectRecord ? getTrimmedString(projectRecord.repoFullName) : void 0) ?? getTrimmedString(normalized.repoFullName) ?? getTrimmedString(normalized.githubRepo);
8416
8414
  const localProjectId = (projectRecord ? getTrimmedString(projectRecord.localProjectId) : void 0) ?? getTrimmedString(normalized.localProjectId);
@@ -8444,7 +8442,7 @@ function normalizeLegacySessionProject(message) {
8444
8442
  return normalized;
8445
8443
  }
8446
8444
  function normalizeLegacyAcpSessionConfig(value) {
8447
- if (!isRecord$d(value)) {
8445
+ if (!isRecord$e(value)) {
8448
8446
  return value;
8449
8447
  }
8450
8448
  const normalized = { ...value };
@@ -8477,13 +8475,13 @@ function normalizeLegacyAcpSessionConfig(value) {
8477
8475
  return normalized;
8478
8476
  }
8479
8477
  function normalizeLegacySessionMessage(parsed) {
8480
- if (!isRecord$d(parsed)) {
8478
+ if (!isRecord$e(parsed)) {
8481
8479
  return parsed;
8482
8480
  }
8483
8481
  const messageType = parsed.type;
8484
8482
  if (messageType === "session/create" || messageType === "session/chat") {
8485
8483
  const normalized = normalizeLegacySessionProject(parsed);
8486
- if (!isRecord$d(normalized)) {
8484
+ if (!isRecord$e(normalized)) {
8487
8485
  return normalized;
8488
8486
  }
8489
8487
  normalized.acpSessionConfig = normalizeLegacyAcpSessionConfig(normalized.acpSessionConfig);
@@ -13896,8 +13894,8 @@ const parseRateLimitEntryKey = (key2) => {
13896
13894
  };
13897
13895
  };
13898
13896
  const historyItemAnySchema = schema.Any({ defaultLoroText: false });
13899
- const isRecord$c = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
13900
- const isWorktreeScriptHistoryStep = (value) => isRecord$c(value) && typeof value.command === "string" && (value.status === "in_progress" || value.status === "completed" || value.status === "failed") && typeof value.output === "string";
13897
+ const isRecord$d = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
13898
+ const isWorktreeScriptHistoryStep = (value) => isRecord$d(value) && typeof value.command === "string" && (value.status === "in_progress" || value.status === "completed" || value.status === "failed") && typeof value.output === "string";
13901
13899
  const historyNestedPayloadSchema = schema.Any({ defaultLoroText: false });
13902
13900
  const historyToolContentSchema = schema.LoroMap({
13903
13901
  type: schema.String({ required: false }),
@@ -13992,7 +13990,7 @@ const historyMessageItemSchema = schema.LoroMap(
13992
13990
  return typeof v2.name === "string" ? true : "Missing name";
13993
13991
  case "operation_progress":
13994
13992
  return typeof v2.operationId === "string" && (v2.operationKind === "session_create" || v2.operationKind === "session_create_many") && Array.isArray(v2.items) && v2.items.every(
13995
- (item) => isRecord$c(item) && isRecord$c(item.target) && typeof item.target.sessionId === "string" && typeof item.target.userTurnId === "string" && (item.label === void 0 || typeof item.label === "string") && typeof item.status === "string" && ["created", "running", "succeeded", "failed", "cancelled"].includes(item.status)
13993
+ (item) => isRecord$d(item) && isRecord$d(item.target) && typeof item.target.sessionId === "string" && typeof item.target.userTurnId === "string" && (item.label === void 0 || typeof item.label === "string") && typeof item.status === "string" && ["created", "running", "succeeded", "failed", "cancelled"].includes(item.status)
13996
13994
  ) ? true : "Missing operation progress metadata";
13997
13995
  case "operation_completion":
13998
13996
  return typeof v2.deliveryId === "string" && typeof v2.operationId === "string" && typeof v2.operationKind === "string" && typeof v2.completion === "object" && v2.completion !== null ? true : "Missing operation completion metadata";
@@ -14442,7 +14440,7 @@ function assertHistoryJson(value, path2 = [], ancestors = /* @__PURE__ */ new Se
14442
14440
  ancestors.delete(value);
14443
14441
  }
14444
14442
  const CID_KEY$1 = "$cid";
14445
- const isRecord$b = (value) => typeof value === "object" && value !== null && !Array.isArray(value) && !(value instanceof Date) && !(value instanceof RegExp) && typeof value !== "function";
14443
+ const isRecord$c = (value) => typeof value === "object" && value !== null && !Array.isArray(value) && !(value instanceof Date) && !(value instanceof RegExp) && typeof value !== "function";
14446
14444
  const isMapSchema = (schema2) => schema2?.type === "loro-map";
14447
14445
  const isListSchema = (schema2) => schema2?.type === "loro-list" || schema2?.type === "loro-movable-list";
14448
14446
  const isAnySchema = (schema2) => schema2?.type === "any";
@@ -14471,7 +14469,7 @@ function applySchemaToInfer(schema2, base) {
14471
14469
  return next2;
14472
14470
  }
14473
14471
  function inferContainerType(value, infer) {
14474
- if (isRecord$b(value)) return "Map";
14472
+ if (isRecord$c(value)) return "Map";
14475
14473
  if (Array.isArray(value)) return infer?.defaultMovableList ? "MovableList" : "List";
14476
14474
  if (typeof value === "string") return infer?.defaultLoroText ? "Text" : void 0;
14477
14475
  return void 0;
@@ -14479,7 +14477,7 @@ function inferContainerType(value, infer) {
14479
14477
  function matchesContainerType(type2, value) {
14480
14478
  switch (type2) {
14481
14479
  case "Map":
14482
- return isRecord$b(value);
14480
+ return isRecord$c(value);
14483
14481
  case "List":
14484
14482
  case "MovableList":
14485
14483
  case "Tree":
@@ -14538,7 +14536,7 @@ function insertContainerIntoList(list2, schema2, index, value, infer) {
14538
14536
  function populateContainer(container2, schema2, value, infer) {
14539
14537
  const kind2 = container2.kind();
14540
14538
  if (kind2 === "Map") {
14541
- if (!isRecord$b(value)) return;
14539
+ if (!isRecord$c(value)) return;
14542
14540
  populateMap(container2, isMapSchema(schema2) ? schema2 : void 0, value, infer);
14543
14541
  } else if (kind2 === "List" || kind2 === "MovableList") {
14544
14542
  if (!Array.isArray(value)) return;
@@ -14655,7 +14653,7 @@ function diffHistoryContainer(container2, schema2, oldValue, newValue, infer) {
14655
14653
  const effective = applySchemaToInfer(schema2, infer);
14656
14654
  const kind2 = container2.kind();
14657
14655
  if (kind2 === "Map") {
14658
- if (!isRecord$b(oldValue) || !isRecord$b(newValue)) {
14656
+ if (!isRecord$c(oldValue) || !isRecord$c(newValue)) {
14659
14657
  throw new Error("Failed to diff container(map). Old and new state must be objects");
14660
14658
  }
14661
14659
  diffMap(
@@ -16586,6 +16584,80 @@ function collectScheduleIds(roomIds, rows) {
16586
16584
  }
16587
16585
  return [...ids2].sort();
16588
16586
  }
16587
+ const isRecord$b = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
16588
+ const parseModelControls = (value) => {
16589
+ if (!isRecord$b(value)) return void 0;
16590
+ const controls = {};
16591
+ if (value.effortValues !== void 0) {
16592
+ if (!Array.isArray(value.effortValues) || !value.effortValues.every((effort) => typeof effort === "string")) {
16593
+ return void 0;
16594
+ }
16595
+ controls.effortValues = [...value.effortValues];
16596
+ }
16597
+ if (value.fastMode !== void 0) {
16598
+ if (typeof value.fastMode !== "boolean") return void 0;
16599
+ controls.fastMode = value.fastMode;
16600
+ }
16601
+ return controls;
16602
+ };
16603
+ const parseModels = (value) => {
16604
+ if (!isRecord$b(value)) return void 0;
16605
+ const models = {};
16606
+ for (const [modelId, controls] of Object.entries(value)) {
16607
+ const parsed = parseModelControls(controls);
16608
+ if (!parsed) return void 0;
16609
+ models[modelId] = parsed;
16610
+ }
16611
+ return Object.keys(models).length > 0 ? models : void 0;
16612
+ };
16613
+ const readAcpModelCapabilitiesMeta = (sessionResponse) => {
16614
+ if (!isRecord$b(sessionResponse) || !isRecord$b(sessionResponse._meta)) return void 0;
16615
+ const lody = sessionResponse._meta.lody;
16616
+ if (!isRecord$b(lody) || !isRecord$b(lody.modelCapabilities)) return void 0;
16617
+ const declaration = lody.modelCapabilities;
16618
+ return declaration.version === 1 ? parseModels(declaration.models) : void 0;
16619
+ };
16620
+ const isAcpModelCapabilities = (value) => isRecord$b(value) && value.version === 1 && typeof value.sourceVersion === "string" && parseModels(value.models) !== void 0;
16621
+ const getDeclaredModelControls = (entry, modelId) => modelId ? entry?.declaredModelControls?.[modelId] : void 0;
16622
+ const BUILTIN_MODEL_CONTROL_BINDINGS = {
16623
+ claude: {
16624
+ effortConfigId: "effort",
16625
+ effortLabel: "Effort",
16626
+ providerDefaultEffort: "default",
16627
+ omittedEffortMeansUnsupported: true,
16628
+ fastConfigId: "fast"
16629
+ },
16630
+ codex: {
16631
+ effortConfigId: "reasoning_effort",
16632
+ effortLabel: "Reasoning effort",
16633
+ omittedEffortMeansUnsupported: false,
16634
+ fastConfigId: "fast-mode"
16635
+ }
16636
+ };
16637
+ const getBuiltinModelControlBinding = (agent2) => agent2?.cliType === "builtin" && agent2.agentType ? BUILTIN_MODEL_CONTROL_BINDINGS[agent2.agentType.toLowerCase()] : void 0;
16638
+ const defaultEffortValue = (values) => values.includes("medium") ? "medium" : values[0] ?? "";
16639
+ const resolveDeclaredEffortSupport = (entry, modelId) => {
16640
+ const controls = getDeclaredModelControls(entry, modelId);
16641
+ if (!controls) return { state: "unknown" };
16642
+ const binding = getBuiltinModelControlBinding(entry);
16643
+ const levels2 = controls.effortValues;
16644
+ if (levels2 === void 0) {
16645
+ return binding?.omittedEffortMeansUnsupported ? { state: "unsupported" } : { state: "unknown" };
16646
+ }
16647
+ if (levels2.length === 0) return { state: "unsupported" };
16648
+ const providerDefault = binding?.providerDefaultEffort;
16649
+ return {
16650
+ state: "supported",
16651
+ values: providerDefault ? [providerDefault, ...levels2] : [...levels2],
16652
+ fallbackValue: providerDefault ?? defaultEffortValue(levels2)
16653
+ };
16654
+ };
16655
+ const getModelEffortChoices = (entry, modelId) => {
16656
+ const declared = resolveDeclaredEffortSupport(entry, modelId);
16657
+ if (declared.state === "supported") return declared.values;
16658
+ if (declared.state === "unsupported") return [];
16659
+ return modelId ? entry?.modelReasoningEfforts?.[modelId] : void 0;
16660
+ };
16589
16661
  const ACP_FAST_MODE_CONFIG_IDS = ["fast-mode", "fast"];
16590
16662
  const ACP_COLLABORATION_MODE_CONFIG_ID = "collaboration_mode";
16591
16663
  const ACP_COLLABORATION_MODE_DEFAULT_VALUE = "default";
@@ -16671,11 +16743,10 @@ const listModels = (capability) => {
16671
16743
  return (capability?.models ?? []).map((model) => ({ id: model.modelId, name: model.name }));
16672
16744
  };
16673
16745
  const summarizeAgentRunConfigCapabilities = (capability) => {
16674
- const perModelEfforts = capability?.modelReasoningEfforts;
16675
16746
  const measuredForModelId = findCurrentModelId(capability);
16676
16747
  return {
16677
16748
  models: listModels(capability).map((model) => {
16678
- const efforts = perModelEfforts?.[model.id];
16749
+ const efforts = getModelEffortChoices(capability, model.id);
16679
16750
  return { ...model, ...efforts ? { reasoningEffortValues: efforts } : {} };
16680
16751
  }),
16681
16752
  reasoningEffortValues: (findReasoningEffortOption(capability)?.options ?? []).map(
@@ -16704,11 +16775,14 @@ const resolveAgentRunConfigSelection = (selection, capability) => {
16704
16775
  let modeId;
16705
16776
  if (selection.reasoningEffort !== void 0) {
16706
16777
  const option2 = findReasoningEffortOption(capability);
16707
- const targetModelEfforts = targetModelId ? capability.modelReasoningEfforts?.[targetModelId] : void 0;
16778
+ const targetModelEfforts = getModelEffortChoices(capability, targetModelId);
16708
16779
  if (!option2 && !targetModelEfforts) {
16709
16780
  throw new Error("The selected agent does not offer a reasoning effort option.");
16710
16781
  }
16711
- const configId = option2?.id ?? ACP_REASONING_EFFORT_CONFIG_ID;
16782
+ if (targetModelEfforts?.length === 0) {
16783
+ throw new Error(`Model ${targetModelId} does not offer a reasoning effort option.`);
16784
+ }
16785
+ const configId = option2?.id ?? getBuiltinModelControlBinding(capability)?.effortConfigId ?? ACP_REASONING_EFFORT_CONFIG_ID;
16712
16786
  if (targetModelEfforts) {
16713
16787
  if (!targetModelEfforts.includes(selection.reasoningEffort)) {
16714
16788
  throw new Error(
@@ -16724,11 +16798,20 @@ const resolveAgentRunConfigSelection = (selection, capability) => {
16724
16798
  }
16725
16799
  if (selection.fastMode !== void 0) {
16726
16800
  const option2 = findFastModeOption(capability);
16727
- if (!option2) {
16801
+ const declaredFast = getDeclaredModelControls(capability, targetModelId)?.fastMode;
16802
+ const builtinFastId = getBuiltinModelControlBinding(capability)?.fastConfigId;
16803
+ if (declaredFast === false) {
16804
+ if (selection.fastMode) throw new Error(`Model ${targetModelId} does not offer fast mode.`);
16805
+ } else if (option2) {
16806
+ configOptionValues[option2.id] = toggleValue(option2, selection.fastMode);
16807
+ if (declaredFast) validatedConfigIds.push(option2.id);
16808
+ } else if (declaredFast && builtinFastId) {
16809
+ configOptionValues[builtinFastId] = selection.fastMode;
16810
+ validatedConfigIds.push(builtinFastId);
16811
+ } else {
16728
16812
  throw new Error("The selected agent does not offer a fast mode option.");
16729
16813
  }
16730
- configOptionValues[option2.id] = toggleValue(option2, selection.fastMode);
16731
- if (switchesModel) {
16814
+ if (switchesModel && declaredFast === void 0) {
16732
16815
  unverifiedSelections.push(`fastMode=${selection.fastMode}`);
16733
16816
  }
16734
16817
  }
@@ -19076,7 +19159,7 @@ const DevinSubagentContextSchema = object({
19076
19159
  parentAgentId: string$1().min(1)
19077
19160
  });
19078
19161
  const parseDevinSubagentTaskMeta = (meta) => {
19079
- if (!isRecord$g(meta)) return null;
19162
+ if (!isRecord$h(meta)) return null;
19080
19163
  const completed = DevinSubagentCompletedSchema.safeParse(meta[DEVIN_SUBAGENT_COMPLETED_META_KEY]);
19081
19164
  if (completed.success) {
19082
19165
  const c = completed.data;
@@ -19108,12 +19191,12 @@ const parseDevinSubagentTaskMeta = (meta) => {
19108
19191
  return null;
19109
19192
  };
19110
19193
  const getDevinSubagentContextId = (meta) => {
19111
- if (!isRecord$g(meta)) return null;
19194
+ if (!isRecord$h(meta)) return null;
19112
19195
  const parsed = DevinSubagentContextSchema.safeParse(meta[DEVIN_SUBAGENT_CONTEXT_META_KEY]);
19113
19196
  if (!parsed.success || parsed.data.parentAgentId === "root") return null;
19114
19197
  return parsed.data.parentAgentId;
19115
19198
  };
19116
- const hasOtherDevinSubagentMeta = (meta) => isRecord$g(meta) && Object.keys(meta).some(
19199
+ const hasOtherDevinSubagentMeta = (meta) => isRecord$h(meta) && Object.keys(meta).some(
19117
19200
  (key2) => key2.startsWith("cognition.ai/subagent") && key2 !== DEVIN_SUBAGENT_CONTEXT_META_KEY
19118
19201
  );
19119
19202
  const zMeta = record$3(string$1(), unknown()).nullish();
@@ -25999,6 +26082,10 @@ const machineFlockKeys = {
25999
26082
  "acpCapability",
26000
26083
  configId
26001
26084
  ],
26085
+ acpModelCapability: (configId) => [
26086
+ "acpModelCapability",
26087
+ configId
26088
+ ],
26002
26089
  rateLimit: (cliType, limitId) => [
26003
26090
  "rateLimit",
26004
26091
  cliType,
@@ -26082,6 +26169,14 @@ const parseMachineFlockKey = (key2) => {
26082
26169
  agentConfigId
26083
26170
  };
26084
26171
  }
26172
+ if (key2.length === 2 && key2[0] === "acpModelCapability" && isNonEmptyString$2(key2[1])) {
26173
+ const configId = key2[1];
26174
+ return {
26175
+ kind: "acpModelCapability",
26176
+ key: machineFlockKeys.acpModelCapability(configId),
26177
+ configId
26178
+ };
26179
+ }
26085
26180
  if (key2.length === 2 && key2[0] === "acpCapability" && isNonEmptyString$2(key2[1])) {
26086
26181
  const configId = key2[1];
26087
26182
  return {
@@ -26127,6 +26222,7 @@ const MACHINE_FLOCK_ROW_FAMILY_PREFIXES = {
26127
26222
  providerSetupCancellation: ["providerSetupCancellation"],
26128
26223
  agentConfigIndex: ["agentConfigIndex"],
26129
26224
  acpCapability: ["acpCapability"],
26225
+ acpModelCapability: ["acpModelCapability"],
26130
26226
  rateLimit: ["rateLimit"],
26131
26227
  builtinAgentOptOut: ["builtinAgentOptOut"],
26132
26228
  sessionLaunchConfig: ["sessionLaunchConfig"]
@@ -26163,6 +26259,7 @@ function readMachineFlockRowsFromFlock(flock, options) {
26163
26259
  const isMachineFlockLocalProjectRow = (row) => row.key[0] === "localProject";
26164
26260
  const isMachineFlockDeleteLocalProjectCommandRow = (row) => row.key[0] === "cmd" && row.key[1] === "deleteLocalProject";
26165
26261
  const isMachineFlockAcpCapabilityRow = (row) => row.key[0] === "acpCapability";
26262
+ const isMachineFlockAcpModelCapabilityRow = (row) => row.key[0] === "acpModelCapability";
26166
26263
  const isMachineFlockAgentConfigRow = (row) => row.key[0] === "agentConfig";
26167
26264
  const isMachineFlockProviderSetupRow = (row) => row.key[0] === "providerSetup";
26168
26265
  const isMachineFlockProviderSetupCancellationRow = (row) => row.key[0] === "providerSetupCancellation";
@@ -26190,13 +26287,35 @@ function getMachineFlockDeleteLocalProjectEntries(rows) {
26190
26287
  }
26191
26288
  return entries;
26192
26289
  }
26290
+ const ACP_CAPABILITY_ROW_FAMILIES = ["acpCapability", "acpModelCapability"];
26291
+ const mergedAcpCapabilityEntries = /* @__PURE__ */ new WeakMap();
26292
+ const withDeclaredModelControls = (entry, declaration) => {
26293
+ let byDeclaration = mergedAcpCapabilityEntries.get(entry);
26294
+ if (!byDeclaration) {
26295
+ byDeclaration = /* @__PURE__ */ new WeakMap();
26296
+ mergedAcpCapabilityEntries.set(entry, byDeclaration);
26297
+ }
26298
+ let merged = byDeclaration.get(declaration);
26299
+ if (!merged) {
26300
+ merged = { ...entry, declaredModelControls: declaration.models };
26301
+ byDeclaration.set(declaration, merged);
26302
+ }
26303
+ return merged;
26304
+ };
26193
26305
  function getMachineFlockAcpCapabilities(rows) {
26194
26306
  const capabilities = {};
26195
26307
  for (const row of Object.values(rows)) {
26196
- if (!isMachineFlockAcpCapabilityRow(row)) {
26197
- continue;
26308
+ if (isMachineFlockAcpCapabilityRow(row)) {
26309
+ capabilities[getAcpCapabilityCacheKey(row.key[1])] = row.value;
26310
+ }
26311
+ }
26312
+ for (const row of Object.values(rows)) {
26313
+ if (!isMachineFlockAcpModelCapabilityRow(row)) continue;
26314
+ const key2 = getAcpCapabilityCacheKey(row.key[1]);
26315
+ const entry = capabilities[key2];
26316
+ if (entry && entry.sourceVersion === row.value.sourceVersion) {
26317
+ capabilities[key2] = withDeclaredModelControls(entry, row.value);
26198
26318
  }
26199
- capabilities[getAcpCapabilityCacheKey(row.key[1])] = row.value;
26200
26319
  }
26201
26320
  return capabilities;
26202
26321
  }
@@ -26473,6 +26592,8 @@ function parseMachineFlockRow(key2, value) {
26473
26592
  }
26474
26593
  case "acpCapability":
26475
26594
  return isAcpCapabilityCacheEntry(value) ? { key: parsedKey.key, value } : void 0;
26595
+ case "acpModelCapability":
26596
+ return isAcpModelCapabilities(value) ? { key: parsedKey.key, value } : void 0;
26476
26597
  case "rateLimit":
26477
26598
  return isRecord$8(value) ? { key: parsedKey.key, value } : void 0;
26478
26599
  case "builtinAgentOptOut": {
@@ -27051,7 +27172,23 @@ const SessionActiveInvocationContextResultSchema = discriminatedUnion("active",
27051
27172
  inputConfig: record$3(string$1(), unknown())
27052
27173
  }).strict()
27053
27174
  ]);
27175
+ const SessionToolResultSchema = object({
27176
+ type: literal$1("session/tool-result"),
27177
+ content: array$2(object({ type: literal$1("text"), text: string$1() }).strict()),
27178
+ isError: boolean().optional()
27179
+ }).strict();
27054
27180
  const LocalMachineRpcRequestSchema = discriminatedUnion("method", [
27181
+ BaseLocalMachineRpcRequestSchema.extend({
27182
+ method: literal$1("session/call-tool"),
27183
+ params: object({
27184
+ sessionId: SessionIdSchema$1,
27185
+ name: string$1().min(1).max(100),
27186
+ arguments: record$3(string$1(), json$1()).refine(
27187
+ (value) => new TextEncoder().encode(JSON.stringify(value)).byteLength <= 256 * 1024,
27188
+ "Session tool arguments exceed 256 KiB"
27189
+ )
27190
+ }).strict()
27191
+ }).strict(),
27055
27192
  BaseLocalMachineRpcRequestSchema.extend({
27056
27193
  method: literal$1("session/get-active-invocation-context"),
27057
27194
  params: object({
@@ -27219,6 +27356,7 @@ const LocalMachineRpcRequestSchema = discriminatedUnion("method", [
27219
27356
  }).strict()
27220
27357
  ]);
27221
27358
  const LocalMachineRpcResultSchema = union$7([
27359
+ SessionToolResultSchema,
27222
27360
  SessionActiveInvocationContextResultSchema,
27223
27361
  CodeCollabV2FileIndexSnapshotSchema,
27224
27362
  CodeCollabV2OpenTextOkSchema,
@@ -112568,18 +112706,20 @@ class MachineDocument {
112568
112706
  const existing = getMachineFlockAcpCapabilities(
112569
112707
  readMachineFlockRowsFromFlock(handle.flock, { families: ["acpCapability"] })
112570
112708
  )[capabilityKey];
112571
- if (existing && serializeAcpCapabilityWithoutFetchTime(existing) === serializeAcpCapabilityWithoutFetchTime(entry) && // Unchanged content is still rewritten once it is old enough: the refresh
112709
+ const modelCapabilitiesChanged = options.modelCapabilities !== void 0 && writeMachineFlockRowToFlock(handle.flock, {
112710
+ key: machineFlockKeys.acpModelCapability(configId),
112711
+ value: { version: 1, sourceVersion: sourceVersion2, models: options.modelCapabilities }
112712
+ });
112713
+ const capabilityUnchanged = existing && serializeAcpCapabilityWithoutFetchTime(existing) === serializeAcpCapabilityWithoutFetchTime(entry) && // Unchanged content is still rewritten once it is old enough: the refresh
112572
112714
  // cache trusts `fetchedAt`, and an entry never renewed would expire once
112573
112715
  // and then miss on every later request, re-probing forever.
112574
- !shouldRenewAcpCapabilityFetchTime(existing, entry.fetchedAt)) {
112575
- return existing;
112576
- }
112716
+ !shouldRenewAcpCapabilityFetchTime(existing, entry.fetchedAt);
112577
112717
  options.signal?.throwIfAborted();
112578
- const changed = writeMachineFlockRowToFlock(handle.flock, {
112718
+ const changed = !capabilityUnchanged && writeMachineFlockRowToFlock(handle.flock, {
112579
112719
  key: machineFlockKeys.acpCapability(configId),
112580
112720
  value: entry
112581
112721
  });
112582
- if (changed) {
112722
+ if (changed || modelCapabilitiesChanged) {
112583
112723
  await this.repo.flush();
112584
112724
  if (this.markMachineFlockDirty) {
112585
112725
  this.markMachineFlockDirty("acp-capability-update");
@@ -112587,7 +112727,7 @@ class MachineDocument {
112587
112727
  await handle.syncOnce().catch(() => void 0);
112588
112728
  }
112589
112729
  }
112590
- return entry;
112730
+ return (capabilityUnchanged ? existing : void 0) ?? entry;
112591
112731
  }
112592
112732
  async getAcpCapabilities(configId) {
112593
112733
  const key2 = getAcpCapabilityCacheKey(configId);
@@ -122446,7 +122586,7 @@ async function decompressStream(input2, options) {
122446
122586
  }, new ByteLengthQueuingStrategy({ highWaterMark }));
122447
122587
  }
122448
122588
  const version$b = "1.12.0";
122449
- const dependencies = { "@openai/codex": "^0.156.0" };
122589
+ const dependencies = { "@openai/codex": "^0.159.2" };
122450
122590
  const codexPackageJson = {
122451
122591
  version: version$b,
122452
122592
  dependencies
@@ -122479,8 +122619,8 @@ const claudeRuntimeManifestJson = {
122479
122619
  version: version$6,
122480
122620
  artifacts: artifacts$2
122481
122621
  };
122482
- const version$5 = "0.156.0";
122483
- const artifacts$1 = { "darwin-arm64": { "fileName": "codex-package-aarch64-apple-darwin.tar.zst", "sha256": "27a4c6ad8d63ab0988eb2a6699fb092d999b78845c75edad1eef674064a026de", "size": 91943742 }, "darwin-x64": { "fileName": "codex-package-x86_64-apple-darwin.tar.zst", "sha256": "545de467983f6d1fa1ee67266b0df4fcdd864bf1e8681254ee3691a48ea296fd", "size": 101404952 }, "linux-arm64": { "fileName": "codex-package-aarch64-unknown-linux-musl.tar.zst", "sha256": "cb2573ebaa76503f763cf2ac858219114c69a2000961ca14330e5a4a9ebd734f", "size": 100178344 }, "linux-x64": { "fileName": "codex-package-x86_64-unknown-linux-musl.tar.zst", "sha256": "30933220521da2a9eef5ca7be5cbb215edcb088835d0a55ba7488168da5b341f", "size": 106005443 }, "win32-arm64": { "fileName": "codex-package-aarch64-pc-windows-msvc.tar.zst", "sha256": "3041dfb02eff1f8e68bbbcc7603534b02ee0bb55b7b93bdd522b12dc3e12162f", "size": 106301619 }, "win32-x64": { "fileName": "codex-package-x86_64-pc-windows-msvc.tar.zst", "sha256": "887cc9593dbb59b3122afe4c8520c32e633ab644d685c95bcba23e115e56fcaf", "size": 115013735 } };
122622
+ const version$5 = "0.159.2";
122623
+ const artifacts$1 = { "darwin-arm64": { "fileName": "codex-package-aarch64-apple-darwin.tar.zst", "sha256": "2958825ae590c52093e13dc5e00bdeab5d84947d9a1c76c91f3c42338444909b", "size": 93587821 }, "darwin-x64": { "fileName": "codex-package-x86_64-apple-darwin.tar.zst", "sha256": "22609e143919c817c642c0a801ad67874b5395dfdd118e077b5699697629618b", "size": 102536488 }, "linux-arm64": { "fileName": "codex-package-aarch64-unknown-linux-musl.tar.zst", "sha256": "1017b8175e4c4c6529866ed4b67c8e93ad7f0169ad89888068f0ad9707c5999d", "size": 109213770 }, "linux-x64": { "fileName": "codex-package-x86_64-unknown-linux-musl.tar.zst", "sha256": "fbca2d1e23dc9f827fe6eb19cbca2942140f99a48769f62355d647f5d75ee91e", "size": 115217118 }, "win32-arm64": { "fileName": "codex-package-aarch64-pc-windows-msvc.tar.zst", "sha256": "47d79aa012f3f04fc89a70a9a3ad555def7c83384b3f24d8ba1d3ac5610cb25f", "size": 108217158 }, "win32-x64": { "fileName": "codex-package-x86_64-pc-windows-msvc.tar.zst", "sha256": "57133a65c41976304cfcd24367c4b7e297562ffe2efe4a6ebe560c9a8843aeb8", "size": 116901172 } };
122484
122624
  const codexRuntimeManifestJson = {
122485
122625
  version: version$5,
122486
122626
  artifacts: artifacts$1
@@ -125643,9 +125783,27 @@ const readManagedCandidate = async (repoFullName, source, invalidatedPersonalTok
125643
125783
  }, 15000);
125644
125784
  if (!response || !response.ok) throw new Error('GitHub credential service is unavailable; no operation was attempted.');
125645
125785
  const body = await response.json();
125646
- if (body.available === false) return null;
125786
+ if (body.available === false) return { token: null, reason: typeof body.reason === 'string' ? body.reason : null };
125647
125787
  if (!body.token || body.tokenSource !== source) throw new Error('Invalid GitHub credential response.');
125648
- return body.token;
125788
+ return { token: body.token, reason: null };
125789
+ };
125790
+
125791
+ // Why the personal identity was skipped, in words the user can act on. Never
125792
+ // includes token material; reasons are backend policy codes or preflight states.
125793
+ const describePersonalUnavailable = (repo, reason) => {
125794
+ switch (reason) {
125795
+ case 'personal_auth_missing':
125796
+ return 'your personal GitHub account is not authorized yet (Settings > Integrations > GitHub > Authorize)';
125797
+ case 'personal_token_expired':
125798
+ case 'personal_token_refresh_failed':
125799
+ return 'your personal GitHub authorization has expired or been revoked; re-authorize in Settings > Integrations > GitHub';
125800
+ case 'no_repository_access':
125801
+ return 'your GitHub account cannot access ' + repo + ' with the required permission';
125802
+ case 'token_invalid':
125803
+ return 'GitHub rejected your personal token; re-authorize in Settings > Integrations > GitHub';
125804
+ default:
125805
+ return reason ? 'personal access is unavailable (' + reason + ')' : 'personal access is unavailable';
125806
+ }
125649
125807
  };
125650
125808
 
125651
125809
  // Read-only preflight. Never replay an actual write with another identity.
@@ -125673,33 +125831,38 @@ const checkRepositoryCredential = async (token, repo, requireWrite, requirePubli
125673
125831
  };
125674
125832
 
125675
125833
  const selectGitHubCredential = async (repo, policy, localCandidate, requireWrite, anonymousCandidate) => {
125676
- let personalUnavailable = false;
125834
+ let personalUnavailable = null;
125677
125835
  if (policy.personalEnabled) {
125678
- let token = await readManagedCandidate(repo, 'personal');
125836
+ let candidate = await readManagedCandidate(repo, 'personal');
125837
+ let token = candidate.token;
125838
+ personalUnavailable = candidate.reason;
125679
125839
  if (token) {
125680
125840
  let status = await checkRepositoryCredential(token, repo, requireWrite);
125681
125841
  if (status === 'invalid') {
125682
- token = await readManagedCandidate(repo, 'personal', token);
125842
+ candidate = await readManagedCandidate(repo, 'personal', token);
125843
+ token = candidate.token;
125844
+ personalUnavailable = candidate.reason ?? 'token_invalid';
125683
125845
  if (token) status = await checkRepositoryCredential(token, repo, requireWrite);
125684
125846
  }
125685
125847
  if (token && status === 'usable') return { token, source: 'personal' };
125848
+ if (token) personalUnavailable = status === 'invalid' ? 'token_invalid' : 'no_repository_access';
125686
125849
  }
125687
- personalUnavailable = true;
125850
+ personalUnavailable = describePersonalUnavailable(repo, personalUnavailable);
125688
125851
  }
125689
125852
  if (policy.allowLocalAuth) {
125690
125853
  const local = await localCandidate();
125691
125854
  if (local) {
125692
- if (personalUnavailable) console.error('[Lody] Personal GitHub access is unavailable for ' + repo + '; using machine-local credentials.');
125855
+ if (personalUnavailable) console.error('[Lody] Using machine-local GitHub credentials for ' + repo + ': ' + personalUnavailable + '.');
125693
125856
  return { ...local, source: 'local' };
125694
125857
  }
125695
125858
  }
125696
- const token = await readManagedCandidate(repo, 'app');
125859
+ const token = (await readManagedCandidate(repo, 'app')).token;
125697
125860
  if (!token && !requireWrite && anonymousCandidate && await anonymousCandidate()) {
125698
125861
  console.error('[Lody] Reading public GitHub repository ' + repo + ' anonymously (no applicable credential).');
125699
125862
  return { token: null, source: 'anonymous' };
125700
125863
  }
125701
125864
  if (!token) throw new Error('No GitHub credential is available for ' + repo + '.');
125702
- console.error('[Lody] Using GitHub App identity for ' + repo + (personalUnavailable ? ' (personal access unavailable).' : '.'));
125865
+ console.error('[Lody] Using GitHub App identity for ' + repo + (personalUnavailable ? ': ' + personalUnavailable + '.' : '.'));
125703
125866
  return { token, source: 'app' };
125704
125867
  };
125705
125868
  `;
@@ -127633,10 +127796,15 @@ const ProfileRecordSchema = object({
127633
127796
  configId: string$1().min(1),
127634
127797
  profile: CodexAuthProfileSchema,
127635
127798
  state: _enum(["pending", "ready", "removed"]),
127799
+ authStore: _enum(["codex-default", "keyring"]).optional(),
127636
127800
  activeGeneration: uuid().optional(),
127637
127801
  generations: array$2(uuid()),
127638
127802
  credentialsRemoved: boolean().optional()
127639
127803
  }).strict();
127804
+ function resolveAuthStore(record2) {
127805
+ if (record2.authStore) return record2.authStore;
127806
+ return record2.profile.mode === "chatgpt" && record2.state !== "pending" ? "keyring" : "codex-default";
127807
+ }
127640
127808
  const identity$1 = (owner) => createHash("sha256").update(JSON.stringify([owner.workspaceId, owner.machineId, owner.configId])).digest("hex");
127641
127809
  class CodexProfileStore {
127642
127810
  constructor(root = path__default.join(getLodyDataDir(), "codex-profiles"), vault = new SystemCodexCredentialVault(), logout = logoutNativeProfile) {
@@ -127724,7 +127892,14 @@ class CodexProfileStore {
127724
127892
  if (!record2) {
127725
127893
  if (!allowPending)
127726
127894
  throw new Error("This Codex account has not been authenticated on this machine");
127727
- record2 = { version: 1, ...owner, profile, state: "pending", generations: [] };
127895
+ record2 = {
127896
+ version: 1,
127897
+ ...owner,
127898
+ profile,
127899
+ state: "pending",
127900
+ authStore: "codex-default",
127901
+ generations: []
127902
+ };
127728
127903
  await this.write(directory, record2);
127729
127904
  }
127730
127905
  this.assertBinding(record2, owner, profile);
@@ -127736,7 +127911,7 @@ class CodexProfileStore {
127736
127911
  });
127737
127912
  if ((await lstat(home)).isSymbolicLink() || await realpath(home) !== home)
127738
127913
  throw new Error("Invalid Codex account home");
127739
- return { ...owner, profile, home };
127914
+ return { ...owner, profile, home, authStore: resolveAuthStore(record2) };
127740
127915
  });
127741
127916
  }
127742
127917
  credentialId(owner, profileId, generation) {
@@ -127797,7 +127972,7 @@ class CodexProfileStore {
127797
127972
  const record2 = await this.read(directory);
127798
127973
  if (!record2) throw new Error("Codex account is unavailable");
127799
127974
  this.assertBinding(record2, resolved, resolved.profile);
127800
- await this.write(directory, { ...record2, state: "ready" });
127975
+ await this.write(directory, { ...record2, state: "ready", authStore: resolved.authStore });
127801
127976
  });
127802
127977
  }
127803
127978
  async remove(resolved) {
@@ -127807,7 +127982,7 @@ class CodexProfileStore {
127807
127982
  if (!record2) return true;
127808
127983
  if (identity$1(record2) !== identity$1(resolved)) throw new Error("Codex account owner mismatch");
127809
127984
  if (record2.credentialsRemoved) return true;
127810
- await this.write(directory, { ...record2, state: "removed" });
127985
+ await this.write(directory, { ...record2, state: "removed", authStore: resolved.authStore });
127811
127986
  if (record2.profile.mode === "chatgpt") {
127812
127987
  if (!await reconcileCodexProfileProcesses(resolved)) return false;
127813
127988
  const lease = await registerCodexProfileProcess(resolved, {
@@ -127826,6 +128001,7 @@ class CodexProfileStore {
127826
128001
  await this.write(directory, {
127827
128002
  ...record2,
127828
128003
  state: "removed",
128004
+ authStore: resolved.authStore,
127829
128005
  generations: [],
127830
128006
  activeGeneration: void 0,
127831
128007
  credentialsRemoved: true
@@ -127864,7 +128040,11 @@ class CodexProfileStore {
127864
128040
  const directory = await this.directory(entry.name);
127865
128041
  const record2 = await this.read(directory);
127866
128042
  if (record2?.workspaceId === workspaceId)
127867
- profiles.push({ ...record2, home: path__default.join(directory, "home") });
128043
+ profiles.push({
128044
+ ...record2,
128045
+ home: path__default.join(directory, "home"),
128046
+ authStore: resolveAuthStore(record2)
128047
+ });
127868
128048
  }
127869
128049
  return profiles;
127870
128050
  }
@@ -127884,7 +128064,10 @@ async function logoutNativeProfile(profile, lease) {
127884
128064
  await new Promise((resolve2, reject2) => {
127885
128065
  const child = execFile(
127886
128066
  launch.command,
127887
- ["-c", 'cli_auth_credentials_store="keyring"', "logout"],
128067
+ [
128068
+ ...profile.authStore === "keyring" ? ["-c", 'cli_auth_credentials_store="keyring"'] : [],
128069
+ "logout"
128070
+ ],
127888
128071
  { env: env2, timeout: 2e4, windowsHide: true },
127889
128072
  (error2) => {
127890
128073
  if (error2) reject2(new Error("Codex account cleanup could not complete"));
@@ -136648,6 +136831,7 @@ function normalizeAcpSessionCapabilities(sessionResponse, lifecycleCapabilities
136648
136831
  const legacyModels = readLegacySessionModelState(sessionResponse)?.availableModels ?? [];
136649
136832
  const models = modelsFromConfigOptions.length > 0 ? modelsFromConfigOptions : legacyModels;
136650
136833
  const availableCommands = readSessionAvailableCommands(sessionResponse);
136834
+ const modelCapabilities = readAcpModelCapabilitiesMeta(sessionResponse);
136651
136835
  const modelReasoningEfforts = {
136652
136836
  ...readLodyModelReasoningEfforts(sessionResponse),
136653
136837
  ...usesCodexModelEffortIds(lifecycleCapabilities.agent) ? deriveModelReasoningEffortsFromLegacyModelIds(legacyModels.map((model) => model.modelId)) : void 0
@@ -136661,7 +136845,8 @@ function normalizeAcpSessionCapabilities(sessionResponse, lifecycleCapabilities
136661
136845
  acknowledgedSteer: lifecycleCapabilities.acknowledgedSteer === true,
136662
136846
  sessionTitle: lifecycleCapabilities.sessionTitle === true,
136663
136847
  ...lifecycleCapabilities.goalActions?.length ? { goalActions: lifecycleCapabilities.goalActions } : {},
136664
- ...Object.keys(modelReasoningEfforts).length > 0 ? { modelReasoningEfforts } : {}
136848
+ ...Object.keys(modelReasoningEfforts).length > 0 ? { modelReasoningEfforts } : {},
136849
+ ...modelCapabilities ? { modelCapabilities } : {}
136665
136850
  };
136666
136851
  }
136667
136852
  const MAX_LISTED_IDS = 12;
@@ -142036,7 +142221,7 @@ async function startCodexCredentialBroker(options) {
142036
142221
  }
142037
142222
  function codexProfileConfig(profile, baseUrl) {
142038
142223
  const base = {
142039
- cli_auth_credentials_store: "keyring",
142224
+ ...profile.authStore === "keyring" ? { cli_auth_credentials_store: "keyring" } : {},
142040
142225
  check_for_update_on_startup: false,
142041
142226
  shell_environment_policy: {
142042
142227
  inherit: "all",
@@ -142849,7 +143034,7 @@ function getBuiltinDisplayName(agentType) {
142849
143034
  function formatAuthenticationExitError(agentType, displayName, exitCode) {
142850
143035
  const base = `${displayName} authentication exited with code ${exitCode ?? "unknown"}`;
142851
143036
  if (agentType !== "codex") return base;
142852
- return `${base}. Make sure device-code login is enabled in your ChatGPT security settings or workspace permissions, then try again.`;
143037
+ return `${base}. Check the Codex login log on the execution machine for the cause, then try again.`;
142853
143038
  }
142854
143039
  async function buildAuthenticationProcessEnv(options) {
142855
143040
  const loginShellEnv = await options.resolveLoginShellEnv();
@@ -142973,8 +143158,6 @@ class AcpAuthenticationManager {
142973
143158
  this.resolveLoginShellEnv = options.resolveLoginShellEnv ?? getLoginShellEnv;
142974
143159
  this.resolveAuthenticationProcessLaunch = options.resolveAuthenticationProcessLaunch ?? resolveBuiltinAuthenticationProcessLaunch;
142975
143160
  }
142976
- // Each builtin provider has one shared credential store, so concurrent login
142977
- // attempts are intentionally keyed by agent type.
142978
143161
  runningByAgentType = /* @__PURE__ */ new Map();
142979
143162
  authenticationTimeoutMs;
142980
143163
  terminationGraceMs;
@@ -143094,13 +143277,7 @@ class AcpAuthenticationManager {
143094
143277
  options.onProgress?.({ status: "starting" });
143095
143278
  const child = this.spawnProcess(
143096
143279
  launch.command,
143097
- options.codexProfile ? [
143098
- "-c",
143099
- 'cli_auth_credentials_store="keyring"',
143100
- "-c",
143101
- 'forced_login_method="chatgpt"',
143102
- ...launch.args
143103
- ] : launch.args,
143280
+ options.codexProfile ? ["-c", 'forced_login_method="chatgpt"', ...launch.args] : launch.args,
143104
143281
  {
143105
143282
  cwd: os__default$1.homedir(),
143106
143283
  env: env2,
@@ -150926,13 +151103,18 @@ class SessionExecutionService {
150926
151103
  let staleAcpPromptRecoveryAttempted = false;
150927
151104
  let baseCommitHash = null;
150928
151105
  let turnStartWorkingTreeDiff = null;
151106
+ const gitIdentityOptions = yield* self2.tryPromise(async () => {
151107
+ try {
151108
+ return await self2.deps.sessionManager.resolveGitIdentityOptions(message.userId);
151109
+ } catch {
151110
+ return { preferMachineIdentity: message.userId === self2.deps.userId };
151111
+ }
151112
+ });
150929
151113
  const bindReadySession = (nextSession) => {
150930
151114
  activeSession = nextSession;
150931
151115
  session2 = nextSession;
150932
151116
  ctx.bindSession(nextSession);
150933
- nextSession.updateGitIdentity(userName, userEmail, message.userId, {
150934
- preferMachineIdentity: message.userId === self2.deps.userId
150935
- });
151117
+ nextSession.updateGitIdentity(userName, userEmail, message.userId, gitIdentityOptions);
150936
151118
  };
150937
151119
  const sessionInputBlocks = normalizeSessionInputBlocks(
150938
151120
  acpSessionConfig.inputBlocks,
@@ -151987,7 +152169,10 @@ class SessionExecutionService {
151987
152169
  capabilities.modelReasoningEfforts,
151988
152170
  capabilities.acknowledgedSteer,
151989
152171
  capabilities.goalActions,
151990
- { sessionTitle: capabilities.sessionTitle }
152172
+ {
152173
+ sessionTitle: capabilities.sessionTitle,
152174
+ modelCapabilities: capabilities.modelCapabilities
152175
+ }
151991
152176
  );
151992
152177
  this.acpCapabilityLaunchInputFingerprints.set(
151993
152178
  agentConfigId,
@@ -152417,6 +152602,7 @@ class SessionExecutionService {
152417
152602
  sessionTitle,
152418
152603
  goalActions,
152419
152604
  modelReasoningEfforts,
152605
+ modelCapabilities,
152420
152606
  capabilitySourceVersion
152421
152607
  } = await this.deps.fetchAcpCapabilities(
152422
152608
  message.cliType,
@@ -152456,7 +152642,7 @@ class SessionExecutionService {
152456
152642
  modelReasoningEfforts,
152457
152643
  acknowledgedSteer,
152458
152644
  goalActions,
152459
- { signal: options.signal, sessionTitle }
152645
+ { signal: options.signal, sessionTitle, modelCapabilities }
152460
152646
  );
152461
152647
  this.acpCapabilityLaunchInputFingerprints.set(
152462
152648
  message.configId,
@@ -155156,10 +155342,9 @@ const normalizeName$1 = (name2, email2) => {
155156
155342
  }
155157
155343
  return email2;
155158
155344
  };
155159
- const readGitConfig = (key2, cwd) => {
155345
+ const readGitConfig = (key2) => {
155160
155346
  try {
155161
- const output = execFileSync("git", ["config", key2], {
155162
- cwd,
155347
+ const output = execFileSync("git", ["config", "--global", key2], {
155163
155348
  encoding: "utf8",
155164
155349
  stdio: ["ignore", "pipe", "ignore"],
155165
155350
  windowsHide: true
@@ -155169,13 +155354,18 @@ const readGitConfig = (key2, cwd) => {
155169
155354
  return void 0;
155170
155355
  }
155171
155356
  };
155172
- const readHostDefaultGitIdentity = (cwd) => ({
155173
- name: trimNonEmpty$1(process.env.GIT_AUTHOR_NAME) ?? trimNonEmpty$1(process.env.GIT_COMMITTER_NAME) ?? readGitConfig("user.name", cwd),
155174
- email: trimNonEmpty$1(process.env.GIT_AUTHOR_EMAIL) ?? trimNonEmpty$1(process.env.GIT_COMMITTER_EMAIL) ?? readGitConfig("user.email", cwd)
155357
+ const readHostDefaultGitIdentity = () => ({
155358
+ name: trimNonEmpty$1(process.env.GIT_AUTHOR_NAME) ?? trimNonEmpty$1(process.env.GIT_COMMITTER_NAME) ?? readGitConfig("user.name"),
155359
+ email: trimNonEmpty$1(process.env.GIT_AUTHOR_EMAIL) ?? trimNonEmpty$1(process.env.GIT_COMMITTER_EMAIL) ?? readGitConfig("user.email")
155175
155360
  });
155176
155361
  const resolveSessionGitIdentity = (requested, options) => {
155362
+ const requestedEmail = trimNonEmpty$1(requested.email);
155363
+ const requestedIdentity = isUsableEmail(requestedEmail) ? { name: normalizeName$1(trimNonEmpty$1(requested.name), requestedEmail), email: requestedEmail } : void 0;
155364
+ if (options.personalIdentityEnabled && requestedIdentity) {
155365
+ return requestedIdentity;
155366
+ }
155177
155367
  if (options.preferMachineIdentity) {
155178
- const machineIdentity = options.machineIdentity ?? readHostDefaultGitIdentity(options.cwd);
155368
+ const machineIdentity = options.machineIdentity ?? readHostDefaultGitIdentity();
155179
155369
  const machineEmail = trimNonEmpty$1(machineIdentity.email);
155180
155370
  if (isUsableEmail(machineEmail)) {
155181
155371
  return {
@@ -155184,12 +155374,8 @@ const resolveSessionGitIdentity = (requested, options) => {
155184
155374
  };
155185
155375
  }
155186
155376
  }
155187
- const requestedEmail = trimNonEmpty$1(requested.email);
155188
- if (isUsableEmail(requestedEmail)) {
155189
- return {
155190
- name: normalizeName$1(trimNonEmpty$1(requested.name), requestedEmail),
155191
- email: requestedEmail
155192
- };
155377
+ if (requestedIdentity) {
155378
+ return requestedIdentity;
155193
155379
  }
155194
155380
  return {
155195
155381
  name: DEFAULT_AI_GIT_AUTHOR_NAME,
@@ -158335,12 +158521,13 @@ class LodyOperationCoordinator {
158335
158521
  }
158336
158522
  claimedMaterialization = true;
158337
158523
  try {
158338
- await this.options.workspaceDocument.syncRemoteDocOrThrow(
158339
- getSessionRoomId(target.sessionId),
158340
- {
158341
- reason: `orchestration.materialize:${operation.operationId}:${index}`
158342
- }
158343
- );
158524
+ const docId = getSessionRoomId(target.sessionId);
158525
+ const reason = `orchestration.materialize:${operation.operationId}:${index}`;
158526
+ if (this.options.confirmTargetReadable) {
158527
+ await this.options.confirmTargetReadable(docId, reason);
158528
+ } else {
158529
+ await this.options.workspaceDocument.syncRemoteDocOrThrow(docId, { reason });
158530
+ }
158344
158531
  } catch (error2) {
158345
158532
  if (signal.aborted) return item;
158346
158533
  if (!isAtDeadline()) {
@@ -159099,6 +159286,40 @@ class LodyOperationCoordinator {
159099
159286
  });
159100
159287
  }
159101
159288
  }
159289
+ const environments = new AsyncLocalStorage();
159290
+ const getSessionCommandEnvironment = () => environments.getStore();
159291
+ const runWithSessionCommandEnvironment = (environment2, run2) => environments.run(environment2, run2);
159292
+ function createLocalSessionCommandEnvironment(args2) {
159293
+ const { manager, workspaceId, machineId, userId } = args2;
159294
+ return {
159295
+ auth: {
159296
+ token: "",
159297
+ userId,
159298
+ userName: userId,
159299
+ userEmail: "",
159300
+ machineId,
159301
+ machineName: args2.machineName
159302
+ },
159303
+ workspace: { id: workspaceId, name: "Lody", slug: "local", role: "owner" },
159304
+ manager,
159305
+ host: args2.host,
159306
+ async checkMachineAccess(target) {
159307
+ if (target.workspaceId !== workspaceId || target.requesterUserId !== userId)
159308
+ return { allowed: false, reason: "requester_not_member" };
159309
+ if (target.machineId !== machineId)
159310
+ return { allowed: false, reason: "machine_not_registered" };
159311
+ const row = await manager.repo.getDocMeta(getMachineRoomId(machineId));
159312
+ if (!row?.meta || isLoroRepoDocDeleted(row) || row.meta.ownerUserId !== userId)
159313
+ return { allowed: false, reason: "not_visible" };
159314
+ if (target.localProjectId) {
159315
+ const projects = await readMachineLocalProjects(manager.repo, workspaceId, machineId);
159316
+ const project = Object.values(projects).find((entry) => entry.id === target.localProjectId);
159317
+ if (!project) return { allowed: false, reason: "project_not_shared" };
159318
+ }
159319
+ return { allowed: true };
159320
+ }
159321
+ };
159322
+ }
159102
159323
  function hasSessionDispatchEvidence(meta, history, userTurnId) {
159103
159324
  const user = history.find((entry) => entry.id === userTurnId && entry.role === "user");
159104
159325
  return !!user && (meta.latestUserMsgId === userTurnId || meta.processingUserMsgId === userTurnId || meta.lastHandledUserMsgId === userTurnId || user.status === "handled" || user.status === "failed" || user.status === "canceled" || history.some(
@@ -167332,6 +167553,25 @@ async function canUseMachineForCliToken(input2) {
167332
167553
  throw error2;
167333
167554
  }
167334
167555
  }
167556
+ const MISSING_PUBLIC_FUNCTION_ERROR = /Could not find (public )?function/;
167557
+ async function canDelegateMachineUseForCliToken(input2) {
167558
+ const client2 = createAuthConvexClient();
167559
+ try {
167560
+ const raw2 = await client2.query(api.machines.canDelegateMachineUseFromCliToken, {
167561
+ cliToken: input2.token,
167562
+ workspaceId: input2.workspaceId,
167563
+ machineId: input2.machineId,
167564
+ requesterUserId: input2.requesterUserId,
167565
+ ...input2.localProjectId !== void 0 ? { localProjectId: input2.localProjectId } : {}
167566
+ });
167567
+ return MachineAccessCheckResultSchema.parse(raw2);
167568
+ } catch (error2) {
167569
+ if (error2 instanceof Error && MISSING_PUBLIC_FUNCTION_ERROR.test(error2.message)) {
167570
+ return null;
167571
+ }
167572
+ throw error2;
167573
+ }
167574
+ }
167335
167575
  async function canRequestMachineForCliToken(input2) {
167336
167576
  const client2 = createAuthConvexClient();
167337
167577
  const raw2 = await client2.query(api.machines.canRequestMachineFromCliToken, {
@@ -167645,6 +167885,11 @@ const PRICE_DATA = {
167645
167885
  cacheReadInputTokenCost: 1e-6,
167646
167886
  outputCostPerToken: 5e-5
167647
167887
  },
167888
+ "gpt-6.1-sol": {
167889
+ inputCostPerToken: 2e-6,
167890
+ cacheReadInputTokenCost: 1e-7,
167891
+ outputCostPerToken: 1e-5
167892
+ },
167648
167893
  "gpt-6-sol": {
167649
167894
  inputCostPerToken: 2e-6,
167650
167895
  cacheReadInputTokenCost: 2e-7,
@@ -167979,8 +168224,13 @@ class GitHubTokenManager {
167979
168224
  })
167980
168225
  );
167981
168226
  if (!result.success) {
167982
- if (result.errorCode === "repo_not_linked" || source2 === "personal" && result.errorCode === "personal_unavailable")
167983
- return null;
168227
+ if (result.errorCode === "repo_not_linked") return null;
168228
+ if (source2 === "personal" && result.errorCode === "personal_unavailable") {
168229
+ this.logger.debug(
168230
+ `[github-token] Personal GitHub identity unavailable for ${repoFullName} (requester ${context2.requesterUserId}): ${result.errorMessage}`
168231
+ );
168232
+ return { available: false, reason: result.errorMessage };
168233
+ }
167984
168234
  throw new GitHubTokenFetchError(result.errorCode, result.errorMessage);
167985
168235
  }
167986
168236
  return { token: result.token, tokenSource: result.tokenSource ?? "app" };
@@ -168755,6 +169005,8 @@ function selectWorkspaceSummary(workspaces, selector) {
168755
169005
  );
168756
169006
  }
168757
169007
  function getAuthContextOrThrow$1(loggerName) {
169008
+ const environment2 = getSessionCommandEnvironment();
169009
+ if (environment2) return environment2.auth;
168758
169010
  const authClient = new AuthClient(getLogger(loggerName));
168759
169011
  const authInfo = authClient.getAuthInfo();
168760
169012
  if (!authInfo) {
@@ -168770,11 +169022,22 @@ function getAuthContextOrThrow$1(loggerName) {
168770
169022
  };
168771
169023
  }
168772
169024
  async function resolveWorkspaceOrThrow$1(auth, selector) {
169025
+ const environment2 = getSessionCommandEnvironment();
169026
+ if (environment2) {
169027
+ if (auth !== environment2.auth) throw new Error("Session command identity mismatch");
169028
+ return selectWorkspaceSummary([environment2.workspace], selector);
169029
+ }
168773
169030
  const workspaces = await listWorkspacesForToken(auth.token);
168774
169031
  const effectiveSelector = normalizeCliValue(selector) ?? normalizeCliValue(process.env.LODY_WORKSPACE_ID);
168775
169032
  return selectWorkspaceSummary(workspaces, effectiveSelector);
168776
169033
  }
168777
169034
  async function withWorkspaceManager$1(auth, workspace, loggerName, fn) {
169035
+ const environment2 = getSessionCommandEnvironment();
169036
+ if (environment2) {
169037
+ if (auth !== environment2.auth || workspace.id !== environment2.workspace.id)
169038
+ throw new Error("Session command workspace mismatch");
169039
+ return fn(environment2.manager);
169040
+ }
168778
169041
  if (!LODY_AUTH_URL) {
168779
169042
  throw new Error("Cloud workspace commands require LODY_AUTH_URL");
168780
169043
  }
@@ -171026,8 +171289,6 @@ class ResourceDiscovery {
171026
171289
  const modeId = role.runConfig.modeId ?? role.runConfig.configOptionValues?._permission;
171027
171290
  if (state2.state === "available" && capability && modeId && !(permission ? permission.options.some((option2) => option2.value === modeId) : capability.modes.some((mode2) => mode2.id === modeId)))
171028
171291
  state2 = { state: "unavailable", reason: "mode_unavailable" };
171029
- if (state2.state === "available" && source2.roleMachineScope && role.machineId !== source2.roleMachineScope)
171030
- state2 = { state: "unavailable", reason: "outside_work_context" };
171031
171292
  return {
171032
171293
  id: role.id,
171033
171294
  name: role.name,
@@ -171075,14 +171336,6 @@ class ResourceDiscovery {
171075
171336
  async function createResourceDiscovery(args2) {
171076
171337
  const { manager, auth, workspaceId } = args2;
171077
171338
  if (!args2.offline) await syncWorkspaceMetaForRead(manager, "resource.discovery");
171078
- let roleMachineScope;
171079
- if (args2.requesterSessionId) {
171080
- const record2 = await manager.repo.getDocMeta(getSessionRoomId(args2.requesterSessionId));
171081
- if (!record2?.meta || isLoroRepoDocDeleted(record2))
171082
- throw new Error("Requester Session not found.");
171083
- const session2 = record2.meta;
171084
- if (session2.project?.kind !== "github") roleMachineScope = session2.machineId;
171085
- }
171086
171339
  const synced = /* @__PURE__ */ new Set();
171087
171340
  async function sync2(id2) {
171088
171341
  if (!args2.offline && !synced.has(id2)) {
@@ -171094,9 +171347,8 @@ async function createResourceDiscovery(args2) {
171094
171347
  workspaceId,
171095
171348
  userId: args2.delegatedRequester?.userId ?? auth.userId,
171096
171349
  selectedMcpServerIds: args2.selectedMcpServerIds,
171097
- roleMachineScope,
171098
171350
  machines: async () => (await listAliveDocMetas(manager, isMachineDocRoomId)).map((row) => row.meta),
171099
- onlineMachineIds: async () => args2.offline ? null : manager.getOnlineMachineIds(),
171351
+ onlineMachineIds: async () => getSessionCommandEnvironment() ? /* @__PURE__ */ new Set([auth.machineId]) : args2.offline ? null : manager.getOnlineMachineIds(),
171100
171352
  canAccess: async (machineId, localProjectId) => (await readSessionMachineAccess({
171101
171353
  auth,
171102
171354
  workspaceId,
@@ -172789,11 +173041,10 @@ function validateModelDependentTurnConfigOptionValues(values, capability, target
172789
173041
  const optionsById = new Map(
172790
173042
  (capability.configOptions ?? []).map((option2) => [option2.id, option2])
172791
173043
  );
173044
+ const efforts = getModelEffortChoices(capability, targetModelId);
173045
+ const declaredFast = getDeclaredModelControls(capability, targetModelId)?.fastMode;
172792
173046
  for (const [id2, value] of Object.entries(values)) {
172793
- const option2 = optionsById.get(id2);
172794
- const isEffort = isAcpThoughtLevelConfigOption(option2 ?? { id: id2 }) || id2 === "effort";
172795
- if (isEffort) {
172796
- const efforts = capability.modelReasoningEfforts?.[targetModelId];
173047
+ if (isTurnEffortEntry(optionsById, id2)) {
172797
173048
  if (efforts !== void 0) {
172798
173049
  if (typeof value !== "string" || !efforts.includes(value)) {
172799
173050
  throw new Error(
@@ -172804,12 +173055,20 @@ function validateModelDependentTurnConfigOptionValues(values, capability, target
172804
173055
  } else if (targetModelId !== probedModelId) {
172805
173056
  validatedIds.add(id2);
172806
173057
  }
172807
- } else if (isAcpFastModeConfigId(id2) && targetModelId !== probedModelId) {
172808
- validatedIds.add(id2);
173058
+ } else if (isAcpFastModeConfigId(id2)) {
173059
+ if (declaredFast === false && (value === true || value === ACP_CONFIG_OPTION_ON_VALUE)) {
173060
+ throw new Error(`Model ${targetModelId} does not offer fast mode.`);
173061
+ }
173062
+ if (declaredFast !== void 0 || targetModelId !== probedModelId) {
173063
+ validatedIds.add(id2);
173064
+ }
172809
173065
  }
172810
173066
  }
172811
173067
  return validatedIds;
172812
173068
  }
173069
+ function isTurnEffortEntry(optionsById, id2) {
173070
+ return isAcpThoughtLevelConfigOption(optionsById.get(id2) ?? { id: id2 }) || id2 === "effort";
173071
+ }
172813
173072
  function filterCompatibleTurnConfigOptionValues(values, capability, targetModelId) {
172814
173073
  if (!values || !capability) {
172815
173074
  return void 0;
@@ -172817,24 +173076,24 @@ function filterCompatibleTurnConfigOptionValues(values, capability, targetModelI
172817
173076
  const optionsById = new Map(
172818
173077
  (capability.configOptions ?? []).map((option2) => [option2.id, option2])
172819
173078
  );
172820
- const probedModelId = capability.configOptions?.find(
172821
- (option2) => option2.category === "model"
172822
- )?.currentValue;
173079
+ const probedModelId = findTurnConfigOptionByCategory(capability, "model")?.currentValue;
173080
+ const efforts = getModelEffortChoices(capability, targetModelId);
173081
+ const declared = getDeclaredModelControls(capability, targetModelId);
173082
+ const keepUnverified = targetModelId !== probedModelId || declared !== void 0;
172823
173083
  const compatible = Object.fromEntries(
172824
173084
  Object.entries(values).filter(([id2, value]) => {
172825
- const option2 = optionsById.get(id2);
172826
173085
  if (targetModelId) {
172827
- const isEffort = isAcpThoughtLevelConfigOption(option2 ?? { id: id2 }) || id2 === "effort";
172828
- if (isEffort) {
172829
- const efforts = capability.modelReasoningEfforts?.[targetModelId];
173086
+ if (isTurnEffortEntry(optionsById, id2)) {
172830
173087
  if (efforts !== void 0) return typeof value === "string" && efforts.includes(value);
172831
- }
172832
- if (targetModelId !== probedModelId) {
172833
- if (isEffort) return typeof value === "string";
172834
- if (isAcpFastModeConfigId(id2))
172835
- return typeof value === "boolean" || value === "on" || value === "off";
173088
+ if (keepUnverified) return typeof value === "string";
173089
+ } else if (isAcpFastModeConfigId(id2)) {
173090
+ if (declared?.fastMode === false) return false;
173091
+ if (keepUnverified) {
173092
+ return typeof value === "boolean" || value === ACP_CONFIG_OPTION_ON_VALUE || value === ACP_CONFIG_OPTION_OFF_VALUE;
173093
+ }
172836
173094
  }
172837
173095
  }
173096
+ const option2 = optionsById.get(id2);
172838
173097
  return option2 !== void 0 && validateConfigOptionValue(option2, value) === void 0;
172839
173098
  })
172840
173099
  );
@@ -172895,7 +173154,9 @@ async function readAgentAcpCapability(args2) {
172895
173154
  getMachineFlockDocId(args2.workspaceId, args2.machineId)
172896
173155
  );
172897
173156
  const capabilities = getMachineFlockAcpCapabilities(
172898
- readMachineFlockRowsFromFlock(handle.flock, { families: ["acpCapability"] })
173157
+ readMachineFlockRowsFromFlock(handle.flock, {
173158
+ families: ACP_CAPABILITY_ROW_FAMILIES
173159
+ })
172899
173160
  );
172900
173161
  return capabilities[getAcpCapabilityCacheKey(args2.agentConfigId)];
172901
173162
  }
@@ -173136,6 +173397,12 @@ async function withMachineRpcClient(args2, fn) {
173136
173397
  }
173137
173398
  }
173138
173399
  async function ensureTargetMachineOnline(args2) {
173400
+ const environment2 = getSessionCommandEnvironment();
173401
+ if (environment2) {
173402
+ if (args2.workspaceId !== environment2.workspace.id || args2.machineId !== environment2.auth.machineId)
173403
+ throw new Error("Target machine is unavailable in this workspace");
173404
+ return;
173405
+ }
173139
173406
  if (args2.machineId === args2.auth.machineId) {
173140
173407
  await ensureLocalRuntimeAvailable(args2.machineId, args2.workspaceId);
173141
173408
  return;
@@ -173176,16 +173443,48 @@ async function readSessionMachineAccess(args2) {
173176
173443
  ...args2.localProjectId ? { localProjectId: args2.localProjectId } : {}
173177
173444
  });
173178
173445
  }
173446
+ const defaultMachineAccessReaders = {
173447
+ delegated: canDelegateMachineUseForCliToken,
173448
+ asTokenUser: canRequestMachineForCliToken,
173449
+ asServedRequester: canUseMachineForCliToken
173450
+ };
173451
+ async function readDelegatedMachineAccess(input2, readers = defaultMachineAccessReaders) {
173452
+ const target = {
173453
+ token: input2.token,
173454
+ workspaceId: input2.workspaceId,
173455
+ machineId: input2.machineId,
173456
+ ...input2.localProjectId ? { localProjectId: input2.localProjectId } : {}
173457
+ };
173458
+ const verdict = await readers.delegated({ ...target, requesterUserId: input2.requesterUserId });
173459
+ if (verdict) {
173460
+ return verdict;
173461
+ }
173462
+ const owner = await readers.asTokenUser({ ...target, requesterUserId: input2.tokenUserId });
173463
+ if (!owner.allowed || input2.requesterUserId === input2.tokenUserId) {
173464
+ return owner;
173465
+ }
173466
+ return await readers.asServedRequester({ ...target, requesterUserId: input2.requesterUserId });
173467
+ }
173179
173468
  async function readResolvedSessionMachineAccess(args2) {
173180
- const readAccess = args2.requester.isDelegated ? canUseMachineForCliToken : canRequestMachineForCliToken;
173181
- return await readMachineAccessWithBoundedRetry({
173182
- verify: async () => await readAccess({
173183
- token: args2.auth.token,
173469
+ const environment2 = getSessionCommandEnvironment();
173470
+ if (environment2) {
173471
+ if (args2.auth !== environment2.auth) throw new Error("Session command identity mismatch");
173472
+ return environment2.checkMachineAccess({
173184
173473
  workspaceId: args2.workspaceId,
173185
173474
  machineId: args2.machineId,
173186
173475
  requesterUserId: args2.requester.userId,
173187
- ...args2.localProjectId ? { localProjectId: args2.localProjectId } : {}
173188
- }),
173476
+ localProjectId: args2.localProjectId
173477
+ });
173478
+ }
173479
+ const target = {
173480
+ token: args2.auth.token,
173481
+ workspaceId: args2.workspaceId,
173482
+ machineId: args2.machineId,
173483
+ requesterUserId: args2.requester.userId,
173484
+ ...args2.localProjectId ? { localProjectId: args2.localProjectId } : {}
173485
+ };
173486
+ return await readMachineAccessWithBoundedRetry({
173487
+ verify: async () => args2.requester.isDelegated ? await readDelegatedMachineAccess({ ...target, tokenUserId: args2.auth.userId }) : await canRequestMachineForCliToken(target),
173189
173488
  onRetry: ({ attempt, maxAttempts, delayMs, error: error2 }) => {
173190
173489
  getLogger("session").warn(
173191
173490
  `Machine access verification unavailable; retrying (attempt=${attempt}/${maxAttempts} delayMs=${delayMs}): ${error2}`
@@ -173200,6 +173499,11 @@ async function assertMachineAccess(args2) {
173200
173499
  }
173201
173500
  }
173202
173501
  async function dispatchTurnFastPath(args2) {
173502
+ const environment2 = getSessionCommandEnvironment();
173503
+ if (environment2) {
173504
+ await environment2.host.dispatchSession(args2.sessionId);
173505
+ return;
173506
+ }
173203
173507
  if (!args2.inputConfig) {
173204
173508
  return;
173205
173509
  }
@@ -173430,6 +173734,8 @@ async function resolveAgentConfigForCreate(args2) {
173430
173734
  );
173431
173735
  }
173432
173736
  async function assertGitHubRepoAccess(args2) {
173737
+ if (getSessionCommandEnvironment())
173738
+ throw new Error("Hosted repository contexts are unavailable; use a registered local project.");
173433
173739
  const repos = await listWorkspaceGitHubRepositoriesForCliToken({
173434
173740
  token: args2.auth.token,
173435
173741
  workspaceId: args2.workspaceId,
@@ -174175,6 +174481,22 @@ async function readSessionLiveStatus(args2) {
174175
174481
  }
174176
174482
  }
174177
174483
  async function readSessionLiveStatusesMany(args2) {
174484
+ const environment2 = getSessionCommandEnvironment();
174485
+ if (environment2) {
174486
+ const output2 = /* @__PURE__ */ new Map();
174487
+ for (const session2 of args2.sessions) {
174488
+ output2.set(
174489
+ session2.id,
174490
+ session2.machineId === environment2.auth.machineId ? await environment2.host.readLiveStatus(session2.id) : {
174491
+ sessionId: session2.id,
174492
+ machineOnline: false,
174493
+ fresh: false,
174494
+ reason: "Machine unavailable in local workspace"
174495
+ }
174496
+ );
174497
+ }
174498
+ return output2;
174499
+ }
174178
174500
  const groups = /* @__PURE__ */ new Map();
174179
174501
  for (const session2 of args2.sessions) {
174180
174502
  const group = groups.get(session2.machineId) ?? [];
@@ -175019,6 +175341,7 @@ const session = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePrope
175019
175341
  normalizeLocalProjectPathSelector,
175020
175342
  prepareSessionInput,
175021
175343
  readAgentAcpCapability,
175344
+ readDelegatedMachineAccess,
175022
175345
  readLocalProjectGitStateOnMachine,
175023
175346
  readSessionLiveStatusesMany,
175024
175347
  readSessionMachineAccess,
@@ -185761,7 +186084,14 @@ class MessageHandler {
185761
186084
  dispatchWatcher: this.sessionDispatchWatcher,
185762
186085
  userResolver: this.sessionUserResolver,
185763
186086
  logger: this.logger,
185764
- materializeTarget: async (operation, item, index) => await this.materializeOperationTarget(operation, item, index)
186087
+ ...this.cloudPort.kind === "local" ? {
186088
+ confirmTargetReadable: async () => {
186089
+ await this.workspaceDocument.repo.flush();
186090
+ }
186091
+ } : {},
186092
+ materializeTarget: async (operation, item, index) => await this.withSessionCommandEnvironment(
186093
+ () => this.materializeOperationTarget(operation, item, index)
186094
+ )
185765
186095
  });
185766
186096
  this.setupSessionEventHandlers();
185767
186097
  this.setupSessionLifecycleWatchers();
@@ -187348,7 +187678,7 @@ class MessageHandler {
187348
187678
  if (!prompt2) {
187349
187679
  throw new Error(`Operation ${operation.operationId} item ${index} has no prompt.`);
187350
187680
  }
187351
- const auth = {
187681
+ const auth = getSessionCommandEnvironment()?.auth ?? {
187352
187682
  token: this.token,
187353
187683
  userId: this.userId,
187354
187684
  userName: this.userId,
@@ -189681,6 +190011,61 @@ class MessageHandler {
189681
190011
  const ownerUserId = args2.ownerMeta?.userId?.trim();
189682
190012
  return requester === ownerUserId || requester === this.userId;
189683
190013
  }
190014
+ withSessionCommandEnvironment(run2) {
190015
+ if (this.cloudPort.kind !== "local") return run2();
190016
+ return runWithSessionCommandEnvironment(
190017
+ createLocalSessionCommandEnvironment({
190018
+ manager: this.workspaceDocument,
190019
+ workspaceId: this.workspaceId,
190020
+ machineId: this.machineId,
190021
+ machineName: this.machineName,
190022
+ userId: this.userId,
190023
+ host: {
190024
+ readInvocation: (sessionId) => {
190025
+ const invocation = this.executionService.getActiveInvocationContext(sessionId);
190026
+ return invocation ? {
190027
+ type: "session/active-invocation-context",
190028
+ sessionId,
190029
+ active: true,
190030
+ ...invocation
190031
+ } : { type: "session/active-invocation-context", sessionId, active: false };
190032
+ },
190033
+ readLiveStatus: async (sessionId) => {
190034
+ const live = resolveSessionLiveStatus({
190035
+ presence: this.sessionActivePresence.getStatus(sessionId),
190036
+ execution: this.executionService.getExecutionSnapshot(sessionId),
190037
+ hasPendingDispatch: this.sessionDispatchWatcher.hasPendingDispatch(sessionId)
190038
+ });
190039
+ return {
190040
+ sessionId,
190041
+ machineOnline: true,
190042
+ fresh: true,
190043
+ state: live.state,
190044
+ observedAt: getServerNow()
190045
+ };
190046
+ },
190047
+ cancelSession: async (sessionId, turnId) => {
190048
+ const targetTurnId = turnId ?? this.executionService.getExecutionSnapshot(sessionId).activeTurnId;
190049
+ if (!targetTurnId) return { success: false, error: "Session has no active turn" };
190050
+ return this.executionService.cancelSession(
190051
+ {
190052
+ type: "session/cancel",
190053
+ machineId: this.machineId,
190054
+ workspaceId: this.workspaceId,
190055
+ sessionId,
190056
+ turnId: targetTurnId
190057
+ },
190058
+ { pendingInput: "promote", prePromptSession: "discard" }
190059
+ );
190060
+ },
190061
+ dispatchSession: async (sessionId) => {
190062
+ void this.sessionDispatchWatcher.enqueueSessionCheck(sessionId);
190063
+ }
190064
+ }
190065
+ }),
190066
+ run2
190067
+ );
190068
+ }
189684
190069
  async handleLocalMachineRpc(request2) {
189685
190070
  try {
189686
190071
  const result = await this.dispatchLocalMachineRpc(request2);
@@ -189707,6 +190092,27 @@ class MessageHandler {
189707
190092
  }
189708
190093
  };
189709
190094
  switch (request2.method) {
190095
+ case "session/call-tool": {
190096
+ if (this.cloudPort.kind !== "local")
190097
+ throw new Error("Daemon Session tools require a local workspace");
190098
+ const { sessionId, name: name2, arguments: args2 } = request2.params;
190099
+ if (request2.workspaceId !== this.workspaceId || request2.machineId !== this.machineId || request2.ownerSessionId !== sessionId)
190100
+ throw new Error("Session tool scope mismatch");
190101
+ const { executeDaemonSessionTool } = await import("./chunks/daemon-session-tools-DESvdAeY.js");
190102
+ return this.withSessionCommandEnvironment(
190103
+ () => executeDaemonSessionTool(
190104
+ {
190105
+ machineId: this.machineId,
190106
+ workspaceId: this.workspaceId,
190107
+ sessionId,
190108
+ localControlSocketPath: void 0,
190109
+ workdir: process.cwd()
190110
+ },
190111
+ name2,
190112
+ args2
190113
+ )
190114
+ );
190115
+ }
189710
190116
  case "code-collab/get-file-index":
189711
190117
  await assertOwner(request2.params.sessionId);
189712
190118
  return await this.codeCollabV2Service.getFileIndex(request2.params);
@@ -194594,7 +195000,9 @@ const createGitCredentialBrokerHandler = (options) => {
194594
195000
  if (!isContextCurrent()) return;
194595
195001
  res.writeHead(200, { "Content-Type": "application/json" });
194596
195002
  res.end(
194597
- JSON.stringify(candidate ? { ...candidate, available: true } : { available: false })
195003
+ JSON.stringify(
195004
+ candidate && "token" in candidate ? { ...candidate, available: true } : { available: false, ...candidate?.reason ? { reason: candidate.reason } : {} }
195005
+ )
194598
195006
  );
194599
195007
  return;
194600
195008
  }
@@ -194750,6 +195158,11 @@ class GitCredentialBroker {
194750
195158
  this.startHealthCheck();
194751
195159
  return this.env;
194752
195160
  }
195161
+ /** Rotate only sessions that opted into managed credentials during preparation. */
195162
+ refreshSessionContext(context2) {
195163
+ if (!this.sessionContextTokens.has(context2.sessionId)) return void 0;
195164
+ return this.activateSessionContext(context2);
195165
+ }
194753
195166
  activateSessionContext(context2) {
194754
195167
  const existingToken = this.sessionContextTokens.get(context2.sessionId);
194755
195168
  if (existingToken) {
@@ -196279,12 +196692,15 @@ class Session extends EventEmitter {
196279
196692
  const configEnv = this.config.env ?? {};
196280
196693
  if (this.config.githubCredentialPolicy) {
196281
196694
  this.config.githubCredentialPolicy.allowLocalAuth = options.preferMachineIdentity;
196695
+ if (options.personalIdentityEnabled !== void 0) {
196696
+ this.config.githubCredentialPolicy.personalEnabled = options.personalIdentityEnabled;
196697
+ }
196282
196698
  }
196283
196699
  const { name: name2, email: email2 } = resolveSessionGitIdentity(
196284
196700
  { name: userName, email: userEmail },
196285
196701
  {
196286
196702
  preferMachineIdentity: options.preferMachineIdentity,
196287
- cwd: this.getWorkdir()
196703
+ personalIdentityEnabled: options.personalIdentityEnabled ?? this.config.githubCredentialPolicy?.personalEnabled ?? false
196288
196704
  }
196289
196705
  );
196290
196706
  configEnv.GIT_AUTHOR_NAME = name2;
@@ -197988,9 +198404,12 @@ class SessionManager extends EventEmitter {
197988
198404
  "session.createSessionInner.prepared",
197989
198405
  sessionId
197990
198406
  );
197991
- session2.updateGitIdentity(config2.userName, config2.userEmail, config2.requesterUserId, {
197992
- preferMachineIdentity: config2.requesterUserId === this.cloudPort.identity.userId
197993
- });
198407
+ session2.updateGitIdentity(
198408
+ config2.userName,
198409
+ config2.userEmail,
198410
+ config2.requesterUserId,
198411
+ await this.resolveGitIdentityOptions(config2.requesterUserId)
198412
+ );
197994
198413
  const acpSessionId = await prepared.agentResult;
197995
198414
  const sessionDoc = await this.workspaceDocument.getOrCreateSessionDoc(sessionId);
197996
198415
  await sessionDoc.setACPSessionId(acpSessionId);
@@ -198107,9 +198526,12 @@ class SessionManager extends EventEmitter {
198107
198526
  );
198108
198527
  const sessionId = config2.sessionId;
198109
198528
  this.logger.debug(`[${sessionId}] Session workdir resolved: ${session2.getWorkdir()}`);
198110
- session2.updateGitIdentity(config2.userName, config2.userEmail, config2.requesterUserId, {
198111
- preferMachineIdentity: config2.requesterUserId === this.cloudPort.identity.userId
198112
- });
198529
+ session2.updateGitIdentity(
198530
+ config2.userName,
198531
+ config2.userEmail,
198532
+ config2.requesterUserId,
198533
+ await this.resolveGitIdentityOptions(config2.requesterUserId)
198534
+ );
198113
198535
  let acpSessionId;
198114
198536
  const launchResolutionStartedAt = performance.now();
198115
198537
  let managedRuntimeReadyLogged = false;
@@ -198261,7 +198683,31 @@ class SessionManager extends EventEmitter {
198261
198683
  runtimeOverrides: config2.runtimeOverrides
198262
198684
  });
198263
198685
  }
198686
+ /**
198687
+ * Commit identity follows the same precedence as GitHub credentials: a
198688
+ * requester who enabled "Act as you" commits as themselves; otherwise the
198689
+ * machine owner may use the machine's global Git identity. Policy lookup
198690
+ * failures degrade to "not enabled" rather than blocking the turn.
198691
+ */
198692
+ async resolveGitIdentityOptions(requesterUserId) {
198693
+ const preferMachineIdentity = requesterUserId === this.cloudPort.identity.userId;
198694
+ const tokenManager = this.getGitHubTokenManager();
198695
+ if (!tokenManager) return { preferMachineIdentity, personalIdentityEnabled: false };
198696
+ try {
198697
+ const policy = await tokenManager.getCredentialPolicy({
198698
+ requesterUserId,
198699
+ machineId: this.machineId
198700
+ });
198701
+ return { preferMachineIdentity, personalIdentityEnabled: policy.personalEnabled };
198702
+ } catch (error2) {
198703
+ this.logger.warn(
198704
+ `Could not read the GitHub identity preference for ${requesterUserId}; committing without personal identity: ${formatErrorMessage(error2)}`
198705
+ );
198706
+ return { preferMachineIdentity, personalIdentityEnabled: false };
198707
+ }
198708
+ }
198264
198709
  async prepareGitHubRepoSessionConfig(config2) {
198710
+ if (config2.project?.kind === "local") return;
198265
198711
  const githubRepo = config2.githubRepo ?? tryDeriveGitHubRepoFromUrl(config2.githubRepoUrl);
198266
198712
  if (githubRepo) {
198267
198713
  config2.githubRepo = githubRepo;
@@ -198340,7 +198786,7 @@ class SessionManager extends EventEmitter {
198340
198786
  };
198341
198787
  }
198342
198788
  async refreshGhTokenForSession(session2, _githubRepo, requesterUserId) {
198343
- const contextToken = this.gitCredentialBroker?.activateSessionContext({
198789
+ const contextToken = this.gitCredentialBroker?.refreshSessionContext({
198344
198790
  sessionId: session2.sessionId,
198345
198791
  requesterUserId,
198346
198792
  machineId: this.machineId
@@ -232934,7 +233380,7 @@ function mergeRateLimits(legacyRateLimits, flockRateLimits) {
232934
233380
  async function mergeMachineFlockJsonState(repo, workspaceId, machine, includeAcpCapabilities) {
232935
233381
  const handle = await repo.openFlockDoc(getMachineFlockDocId(workspaceId, machine.id));
232936
233382
  const rows = readMachineFlockRowsFromFlock(handle.flock, {
232937
- families: includeAcpCapabilities ? ["acpCapability", "rateLimit"] : ["rateLimit"]
233383
+ families: includeAcpCapabilities ? [...ACP_CAPABILITY_ROW_FAMILIES, "rateLimit"] : ["rateLimit"]
232938
233384
  });
232939
233385
  const acpCapabilities = includeAcpCapabilities ? getMachineFlockAcpCapabilities(rows) : {};
232940
233386
  const rateLimits = getMachineFlockRateLimits(rows);
@@ -233902,7 +234348,7 @@ async function runRender(file2, options) {
233902
234348
  data = createReviewBundleSnapshot(bundle);
233903
234349
  }
233904
234350
  const { injectReviewSnapshot } = await import("./chunks/index-BeRTvYK1.js");
233905
- const { resolveReviewViewerTemplate } = await import("./chunks/review-viewer-CEUQAboP.js");
234351
+ const { resolveReviewViewerTemplate } = await import("./chunks/review-viewer-BZiXmQnJ.js");
233906
234352
  const template = await resolveReviewViewerTemplate();
233907
234353
  const html = injectReviewSnapshot(template, data);
233908
234354
  const outputPath = options.output ? path__default.resolve(options.output) : defaultHtmlOutputPath(inputPath);
@@ -252338,7 +252784,7 @@ async function configureWorkspaceMcpServer(manager, workspaceId, userId, rawInpu
252338
252784
  };
252339
252785
  });
252340
252786
  }
252341
- function registerDiscoveryTools(server, withDiscovery) {
252787
+ function registerDiscoveryTools(registerTool, withDiscovery) {
252342
252788
  const descriptions = {
252343
252789
  machine: "List readable machines, including offline machines, with online/offline/unknown presence and protocol capabilities.",
252344
252790
  project: "List readable local projects across machines and enabled GitHub repositories. kind and machineId restrict the catalog. Local project identity includes machineId.",
@@ -252364,7 +252810,7 @@ function registerDiscoveryTools(server, withDiscovery) {
252364
252810
  }
252365
252811
  };
252366
252812
  for (const resource of Object.keys(ResourceListSchemas)) {
252367
- server.registerTool(
252813
+ registerTool(
252368
252814
  `lody_${resource}_list`,
252369
252815
  {
252370
252816
  description: `${descriptions[resource]} Returns a bounded page (default 20, maximum 100); follow nextCursor with the same filters to enumerate all entries.`,
@@ -252375,7 +252821,7 @@ function registerDiscoveryTools(server, withDiscovery) {
252375
252821
  );
252376
252822
  }
252377
252823
  for (const resource of ["agent_config", "agent_role"]) {
252378
- server.registerTool(
252824
+ registerTool(
252379
252825
  `lody_${resource}_get`,
252380
252826
  {
252381
252827
  description: `Read one ${resource} by stable id from its list tool.`,
@@ -252386,6 +252832,20 @@ function registerDiscoveryTools(server, withDiscovery) {
252386
252832
  );
252387
252833
  }
252388
252834
  }
252835
+ function createSessionToolRegistrar(server, route2, handlers) {
252836
+ return (name2, config2, callback) => {
252837
+ handlers?.set(name2, async (args2) => callback(await config2.inputSchema.parseAsync(args2)));
252838
+ const inputSchema = config2.inputSchema;
252839
+ return server.registerTool(
252840
+ name2,
252841
+ { ...config2, inputSchema },
252842
+ async (args2) => (
252843
+ // The SDK has already parsed MCP input; only direct daemon calls need parsing here.
252844
+ route2(name2, args2, () => callback(args2))
252845
+ )
252846
+ );
252847
+ };
252848
+ }
252389
252849
  const PREVIEW_TOOL_NAME = "lody_report_preview_candidate";
252390
252850
  const IMAGE_UPLOAD_TOOL_NAME = "lody_upload_images";
252391
252851
  const FILE_UPLOAD_TOOL_NAME = "lody_upload_files";
@@ -252850,6 +253310,8 @@ const postSessionControl = async (request2, localControlSocketPath, timeoutMs =
252850
253310
  return responses.map((response2) => LocalSessionControlResponseSchema.parse(response2));
252851
253311
  };
252852
253312
  const readActiveInvocationContext = async (ctx) => {
253313
+ const environment2 = getSessionCommandEnvironment();
253314
+ if (environment2) return environment2.host.readInvocation(ctx.sessionId);
252853
253315
  const response2 = await runPromise(
252854
253316
  makeLocalControlClientAuto({ socketPath: ctx.localControlSocketPath }).machineRpc(
252855
253317
  {
@@ -253035,13 +253497,6 @@ const resolveMcpSessionCreate = (input2, invoking, requester, role) => {
253035
253497
  );
253036
253498
  }
253037
253499
  const project = requester.project;
253038
- if (project?.kind !== "github" && role.machineId !== requester.machineId) {
253039
- throw new LodyOperationStoreError(
253040
- "AGENT_ROLE_MACHINE_MISMATCH",
253041
- project?.kind === "local" ? `Agent Role ${role.name} must run on the Local Project's Machine.` : `Agent Role ${role.name} must run on the current Machine in a chat Session.`,
253042
- false
253043
- );
253044
- }
253045
253500
  let useCurrentSessionAsParent = input2.useCurrentSessionAsParent;
253046
253501
  let workContext = input2.workContext;
253047
253502
  if (project?.kind === "github" && useCurrentSessionAsParent !== true && workContext === void 0) {
@@ -253050,7 +253505,7 @@ const resolveMcpSessionCreate = (input2, invoking, requester, role) => {
253050
253505
  repo: project.repoFullName,
253051
253506
  ...project.branch ? { branch: project.branch } : {}
253052
253507
  };
253053
- } else if (project?.kind === "local" && useCurrentSessionAsParent === void 0 && workContext === void 0) {
253508
+ } else if (project?.kind === "local" && role.machineId === requester.machineId && useCurrentSessionAsParent === void 0 && workContext === void 0) {
253054
253509
  useCurrentSessionAsParent = true;
253055
253510
  }
253056
253511
  const resolvedInput = {
@@ -253684,7 +254139,9 @@ const assertDifferentMcpSession = (source2, target) => {
253684
254139
  const readMachineAcpCapabilities = async (manager, workspaceId, machineId) => {
253685
254140
  const handle = await manager.repo.openFlockDoc(getMachineFlockDocId(workspaceId, machineId));
253686
254141
  return getMachineFlockAcpCapabilities(
253687
- readMachineFlockRowsFromFlock(handle.flock, { families: ["acpCapability"] })
254142
+ readMachineFlockRowsFromFlock(handle.flock, {
254143
+ families: ACP_CAPABILITY_ROW_FAMILIES
254144
+ })
253688
254145
  );
253689
254146
  };
253690
254147
  const buildSessionWorkContext = async (manager, workspaceId, session2) => {
@@ -253851,7 +254308,7 @@ const buildSessionCreateOptions = async (input2) => {
253851
254308
  )
253852
254309
  );
253853
254310
  const repoQuery = normalizeCliValue(input2.repoQuery)?.toLowerCase();
253854
- const repos = repoQuery ? (await listWorkspaceGitHubRepositoriesForCliToken({
254311
+ const repos = repoQuery && !getSessionCommandEnvironment() ? (await listWorkspaceGitHubRepositoriesForCliToken({
253855
254312
  token: auth.token,
253856
254313
  workspaceId,
253857
254314
  requesterUserId,
@@ -254731,6 +255188,9 @@ const ReviewSubmitToolInputSchema = object({
254731
255188
  summary: string$1().trim().max(2e3).optional()
254732
255189
  }).strict();
254733
255190
  function buildLodyMcpServer() {
255191
+ return buildSessionToolServer();
255192
+ }
255193
+ function buildSessionToolServer(handlers) {
254734
255194
  initCliAnalytics();
254735
255195
  const server = new McpServer(
254736
255196
  {
@@ -254755,10 +255215,41 @@ function buildLodyMcpServer() {
254755
255215
  });
254756
255216
  }
254757
255217
  });
254758
- registerDiscoveryTools(server, async (read) => {
254759
- if (getCliPlatformKind() === "local") {
254760
- throw new Error("Workspace catalog discovery is unavailable on the local platform.");
254761
- }
255218
+ const registerSessionTool = createSessionToolRegistrar(
255219
+ server,
255220
+ async (name2, args2, execute) => {
255221
+ if (getCliPlatformKind() !== "local" || getSessionCommandEnvironment()) return execute();
255222
+ try {
255223
+ const ctx = getSessionContext();
255224
+ const outcome = await runPromise(
255225
+ makeLocalControlClientAuto({ socketPath: ctx.localControlSocketPath }).machineRpc(
255226
+ {
255227
+ method: "session/call-tool",
255228
+ machineId: ctx.machineId,
255229
+ workspaceId: ctx.workspaceId,
255230
+ ownerSessionId: ctx.sessionId,
255231
+ params: {
255232
+ sessionId: ctx.sessionId,
255233
+ name: name2,
255234
+ arguments: record$3(string$1(), json$1()).parse(args2)
255235
+ }
255236
+ },
255237
+ { timeoutMs: SESSION_CONTROL_TIMEOUT_MS }
255238
+ ).pipe(either)
255239
+ );
255240
+ if (outcome._tag === "Left") throw classifyLocalDaemonIpcError(outcome.left);
255241
+ const response2 = outcome.right;
255242
+ if (!response2.ok) throw new Error(response2.error);
255243
+ if (!("type" in response2.result) || response2.result.type !== "session/tool-result")
255244
+ throw new Error("Unexpected Session tool response");
255245
+ return { content: response2.result.content, isError: response2.result.isError };
255246
+ } catch (error2) {
255247
+ return mcpErrorResult(error2);
255248
+ }
255249
+ },
255250
+ handlers
255251
+ );
255252
+ registerDiscoveryTools(registerSessionTool, async (read) => {
254762
255253
  const ctx = getSessionContext();
254763
255254
  const source2 = await resolveInvokingTurnSource();
254764
255255
  const auth = getAuthContextOrThrow$1("mcp");
@@ -254772,7 +255263,6 @@ function buildLodyMcpServer() {
254772
255263
  manager,
254773
255264
  auth,
254774
255265
  workspaceId: workspace.id,
254775
- requesterSessionId: ctx.sessionId,
254776
255266
  delegatedRequester: { userId: source2.userId },
254777
255267
  selectedMcpServerIds: source2.inputConfig.mcpServerIds
254778
255268
  })
@@ -255014,7 +255504,7 @@ ${lines2.join("\n")}` : ""}${suffix}`
255014
255504
  }
255015
255505
  }
255016
255506
  );
255017
- server.registerTool(
255507
+ registerSessionTool(
255018
255508
  SESSION_CREATE_OPTIONS_TOOL_NAME,
255019
255509
  {
255020
255510
  title: "List session create options",
@@ -255029,11 +255519,11 @@ ${lines2.join("\n")}` : ""}${suffix}`
255029
255519
  }
255030
255520
  }
255031
255521
  );
255032
- server.registerTool(
255522
+ registerSessionTool(
255033
255523
  SESSION_CREATE_TOOL_NAME,
255034
255524
  {
255035
255525
  title: "Create a Lody session",
255036
- description: "Start durable asynchronous work that creates a Lody session. Supply operationId; the result arrives automatically as a continuation, so do not poll operation_get. To use an Agent Role, pass agentRoleId; the current workspace catalog row supplies the exact Machine, Agent config, model, reasoning, and permission mode. If manual machine or run-config fields are also present, the Role takes precedence and those fields are ignored. To recover an already accepted create without resending its prompt, send only operationId with resume=true. useCurrentSessionAsParent=true and workContext are mutually exclusive schema branches. Machine/config ids and runConfig values for non-Role creates come from lody_session_create_options. The wait field is temporary legacy compatibility only.",
255526
+ description: "Start durable asynchronous work that creates a Lody session. Supply operationId; the result arrives automatically as a continuation, so do not poll operation_get. To use an Agent Role, pass agentRoleId; the current workspace catalog row supplies the exact Machine, Agent config, model, reasoning, and permission mode. If manual machine or run-config fields are also present, the Role takes precedence and those fields are ignored. A Role may run on any Machine the owner of this Machine can use; to work in a project there, pass workContext for a local project on that Machine (find it with lody_session_create_options machineId + localProjectQuery). Without workContext a Role on another Machine starts as a plain chat there. To recover an already accepted create without resending its prompt, send only operationId with resume=true. useCurrentSessionAsParent=true and workContext are mutually exclusive schema branches. Machine/config ids and runConfig values for non-Role creates come from lody_session_create_options. The wait field is temporary legacy compatibility only.",
255037
255527
  inputSchema: SessionCreateToolInputSchema
255038
255528
  },
255039
255529
  async (input2) => {
@@ -255117,7 +255607,7 @@ ${lines2.join("\n")}` : ""}${suffix}`
255117
255607
  }
255118
255608
  }
255119
255609
  );
255120
- server.registerTool(
255610
+ registerSessionTool(
255121
255611
  SESSION_CHAT_TOOL_NAME,
255122
255612
  {
255123
255613
  title: "Send a prompt to a Lody session",
@@ -255180,7 +255670,7 @@ ${lines2.join("\n")}` : ""}${suffix}`
255180
255670
  }
255181
255671
  }
255182
255672
  );
255183
- server.registerTool(
255673
+ registerSessionTool(
255184
255674
  SESSION_CREATE_MANY_TOOL_NAME,
255185
255675
  {
255186
255676
  title: "Create multiple Lody sessions",
@@ -255196,7 +255686,7 @@ ${lines2.join("\n")}` : ""}${suffix}`
255196
255686
  }
255197
255687
  }
255198
255688
  );
255199
- server.registerTool(
255689
+ registerSessionTool(
255200
255690
  SESSION_CHAT_MANY_TOOL_NAME,
255201
255691
  {
255202
255692
  title: "Chat multiple Lody sessions",
@@ -255211,7 +255701,7 @@ ${lines2.join("\n")}` : ""}${suffix}`
255211
255701
  }
255212
255702
  }
255213
255703
  );
255214
- server.registerTool(
255704
+ registerSessionTool(
255215
255705
  SESSION_CANCEL_TOOL_NAME,
255216
255706
  {
255217
255707
  title: "Cancel a Lody session turn",
@@ -255223,6 +255713,14 @@ ${lines2.join("\n")}` : ""}${suffix}`
255223
255713
  const ctx = getSessionContext();
255224
255714
  const auth = getAuthContextOrThrow$1("mcp");
255225
255715
  await resolveWorkspaceOrThrow$1(auth, getMcpWorkspaceId(ctx));
255716
+ const environment2 = getSessionCommandEnvironment();
255717
+ if (environment2) {
255718
+ const sessionId = resolveMcpSessionId(args2.sessionId, ctx);
255719
+ const session2 = await readCurrentSessionMeta(environment2.manager, sessionId);
255720
+ if (!session2 || session2.machineId !== auth.machineId)
255721
+ throw new Error("Session not found on this machine");
255722
+ return jsonTextResult(await environment2.host.cancelSession(sessionId));
255723
+ }
255226
255724
  return jsonTextResult(
255227
255725
  await runLodyCliJson([
255228
255726
  "session",
@@ -255238,7 +255736,7 @@ ${lines2.join("\n")}` : ""}${suffix}`
255238
255736
  }
255239
255737
  }
255240
255738
  );
255241
- server.registerTool(
255739
+ registerSessionTool(
255242
255740
  "lody_operation_list",
255243
255741
  {
255244
255742
  description: "List durable Operation summaries owned by the current Session and invoking user. Optional state filter and keyset pagination. Completion is automatic; do not poll.",
@@ -255266,7 +255764,7 @@ ${lines2.join("\n")}` : ""}${suffix}`
255266
255764
  }
255267
255765
  }
255268
255766
  );
255269
- server.registerTool(
255767
+ registerSessionTool(
255270
255768
  OPERATION_GET_TOOL_NAME,
255271
255769
  {
255272
255770
  title: "Get a Lody Operation snapshot",
@@ -255284,7 +255782,7 @@ ${lines2.join("\n")}` : ""}${suffix}`
255284
255782
  }
255285
255783
  }
255286
255784
  );
255287
- server.registerTool(
255785
+ registerSessionTool(
255288
255786
  OPERATION_CANCEL_TOOL_NAME,
255289
255787
  {
255290
255788
  title: "Cancel a Lody Operation",
@@ -255302,12 +255800,13 @@ ${lines2.join("\n")}` : ""}${suffix}`
255302
255800
  (store) => store.cancel(requesterSessionId, args2.operationId)
255303
255801
  );
255304
255802
  if (cancellation.didCancel && before.state === "active") {
255803
+ const environment2 = getSessionCommandEnvironment();
255305
255804
  const startedTargets = before.items.filter(
255306
255805
  (item) => item.status === "active" && item.inputDurable
255307
255806
  );
255308
255807
  await Promise.allSettled(
255309
255808
  startedTargets.map(
255310
- (item) => item.status === "active" ? runLodyCliJson(buildOperationTargetCancelArgs(getMcpWorkspaceId(ctx), item)) : Promise.resolve()
255809
+ (item) => item.status === "active" ? environment2 ? environment2.host.cancelSession(item.target.sessionId, item.target.userTurnId) : runLodyCliJson(buildOperationTargetCancelArgs(getMcpWorkspaceId(ctx), item)) : Promise.resolve()
255311
255810
  )
255312
255811
  );
255313
255812
  }
@@ -255319,7 +255818,7 @@ ${lines2.join("\n")}` : ""}${suffix}`
255319
255818
  }
255320
255819
  }
255321
255820
  );
255322
- server.registerTool(
255821
+ registerSessionTool(
255323
255822
  SESSION_RENAME_TOOL_NAME,
255324
255823
  {
255325
255824
  title: "Rename a Lody session",
@@ -255340,7 +255839,7 @@ ${lines2.join("\n")}` : ""}${suffix}`
255340
255839
  }
255341
255840
  }
255342
255841
  );
255343
- server.registerTool(
255842
+ registerSessionTool(
255344
255843
  SESSION_RENAME_MANY_TOOL_NAME,
255345
255844
  {
255346
255845
  title: "Rename multiple Lody sessions",
@@ -255386,7 +255885,7 @@ ${lines2.join("\n")}` : ""}${suffix}`
255386
255885
  }
255387
255886
  }
255388
255887
  );
255389
- server.registerTool(
255888
+ registerSessionTool(
255390
255889
  SESSION_LIST_TOOL_NAME,
255391
255890
  {
255392
255891
  title: "List Lody sessions",
@@ -255401,7 +255900,7 @@ ${lines2.join("\n")}` : ""}${suffix}`
255401
255900
  }
255402
255901
  }
255403
255902
  );
255404
- server.registerTool(
255903
+ registerSessionTool(
255405
255904
  SESSION_STATUS_MANY_TOOL_NAME,
255406
255905
  {
255407
255906
  title: "Get Lody session statuses",
@@ -255416,7 +255915,7 @@ ${lines2.join("\n")}` : ""}${suffix}`
255416
255915
  }
255417
255916
  }
255418
255917
  );
255419
- server.registerTool(
255918
+ registerSessionTool(
255420
255919
  SESSION_HISTORY_TOOL_NAME,
255421
255920
  {
255422
255921
  title: "Read Lody session history",
@@ -257141,7 +257640,13 @@ void (async () => {
257141
257640
  }
257142
257641
  })();
257143
257642
  export {
257643
+ SessionToolResultSchema as S,
257644
+ getSessionCommandEnvironment as a,
257645
+ getSessionRoomId as b,
257646
+ buildSessionToolServer as c,
257144
257647
  program as default,
257145
- getLodyDataDir as g
257648
+ getLodyDataDir as g,
257649
+ isLoroRepoDocDeleted as i,
257650
+ runWithMcpSessionContext as r
257146
257651
  };
257147
257652
  //# sourceMappingURL=index.js.map