localclawd 2.3.3 → 2.3.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +4 -5
  2. package/dist/cli.mjs +876 -834
  3. package/package.json +1 -1
package/dist/cli.mjs CHANGED
@@ -34087,8 +34087,9 @@ var init_settings2 = __esm(() => {
34087
34087
  });
34088
34088
 
34089
34089
  // src/memdir/paths.ts
34090
+ import { createHash as createHash2 } from "crypto";
34090
34091
  import { existsSync as existsSync3, readFileSync as readFileSync4 } from "fs";
34091
- import { join as join20, normalize as normalize3, sep as sep4 } from "path";
34092
+ import { basename as basename4, isAbsolute as isAbsolute4, join as join20, normalize as normalize3, relative as relative3, sep as sep4 } from "path";
34092
34093
  function isAutoMemoryEnabled() {
34093
34094
  const localclawdEnvVal = process.env.LOCALCLAWD_DISABLE_MEMORY;
34094
34095
  if (isEnvTruthy(localclawdEnvVal))
@@ -34139,9 +34140,37 @@ function hasAutoMemPathOverride() {
34139
34140
  function getAutoMemBase() {
34140
34141
  return findCanonicalGitRoot(getProjectRoot()) ?? getProjectRoot();
34141
34142
  }
34143
+ function hashPath(path4) {
34144
+ return createHash2("sha256").update(path4).digest("hex").slice(0, 12);
34145
+ }
34146
+ function sanitizeDirectorySegment(segment) {
34147
+ const cleaned = segment.normalize("NFC").replace(/[^A-Za-z0-9._-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 80);
34148
+ const value = cleaned || "dir";
34149
+ return /^(con|prn|aux|nul|com[1-9]|lpt[1-9])$/i.test(value) ? `${value}-dir` : value;
34150
+ }
34151
+ function directoryKeyParts(directory = getOriginalCwd()) {
34152
+ const normalizedDirectory = normalize3(directory).normalize("NFC");
34153
+ const base = getAutoMemBase();
34154
+ const relativeToBase = relative3(base, normalizedDirectory);
34155
+ if (!relativeToBase || relativeToBase === ".") {
34156
+ return ["root"];
34157
+ }
34158
+ const outsideBase = relativeToBase.startsWith("..") || isAbsolute4(relativeToBase);
34159
+ if (outsideBase) {
34160
+ const leaf = sanitizeDirectorySegment(basename4(normalizedDirectory) || "directory");
34161
+ return ["external", `${leaf}-${hashPath(normalizedDirectory)}`];
34162
+ }
34163
+ return relativeToBase.split(/[\\/]+/).filter(Boolean).map(sanitizeDirectorySegment);
34164
+ }
34165
+ function getDirectoryMemoryKey(directory = getOriginalCwd()) {
34166
+ return directoryKeyParts(directory).join("/");
34167
+ }
34142
34168
  function getAutoMemEntrypoint() {
34143
34169
  return join20(getAutoMemPath(), AUTO_MEM_ENTRYPOINT_NAME);
34144
34170
  }
34171
+ function getDirectoryMemoryPath(directory = getOriginalCwd()) {
34172
+ return (join20(getAutoMemPath(), DIRECTORY_MEM_DIRNAME, ...directoryKeyParts(directory)) + sep4).normalize("NFC");
34173
+ }
34145
34174
  function isAutoMemPath(absolutePath) {
34146
34175
  const normalizedPath = normalize3(absolutePath);
34147
34176
  if (process.platform === "win32") {
@@ -34149,7 +34178,7 @@ function isAutoMemPath(absolutePath) {
34149
34178
  }
34150
34179
  return normalizedPath.startsWith(getAutoMemPath());
34151
34180
  }
34152
- var AUTO_MEM_DIRNAME = "memory", AUTO_MEM_ENTRYPOINT_NAME = "MEMORY.md", getAutoMemPath;
34181
+ var AUTO_MEM_DIRNAME = "memory", AUTO_MEM_ENTRYPOINT_NAME = "MEMORY.md", DIRECTORY_MEM_DIRNAME = "directories", getAutoMemPath;
34153
34182
  var init_paths = __esm(() => {
34154
34183
  init_memoize();
34155
34184
  init_state();
@@ -35756,7 +35785,7 @@ __export(exports_config, {
35756
35785
  });
35757
35786
  import { randomBytes } from "crypto";
35758
35787
  import { unwatchFile as unwatchFile2, watchFile as watchFile2 } from "fs";
35759
- import { basename as basename4, dirname as dirname11, join as join21, resolve as resolve8 } from "path";
35788
+ import { basename as basename5, dirname as dirname11, join as join21, resolve as resolve8 } from "path";
35760
35789
  function createDefaultGlobalConfig() {
35761
35790
  return {
35762
35791
  numStartups: 0,
@@ -35907,13 +35936,22 @@ function reportConfigCacheStats() {
35907
35936
  configCacheHits = 0;
35908
35937
  configCacheMisses = 0;
35909
35938
  }
35910
- function migrateConfigFields(config) {
35911
- if (config.installMethod !== undefined) {
35939
+ function removeLegacyGlobalProjectSettings(config) {
35940
+ const legacyLocalOnlyFields = config;
35941
+ if (legacyLocalOnlyFields.compactContextWindowTokens === undefined) {
35912
35942
  return config;
35913
35943
  }
35914
- const legacy = config;
35944
+ const { compactContextWindowTokens: _legacy, ...rest } = legacyLocalOnlyFields;
35945
+ return rest;
35946
+ }
35947
+ function migrateConfigFields(config) {
35948
+ const normalizedConfig = removeLegacyGlobalProjectSettings(config);
35949
+ if (normalizedConfig.installMethod !== undefined) {
35950
+ return normalizedConfig;
35951
+ }
35952
+ const legacy = normalizedConfig;
35915
35953
  let installMethod = "unknown";
35916
- let autoUpdates = config.autoUpdates ?? true;
35954
+ let autoUpdates = normalizedConfig.autoUpdates ?? true;
35917
35955
  switch (legacy.autoUpdaterStatus) {
35918
35956
  case "migrated":
35919
35957
  installMethod = "local";
@@ -35933,7 +35971,7 @@ function migrateConfigFields(config) {
35933
35971
  break;
35934
35972
  }
35935
35973
  return {
35936
- ...config,
35974
+ ...normalizedConfig,
35937
35975
  installMethod,
35938
35976
  autoUpdates
35939
35977
  };
@@ -36095,7 +36133,7 @@ function saveConfigWithLock(file, createDefault, mergeFn) {
36095
36133
  }
36096
36134
  const filteredConfig = pickBy_default(mergedConfig, (value, key) => jsonStringify(value) !== jsonStringify(defaultConfig[key]));
36097
36135
  try {
36098
- const fileBase = basename4(file);
36136
+ const fileBase = basename5(file);
36099
36137
  const backupDir = getConfigBackupDir();
36100
36138
  try {
36101
36139
  fs2.mkdirSync(backupDir);
@@ -36160,7 +36198,7 @@ function getConfigBackupDir() {
36160
36198
  }
36161
36199
  function findMostRecentBackup(file) {
36162
36200
  const fs2 = getFsImplementation();
36163
- const fileBase = basename4(file);
36201
+ const fileBase = basename5(file);
36164
36202
  const backupDir = getConfigBackupDir();
36165
36203
  try {
36166
36204
  const backups = fs2.readdirStringSync(backupDir).filter((f) => f.startsWith(`${fileBase}.backup.`)).sort();
@@ -36241,7 +36279,7 @@ Claude configuration file not found at: ${file}
36241
36279
  process.stderr.write(`
36242
36280
  Claude configuration file at ${file} is corrupted: ${error2.message}
36243
36281
  `);
36244
- const fileBase = basename4(file);
36282
+ const fileBase = basename5(file);
36245
36283
  const corruptedBackupDir = getConfigBackupDir();
36246
36284
  try {
36247
36285
  fs2.mkdirSync(corruptedBackupDir);
@@ -36480,8 +36518,6 @@ var init_config = __esm(() => {
36480
36518
  "shiftEnterKeyBindingInstalled",
36481
36519
  "editorMode",
36482
36520
  "hasUsedBackslashReturn",
36483
- "autoCompactEnabled",
36484
- "compactContextWindowTokens",
36485
36521
  "localBackendProvider",
36486
36522
  "localBackendBaseUrl",
36487
36523
  "localBackendModel",
@@ -36517,7 +36553,9 @@ var init_config = __esm(() => {
36517
36553
  PROJECT_CONFIG_KEYS = [
36518
36554
  "allowedTools",
36519
36555
  "hasTrustDialogAccepted",
36520
- "hasCompletedProjectOnboarding"
36556
+ "hasCompletedProjectOnboarding",
36557
+ "compactContextWindowTokens",
36558
+ "autoCompactEnabled"
36521
36559
  ];
36522
36560
  TEST_GLOBAL_CONFIG_FOR_TESTING = {
36523
36561
  ...DEFAULT_GLOBAL_CONFIG,
@@ -69235,12 +69273,12 @@ var require_fromHttp = __commonJS((exports) => {
69235
69273
  var fromHttp = (options = {}) => {
69236
69274
  options.logger?.debug("@aws-sdk/credential-provider-http - fromHttp");
69237
69275
  let host;
69238
- const relative3 = options.awsContainerCredentialsRelativeUri ?? process.env[AWS_CONTAINER_CREDENTIALS_RELATIVE_URI];
69276
+ const relative4 = options.awsContainerCredentialsRelativeUri ?? process.env[AWS_CONTAINER_CREDENTIALS_RELATIVE_URI];
69239
69277
  const full = options.awsContainerCredentialsFullUri ?? process.env[AWS_CONTAINER_CREDENTIALS_FULL_URI];
69240
69278
  const token = options.awsContainerAuthorizationToken ?? process.env[AWS_CONTAINER_AUTHORIZATION_TOKEN];
69241
69279
  const tokenFile = options.awsContainerAuthorizationTokenFile ?? process.env[AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE];
69242
69280
  const warn = options.logger?.constructor?.name === "NoOpLogger" || !options.logger?.warn ? console.warn : options.logger.warn.bind(options.logger);
69243
- if (relative3 && full) {
69281
+ if (relative4 && full) {
69244
69282
  warn("@aws-sdk/credential-provider-http: " + "you have set both awsContainerCredentialsRelativeUri and awsContainerCredentialsFullUri.");
69245
69283
  warn("awsContainerCredentialsFullUri will take precedence.");
69246
69284
  }
@@ -69250,8 +69288,8 @@ var require_fromHttp = __commonJS((exports) => {
69250
69288
  }
69251
69289
  if (full) {
69252
69290
  host = full;
69253
- } else if (relative3) {
69254
- host = `${DEFAULT_LINK_LOCAL_HOST}${relative3}`;
69291
+ } else if (relative4) {
69292
+ host = `${DEFAULT_LINK_LOCAL_HOST}${relative4}`;
69255
69293
  } else {
69256
69294
  throw new property_provider_1.CredentialsProviderError(`No HTTP credential provider host provided.
69257
69295
  Set AWS_CONTAINER_CREDENTIALS_FULL_URI or AWS_CONTAINER_CREDENTIALS_RELATIVE_URI.`, { logger: options.logger });
@@ -88046,12 +88084,12 @@ var init_authFileDescriptor = __esm(() => {
88046
88084
  });
88047
88085
 
88048
88086
  // src/utils/secureStorage/macOsKeychainHelpers.ts
88049
- import { createHash as createHash2 } from "crypto";
88087
+ import { createHash as createHash3 } from "crypto";
88050
88088
  import { userInfo as userInfo2 } from "os";
88051
88089
  function getMacOsKeychainStorageServiceName(serviceSuffix = "") {
88052
88090
  const configDir = getClaudeConfigHomeDir();
88053
88091
  const isDefaultDir = !process.env.CLAUDE_CONFIG_DIR;
88054
- const dirHash = isDefaultDir ? "" : `-${createHash2("sha256").update(configDir).digest("hex").substring(0, 8)}`;
88092
+ const dirHash = isDefaultDir ? "" : `-${createHash3("sha256").update(configDir).digest("hex").substring(0, 8)}`;
88055
88093
  return `localclawd${getOauthConfig().OAUTH_FILE_SUFFIX}${serviceSuffix}${dirHash}`;
88056
88094
  }
88057
88095
  function getUsername() {
@@ -88251,7 +88289,7 @@ var init_isEqual = __esm(() => {
88251
88289
 
88252
88290
  // src/utils/userAgent.ts
88253
88291
  function getClaudeCodeUserAgent() {
88254
- return `claude-code/${"2.3.3"}`;
88292
+ return `claude-code/${"2.3.5"}`;
88255
88293
  }
88256
88294
 
88257
88295
  // src/utils/workloadContext.ts
@@ -88273,7 +88311,7 @@ function getUserAgent() {
88273
88311
  const clientApp = process.env.CLAUDE_AGENT_SDK_CLIENT_APP ? `, client-app/${process.env.CLAUDE_AGENT_SDK_CLIENT_APP}` : "";
88274
88312
  const workload = getWorkload();
88275
88313
  const workloadSuffix = workload ? `, workload/${workload}` : "";
88276
- return `claude-cli/${"2.3.3"} (${process.env.USER_TYPE}, ${process.env.CLAUDE_CODE_ENTRYPOINT ?? "cli"}${agentSdkVersion}${clientApp}${workloadSuffix})`;
88314
+ return `claude-cli/${"2.3.5"} (${process.env.USER_TYPE}, ${process.env.CLAUDE_CODE_ENTRYPOINT ?? "cli"}${agentSdkVersion}${clientApp}${workloadSuffix})`;
88277
88315
  }
88278
88316
  function getMCPUserAgent() {
88279
88317
  const parts = [];
@@ -88287,7 +88325,7 @@ function getMCPUserAgent() {
88287
88325
  parts.push(`client-app/${process.env.CLAUDE_AGENT_SDK_CLIENT_APP}`);
88288
88326
  }
88289
88327
  const suffix = parts.length > 0 ? ` (${parts.join(", ")})` : "";
88290
- return `claude-code/${"2.3.3"}${suffix}`;
88328
+ return `claude-code/${"2.3.5"}${suffix}`;
88291
88329
  }
88292
88330
  function getWebFetchUserAgent() {
88293
88331
  return `Claude-User (${getClaudeCodeUserAgent()}; +https://support.anthropic.com/)`;
@@ -115969,7 +116007,7 @@ var init_node_domexception = __esm(() => {
115969
116007
 
115970
116008
  // node_modules/fetch-blob/from.js
115971
116009
  import { statSync as statSync3, createReadStream, promises as fs2 } from "node:fs";
115972
- import { basename as basename5 } from "node:path";
116010
+ import { basename as basename6 } from "node:path";
115973
116011
  var stat6, blobFromSync = (path5, type) => fromBlob(statSync3(path5), path5, type), blobFrom = (path5, type) => stat6(path5).then((stat7) => fromBlob(stat7, path5, type)), fileFrom = (path5, type) => stat6(path5).then((stat7) => fromFile(stat7, path5, type)), fileFromSync = (path5, type) => fromFile(statSync3(path5), path5, type), fromBlob = (stat7, path5, type = "") => new fetch_blob_default([new BlobDataItem({
115974
116012
  path: path5,
115975
116013
  size: stat7.size,
@@ -115980,7 +116018,7 @@ var stat6, blobFromSync = (path5, type) => fromBlob(statSync3(path5), path5, typ
115980
116018
  size: stat7.size,
115981
116019
  lastModified: stat7.mtimeMs,
115982
116020
  start: 0
115983
- })], basename5(path5), { type, lastModified: stat7.mtimeMs }), BlobDataItem;
116021
+ })], basename6(path5), { type, lastModified: stat7.mtimeMs }), BlobDataItem;
115984
116022
  var init_from = __esm(() => {
115985
116023
  init_node_domexception();
115986
116024
  init_file2();
@@ -123552,9 +123590,6 @@ var init_modelCapabilities = __esm(() => {
123552
123590
  });
123553
123591
 
123554
123592
  // src/utils/context.ts
123555
- function getEnvAlias2(localKey, legacyKey) {
123556
- return process.env[localKey] ?? process.env[legacyKey];
123557
- }
123558
123593
  function is1mContextDisabled() {
123559
123594
  return true;
123560
123595
  }
@@ -123584,13 +123619,7 @@ function getLocalProviderContextWindow() {
123584
123619
  return _localProviderContextWindow;
123585
123620
  }
123586
123621
  function getContextWindowForModel(_model, _betas) {
123587
- const envOverrideStr = getEnvAlias2("LOCALCLAWD_MAX_CONTEXT_TOKENS", "CLAUDE_CODE_MAX_CONTEXT_TOKENS");
123588
- if (envOverrideStr) {
123589
- const override = parseContextWindowString(envOverrideStr);
123590
- if (override !== null)
123591
- return override;
123592
- }
123593
- const persisted = getGlobalConfig().compactContextWindowTokens;
123622
+ const persisted = getCurrentProjectConfig().compactContextWindowTokens;
123594
123623
  if (persisted && persisted > 0)
123595
123624
  return persisted;
123596
123625
  if (_localProviderContextWindow && _localProviderContextWindow > 0) {
@@ -123675,7 +123704,7 @@ function getModelMaxOutputTokens(model) {
123675
123704
  function getMaxThinkingTokensForModel(model) {
123676
123705
  return getModelMaxOutputTokens(model).upperLimit - 1;
123677
123706
  }
123678
- var MODEL_CONTEXT_WINDOW_DEFAULT = 131072, COMPACT_CONTEXT_WINDOW_CHOICES, COMPACT_MAX_OUTPUT_TOKENS = 20000, MAX_OUTPUT_TOKENS_DEFAULT = 32000, MAX_OUTPUT_TOKENS_UPPER_LIMIT = 64000, CAPPED_DEFAULT_MAX_TOKENS = 8000, ESCALATED_MAX_TOKENS = 64000, _localProviderContextWindow = null;
123707
+ var MODEL_CONTEXT_WINDOW_DEFAULT = 131072, COMPACT_CONTEXT_WINDOW_CHOICES, COMPACT_MAX_OUTPUT_TOKENS = 8000, MAX_OUTPUT_TOKENS_DEFAULT = 32000, MAX_OUTPUT_TOKENS_UPPER_LIMIT = 64000, CAPPED_DEFAULT_MAX_TOKENS = 8000, ESCALATED_MAX_TOKENS = 64000, _localProviderContextWindow = null;
123679
123708
  var init_context = __esm(() => {
123680
123709
  init_config();
123681
123710
  init_model();
@@ -142581,14 +142610,14 @@ var init_measure_text = __esm(() => {
142581
142610
  });
142582
142611
 
142583
142612
  // src/ink/node-cache.ts
142584
- function addPendingClear(parent, rect, isAbsolute4) {
142613
+ function addPendingClear(parent, rect, isAbsolute5) {
142585
142614
  const existing = pendingClears.get(parent);
142586
142615
  if (existing) {
142587
142616
  existing.push(rect);
142588
142617
  } else {
142589
142618
  pendingClears.set(parent, [rect]);
142590
142619
  }
142591
- if (isAbsolute4) {
142620
+ if (isAbsolute5) {
142592
142621
  absoluteNodeRemoved = true;
142593
142622
  }
142594
142623
  }
@@ -143696,14 +143725,14 @@ function collectRemovedRects(parent, removed, underAbsolute = false) {
143696
143725
  if (removed.nodeName === "#text")
143697
143726
  return;
143698
143727
  const elem = removed;
143699
- const isAbsolute4 = underAbsolute || elem.style.position === "absolute";
143728
+ const isAbsolute5 = underAbsolute || elem.style.position === "absolute";
143700
143729
  const cached = nodeCache.get(elem);
143701
143730
  if (cached) {
143702
- addPendingClear(parent, cached, isAbsolute4);
143731
+ addPendingClear(parent, cached, isAbsolute5);
143703
143732
  nodeCache.delete(elem);
143704
143733
  }
143705
143734
  for (const child of elem.childNodes) {
143706
- collectRemovedRects(parent, child, isAbsolute4);
143735
+ collectRemovedRects(parent, child, isAbsolute5);
143707
143736
  }
143708
143737
  }
143709
143738
  function stylesEqual(a, b) {
@@ -152357,16 +152386,16 @@ function renderChildren(node, output, offsetX, offsetY, hasRemovedChild, prevScr
152357
152386
  for (const childNode of node.childNodes) {
152358
152387
  const childElem = childNode;
152359
152388
  const wasDirty = childElem.dirty;
152360
- const isAbsolute4 = childElem.style.position === "absolute";
152389
+ const isAbsolute5 = childElem.style.position === "absolute";
152361
152390
  renderNodeToOutput(childElem, output, {
152362
152391
  offsetX,
152363
152392
  offsetY,
152364
152393
  prevScreen: hasRemovedChild || seenDirtyChild ? undefined : prevScreen,
152365
- skipSelfBlit: seenDirtyClipped && isAbsolute4 && !childElem.style.opaque && childElem.style.backgroundColor === undefined,
152394
+ skipSelfBlit: seenDirtyClipped && isAbsolute5 && !childElem.style.opaque && childElem.style.backgroundColor === undefined,
152366
152395
  inheritedBackgroundColor
152367
152396
  });
152368
152397
  if (wasDirty && !seenDirtyChild) {
152369
- if (!clipsBothAxes(childElem) || isAbsolute4) {
152398
+ if (!clipsBothAxes(childElem) || isAbsolute5) {
152370
152399
  seenDirtyChild = true;
152371
152400
  } else {
152372
152401
  seenDirtyClipped = true;
@@ -157079,10 +157108,10 @@ var init_readdirp = __esm(() => {
157079
157108
  }
157080
157109
  async _formatEntry(dirent, path5) {
157081
157110
  let entry;
157082
- const basename6 = this._isDirent ? dirent.name : dirent;
157111
+ const basename7 = this._isDirent ? dirent.name : dirent;
157083
157112
  try {
157084
- const fullPath = presolve(pjoin(path5, basename6));
157085
- entry = { path: prelative(this._root, fullPath), fullPath, basename: basename6 };
157113
+ const fullPath = presolve(pjoin(path5, basename7));
157114
+ entry = { path: prelative(this._root, fullPath), fullPath, basename: basename7 };
157086
157115
  entry[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);
157087
157116
  } catch (err) {
157088
157117
  this._onError(err);
@@ -157169,9 +157198,9 @@ class NodeFsHandler {
157169
157198
  _watchWithNodeFs(path5, listener) {
157170
157199
  const opts = this.fsw.options;
157171
157200
  const directory = sp.dirname(path5);
157172
- const basename7 = sp.basename(path5);
157201
+ const basename8 = sp.basename(path5);
157173
157202
  const parent = this.fsw._getWatchedDir(directory);
157174
- parent.add(basename7);
157203
+ parent.add(basename8);
157175
157204
  const absolutePath = sp.resolve(path5);
157176
157205
  const options = {
157177
157206
  persistent: opts.persistent
@@ -157181,7 +157210,7 @@ class NodeFsHandler {
157181
157210
  let closer;
157182
157211
  if (opts.usePolling) {
157183
157212
  const enableBin = opts.interval !== opts.binaryInterval;
157184
- options.interval = enableBin && isBinaryPath(basename7) ? opts.binaryInterval : opts.interval;
157213
+ options.interval = enableBin && isBinaryPath(basename8) ? opts.binaryInterval : opts.interval;
157185
157214
  closer = setFsWatchFileListener(path5, absolutePath, options, {
157186
157215
  listener,
157187
157216
  rawEmitter: this.fsw._emitRaw
@@ -157200,10 +157229,10 @@ class NodeFsHandler {
157200
157229
  return;
157201
157230
  }
157202
157231
  const dirname14 = sp.dirname(file);
157203
- const basename7 = sp.basename(file);
157232
+ const basename8 = sp.basename(file);
157204
157233
  const parent = this.fsw._getWatchedDir(dirname14);
157205
157234
  let prevStats = stats;
157206
- if (parent.has(basename7))
157235
+ if (parent.has(basename8))
157207
157236
  return;
157208
157237
  const listener = async (path5, newStats) => {
157209
157238
  if (!this.fsw._throttle(THROTTLE_MODE_WATCH, file, 5))
@@ -157228,9 +157257,9 @@ class NodeFsHandler {
157228
157257
  prevStats = newStats2;
157229
157258
  }
157230
157259
  } catch (error5) {
157231
- this.fsw._remove(dirname14, basename7);
157260
+ this.fsw._remove(dirname14, basename8);
157232
157261
  }
157233
- } else if (parent.has(basename7)) {
157262
+ } else if (parent.has(basename8)) {
157234
157263
  const at = newStats.atimeMs;
157235
157264
  const mt = newStats.mtimeMs;
157236
157265
  if (!at || at <= mt || mt !== prevStats.mtimeMs) {
@@ -157855,11 +157884,11 @@ function createPattern(matcher) {
157855
157884
  if (matcher.path === string)
157856
157885
  return true;
157857
157886
  if (matcher.recursive) {
157858
- const relative5 = sp2.relative(matcher.path, string);
157859
- if (!relative5) {
157887
+ const relative6 = sp2.relative(matcher.path, string);
157888
+ if (!relative6) {
157860
157889
  return false;
157861
157890
  }
157862
- return !relative5.startsWith("..") && !sp2.isAbsolute(relative5);
157891
+ return !relative6.startsWith("..") && !sp2.isAbsolute(relative6);
157863
157892
  }
157864
157893
  return false;
157865
157894
  };
@@ -158794,7 +158823,7 @@ function getAttributionHeader(fingerprint) {
158794
158823
  if (!isAttributionHeaderEnabled()) {
158795
158824
  return "";
158796
158825
  }
158797
- const version = `${"2.3.3"}.${fingerprint}`;
158826
+ const version = `${"2.3.5"}.${fingerprint}`;
158798
158827
  const entrypoint = process.env.CLAUDE_CODE_ENTRYPOINT ?? "unknown";
158799
158828
  const cch = "";
158800
158829
  const workload = getWorkload();
@@ -169045,7 +169074,7 @@ var init_readOnlyCommandValidation = __esm(() => {
169045
169074
 
169046
169075
  // src/utils/permissions/pathValidation.ts
169047
169076
  import { homedir as homedir11 } from "os";
169048
- import { dirname as dirname17, isAbsolute as isAbsolute5, resolve as resolve15 } from "path";
169077
+ import { dirname as dirname17, isAbsolute as isAbsolute6, resolve as resolve15 } from "path";
169049
169078
  function formatDirectoryList(directories) {
169050
169079
  const dirCount = directories.length;
169051
169080
  if (dirCount <= MAX_DIRS_TO_LIST) {
@@ -169153,7 +169182,7 @@ function isPathAllowed(resolvedPath, context, operationType, precomputedPathsToC
169153
169182
  }
169154
169183
  function validateGlobPattern(cleanPath, cwd2, toolPermissionContext, operationType) {
169155
169184
  if (containsPathTraversal(cleanPath)) {
169156
- const absolutePath = isAbsolute5(cleanPath) ? cleanPath : resolve15(cwd2, cleanPath);
169185
+ const absolutePath = isAbsolute6(cleanPath) ? cleanPath : resolve15(cwd2, cleanPath);
169157
169186
  const { resolvedPath: resolvedPath2, isCanonical: isCanonical2 } = safeResolvePath(getFsImplementation(), absolutePath);
169158
169187
  const result2 = isPathAllowed(resolvedPath2, toolPermissionContext, operationType, isCanonical2 ? [resolvedPath2] : undefined);
169159
169188
  return {
@@ -169163,7 +169192,7 @@ function validateGlobPattern(cleanPath, cwd2, toolPermissionContext, operationTy
169163
169192
  };
169164
169193
  }
169165
169194
  const basePath = getGlobBaseDirectory(cleanPath);
169166
- const absoluteBasePath = isAbsolute5(basePath) ? basePath : resolve15(cwd2, basePath);
169195
+ const absoluteBasePath = isAbsolute6(basePath) ? basePath : resolve15(cwd2, basePath);
169167
169196
  const { resolvedPath, isCanonical } = safeResolvePath(getFsImplementation(), absoluteBasePath);
169168
169197
  const result = isPathAllowed(resolvedPath, toolPermissionContext, operationType, isCanonical ? [resolvedPath] : undefined);
169169
169198
  return {
@@ -169242,7 +169271,7 @@ function validatePath(path6, cwd2, toolPermissionContext, operationType) {
169242
169271
  }
169243
169272
  return validateGlobPattern(cleanPath, cwd2, toolPermissionContext, operationType);
169244
169273
  }
169245
- const absolutePath = isAbsolute5(cleanPath) ? cleanPath : resolve15(cwd2, cleanPath);
169274
+ const absolutePath = isAbsolute6(cleanPath) ? cleanPath : resolve15(cwd2, cleanPath);
169246
169275
  const { resolvedPath, isCanonical } = safeResolvePath(getFsImplementation(), absolutePath);
169247
169276
  const result = isPathAllowed(resolvedPath, toolPermissionContext, operationType, isCanonical ? [resolvedPath] : undefined);
169248
169277
  return {
@@ -171971,13 +172000,13 @@ var init_esm = __esm(() => {
171971
172000
  });
171972
172001
 
171973
172002
  // src/utils/dxt/zip.ts
171974
- import { isAbsolute as isAbsolute6, normalize as normalize6 } from "path";
172003
+ import { isAbsolute as isAbsolute7, normalize as normalize6 } from "path";
171975
172004
  function isPathSafe(filePath) {
171976
172005
  if (containsPathTraversal(filePath)) {
171977
172006
  return false;
171978
172007
  }
171979
172008
  const normalized = normalize6(filePath);
171980
- if (isAbsolute6(normalized)) {
172009
+ if (isAbsolute7(normalized)) {
171981
172010
  return false;
171982
172011
  }
171983
172012
  return true;
@@ -172121,7 +172150,7 @@ var init_systemDirectories = __esm(() => {
172121
172150
  });
172122
172151
 
172123
172152
  // src/utils/plugins/mcpbHandler.ts
172124
- import { createHash as createHash3 } from "crypto";
172153
+ import { createHash as createHash4 } from "crypto";
172125
172154
  import { chmod, writeFile as writeFile3 } from "fs/promises";
172126
172155
  import { dirname as dirname18, join as join33 } from "path";
172127
172156
  function isMcpbSource(source) {
@@ -172131,13 +172160,13 @@ function isUrl(source) {
172131
172160
  return source.startsWith("http://") || source.startsWith("https://");
172132
172161
  }
172133
172162
  function generateContentHash(data) {
172134
- return createHash3("sha256").update(data).digest("hex").substring(0, 16);
172163
+ return createHash4("sha256").update(data).digest("hex").substring(0, 16);
172135
172164
  }
172136
172165
  function getMcpbCacheDir(pluginPath) {
172137
172166
  return join33(pluginPath, ".mcpb-cache");
172138
172167
  }
172139
172168
  function getMetadataPath(cacheDir, source) {
172140
- const sourceHash = createHash3("md5").update(source).digest("hex").substring(0, 8);
172169
+ const sourceHash = createHash4("md5").update(source).digest("hex").substring(0, 8);
172141
172170
  return join33(cacheDir, `${sourceHash}.metadata.json`);
172142
172171
  }
172143
172172
  function serverSecretsKey(pluginId, serverName) {
@@ -172485,7 +172514,7 @@ async function loadMcpbFile(source, pluginPath, pluginId, onProgress, providedUs
172485
172514
  let mcpbData;
172486
172515
  let mcpbFilePath;
172487
172516
  if (isUrl(source)) {
172488
- const sourceHash = createHash3("md5").update(source).digest("hex").substring(0, 8);
172517
+ const sourceHash = createHash4("md5").update(source).digest("hex").substring(0, 8);
172489
172518
  mcpbFilePath = join33(cacheDir, `${sourceHash}.mcpb`);
172490
172519
  mcpbData = await downloadMcpb(source, mcpbFilePath, onProgress);
172491
172520
  } else {
@@ -172806,7 +172835,7 @@ var init_walkPluginMarkdown = __esm(() => {
172806
172835
  });
172807
172836
 
172808
172837
  // src/utils/plugins/loadPluginAgents.ts
172809
- import { basename as basename8 } from "path";
172838
+ import { basename as basename9 } from "path";
172810
172839
  async function loadAgentsFromDirectory(agentsPath, pluginName, sourceName, pluginPath, pluginManifest, loadedPaths) {
172811
172840
  const agents = [];
172812
172841
  await walkPluginMarkdown(agentsPath, async (fullPath, namespace) => {
@@ -172824,7 +172853,7 @@ async function loadAgentFromFile(filePath, pluginName, namespace, sourceName, pl
172824
172853
  try {
172825
172854
  const content = await fs3.readFile(filePath, { encoding: "utf-8" });
172826
172855
  const { frontmatter, content: markdownContent } = parseFrontmatter(content, filePath);
172827
- const baseAgentName = frontmatter.name || basename8(filePath).replace(/\.md$/, "");
172856
+ const baseAgentName = frontmatter.name || basename9(filePath).replace(/\.md$/, "");
172828
172857
  const nameParts = [pluginName, ...namespace, baseAgentName];
172829
172858
  const agentType = nameParts.join(":");
172830
172859
  const whenToUse = coerceDescriptionToString(frontmatter.description, agentType) ?? coerceDescriptionToString(frontmatter["when-to-use"], agentType) ?? `Agent from ${pluginName} plugin`;
@@ -173749,7 +173778,7 @@ __export(exports_loadAgentsDir, {
173749
173778
  filterAgentsByMcpRequirements: () => filterAgentsByMcpRequirements,
173750
173779
  clearAgentDefinitionsCache: () => clearAgentDefinitionsCache
173751
173780
  });
173752
- import { basename as basename9 } from "path";
173781
+ import { basename as basename10 } from "path";
173753
173782
  import { z as z12 } from "zod/v4";
173754
173783
  function isBuiltInAgent(agent) {
173755
173784
  return agent.source === "built-in";
@@ -173958,7 +173987,7 @@ function parseAgentFromMarkdown(filePath, baseDir, frontmatter, content, source)
173958
173987
  if (maxTurnsRaw !== undefined && maxTurns === undefined) {
173959
173988
  logForDebugging(`Agent file ${filePath} has invalid maxTurns '${maxTurnsRaw}'. Must be a positive integer.`);
173960
173989
  }
173961
- const filename = basename9(filePath, ".md");
173990
+ const filename = basename10(filePath, ".md");
173962
173991
  let tools = parseAgentToolsFromFrontmatter(frontmatter["tools"]);
173963
173992
  if (isAutoMemoryEnabled() && memory && tools !== undefined) {
173964
173993
  const toolSet = new Set(tools);
@@ -174981,7 +175010,7 @@ var init_metadata = __esm(() => {
174981
175010
  COMPOUND_OPERATOR_REGEX = /\s*(?:&&|\|\||[;|])\s*/;
174982
175011
  WHITESPACE_REGEX = /\s+/;
174983
175012
  getVersionBase = memoize_default(() => {
174984
- const match = "2.3.3".match(/^\d+\.\d+\.\d+(?:-[a-z]+)?/);
175013
+ const match = "2.3.5".match(/^\d+\.\d+\.\d+(?:-[a-z]+)?/);
174985
175014
  return match ? match[0] : undefined;
174986
175015
  });
174987
175016
  buildEnvContext = memoize_default(async () => {
@@ -175021,9 +175050,9 @@ var init_metadata = __esm(() => {
175021
175050
  isGithubAction: isEnvTruthy(process.env.GITHUB_ACTIONS),
175022
175051
  isClaudeCodeAction: isEnvTruthy(process.env.CLAUDE_CODE_ACTION),
175023
175052
  isClaudeAiAuth: isClaudeAISubscriber(),
175024
- version: "2.3.3",
175053
+ version: "2.3.5",
175025
175054
  versionBase: getVersionBase(),
175026
- buildTime: "2026-05-10T20:16:44.115Z",
175055
+ buildTime: "2026-06-03T02:51:00.215Z",
175027
175056
  deploymentEnvironment: env3.detectDeploymentEnvironment(),
175028
175057
  ...isEnvTruthy(process.env.GITHUB_ACTIONS) && {
175029
175058
  githubEventName: process.env.GITHUB_EVENT_NAME,
@@ -182671,13 +182700,13 @@ var init_fileStateCache = __esm(() => {
182671
182700
 
182672
182701
  // src/utils/instructionsmd.ts
182673
182702
  import {
182674
- basename as basename10,
182703
+ basename as basename11,
182675
182704
  dirname as dirname19,
182676
182705
  extname as extname4,
182677
- isAbsolute as isAbsolute7,
182706
+ isAbsolute as isAbsolute8,
182678
182707
  join as join35,
182679
182708
  parse as parse3,
182680
- relative as relative5,
182709
+ relative as relative6,
182681
182710
  sep as sep8
182682
182711
  } from "path";
182683
182712
  function pathInOriginalCwd(path6) {
@@ -183025,8 +183054,8 @@ async function processConditionedMdRules(targetPath, rulesDir, type, processedPa
183025
183054
  return false;
183026
183055
  }
183027
183056
  const baseDir = type === "Project" ? dirname19(dirname19(rulesDir)) : getOriginalCwd();
183028
- const relativePath = isAbsolute7(targetPath) ? relative5(baseDir, targetPath) : targetPath;
183029
- if (!relativePath || relativePath.startsWith("..") || isAbsolute7(relativePath)) {
183057
+ const relativePath = isAbsolute8(targetPath) ? relative6(baseDir, targetPath) : targetPath;
183058
+ if (!relativePath || relativePath.startsWith("..") || isAbsolute8(relativePath)) {
183030
183059
  return false;
183031
183060
  }
183032
183061
  return import_ignore.default().add(file.globs).ignores(relativePath);
@@ -184620,7 +184649,7 @@ var init_hooksConfigSnapshot = __esm(() => {
184620
184649
  });
184621
184650
 
184622
184651
  // src/utils/hooks/fileChangedWatcher.ts
184623
- import { isAbsolute as isAbsolute8, join as join38 } from "path";
184652
+ import { isAbsolute as isAbsolute9, join as join38 } from "path";
184624
184653
  function setEnvHookNotifier(cb) {
184625
184654
  notifyCallback = cb;
184626
184655
  }
@@ -184648,7 +184677,7 @@ function resolveWatchPaths(config) {
184648
184677
  for (const name of m3.matcher.split("|").map((s2) => s2.trim())) {
184649
184678
  if (!name)
184650
184679
  continue;
184651
- staticPaths.push(isAbsolute8(name) ? name : join38(currentCwd, name));
184680
+ staticPaths.push(isAbsolute9(name) ? name : join38(currentCwd, name));
184652
184681
  }
184653
184682
  }
184654
184683
  return [...new Set([...staticPaths, ...dynamicWatchPaths])];
@@ -185781,7 +185810,7 @@ var init_powershellProvider = __esm(() => {
185781
185810
  import { execFileSync, spawn as spawn2 } from "child_process";
185782
185811
  import { constants as fsConstants2, readFileSync as readFileSync7, unlinkSync as unlinkSync2 } from "fs";
185783
185812
  import { mkdir as mkdir8, open as open5, realpath as realpath7 } from "fs/promises";
185784
- import { isAbsolute as isAbsolute9, resolve as resolve16 } from "path";
185813
+ import { isAbsolute as isAbsolute10, resolve as resolve16 } from "path";
185785
185814
  import { join as posixJoin3 } from "path/posix";
185786
185815
  import { accessSync } from "fs";
185787
185816
  function isExecutable(shellPath) {
@@ -185975,7 +186004,7 @@ async function exec3(command, abortSignal, shellType, options) {
185975
186004
  }
185976
186005
  }
185977
186006
  function setCwd(path6, relativeTo) {
185978
- const resolved = isAbsolute9(path6) ? path6 : resolve16(relativeTo || getFsImplementation().cwd(), path6);
186007
+ const resolved = isAbsolute10(path6) ? path6 : resolve16(relativeTo || getFsImplementation().cwd(), path6);
185979
186008
  let physicalPath;
185980
186009
  try {
185981
186010
  physicalPath = getFsImplementation().realpathSync(resolved);
@@ -189652,8 +189681,8 @@ function extractBaseCommand(segment2) {
189652
189681
  const stripped = segment2.trim().replace(/^[&.]\s+/, "");
189653
189682
  const firstToken = stripped.split(/\s+/)[0] || "";
189654
189683
  const unquoted = firstToken.replace(/^["']|["']$/g, "");
189655
- const basename11 = unquoted.split(/[\\/]/).pop() || unquoted;
189656
- return basename11.toLowerCase().replace(/\.exe$/, "");
189684
+ const basename12 = unquoted.split(/[\\/]/).pop() || unquoted;
189685
+ return basename12.toLowerCase().replace(/\.exe$/, "");
189657
189686
  }
189658
189687
  function heuristicallyExtractBaseCommand(command) {
189659
189688
  const segments = command.split(/[;|]/).filter((s2) => s2.trim());
@@ -190709,11 +190738,11 @@ var init_parser5 = __esm(() => {
190709
190738
  });
190710
190739
 
190711
190740
  // src/tools/PowerShellTool/gitSafety.ts
190712
- import { basename as basename11, posix as posix2, resolve as resolve17, sep as sep9 } from "path";
190741
+ import { basename as basename12, posix as posix2, resolve as resolve17, sep as sep9 } from "path";
190713
190742
  function resolveCwdReentry(normalized) {
190714
190743
  if (!normalized.startsWith("../"))
190715
190744
  return normalized;
190716
- const cwdBase = basename11(getCwd()).toLowerCase();
190745
+ const cwdBase = basename12(getCwd()).toLowerCase();
190717
190746
  if (!cwdBase)
190718
190747
  return normalized;
190719
190748
  const prefix = "../" + cwdBase + "/";
@@ -192403,7 +192432,7 @@ var init_PermissionUpdate = __esm(() => {
192403
192432
 
192404
192433
  // src/tools/PowerShellTool/pathValidation.ts
192405
192434
  import { homedir as homedir14 } from "os";
192406
- import { isAbsolute as isAbsolute10, resolve as resolve18 } from "path";
192435
+ import { isAbsolute as isAbsolute11, resolve as resolve18 } from "path";
192407
192436
  function matchesParam(paramLower, paramList) {
192408
192437
  for (const p of paramList) {
192409
192438
  if (p === paramLower || paramLower.length > 1 && p.startsWith(paramLower)) {
@@ -192511,7 +192540,7 @@ function checkDenyRuleForGuessedPath(strippedPath, cwd2, toolPermissionContext,
192511
192540
  if (!strippedPath || strippedPath.includes("\x00"))
192512
192541
  return null;
192513
192542
  const tildeExpanded = expandTilde2(strippedPath);
192514
- const abs = isAbsolute10(tildeExpanded) ? tildeExpanded : resolve18(cwd2, tildeExpanded);
192543
+ const abs = isAbsolute11(tildeExpanded) ? tildeExpanded : resolve18(cwd2, tildeExpanded);
192515
192544
  const { resolvedPath } = safeResolvePath(getFsImplementation(), abs);
192516
192545
  const permissionType = operationType === "read" ? "read" : "edit";
192517
192546
  const denyRule = matchingRuleForInput(resolvedPath, toolPermissionContext, permissionType, "deny");
@@ -192601,7 +192630,7 @@ function validatePath2(filePath, cwd2, toolPermissionContext, operationType) {
192601
192630
  };
192602
192631
  }
192603
192632
  if (containsPathTraversal(normalizedPath)) {
192604
- const absolutePath2 = isAbsolute10(normalizedPath) ? normalizedPath : resolve18(cwd2, normalizedPath);
192633
+ const absolutePath2 = isAbsolute11(normalizedPath) ? normalizedPath : resolve18(cwd2, normalizedPath);
192605
192634
  const { resolvedPath: resolvedPath3, isCanonical: isCanonical2 } = safeResolvePath(getFsImplementation(), absolutePath2);
192606
192635
  const result2 = isPathAllowed2(resolvedPath3, toolPermissionContext, operationType, isCanonical2 ? [resolvedPath3] : undefined);
192607
192636
  return {
@@ -192611,7 +192640,7 @@ function validatePath2(filePath, cwd2, toolPermissionContext, operationType) {
192611
192640
  };
192612
192641
  }
192613
192642
  const basePath = getGlobBaseDirectory2(normalizedPath);
192614
- const absoluteBasePath = isAbsolute10(basePath) ? basePath : resolve18(cwd2, basePath);
192643
+ const absoluteBasePath = isAbsolute11(basePath) ? basePath : resolve18(cwd2, basePath);
192615
192644
  const { resolvedPath: resolvedPath2 } = safeResolvePath(getFsImplementation(), absoluteBasePath);
192616
192645
  const permissionType = operationType === "read" ? "read" : "edit";
192617
192646
  const denyRule = matchingRuleForInput(resolvedPath2, toolPermissionContext, permissionType, "deny");
@@ -192631,7 +192660,7 @@ function validatePath2(filePath, cwd2, toolPermissionContext, operationType) {
192631
192660
  }
192632
192661
  };
192633
192662
  }
192634
- const absolutePath = isAbsolute10(normalizedPath) ? normalizedPath : resolve18(cwd2, normalizedPath);
192663
+ const absolutePath = isAbsolute11(normalizedPath) ? normalizedPath : resolve18(cwd2, normalizedPath);
192635
192664
  const { resolvedPath, isCanonical } = safeResolvePath(getFsImplementation(), absolutePath);
192636
192665
  const result = isPathAllowed2(resolvedPath, toolPermissionContext, operationType, isCanonical ? [resolvedPath] : undefined);
192637
192666
  return {
@@ -196420,12 +196449,12 @@ var builders = null;
196420
196449
  // src/skills/loadSkillsDir.ts
196421
196450
  import { realpath as realpath8 } from "fs/promises";
196422
196451
  import {
196423
- basename as basename12,
196452
+ basename as basename13,
196424
196453
  dirname as dirname21,
196425
- isAbsolute as isAbsolute11,
196454
+ isAbsolute as isAbsolute12,
196426
196455
  join as join42,
196427
196456
  sep as pathSep,
196428
- relative as relative6
196457
+ relative as relative7
196429
196458
  } from "path";
196430
196459
  function getSkillsPath(source, dir) {
196431
196460
  switch (source) {
@@ -196639,7 +196668,7 @@ async function loadSkillsFromSkillsDir(basePath, source) {
196639
196668
  return results.filter((r2) => r2 !== null);
196640
196669
  }
196641
196670
  function isSkillFile(filePath) {
196642
- return /^skill\.md$/i.test(basename12(filePath));
196671
+ return /^skill\.md$/i.test(basename13(filePath));
196643
196672
  }
196644
196673
  function transformSkillFiles(files) {
196645
196674
  const filesByDir = new Map;
@@ -196655,7 +196684,7 @@ function transformSkillFiles(files) {
196655
196684
  if (skillFiles.length > 0) {
196656
196685
  const skillFile = skillFiles[0];
196657
196686
  if (skillFiles.length > 1) {
196658
- logForDebugging(`Multiple skill files found in ${dir}, using ${basename12(skillFile.filePath)}`);
196687
+ logForDebugging(`Multiple skill files found in ${dir}, using ${basename13(skillFile.filePath)}`);
196659
196688
  }
196660
196689
  result.push(skillFile);
196661
196690
  } else {
@@ -196675,12 +196704,12 @@ function buildNamespace(targetDir, baseDir) {
196675
196704
  function getSkillCommandName(filePath, baseDir) {
196676
196705
  const skillDirectory = dirname21(filePath);
196677
196706
  const parentOfSkillDir = dirname21(skillDirectory);
196678
- const commandBaseName = basename12(skillDirectory);
196707
+ const commandBaseName = basename13(skillDirectory);
196679
196708
  const namespace = buildNamespace(parentOfSkillDir, baseDir);
196680
196709
  return namespace ? `${namespace}:${commandBaseName}` : commandBaseName;
196681
196710
  }
196682
196711
  function getRegularCommandName(filePath, baseDir) {
196683
- const fileName = basename12(filePath);
196712
+ const fileName = basename13(filePath);
196684
196713
  const fileDirectory = dirname21(filePath);
196685
196714
  const commandBaseName = fileName.replace(/\.md$/, "");
196686
196715
  const namespace = buildNamespace(fileDirectory, baseDir);
@@ -196825,8 +196854,8 @@ function activateConditionalSkillsForPaths(filePaths, cwd2) {
196825
196854
  }
196826
196855
  const skillIgnore = import_ignore2.default().add(skill.paths);
196827
196856
  for (const filePath of filePaths) {
196828
- const relativePath = isAbsolute11(filePath) ? relative6(cwd2, filePath) : filePath;
196829
- if (!relativePath || relativePath.startsWith("..") || isAbsolute11(relativePath)) {
196857
+ const relativePath = isAbsolute12(filePath) ? relative7(cwd2, filePath) : filePath;
196858
+ if (!relativePath || relativePath.startsWith("..") || isAbsolute12(relativePath)) {
196830
196859
  continue;
196831
196860
  }
196832
196861
  if (skillIgnore.ignores(relativePath)) {
@@ -199946,46 +199975,49 @@ function getPartialCompactPrompt(customInstructions, direction = "from") {
199946
199975
  if (customInstructions && customInstructions.trim() !== "") {
199947
199976
  prompt += `
199948
199977
 
199949
- Additional Instructions:
199978
+ Additional instructions:
199950
199979
  ${customInstructions}`;
199951
199980
  }
199952
- prompt += NO_TOOLS_TRAILER;
199953
- return prompt;
199981
+ return prompt + NO_TOOLS_TRAILER;
199954
199982
  }
199955
199983
  function getCompactPrompt(customInstructions) {
199956
199984
  let prompt = NO_TOOLS_PREAMBLE + BASE_COMPACT_PROMPT;
199957
199985
  if (customInstructions && customInstructions.trim() !== "") {
199958
199986
  prompt += `
199959
199987
 
199960
- Additional Instructions:
199988
+ Additional instructions:
199961
199989
  ${customInstructions}`;
199962
199990
  }
199963
- prompt += NO_TOOLS_TRAILER;
199964
- return prompt;
199991
+ return prompt + NO_TOOLS_TRAILER;
199992
+ }
199993
+ function truncateFormattedSummary(summary) {
199994
+ if (summary.length <= MAX_FORMATTED_SUMMARY_CHARS) {
199995
+ return summary;
199996
+ }
199997
+ const sliceAt = Math.max(0, MAX_FORMATTED_SUMMARY_CHARS - SUMMARY_TRUNCATION_MARKER.length);
199998
+ return summary.slice(0, sliceAt).trimEnd() + SUMMARY_TRUNCATION_MARKER;
199965
199999
  }
199966
200000
  function formatCompactSummary(summary) {
199967
- let formattedSummary = summary;
199968
- formattedSummary = formattedSummary.replace(/<analysis>[\s\S]*?<\/analysis>/, "");
199969
- const summaryMatch = formattedSummary.match(/<summary>([\s\S]*?)<\/summary>/);
200001
+ let formattedSummary = summary.replace(/<analysis>[\s\S]*?<\/analysis>/gi, "").trim();
200002
+ const summaryMatch = formattedSummary.match(/<summary>([\s\S]*?)<\/summary>/i);
199970
200003
  if (summaryMatch) {
199971
- const content = summaryMatch[1] || "";
199972
- formattedSummary = formattedSummary.replace(/<summary>[\s\S]*?<\/summary>/, `Summary:
199973
- ${content.trim()}`);
200004
+ formattedSummary = `Summary:
200005
+ ${(summaryMatch[1] || "").trim()}`;
199974
200006
  }
199975
- formattedSummary = formattedSummary.replace(/\n\n+/g, `
200007
+ formattedSummary = formattedSummary.replace(/<\/?summary>/gi, "").replace(/\n\n+/g, `
199976
200008
 
199977
- `);
199978
- return formattedSummary.trim();
200009
+ `).trim();
200010
+ return truncateFormattedSummary(formattedSummary);
199979
200011
  }
199980
200012
  function getCompactUserSummaryMessage(summary, suppressFollowUpQuestions, transcriptPath, recentMessagesPreserved) {
199981
200013
  const formattedSummary = formatCompactSummary(summary);
199982
- let baseSummary = `This session is being continued from a previous conversation that ran out of context. The summary below covers the earlier portion of the conversation.
200014
+ let baseSummary = `This session is being continued after context compaction. The summary below is the working state needed to continue.
199983
200015
 
199984
200016
  ${formattedSummary}`;
199985
200017
  if (transcriptPath) {
199986
200018
  baseSummary += `
199987
200019
 
199988
- If you need specific details from before compaction (like exact code snippets, error messages, or content you generated), read the full transcript at: ${transcriptPath}`;
200020
+ For exact older details, read the full transcript at: ${transcriptPath}`;
199989
200021
  }
199990
200022
  if (recentMessagesPreserved) {
199991
200023
  baseSummary += `
@@ -199994,256 +200026,71 @@ Recent messages are preserved verbatim.`;
199994
200026
  }
199995
200027
  if (suppressFollowUpQuestions) {
199996
200028
  let continuation = `${baseSummary}
199997
- Continue the conversation from where it left off without asking the user any further questions. Resume directly — do not acknowledge the summary, do not recap what was happening, do not preface with "I'll continue" or similar. Pick up the last task as if the break never happened.`;
200029
+ Continue directly from the working state above. Do not acknowledge the summary or ask what to do next unless the summary says user input is required.`;
199998
200030
  if (false) {}
199999
200031
  return continuation;
200000
200032
  }
200001
200033
  return baseSummary;
200002
200034
  }
200003
- var NO_TOOLS_PREAMBLE = `CRITICAL: Respond with TEXT ONLY. Do NOT call any tools.
200004
-
200005
- - Do NOT use Read, Bash, Grep, Glob, Edit, Write, or ANY other tool.
200006
- - You already have all the context you need in the conversation above.
200007
- - Tool calls will be REJECTED and will waste your only turn — you will fail the task.
200008
- - Your entire response must be plain text: an <analysis> block followed by a <summary> block.
200009
-
200010
- `, DETAILED_ANALYSIS_INSTRUCTION_BASE = `Before providing your final summary, wrap your analysis in <analysis> tags to organize your thoughts and ensure you've covered all necessary points. In your analysis process:
200011
-
200012
- 1. Chronologically analyze each message and section of the conversation. For each section thoroughly identify:
200013
- - The user's explicit requests and intents
200014
- - Your approach to addressing the user's requests
200015
- - Key decisions, technical concepts and code patterns
200016
- - Specific details like:
200017
- - file names
200018
- - full code snippets
200019
- - function signatures
200020
- - file edits
200021
- - Errors that you ran into and how you fixed them
200022
- - Pay special attention to specific user feedback that you received, especially if the user told you to do something differently.
200023
- 2. Double-check for technical accuracy and completeness, addressing each required element thoroughly.`, DETAILED_ANALYSIS_INSTRUCTION_PARTIAL = `Before providing your final summary, wrap your analysis in <analysis> tags to organize your thoughts and ensure you've covered all necessary points. In your analysis process:
200024
-
200025
- 1. Analyze the recent messages chronologically. For each section thoroughly identify:
200026
- - The user's explicit requests and intents
200027
- - Your approach to addressing the user's requests
200028
- - Key decisions, technical concepts and code patterns
200029
- - Specific details like:
200030
- - file names
200031
- - full code snippets
200032
- - function signatures
200033
- - file edits
200034
- - Errors that you ran into and how you fixed them
200035
- - Pay special attention to specific user feedback that you received, especially if the user told you to do something differently.
200036
- 2. Double-check for technical accuracy and completeness, addressing each required element thoroughly.`, BASE_COMPACT_PROMPT, PARTIAL_COMPACT_PROMPT, PARTIAL_COMPACT_UP_TO_PROMPT, NO_TOOLS_TRAILER;
200037
- var init_prompt10 = __esm(() => {
200038
- BASE_COMPACT_PROMPT = `Your task is to create a detailed summary of the conversation so far, paying close attention to the user's explicit requests and your previous actions.
200039
- This summary should be thorough in capturing technical details, code patterns, and architectural decisions that would be essential for continuing development work without losing context.
200035
+ var MAX_FORMATTED_SUMMARY_CHARS = 12000, SUMMARY_TRUNCATION_MARKER = `
200040
200036
 
200041
- ${DETAILED_ANALYSIS_INSTRUCTION_BASE}
200037
+ [Summary truncated to keep the post-compact context small. Read the transcript path below if exact older details are needed.]`, NO_TOOLS_PREAMBLE = `Respond with text only. Do not call tools.
200042
200038
 
200043
- Your summary should include the following sections:
200039
+ Write one compact continuation summary in a <summary> block. Do not include an <analysis> block.
200044
200040
 
200045
- 1. Primary Request and Intent: Capture all of the user's explicit requests and intents in detail
200046
- 2. Key Technical Concepts: List all important technical concepts, technologies, and frameworks discussed.
200047
- 3. Files and Code Sections: Enumerate specific files and code sections examined, modified, or created. Pay special attention to the most recent messages and include full code snippets where applicable and include a summary of why this file read or edit is important.
200048
- 4. Errors and fixes: List all errors that you ran into, and how you fixed them. Pay special attention to specific user feedback that you received, especially if the user told you to do something differently.
200049
- 5. Problem Solving: Document problems solved and any ongoing troubleshooting efforts.
200050
- 6. All user messages: List ALL user messages that are not tool results. These are critical for understanding the users' feedback and changing intent.
200051
- 7. Pending Tasks: Outline any pending tasks that you have explicitly been asked to work on.
200052
- 8. Current Work: Describe in detail precisely what was being worked on immediately before this summary request, paying special attention to the most recent messages from both user and assistant. Include file names and code snippets where applicable.
200053
- 9. Optional Next Step: List the next step that you will take that is related to the most recent work you were doing. IMPORTANT: ensure that this step is DIRECTLY in line with the user's most recent explicit requests, and the task you were working on immediately before this summary request. If your last task was concluded, then only list next steps if they are explicitly in line with the users request. Do not start on tangential requests or really old requests that were already completed without confirming with the user first.
200054
- If there is a next step, include direct quotes from the most recent conversation showing exactly what task you were working on and where you left off. This should be verbatim to ensure there's no drift in task interpretation.
200041
+ `, BASE_COMPACT_PROMPT = `Summarize the conversation so the next assistant turn can continue the work without re-reading the full transcript.
200055
200042
 
200056
- Here's an example of how your output should be structured:
200057
-
200058
- <example>
200059
- <analysis>
200060
- [Your thought process, ensuring all points are covered thoroughly and accurately]
200061
- </analysis>
200062
-
200063
- <summary>
200064
- 1. Primary Request and Intent:
200065
- [Detailed description]
200066
-
200067
- 2. Key Technical Concepts:
200068
- - [Concept 1]
200069
- - [Concept 2]
200070
- - [...]
200071
-
200072
- 3. Files and Code Sections:
200073
- - [File Name 1]
200074
- - [Summary of why this file is important]
200075
- - [Summary of the changes made to this file, if any]
200076
- - [Important Code Snippet]
200077
- - [File Name 2]
200078
- - [Important Code Snippet]
200079
- - [...]
200080
-
200081
- 4. Errors and fixes:
200082
- - [Detailed description of error 1]:
200083
- - [How you fixed the error]
200084
- - [User feedback on the error if any]
200085
- - [...]
200086
-
200087
- 5. Problem Solving:
200088
- [Description of solved problems and ongoing troubleshooting]
200089
-
200090
- 6. All user messages:
200091
- - [Detailed non tool use user message]
200092
- - [...]
200093
-
200094
- 7. Pending Tasks:
200095
- - [Task 1]
200096
- - [Task 2]
200097
- - [...]
200098
-
200099
- 8. Current Work:
200100
- [Precise description of current work]
200101
-
200102
- 9. Optional Next Step:
200103
- [Optional Next step to take]
200104
-
200105
- </summary>
200106
- </example>
200107
-
200108
- Please provide your summary based on the conversation so far, following this structure and ensuring precision and thoroughness in your response.
200109
-
200110
- There may be additional summarization instructions provided in the included context. If so, remember to follow these instructions when creating the above summary. Examples of instructions include:
200111
- <example>
200112
- ## Compact Instructions
200113
- When summarizing the conversation focus on typescript code changes and also remember the mistakes you made and how you fixed them.
200114
- </example>
200115
-
200116
- <example>
200117
- # Summary instructions
200118
- When you are using compact - please focus on test output and code changes. Include file reads verbatim.
200119
- </example>
200120
- `;
200121
- PARTIAL_COMPACT_PROMPT = `Your task is to create a detailed summary of the RECENT portion of the conversation — the messages that follow earlier retained context. The earlier messages are being kept intact and do NOT need to be summarized. Focus your summary on what was discussed, learned, and accomplished in the recent messages only.
200043
+ Keep the summary concise and operational. Prefer facts that affect the next action over narrative detail.
200122
200044
 
200123
- ${DETAILED_ANALYSIS_INSTRUCTION_PARTIAL}
200045
+ Include these sections:
200046
+ 1. Current objective: the user's active request and any important constraints.
200047
+ 2. Work completed: key decisions, files changed/read, commands run, and relevant outcomes.
200048
+ 3. Current state: what is in progress, what is known, and what remains uncertain.
200049
+ 4. Important references: filenames, symbols, tests, commands, issue IDs, or config keys needed to continue.
200050
+ 5. Next action: the specific next step that follows from the latest work.
200124
200051
 
200125
- Your summary should include the following sections:
200126
-
200127
- 1. Primary Request and Intent: Capture the user's explicit requests and intents from the recent messages
200128
- 2. Key Technical Concepts: List important technical concepts, technologies, and frameworks discussed recently.
200129
- 3. Files and Code Sections: Enumerate specific files and code sections examined, modified, or created. Include full code snippets where applicable and include a summary of why this file read or edit is important.
200130
- 4. Errors and fixes: List errors encountered and how they were fixed.
200131
- 5. Problem Solving: Document problems solved and any ongoing troubleshooting efforts.
200132
- 6. All user messages: List ALL user messages from the recent portion that are not tool results.
200133
- 7. Pending Tasks: Outline any pending tasks from the recent messages.
200134
- 8. Current Work: Describe precisely what was being worked on immediately before this summary request.
200135
- 9. Optional Next Step: List the next step related to the most recent work. Include direct quotes from the most recent conversation.
200136
-
200137
- Here's an example of how your output should be structured:
200138
-
200139
- <example>
200140
- <analysis>
200141
- [Your thought process, ensuring all points are covered thoroughly and accurately]
200142
- </analysis>
200143
-
200144
- <summary>
200145
- 1. Primary Request and Intent:
200146
- [Detailed description]
200147
-
200148
- 2. Key Technical Concepts:
200149
- - [Concept 1]
200150
- - [Concept 2]
200151
-
200152
- 3. Files and Code Sections:
200153
- - [File Name 1]
200154
- - [Summary of why this file is important]
200155
- - [Important Code Snippet]
200156
-
200157
- 4. Errors and fixes:
200158
- - [Error description]:
200159
- - [How you fixed it]
200160
-
200161
- 5. Problem Solving:
200162
- [Description]
200163
-
200164
- 6. All user messages:
200165
- - [Detailed non tool use user message]
200166
-
200167
- 7. Pending Tasks:
200168
- - [Task 1]
200169
-
200170
- 8. Current Work:
200171
- [Precise description of current work]
200172
-
200173
- 9. Optional Next Step:
200174
- [Optional Next step to take]
200175
-
200176
- </summary>
200177
- </example>
200178
-
200179
- Please provide your summary based on the RECENT messages only (after the retained earlier context), following this structure and ensuring precision and thoroughness in your response.
200180
- `;
200181
- PARTIAL_COMPACT_UP_TO_PROMPT = `Your task is to create a detailed summary of this conversation. This summary will be placed at the start of a continuing session; newer messages that build on this context will follow after your summary (you do not see them here). Summarize thoroughly so that someone reading only your summary and then the newer messages can fully understand what happened and continue the work.
200182
-
200183
- ${DETAILED_ANALYSIS_INSTRUCTION_BASE}
200184
-
200185
- Your summary should include the following sections:
200186
-
200187
- 1. Primary Request and Intent: Capture the user's explicit requests and intents in detail
200188
- 2. Key Technical Concepts: List important technical concepts, technologies, and frameworks discussed.
200189
- 3. Files and Code Sections: Enumerate specific files and code sections examined, modified, or created. Include full code snippets where applicable and include a summary of why this file read or edit is important.
200190
- 4. Errors and fixes: List errors encountered and how they were fixed.
200191
- 5. Problem Solving: Document problems solved and any ongoing troubleshooting efforts.
200192
- 6. All user messages: List ALL user messages that are not tool results.
200193
- 7. Pending Tasks: Outline any pending tasks.
200194
- 8. Work Completed: Describe what was accomplished by the end of this portion.
200195
- 9. Context for Continuing Work: Summarize any context, decisions, or state that would be needed to understand and continue the work in subsequent messages.
200196
-
200197
- Here's an example of how your output should be structured:
200198
-
200199
- <example>
200200
- <analysis>
200201
- [Your thought process, ensuring all points are covered thoroughly and accurately]
200202
- </analysis>
200203
-
200204
- <summary>
200205
- 1. Primary Request and Intent:
200206
- [Detailed description]
200207
-
200208
- 2. Key Technical Concepts:
200209
- - [Concept 1]
200210
- - [Concept 2]
200211
-
200212
- 3. Files and Code Sections:
200213
- - [File Name 1]
200214
- - [Summary of why this file is important]
200215
- - [Important Code Snippet]
200216
-
200217
- 4. Errors and fixes:
200218
- - [Error description]:
200219
- - [How you fixed it]
200220
-
200221
- 5. Problem Solving:
200222
- [Description]
200223
-
200224
- 6. All user messages:
200225
- - [Detailed non tool use user message]
200226
-
200227
- 7. Pending Tasks:
200228
- - [Task 1]
200229
-
200230
- 8. Work Completed:
200231
- [Description of what was accomplished]
200232
-
200233
- 9. Context for Continuing Work:
200234
- [Key context, decisions, or state needed to continue the work]
200052
+ Rules:
200053
+ - Preserve exact filenames, function names, command names, errors, and user requirements.
200054
+ - Do not copy long code snippets or long command output. Mention where they came from instead.
200055
+ - Do not list every user message unless each one changes the task.
200056
+ - If the task is complete, say that clearly and leave "Next action" empty or state that no action remains.
200057
+ - Target 600-1200 words; shorter is better when the state is simple.
200058
+ `, PARTIAL_COMPACT_PROMPT = `Summarize only the recent portion of the conversation. Older retained messages will remain available after your summary, so do not restate them unless the recent work depends on them.
200059
+
200060
+ Include these sections:
200061
+ 1. Recent objective: what the user asked for in the recent messages.
200062
+ 2. Recent work completed: key files, decisions, commands, and outcomes.
200063
+ 3. Current state: what changed, what is still pending, and any blockers.
200064
+ 4. Next action: the specific next step that follows from the latest work.
200235
200065
 
200236
- </summary>
200237
- </example>
200066
+ Rules:
200067
+ - Preserve exact filenames, function names, command names, errors, and user requirements.
200068
+ - Do not copy long code snippets or long command output.
200069
+ - Do not list every user message unless each one changes the task.
200070
+ - Target 400-900 words.
200071
+ `, PARTIAL_COMPACT_UP_TO_PROMPT = `Summarize this earlier portion of the conversation. Newer messages will be preserved verbatim after your summary, so focus on context needed to understand those newer messages.
200072
+
200073
+ Include these sections:
200074
+ 1. Earlier objective and constraints.
200075
+ 2. Work completed and decisions made.
200076
+ 3. Important references: files, symbols, tests, commands, errors, and config values.
200077
+ 4. Context for continuing: facts the later preserved messages depend on.
200238
200078
 
200239
- Please provide your summary following this structure, ensuring precision and thoroughness in your response.
200240
- `;
200241
- NO_TOOLS_TRAILER = `
200079
+ Rules:
200080
+ - Preserve exact filenames, function names, command names, errors, and user requirements.
200081
+ - Do not copy long code snippets or long command output.
200082
+ - Do not list every user message unless each one changes the task.
200083
+ - Target 400-900 words.
200084
+ `, NO_TOOLS_TRAILER = `
200242
200085
 
200243
- REMINDER: Do NOT call any tools. Respond with plain text only ` + "an <analysis> block followed by a <summary> block. " + "Tool calls will be rejected and you will fail the task.";
200244
- });
200086
+ Reminder: respond with plain text only in a single <summary> block. Do not call tools.`;
200245
200087
 
200246
200088
  // src/services/compact/compact.ts
200089
+ function getCompactOutputTokenLimit(model) {
200090
+ const contextTokens = getContextWindowForModel(model, []);
200091
+ const scaledForWindow = Math.max(1024, Math.floor(contextTokens * 0.2));
200092
+ return Math.min(COMPACT_MAX_OUTPUT_TOKENS, getMaxOutputTokensForModel(model), scaledForWindow);
200093
+ }
200247
200094
  function stripImagesFromMessages(messages) {
200248
200095
  return messages.map((message) => {
200249
200096
  if (message.type !== "user") {
@@ -200509,6 +200356,7 @@ async function compactConversation(messages, context4, cacheSafeParams, suppress
200509
200356
  ...postCompactFileAttachments,
200510
200357
  ...hookMessages
200511
200358
  ]);
200359
+ boundaryMarker.compactMetadata.truePostCompactTokenCount = truePostCompactTokenCount;
200512
200360
  const compactionUsage = getTokenUsage(summaryResponse);
200513
200361
  const querySourceForEvent = recompactionInfo?.querySource ?? context4.options.querySource ?? "unknown";
200514
200362
  logEvent("tengu_compact", {
@@ -200802,6 +200650,29 @@ function createCompactCanUseTool() {
200802
200650
  }
200803
200651
  });
200804
200652
  }
200653
+ function normalizeLocalChatCompletionsUrl(baseUrl) {
200654
+ const trimmed = baseUrl.trim().replace(/\/+$/, "");
200655
+ const withV1 = trimmed.endsWith("/v1") ? trimmed : `${trimmed}/v1`;
200656
+ return `${withV1}/chat/completions`;
200657
+ }
200658
+ function isLocalContextOverflowMessage(message) {
200659
+ return LOCAL_CONTEXT_OVERFLOW_PATTERNS.some((pattern) => pattern.test(message));
200660
+ }
200661
+ async function readProviderErrorMessage(response) {
200662
+ try {
200663
+ const payload = await response.clone().json();
200664
+ const message = payload.error?.message ?? payload.message;
200665
+ if (typeof message === "string" && message.trim()) {
200666
+ return message.trim();
200667
+ }
200668
+ } catch {}
200669
+ try {
200670
+ const text = await response.clone().text();
200671
+ if (text.trim())
200672
+ return text.trim();
200673
+ } catch {}
200674
+ return `HTTP ${response.status}`;
200675
+ }
200805
200676
  function serializeMessagesForCleanRoom(messages, maxChars) {
200806
200677
  const parts = [];
200807
200678
  for (const msg of messages) {
@@ -200828,9 +200699,15 @@ ${text}`);
200828
200699
  `);
200829
200700
  if (full.length <= maxChars)
200830
200701
  return full;
200831
- return `[earlier conversation truncated]
200702
+ const headChars = Math.max(1000, Math.floor(maxChars * 0.2));
200703
+ const tailChars = Math.max(1000, maxChars - headChars);
200704
+ return [
200705
+ full.slice(0, headChars),
200706
+ "[middle conversation omitted for local compaction budget]",
200707
+ full.slice(full.length - tailChars)
200708
+ ].join(`
200832
200709
 
200833
- ` + full.slice(full.length - maxChars);
200710
+ `);
200834
200711
  }
200835
200712
  async function tryDirectLocalCompact({
200836
200713
  messages,
@@ -200843,6 +200720,7 @@ async function tryDirectLocalCompact({
200843
200720
  const apiKey = getLocalLLMApiKey();
200844
200721
  if (!baseUrl || !model)
200845
200722
  return null;
200723
+ const outputTokenLimit = getCompactOutputTokenLimit(model);
200846
200724
  const contextTokens = getContextWindowForModel(model, []);
200847
200725
  const charBudget = Math.max(4000, Math.floor(contextTokens * 0.5 * 3.5));
200848
200726
  const serialized = serializeMessagesForCleanRoom(messages, charBudget);
@@ -200856,13 +200734,13 @@ ${serialized}
200856
200734
  </conversation>
200857
200735
 
200858
200736
  ${compactPromptText}`;
200859
- const timeoutMs = parseInt(process.env.COMPACT_TIMEOUT_MS || "", 10) || 5 * 60000;
200737
+ const timeoutMs = LOCAL_COMPACT_TIMEOUT_MS;
200860
200738
  const timeoutController = new AbortController;
200861
200739
  const timer = setTimeout(() => timeoutController.abort(new Error("compact timeout")), timeoutMs);
200862
200740
  const onAbort = () => timeoutController.abort(context4.abortController.signal.reason);
200863
200741
  context4.abortController.signal.addEventListener("abort", onAbort, { once: true });
200864
200742
  try {
200865
- const url2 = `${baseUrl.replace(/\/$/, "")}/chat/completions`;
200743
+ const url2 = normalizeLocalChatCompletionsUrl(baseUrl);
200866
200744
  const res = await fetch(url2, {
200867
200745
  method: "POST",
200868
200746
  headers: {
@@ -200875,14 +200753,20 @@ ${compactPromptText}`;
200875
200753
  { role: "system", content: "You are a helpful assistant that summarizes conversations." },
200876
200754
  { role: "user", content: userText }
200877
200755
  ],
200878
- max_tokens: COMPACT_MAX_OUTPUT_TOKENS,
200756
+ max_tokens: outputTokenLimit,
200879
200757
  temperature: 0.2,
200880
200758
  stream: false
200881
200759
  }),
200882
200760
  signal: timeoutController.signal
200883
200761
  });
200884
200762
  if (!res.ok) {
200885
- logForDebugging(`compact direct-local: HTTP ${res.status}`, { level: "warn" });
200763
+ const providerMessage = await readProviderErrorMessage(res);
200764
+ logForDebugging(`compact direct-local: HTTP ${res.status}: ${providerMessage}`, { level: "warn" });
200765
+ if (isLocalContextOverflowMessage(providerMessage)) {
200766
+ return createAssistantAPIErrorMessage({
200767
+ content: `${PROMPT_TOO_LONG_ERROR_MESSAGE}: ${providerMessage}`
200768
+ });
200769
+ }
200886
200770
  return null;
200887
200771
  }
200888
200772
  const data = await res.json();
@@ -200915,7 +200799,8 @@ async function tryCleanRoomCompactSummary({
200915
200799
  try {
200916
200800
  const model = context4.options.mainLoopModel;
200917
200801
  const contextTokens = getContextWindowForModel(model, []);
200918
- const reserve = Math.min(COMPACT_MAX_OUTPUT_TOKENS, Math.max(2000, Math.floor(contextTokens * 0.25)));
200802
+ const outputTokenLimit = getCompactOutputTokenLimit(model);
200803
+ const reserve = Math.min(outputTokenLimit, Math.max(2000, Math.floor(contextTokens * 0.25)));
200919
200804
  const inputTokens = Math.max(Math.floor(contextTokens * 0.5), contextTokens - reserve - 2000);
200920
200805
  const charBudget = Math.max(4000, Math.floor(inputTokens * 3.5));
200921
200806
  const serialized = serializeMessagesForCleanRoom(messages, charBudget);
@@ -200946,7 +200831,7 @@ ${compactPromptText}`
200946
200831
  toolChoice: undefined,
200947
200832
  isNonInteractiveSession: context4.options.isNonInteractiveSession,
200948
200833
  hasAppendSystemPrompt: false,
200949
- maxOutputTokensOverride: Math.min(COMPACT_MAX_OUTPUT_TOKENS, getMaxOutputTokensForModel(model)),
200834
+ maxOutputTokensOverride: outputTokenLimit,
200950
200835
  querySource: "compact",
200951
200836
  agents: context4.options.agentDefinitions.activeAgents,
200952
200837
  mcpTools: [],
@@ -200993,10 +200878,14 @@ async function streamCompactSummary({
200993
200878
  preCompactTokenCount
200994
200879
  });
200995
200880
  if (directResp) {
200996
- const directText = getAssistantMessageText(directResp);
200997
- if (directText && !directResp.isApiErrorMessage && !directText.startsWith(PROMPT_TOO_LONG_ERROR_MESSAGE)) {
200998
- return directResp;
200999
- }
200881
+ return directResp;
200882
+ }
200883
+ if (isLocalLLMProviderEnabled()) {
200884
+ logEvent("tengu_compact_failed", {
200885
+ reason: "local_direct_compact_failed",
200886
+ preCompactTokenCount
200887
+ });
200888
+ throw new Error(ERROR_MESSAGE_INCOMPLETE_RESPONSE);
201000
200889
  }
201001
200890
  const cleanRoomFirst = await tryCleanRoomCompactSummary({
201002
200891
  messages,
@@ -201081,7 +200970,7 @@ async function streamCompactSummary({
201081
200970
  toolChoice: undefined,
201082
200971
  isNonInteractiveSession: context4.options.isNonInteractiveSession,
201083
200972
  hasAppendSystemPrompt: !!context4.options.appendSystemPrompt,
201084
- maxOutputTokensOverride: Math.min(COMPACT_MAX_OUTPUT_TOKENS, getMaxOutputTokensForModel(context4.options.mainLoopModel)),
200973
+ maxOutputTokensOverride: getCompactOutputTokenLimit(context4.options.mainLoopModel),
201085
200974
  querySource: "compact",
201086
200975
  agents: context4.options.agentDefinitions.activeAgents,
201087
200976
  mcpTools: [],
@@ -201285,7 +201174,7 @@ function shouldExcludeFromPostCompactRestore(filename, agentId) {
201285
201174
  } catch {}
201286
201175
  return false;
201287
201176
  }
201288
- var POST_COMPACT_MAX_FILES_TO_RESTORE = 5, POST_COMPACT_TOKEN_BUDGET = 50000, POST_COMPACT_MAX_TOKENS_PER_FILE = 5000, POST_COMPACT_MAX_TOKENS_PER_SKILL = 5000, POST_COMPACT_SKILLS_TOKEN_BUDGET = 25000, MAX_COMPACT_STREAMING_RETRIES = 2, ERROR_MESSAGE_NOT_ENOUGH_MESSAGES = "Not enough messages to compact.", MAX_PTL_RETRIES = 3, PTL_RETRY_MARKER = "[earlier conversation truncated for compaction retry]", ERROR_MESSAGE_PROMPT_TOO_LONG = "Conversation too long. Press esc twice to go up a few messages and try again.", ERROR_MESSAGE_USER_ABORT = "API Error: Request was aborted.", ERROR_MESSAGE_INCOMPLETE_RESPONSE = "Compaction interrupted · This may be due to network issues — please try again.", SKILL_TRUNCATION_MARKER = `
201177
+ var POST_COMPACT_MAX_FILES_TO_RESTORE = 5, POST_COMPACT_TOKEN_BUDGET = 50000, POST_COMPACT_MAX_TOKENS_PER_FILE = 5000, POST_COMPACT_MAX_TOKENS_PER_SKILL = 5000, POST_COMPACT_SKILLS_TOKEN_BUDGET = 25000, MAX_COMPACT_STREAMING_RETRIES = 2, LOCAL_COMPACT_TIMEOUT_MS = 120000, LOCAL_CONTEXT_OVERFLOW_PATTERNS, ERROR_MESSAGE_NOT_ENOUGH_MESSAGES = "Not enough messages to compact.", MAX_PTL_RETRIES = 3, PTL_RETRY_MARKER = "[earlier conversation truncated for compaction retry]", ERROR_MESSAGE_PROMPT_TOO_LONG = "Conversation too long. Press esc twice to go up a few messages and try again.", ERROR_MESSAGE_USER_ABORT = "API Error: Request was aborted.", ERROR_MESSAGE_INCOMPLETE_RESPONSE = "Compaction interrupted · This may be due to network issues — please try again.", SKILL_TRUNCATION_MARKER = `
201289
201178
 
201290
201179
  [... skill content truncated for compaction; use Read on the skill path if you need the full text]`;
201291
201180
  var init_compact = __esm(() => {
@@ -201324,7 +201213,15 @@ var init_compact = __esm(() => {
201324
201213
  init_withRetry();
201325
201214
  init_internalLogging();
201326
201215
  init_tokenEstimation();
201327
- init_prompt10();
201216
+ LOCAL_CONTEXT_OVERFLOW_PATTERNS = [
201217
+ /prompt is too long/i,
201218
+ /context.{0,20}(length|limit|window).{0,30}exceeded/i,
201219
+ /input.{0,20}(length|limit).{0,30}exceeded/i,
201220
+ /maximum.{0,20}(context|token)/i,
201221
+ /tokens?.{0,20}exceeds?.{0,20}(max|limit|context)/i,
201222
+ /too.{0,5}many.{0,10}tokens/i,
201223
+ /\bKV.{0,10}cache.{0,20}(full|exceeded)/i
201224
+ ];
201328
201225
  });
201329
201226
 
201330
201227
  // src/constants/systemPromptSections.ts
@@ -205725,13 +205622,13 @@ var init_sedValidation = __esm(() => {
205725
205622
 
205726
205623
  // src/tools/BashTool/pathValidation.ts
205727
205624
  import { homedir as homedir15 } from "os";
205728
- import { isAbsolute as isAbsolute12, resolve as resolve21 } from "path";
205625
+ import { isAbsolute as isAbsolute13, resolve as resolve21 } from "path";
205729
205626
  function checkDangerousRemovalPaths(command, args, cwd2) {
205730
205627
  const extractor = PATH_EXTRACTORS[command];
205731
205628
  const paths2 = extractor(args);
205732
205629
  for (const path6 of paths2) {
205733
205630
  const cleanPath = expandTilde(path6.replace(/^['"]|['"]$/g, ""));
205734
- const absolutePath = isAbsolute12(cleanPath) ? cleanPath : resolve21(cwd2, cleanPath);
205631
+ const absolutePath = isAbsolute13(cleanPath) ? cleanPath : resolve21(cwd2, cleanPath);
205735
205632
  if (isDangerousRemovalPath(absolutePath)) {
205736
205633
  return {
205737
205634
  behavior: "ask",
@@ -207640,7 +207537,7 @@ function getTelemetryAttributes() {
207640
207537
  attributes["session.id"] = sessionId;
207641
207538
  }
207642
207539
  if (shouldIncludeAttribute("OTEL_METRICS_INCLUDE_VERSION")) {
207643
- attributes["app.version"] = "2.3.3";
207540
+ attributes["app.version"] = "2.3.5";
207644
207541
  }
207645
207542
  const oauthAccount = getOauthAccountInfo();
207646
207543
  if (oauthAccount) {
@@ -207725,7 +207622,7 @@ var init_events = __esm(() => {
207725
207622
  });
207726
207623
 
207727
207624
  // src/utils/telemetry/betaSessionTracing.ts
207728
- import { createHash as createHash4 } from "crypto";
207625
+ import { createHash as createHash5 } from "crypto";
207729
207626
  function clearBetaTracingState() {
207730
207627
  seenHashes.clear();
207731
207628
  lastReportedMessageHash.clear();
@@ -207752,7 +207649,7 @@ function truncateContent(content, maxSize = MAX_CONTENT_SIZE) {
207752
207649
  };
207753
207650
  }
207754
207651
  function shortHash(content) {
207755
- return createHash4("sha256").update(content).digest("hex").slice(0, 12);
207652
+ return createHash5("sha256").update(content).digest("hex").slice(0, 12);
207756
207653
  }
207757
207654
  function hashSystemPrompt(systemPrompt) {
207758
207655
  return `sp_${shortHash(systemPrompt)}`;
@@ -208092,10 +207989,11 @@ function isAutoCompactEnabled() {
208092
207989
  if (isEnvTruthy(process.env.DISABLE_COMPACT)) {
208093
207990
  return false;
208094
207991
  }
208095
- if (isEnvTruthy(process.env.DISABLE_AUTO_COMPACT)) {
208096
- return false;
207992
+ const projectSetting = getCurrentProjectConfig().autoCompactEnabled;
207993
+ if (typeof projectSetting === "boolean") {
207994
+ return projectSetting;
208097
207995
  }
208098
- return true;
207996
+ return getGlobalConfig().autoCompactEnabled !== false;
208099
207997
  }
208100
207998
  async function shouldAutoCompact(messages, model, querySource, snipTokensFreed = 0) {
208101
207999
  if (querySource === "session_memory" || querySource === "compact" || querySource === "keepgoing_synthesis") {
@@ -208110,6 +208008,14 @@ async function shouldAutoCompact(messages, model, querySource, snipTokensFreed =
208110
208008
  const tokenCount = tokenCountWithEstimation(messages) - snipTokensFreed;
208111
208009
  const threshold = getAutoCompactThreshold(model);
208112
208010
  const effectiveWindow = getEffectiveContextWindowSize(model);
208011
+ const compactBoundaryIndex = findLastCompactBoundaryIndex(messages);
208012
+ if (compactBoundaryIndex >= 0) {
208013
+ const assistantTurnsAfterCompact = messages.slice(compactBoundaryIndex + 1).filter((message) => message.type === "assistant").length;
208014
+ if (assistantTurnsAfterCompact < MIN_ASSISTANT_TURNS_AFTER_COMPACT && tokenCount < effectiveWindow) {
208015
+ logForDebugging(`autocompact: skipping immediate recompact after boundary (assistantTurns=${assistantTurnsAfterCompact} tokens=${tokenCount} threshold=${threshold} effectiveWindow=${effectiveWindow})`);
208016
+ return false;
208017
+ }
208018
+ }
208113
208019
  logForDebugging(`autocompact: tokens=${tokenCount} threshold=${threshold} effectiveWindow=${effectiveWindow}${snipTokensFreed > 0 ? ` snipFreed=${snipTokensFreed}` : ""}`);
208114
208020
  const { isAboveAutoCompactThreshold } = calculateTokenWarningState(tokenCount, model);
208115
208021
  return isAboveAutoCompactThreshold;
@@ -208154,14 +208060,16 @@ async function autoCompactIfNeeded(messages, toolUseContext, cacheSafeParams, qu
208154
208060
  return { wasCompacted: false, consecutiveFailures: nextFailures };
208155
208061
  }
208156
208062
  }
208157
- var MAX_OUTPUT_TOKENS_FOR_SUMMARY = 20000, AUTOCOMPACT_BUFFER_TOKENS = 13000, WARNING_THRESHOLD_BUFFER_TOKENS = 20000, ERROR_THRESHOLD_BUFFER_TOKENS = 20000, MANUAL_COMPACT_BUFFER_TOKENS = 3000, MAX_CONSECUTIVE_AUTOCOMPACT_FAILURES = 3;
208063
+ var MAX_OUTPUT_TOKENS_FOR_SUMMARY = 20000, AUTOCOMPACT_BUFFER_TOKENS = 13000, WARNING_THRESHOLD_BUFFER_TOKENS = 20000, ERROR_THRESHOLD_BUFFER_TOKENS = 20000, MANUAL_COMPACT_BUFFER_TOKENS = 3000, MAX_CONSECUTIVE_AUTOCOMPACT_FAILURES = 3, MIN_ASSISTANT_TURNS_AFTER_COMPACT = 2;
208158
208064
  var init_autoCompact = __esm(() => {
208159
208065
  init_state();
208066
+ init_config();
208160
208067
  init_context();
208161
208068
  init_debug();
208162
208069
  init_envUtils();
208163
208070
  init_errors();
208164
208071
  init_log2();
208072
+ init_messages3();
208165
208073
  init_tokens();
208166
208074
  init_llm();
208167
208075
  init_compact();
@@ -208266,13 +208174,10 @@ function objectGroupBy(items, keySelector) {
208266
208174
  // src/utils/messageQueueManager.ts
208267
208175
  var exports_messageQueueManager = {};
208268
208176
  __export(exports_messageQueueManager, {
208269
- subscribeToPendingNotifications: () => subscribeToPendingNotifications,
208270
208177
  subscribeToCommandQueue: () => subscribeToCommandQueue,
208271
- resetPendingNotifications: () => resetPendingNotifications,
208272
208178
  resetCommandQueue: () => resetCommandQueue,
208273
208179
  removeByFilter: () => removeByFilter,
208274
208180
  remove: () => remove,
208275
- recheckPendingNotifications: () => recheckPendingNotifications,
208276
208181
  recheckCommandQueue: () => recheckCommandQueue,
208277
208182
  popAllEditable: () => popAllEditable,
208278
208183
  peek: () => peek,
@@ -208280,21 +208185,16 @@ __export(exports_messageQueueManager, {
208280
208185
  isQueuedCommandVisible: () => isQueuedCommandVisible,
208281
208186
  isQueuedCommandEditable: () => isQueuedCommandEditable,
208282
208187
  isPromptInputModeEditable: () => isPromptInputModeEditable,
208283
- hasPendingNotifications: () => hasPendingNotifications,
208284
208188
  hasCommandsInQueue: () => hasCommandsInQueue,
208285
- getPendingNotificationsSnapshot: () => getPendingNotificationsSnapshot,
208286
- getPendingNotificationsCount: () => getPendingNotificationsCount,
208287
208189
  getCommandsByMaxPriority: () => getCommandsByMaxPriority,
208288
208190
  getCommandQueueSnapshot: () => getCommandQueueSnapshot,
208289
208191
  getCommandQueueLength: () => getCommandQueueLength,
208290
208192
  getCommandQueue: () => getCommandQueue,
208291
208193
  enqueuePendingNotification: () => enqueuePendingNotification,
208292
208194
  enqueue: () => enqueue,
208293
- dequeuePendingNotification: () => dequeuePendingNotification,
208294
208195
  dequeueAllMatching: () => dequeueAllMatching,
208295
208196
  dequeueAll: () => dequeueAll,
208296
208197
  dequeue: () => dequeue,
208297
- clearPendingNotifications: () => clearPendingNotifications,
208298
208198
  clearCommandQueue: () => clearCommandQueue
208299
208199
  });
208300
208200
  function logOperation(operation, content) {
@@ -208528,12 +208428,6 @@ function popAllEditable(currentInput, currentCursorOffset) {
208528
208428
  notifySubscribers();
208529
208429
  return { text: newInput, cursorOffset, images };
208530
208430
  }
208531
- function getPendingNotificationsSnapshot() {
208532
- return snapshot;
208533
- }
208534
- function dequeuePendingNotification() {
208535
- return dequeue();
208536
- }
208537
208431
  function getCommandsByMaxPriority(maxPriority) {
208538
208432
  const threshold = PRIORITY_ORDER[maxPriority];
208539
208433
  return commandQueue.filter((cmd) => PRIORITY_ORDER[cmd.priority ?? "next"] <= threshold);
@@ -208541,7 +208435,7 @@ function getCommandsByMaxPriority(maxPriority) {
208541
208435
  function isSlashCommand(cmd) {
208542
208436
  return typeof cmd.value === "string" && cmd.value.trim().startsWith("/") && !cmd.skipSlashCommands;
208543
208437
  }
208544
- var commandQueue, snapshot, queueChanged, subscribeToCommandQueue, PRIORITY_ORDER, NON_EDITABLE_MODES, subscribeToPendingNotifications, hasPendingNotifications, getPendingNotificationsCount, recheckPendingNotifications, resetPendingNotifications, clearPendingNotifications;
208438
+ var commandQueue, snapshot, queueChanged, subscribeToCommandQueue, PRIORITY_ORDER, NON_EDITABLE_MODES;
208545
208439
  var init_messageQueueManager = __esm(() => {
208546
208440
  init_state();
208547
208441
  init_messages3();
@@ -208558,12 +208452,6 @@ var init_messageQueueManager = __esm(() => {
208558
208452
  NON_EDITABLE_MODES = new Set([
208559
208453
  "task-notification"
208560
208454
  ]);
208561
- subscribeToPendingNotifications = subscribeToCommandQueue;
208562
- hasPendingNotifications = hasCommandsInQueue;
208563
- getPendingNotificationsCount = getCommandQueueLength;
208564
- recheckPendingNotifications = recheckCommandQueue;
208565
- resetPendingNotifications = resetCommandQueue;
208566
- clearPendingNotifications = clearCommandQueue;
208567
208455
  });
208568
208456
 
208569
208457
  // src/utils/commandLifecycle.ts
@@ -208671,7 +208559,7 @@ var init_headlessProfiler = __esm(() => {
208671
208559
 
208672
208560
  // src/tools/SleepTool/prompt.ts
208673
208561
  var SLEEP_TOOL_NAME = "Sleep", SLEEP_TOOL_PROMPT;
208674
- var init_prompt11 = __esm(() => {
208562
+ var init_prompt10 = __esm(() => {
208675
208563
  init_xml();
208676
208564
  SLEEP_TOOL_PROMPT = `Wait for a specified duration. The user can interrupt the sleep at any time.
208677
208565
 
@@ -208715,11 +208603,11 @@ var init_postSamplingHooks = __esm(() => {
208715
208603
  });
208716
208604
 
208717
208605
  // src/services/api/dumpPrompts.ts
208718
- import { createHash as createHash5 } from "crypto";
208606
+ import { createHash as createHash6 } from "crypto";
208719
208607
  import { promises as fs3 } from "fs";
208720
208608
  import { dirname as dirname22, join as join44 } from "path";
208721
208609
  function hashString3(str2) {
208722
- return createHash5("sha256").update(str2).digest("hex");
208610
+ return createHash6("sha256").update(str2).digest("hex");
208723
208611
  }
208724
208612
  function clearDumpState(agentIdOrSessionId) {
208725
208613
  dumpState.delete(agentIdOrSessionId);
@@ -253766,49 +253654,49 @@ var require_fast_uri = __commonJS((exports, module) => {
253766
253654
  schemelessOptions.skipEscape = true;
253767
253655
  return serialize(resolved, schemelessOptions);
253768
253656
  }
253769
- function resolveComponent(base, relative7, options, skipNormalization) {
253657
+ function resolveComponent(base, relative8, options, skipNormalization) {
253770
253658
  const target = {};
253771
253659
  if (!skipNormalization) {
253772
253660
  base = parse4(serialize(base, options), options);
253773
- relative7 = parse4(serialize(relative7, options), options);
253661
+ relative8 = parse4(serialize(relative8, options), options);
253774
253662
  }
253775
253663
  options = options || {};
253776
- if (!options.tolerant && relative7.scheme) {
253777
- target.scheme = relative7.scheme;
253778
- target.userinfo = relative7.userinfo;
253779
- target.host = relative7.host;
253780
- target.port = relative7.port;
253781
- target.path = removeDotSegments(relative7.path || "");
253782
- target.query = relative7.query;
253783
- } else {
253784
- if (relative7.userinfo !== undefined || relative7.host !== undefined || relative7.port !== undefined) {
253785
- target.userinfo = relative7.userinfo;
253786
- target.host = relative7.host;
253787
- target.port = relative7.port;
253788
- target.path = removeDotSegments(relative7.path || "");
253789
- target.query = relative7.query;
253790
- } else {
253791
- if (!relative7.path) {
253664
+ if (!options.tolerant && relative8.scheme) {
253665
+ target.scheme = relative8.scheme;
253666
+ target.userinfo = relative8.userinfo;
253667
+ target.host = relative8.host;
253668
+ target.port = relative8.port;
253669
+ target.path = removeDotSegments(relative8.path || "");
253670
+ target.query = relative8.query;
253671
+ } else {
253672
+ if (relative8.userinfo !== undefined || relative8.host !== undefined || relative8.port !== undefined) {
253673
+ target.userinfo = relative8.userinfo;
253674
+ target.host = relative8.host;
253675
+ target.port = relative8.port;
253676
+ target.path = removeDotSegments(relative8.path || "");
253677
+ target.query = relative8.query;
253678
+ } else {
253679
+ if (!relative8.path) {
253792
253680
  target.path = base.path;
253793
- if (relative7.query !== undefined) {
253794
- target.query = relative7.query;
253681
+ if (relative8.query !== undefined) {
253682
+ target.query = relative8.query;
253795
253683
  } else {
253796
253684
  target.query = base.query;
253797
253685
  }
253798
253686
  } else {
253799
- if (relative7.path[0] === "/") {
253800
- target.path = removeDotSegments(relative7.path);
253687
+ if (relative8.path[0] === "/") {
253688
+ target.path = removeDotSegments(relative8.path);
253801
253689
  } else {
253802
253690
  if ((base.userinfo !== undefined || base.host !== undefined || base.port !== undefined) && !base.path) {
253803
- target.path = "/" + relative7.path;
253691
+ target.path = "/" + relative8.path;
253804
253692
  } else if (!base.path) {
253805
- target.path = relative7.path;
253693
+ target.path = relative8.path;
253806
253694
  } else {
253807
- target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) + relative7.path;
253695
+ target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) + relative8.path;
253808
253696
  }
253809
253697
  target.path = removeDotSegments(target.path);
253810
253698
  }
253811
- target.query = relative7.query;
253699
+ target.query = relative8.query;
253812
253700
  }
253813
253701
  target.userinfo = base.userinfo;
253814
253702
  target.host = base.host;
@@ -253816,7 +253704,7 @@ var require_fast_uri = __commonJS((exports, module) => {
253816
253704
  }
253817
253705
  target.scheme = base.scheme;
253818
253706
  }
253819
- target.fragment = relative7.fragment;
253707
+ target.fragment = relative8.fragment;
253820
253708
  return target;
253821
253709
  }
253822
253710
  function equal(uriA, uriB, options) {
@@ -256663,7 +256551,7 @@ function isKairosCronEnabled() {
256663
256551
  return false;
256664
256552
  }
256665
256553
  var KAIROS_CRON_REFRESH_MS, DEFAULT_MAX_AGE_DAYS;
256666
- var init_prompt12 = __esm(() => {
256554
+ var init_prompt11 = __esm(() => {
256667
256555
  init_cronTasks();
256668
256556
  init_envUtils();
256669
256557
  KAIROS_CRON_REFRESH_MS = 5 * 60 * 1000;
@@ -256682,7 +256570,7 @@ var init_tools = __esm(() => {
256682
256570
  init_prompt3();
256683
256571
  init_prompt8();
256684
256572
  init_SyntheticOutputTool();
256685
- init_prompt12();
256573
+ init_prompt11();
256686
256574
  ALL_AGENT_DISALLOWED_TOOLS = new Set([
256687
256575
  TASK_OUTPUT_TOOL_NAME,
256688
256576
  EXIT_PLAN_MODE_TOOL_NAME,
@@ -265698,7 +265586,7 @@ var init_config2 = __esm(() => {
265698
265586
  });
265699
265587
 
265700
265588
  // src/services/mcp/utils.ts
265701
- import { createHash as createHash6 } from "crypto";
265589
+ import { createHash as createHash7 } from "crypto";
265702
265590
  import { join as join48 } from "path";
265703
265591
  function filterToolsByServer(tools, serverName) {
265704
265592
  const prefix = `mcp__${normalizeNameForMCP(serverName)}__`;
@@ -265738,7 +265626,7 @@ function hashMcpConfig(config) {
265738
265626
  }
265739
265627
  return v2;
265740
265628
  });
265741
- return createHash6("sha256").update(stable).digest("hex").slice(0, 16);
265629
+ return createHash7("sha256").update(stable).digest("hex").slice(0, 16);
265742
265630
  }
265743
265631
  function excludeStalePluginClients(mcp, configs) {
265744
265632
  const stale = mcp.clients.filter((c5) => {
@@ -266483,7 +266371,7 @@ var init_xaaIdpLogin = __esm(() => {
266483
266371
  });
266484
266372
 
266485
266373
  // src/services/mcp/auth.ts
266486
- import { createHash as createHash7, randomBytes as randomBytes6, randomUUID as randomUUID6 } from "crypto";
266374
+ import { createHash as createHash8, randomBytes as randomBytes6, randomUUID as randomUUID6 } from "crypto";
266487
266375
  import { mkdir as mkdir9 } from "fs/promises";
266488
266376
  import { createServer as createServer3 } from "http";
266489
266377
  import { join as join49 } from "path";
@@ -266597,7 +266485,7 @@ function getServerKey(serverName, serverConfig) {
266597
266485
  url: serverConfig.url,
266598
266486
  headers: serverConfig.headers || {}
266599
266487
  });
266600
- const hash = createHash7("sha256").update(configJson).digest("hex").substring(0, 16);
266488
+ const hash = createHash8("sha256").update(configJson).digest("hex").substring(0, 16);
266601
266489
  return `${serverName}|${hash}`;
266602
266490
  }
266603
266491
  function hasMcpDiscoveryButNoToken(serverName, serverConfig) {
@@ -269518,7 +269406,7 @@ var init_IdeOnboardingDialog = __esm(() => {
269518
269406
  import { execa as execa7 } from "execa";
269519
269407
  import { createConnection } from "net";
269520
269408
  import * as os5 from "os";
269521
- import { basename as basename13, join as join52, sep as pathSeparator, resolve as resolve22 } from "path";
269409
+ import { basename as basename14, join as join52, sep as pathSeparator, resolve as resolve22 } from "path";
269522
269410
  function isProcessRunning2(pid) {
269523
269411
  try {
269524
269412
  process.kill(pid, 0);
@@ -269928,7 +269816,7 @@ function getInstallationEnv() {
269928
269816
  return;
269929
269817
  }
269930
269818
  function getClaudeCodeVersion() {
269931
- return "2.3.3";
269819
+ return "2.3.5";
269932
269820
  }
269933
269821
  async function getInstalledVSCodeExtensionVersion(command) {
269934
269822
  const { stdout } = await execFileNoThrow(command, ["--list-extensions", "--show-versions"], {
@@ -270097,7 +269985,7 @@ function toIDEDisplayName(terminal) {
270097
269985
  return editorName;
270098
269986
  }
270099
269987
  const command = terminal.split(" ")[0];
270100
- const commandName = command ? basename13(command).toLowerCase() : null;
269988
+ const commandName = command ? basename14(command).toLowerCase() : null;
270101
269989
  if (commandName) {
270102
269990
  const mappedName = EDITOR_DISPLAY_NAMES[commandName];
270103
269991
  if (mappedName) {
@@ -273118,7 +273006,7 @@ var require_websocket2 = __commonJS((exports, module) => {
273118
273006
  var http4 = __require("http");
273119
273007
  var net3 = __require("net");
273120
273008
  var tls2 = __require("tls");
273121
- var { randomBytes: randomBytes7, createHash: createHash8 } = __require("crypto");
273009
+ var { randomBytes: randomBytes7, createHash: createHash9 } = __require("crypto");
273122
273010
  var { Duplex, Readable: Readable3 } = __require("stream");
273123
273011
  var { URL: URL3 } = __require("url");
273124
273012
  var PerMessageDeflate = require_permessage_deflate2();
@@ -273657,7 +273545,7 @@ var require_websocket2 = __commonJS((exports, module) => {
273657
273545
  abortHandshake(websocket, socket, "Invalid Upgrade header");
273658
273546
  return;
273659
273547
  }
273660
- const digest = createHash8("sha1").update(key + GUID).digest("base64");
273548
+ const digest = createHash9("sha1").update(key + GUID).digest("base64");
273661
273549
  if (res.headers["sec-websocket-accept"] !== digest) {
273662
273550
  abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Accept header");
273663
273551
  return;
@@ -274030,7 +273918,7 @@ var require_websocket_server = __commonJS((exports, module) => {
274030
273918
  var EventEmitter4 = __require("events");
274031
273919
  var http4 = __require("http");
274032
273920
  var { Duplex } = __require("stream");
274033
- var { createHash: createHash8 } = __require("crypto");
273921
+ var { createHash: createHash9 } = __require("crypto");
274034
273922
  var extension = require_extension();
274035
273923
  var PerMessageDeflate = require_permessage_deflate2();
274036
273924
  var subprotocol = require_subprotocol();
@@ -274243,7 +274131,7 @@ var require_websocket_server = __commonJS((exports, module) => {
274243
274131
  }
274244
274132
  if (this._state > RUNNING)
274245
274133
  return abortHandshake(socket, 503);
274246
- const digest = createHash8("sha1").update(key + GUID).digest("base64");
274134
+ const digest = createHash9("sha1").update(key + GUID).digest("base64");
274247
274135
  const headers = [
274248
274136
  "HTTP/1.1 101 Switching Protocols",
274249
274137
  "Upgrade: websocket",
@@ -275202,7 +275090,7 @@ async function setupSdkMcpClients(sdkMcpConfigs, sendMcpMessage) {
275202
275090
  const client4 = new Client({
275203
275091
  name: "localclawd",
275204
275092
  title: "localclawd",
275205
- version: "2.3.3",
275093
+ version: "2.3.5",
275206
275094
  description: "local-first AI coding tool",
275207
275095
  websiteUrl: PRODUCT_URL
275208
275096
  }, {
@@ -275544,7 +275432,7 @@ var init_client9 = __esm(() => {
275544
275432
  const client4 = new Client({
275545
275433
  name: "localclawd",
275546
275434
  title: "localclawd",
275547
- version: "2.3.3",
275435
+ version: "2.3.5",
275548
275436
  description: "local-first AI coding tool",
275549
275437
  websiteUrl: PRODUCT_URL
275550
275438
  }, {
@@ -276553,12 +276441,12 @@ var init_LSPDiagnosticRegistry = __esm(() => {
276553
276441
 
276554
276442
  // src/utils/plugins/lspPluginIntegration.ts
276555
276443
  import { readFile as readFile14 } from "fs/promises";
276556
- import { join as join54, relative as relative7, resolve as resolve23 } from "path";
276444
+ import { join as join54, relative as relative8, resolve as resolve23 } from "path";
276557
276445
  import { z as z27 } from "zod/v4";
276558
276446
  function validatePathWithinPlugin(pluginPath, relativePath) {
276559
276447
  const resolvedPluginPath = resolve23(pluginPath);
276560
276448
  const resolvedFilePath = resolve23(pluginPath, relativePath);
276561
- const rel = relative7(resolvedPluginPath, resolvedFilePath);
276449
+ const rel = relative8(resolvedPluginPath, resolvedFilePath);
276562
276450
  if (rel.startsWith("..") || resolve23(rel) === rel) {
276563
276451
  return null;
276564
276452
  }
@@ -281325,7 +281213,7 @@ var init_diff2 = __esm(() => {
281325
281213
  });
281326
281214
 
281327
281215
  // src/utils/fileHistory.ts
281328
- import { createHash as createHash8 } from "crypto";
281216
+ import { createHash as createHash9 } from "crypto";
281329
281217
  import {
281330
281218
  chmod as chmod3,
281331
281219
  copyFile as copyFile3,
@@ -281335,7 +281223,7 @@ import {
281335
281223
  stat as stat21,
281336
281224
  unlink as unlink5
281337
281225
  } from "fs/promises";
281338
- import { dirname as dirname25, isAbsolute as isAbsolute13, join as join55, relative as relative8 } from "path";
281226
+ import { dirname as dirname25, isAbsolute as isAbsolute14, join as join55, relative as relative9 } from "path";
281339
281227
  import { inspect } from "util";
281340
281228
  function fileHistoryEnabled() {
281341
281229
  if (getIsNonInteractiveSession()) {
@@ -281749,7 +281637,7 @@ async function computeDiffStatsForFile(originalFile, backupFileName) {
281749
281637
  };
281750
281638
  }
281751
281639
  function getBackupFileName(filePath, version) {
281752
- const fileNameHash = createHash8("sha256").update(filePath).digest("hex").slice(0, 16);
281640
+ const fileNameHash = createHash9("sha256").update(filePath).digest("hex").slice(0, 16);
281753
281641
  return `${fileNameHash}@v${version}`;
281754
281642
  }
281755
281643
  function resolveBackupPath(backupFileName, sessionId) {
@@ -281823,17 +281711,17 @@ function getBackupFileNameFirstVersion(trackingPath, state) {
281823
281711
  return;
281824
281712
  }
281825
281713
  function maybeShortenFilePath(filePath) {
281826
- if (!isAbsolute13(filePath)) {
281714
+ if (!isAbsolute14(filePath)) {
281827
281715
  return filePath;
281828
281716
  }
281829
281717
  const cwd2 = getOriginalCwd();
281830
281718
  if (filePath.startsWith(cwd2)) {
281831
- return relative8(cwd2, filePath);
281719
+ return relative9(cwd2, filePath);
281832
281720
  }
281833
281721
  return filePath;
281834
281722
  }
281835
281723
  function maybeExpandFilePath(filePath) {
281836
- if (isAbsolute13(filePath)) {
281724
+ if (isAbsolute14(filePath)) {
281837
281725
  return filePath;
281838
281726
  }
281839
281727
  return join55(getOriginalCwd(), filePath);
@@ -281985,12 +281873,12 @@ var init_fileHistory = __esm(() => {
281985
281873
  });
281986
281874
 
281987
281875
  // src/utils/fileOperationAnalytics.ts
281988
- import { createHash as createHash9 } from "crypto";
281876
+ import { createHash as createHash10 } from "crypto";
281989
281877
  function hashFilePath(filePath) {
281990
- return createHash9("sha256").update(filePath).digest("hex").slice(0, 16);
281878
+ return createHash10("sha256").update(filePath).digest("hex").slice(0, 16);
281991
281879
  }
281992
281880
  function hashFileContent(content) {
281993
- return createHash9("sha256").update(content).digest("hex");
281881
+ return createHash10("sha256").update(content).digest("hex");
281994
281882
  }
281995
281883
  function logFileOperation(params) {
281996
281884
  const metadata = {
@@ -282013,7 +281901,7 @@ var init_fileOperationAnalytics = __esm(() => {
282013
281901
 
282014
281902
  // src/utils/gitDiff.ts
282015
281903
  import { access as access2, readFile as readFile16 } from "fs/promises";
282016
- import { dirname as dirname26, join as join56, relative as relative9, sep as sep11 } from "path";
281904
+ import { dirname as dirname26, join as join56, relative as relative10, sep as sep11 } from "path";
282017
281905
  async function fetchGitDiff() {
282018
281906
  const isGit = await getIsGit();
282019
281907
  if (!isGit)
@@ -282200,7 +282088,7 @@ async function fetchSingleFileGitDiff(absoluteFilePath) {
282200
282088
  const gitRoot = findGitRoot(dirname26(absoluteFilePath));
282201
282089
  if (!gitRoot)
282202
282090
  return null;
282203
- const gitPath = relative9(gitRoot, absoluteFilePath).split(sep11).join("/");
282091
+ const gitPath = relative10(gitRoot, absoluteFilePath).split(sep11).join("/");
282204
282092
  const repository = getCachedRepository();
282205
282093
  const { code: lsFilesCode } = await execFileNoThrowWithCwd(gitExe(), ["--no-optional-locks", "ls-files", "--error-unmatch", gitPath], { cwd: gitRoot, timeout: SINGLE_FILE_DIFF_TIMEOUT_MS });
282206
282094
  if (lsFilesCode === 0) {
@@ -282346,7 +282234,7 @@ Usage:${getPreReadInstruction2()}
282346
282234
  - The edit will FAIL if \`old_string\` is not unique in the file. Either provide a larger string with more surrounding context to make it unique or use \`replace_all\` to change every instance of \`old_string\`.${minimalUniquenessHint}
282347
282235
  - Use \`replace_all\` for replacing and renaming strings across the file. This parameter is useful if you want to rename a variable for instance.`;
282348
282236
  }
282349
- var init_prompt13 = __esm(() => {
282237
+ var init_prompt12 = __esm(() => {
282350
282238
  init_file();
282351
282239
  init_prompt2();
282352
282240
  });
@@ -283457,7 +283345,7 @@ var init_StructuredDiffList = __esm(() => {
283457
283345
  });
283458
283346
 
283459
283347
  // src/components/FileEditToolUseRejectedMessage.tsx
283460
- import { relative as relative10 } from "path";
283348
+ import { relative as relative11 } from "path";
283461
283349
  function FileEditToolUseRejectedMessage(t0) {
283462
283350
  const $2 = c3(38);
283463
283351
  const {
@@ -283490,7 +283378,7 @@ function FileEditToolUseRejectedMessage(t0) {
283490
283378
  }
283491
283379
  let t2;
283492
283380
  if ($2[2] !== file_path || $2[3] !== verbose) {
283493
- t2 = verbose ? file_path : relative10(getCwd(), file_path);
283381
+ t2 = verbose ? file_path : relative11(getCwd(), file_path);
283494
283382
  $2[2] = file_path;
283495
283383
  $2[3] = verbose;
283496
283384
  $2[4] = t2;
@@ -284669,7 +284557,7 @@ var init_UI6 = __esm(() => {
284669
284557
  });
284670
284558
 
284671
284559
  // src/tools/FileEditTool/FileEditTool.ts
284672
- import { dirname as dirname27, isAbsolute as isAbsolute14, sep as sep12 } from "path";
284560
+ import { dirname as dirname27, isAbsolute as isAbsolute15, sep as sep12 } from "path";
284673
284561
  function readFileForEdit(absoluteFilePath) {
284674
284562
  try {
284675
284563
  const meta = readFileSyncWithMetadata(absoluteFilePath);
@@ -284716,7 +284604,7 @@ var init_FileEditTool = __esm(() => {
284716
284604
  init_filesystem();
284717
284605
  init_shellRuleMatching();
284718
284606
  init_validateEditTool();
284719
- init_prompt13();
284607
+ init_prompt12();
284720
284608
  init_types6();
284721
284609
  init_UI6();
284722
284610
  init_utils6();
@@ -284871,7 +284759,7 @@ var init_FileEditTool = __esm(() => {
284871
284759
  behavior: "ask",
284872
284760
  message: "File has not been read yet. Read it first before writing to it.",
284873
284761
  meta: {
284874
- isFilePathAbsolute: String(isAbsolute14(file_path))
284762
+ isFilePathAbsolute: String(isAbsolute15(file_path))
284875
284763
  },
284876
284764
  errorCode: 6
284877
284765
  };
@@ -284899,7 +284787,7 @@ var init_FileEditTool = __esm(() => {
284899
284787
  message: `String to replace not found in file.
284900
284788
  String: ${old_string}`,
284901
284789
  meta: {
284902
- isFilePathAbsolute: String(isAbsolute14(file_path))
284790
+ isFilePathAbsolute: String(isAbsolute15(file_path))
284903
284791
  },
284904
284792
  errorCode: 8
284905
284793
  };
@@ -284912,7 +284800,7 @@ String: ${old_string}`,
284912
284800
  message: `Found ${matches} matches of the string to replace, but replace_all is false. To replace all occurrences, set replace_all to true. To replace only one occurrence, please provide more context to uniquely identify the instance.
284913
284801
  String: ${old_string}`,
284914
284802
  meta: {
284915
- isFilePathAbsolute: String(isAbsolute14(file_path)),
284803
+ isFilePathAbsolute: String(isAbsolute15(file_path)),
284916
284804
  actualOldString
284917
284805
  },
284918
284806
  errorCode: 9
@@ -285078,7 +284966,7 @@ String: ${old_string}`,
285078
284966
  });
285079
284967
 
285080
284968
  // src/tools/FileWriteTool/UI.tsx
285081
- import { isAbsolute as isAbsolute15, resolve as resolve25 } from "path";
284969
+ import { isAbsolute as isAbsolute16, resolve as resolve25 } from "path";
285082
284970
  function countLines(content) {
285083
284971
  const parts = content.split(EOL2);
285084
284972
  return content.endsWith(EOL2) ? parts.length - 1 : parts.length;
@@ -285402,7 +285290,7 @@ function WriteRejectionBody(t0) {
285402
285290
  }
285403
285291
  async function loadRejectionDiff2(filePath, content) {
285404
285292
  try {
285405
- const fullFilePath = isAbsolute15(filePath) ? filePath : resolve25(getCwd(), filePath);
285293
+ const fullFilePath = isAbsolute16(filePath) ? filePath : resolve25(getCwd(), filePath);
285406
285294
  const handle = await openForScan(fullFilePath);
285407
285295
  if (handle === null)
285408
285296
  return {
@@ -285829,7 +285717,7 @@ var init_FileWriteTool = __esm(() => {
285829
285717
  });
285830
285718
 
285831
285719
  // src/utils/plugins/orphanedPluginFilter.ts
285832
- import { dirname as dirname29, isAbsolute as isAbsolute16, join as join57, normalize as normalize9, relative as relative11, sep as sep14 } from "path";
285720
+ import { dirname as dirname29, isAbsolute as isAbsolute17, join as join57, normalize as normalize9, relative as relative12, sep as sep14 } from "path";
285833
285721
  async function getGlobExclusionsForPluginCache(searchPath) {
285834
285722
  const cachePath = normalize9(join57(getPluginsDirectory(), "cache"));
285835
285723
  if (searchPath && !pathsOverlap(searchPath, cachePath)) {
@@ -285850,7 +285738,7 @@ async function getGlobExclusionsForPluginCache(searchPath) {
285850
285738
  ], cachePath, new AbortController().signal);
285851
285739
  cachedExclusions = markers.map((markerPath) => {
285852
285740
  const versionDir = dirname29(markerPath);
285853
- const rel = isAbsolute16(versionDir) ? relative11(cachePath, versionDir) : versionDir;
285741
+ const rel = isAbsolute17(versionDir) ? relative12(cachePath, versionDir) : versionDir;
285854
285742
  const posixRelative = rel.replace(/\\/g, "/");
285855
285743
  return `!**/${posixRelative}/**`;
285856
285744
  });
@@ -285879,13 +285767,13 @@ var init_orphanedPluginFilter = __esm(() => {
285879
285767
  });
285880
285768
 
285881
285769
  // src/utils/glob.ts
285882
- import { basename as basename15, dirname as dirname30, isAbsolute as isAbsolute17, join as join58, sep as sep15 } from "path";
285770
+ import { basename as basename16, dirname as dirname30, isAbsolute as isAbsolute18, join as join58, sep as sep15 } from "path";
285883
285771
  function extractGlobBaseDirectory(pattern) {
285884
285772
  const globChars = /[*?[{]/;
285885
285773
  const match = pattern.match(globChars);
285886
285774
  if (!match || match.index === undefined) {
285887
285775
  const dir = dirname30(pattern);
285888
- const file = basename15(pattern);
285776
+ const file = basename16(pattern);
285889
285777
  return { baseDir: dir, relativePattern: file };
285890
285778
  }
285891
285779
  const staticPrefix = pattern.slice(0, match.index);
@@ -285906,7 +285794,7 @@ function extractGlobBaseDirectory(pattern) {
285906
285794
  async function glob(filePattern, cwd2, { limit, offset }, abortSignal, toolPermissionContext) {
285907
285795
  let searchDir = cwd2;
285908
285796
  let searchPattern = filePattern;
285909
- if (isAbsolute17(filePattern)) {
285797
+ if (isAbsolute18(filePattern)) {
285910
285798
  const { baseDir, relativePattern } = extractGlobBaseDirectory(filePattern);
285911
285799
  if (baseDir) {
285912
285800
  searchDir = baseDir;
@@ -285931,7 +285819,7 @@ async function glob(filePattern, cwd2, { limit, offset }, abortSignal, toolPermi
285931
285819
  args.push("--glob", exclusion);
285932
285820
  }
285933
285821
  const allPaths = await ripGrep(args, searchDir, abortSignal);
285934
- const absolutePaths = allPaths.map((p) => isAbsolute17(p) ? p : join58(searchDir, p));
285822
+ const absolutePaths = allPaths.map((p) => isAbsolute18(p) ? p : join58(searchDir, p));
285935
285823
  const truncated = absolutePaths.length > offset + limit;
285936
285824
  const files = absolutePaths.slice(offset, offset + limit);
285937
285825
  return { files, truncated };
@@ -286972,7 +286860,7 @@ var init_notebook = __esm(() => {
286972
286860
  var DESCRIPTION9 = "Replace the contents of a specific cell in a Jupyter notebook.", PROMPT4 = `Completely replaces the contents of a specific cell in a Jupyter notebook (.ipynb file) with new source. Jupyter notebooks are interactive documents that combine code, text, and visualizations, commonly used for data analysis and scientific computing. The notebook_path parameter must be an absolute path, not a relative path. The cell_number is 0-indexed. Use edit_mode=insert to add a new cell at the index specified by cell_number. Use edit_mode=delete to delete the cell at the index specified by cell_number.`;
286973
286861
 
286974
286862
  // src/components/NotebookEditToolUseRejectedMessage.tsx
286975
- import { relative as relative12 } from "path";
286863
+ import { relative as relative13 } from "path";
286976
286864
  function NotebookEditToolUseRejectedMessage(t0) {
286977
286865
  const $2 = c3(20);
286978
286866
  const {
@@ -287002,7 +286890,7 @@ function NotebookEditToolUseRejectedMessage(t0) {
287002
286890
  }
287003
286891
  let t3;
287004
286892
  if ($2[2] !== notebook_path || $2[3] !== verbose) {
287005
- t3 = verbose ? notebook_path : relative12(getCwd(), notebook_path);
286893
+ t3 = verbose ? notebook_path : relative13(getCwd(), notebook_path);
287006
286894
  $2[2] = notebook_path;
287007
286895
  $2[3] = verbose;
287008
286896
  $2[4] = t3;
@@ -287219,7 +287107,7 @@ var init_UI10 = __esm(() => {
287219
287107
  });
287220
287108
 
287221
287109
  // src/tools/NotebookEditTool/NotebookEditTool.ts
287222
- import { extname as extname8, isAbsolute as isAbsolute18, resolve as resolve26 } from "path";
287110
+ import { extname as extname8, isAbsolute as isAbsolute19, resolve as resolve26 } from "path";
287223
287111
  import { z as z32 } from "zod/v4";
287224
287112
  var inputSchema12, outputSchema11, NotebookEditTool;
287225
287113
  var init_NotebookEditTool = __esm(() => {
@@ -287329,7 +287217,7 @@ var init_NotebookEditTool = __esm(() => {
287329
287217
  renderToolUseErrorMessage: renderToolUseErrorMessage7,
287330
287218
  renderToolResultMessage: renderToolResultMessage10,
287331
287219
  async validateInput({ notebook_path, cell_type, cell_id, edit_mode = "replace" }, toolUseContext) {
287332
- const fullPath = isAbsolute18(notebook_path) ? notebook_path : resolve26(getCwd(), notebook_path);
287220
+ const fullPath = isAbsolute19(notebook_path) ? notebook_path : resolve26(getCwd(), notebook_path);
287333
287221
  if (fullPath.startsWith("\\\\") || fullPath.startsWith("//")) {
287334
287222
  return { result: true };
287335
287223
  }
@@ -287428,7 +287316,7 @@ var init_NotebookEditTool = __esm(() => {
287428
287316
  cell_type,
287429
287317
  edit_mode: originalEditMode
287430
287318
  }, { readFileState, updateFileHistoryState }, _2, parentMessage) {
287431
- const fullPath = isAbsolute18(notebook_path) ? notebook_path : resolve26(getCwd(), notebook_path);
287319
+ const fullPath = isAbsolute19(notebook_path) ? notebook_path : resolve26(getCwd(), notebook_path);
287432
287320
  if (fileHistoryEnabled()) {
287433
287321
  await fileHistoryTrackEdit(updateFileHistoryState, fullPath, parentMessage.uuid);
287434
287322
  }
@@ -289916,7 +289804,7 @@ var init_uuid = __esm(() => {
289916
289804
  });
289917
289805
 
289918
289806
  // src/utils/fingerprint.ts
289919
- import { createHash as createHash10 } from "crypto";
289807
+ import { createHash as createHash11 } from "crypto";
289920
289808
  function extractFirstMessageText(messages) {
289921
289809
  const firstUserMessage = messages.find((msg) => msg.type === "user");
289922
289810
  if (!firstUserMessage) {
@@ -289938,12 +289826,12 @@ function computeFingerprint(messageText, version) {
289938
289826
  const indices = [4, 7, 20];
289939
289827
  const chars = indices.map((i3) => messageText[i3] || "0").join("");
289940
289828
  const fingerprintInput = `${FINGERPRINT_SALT}${chars}${version}`;
289941
- const hash = createHash10("sha256").update(fingerprintInput).digest("hex");
289829
+ const hash = createHash11("sha256").update(fingerprintInput).digest("hex");
289942
289830
  return hash.slice(0, 3);
289943
289831
  }
289944
289832
  function computeFingerprintFromMessages(messages) {
289945
289833
  const firstMessageText = extractFirstMessageText(messages);
289946
- return computeFingerprint(firstMessageText, "2.3.3");
289834
+ return computeFingerprint(firstMessageText, "2.3.5");
289947
289835
  }
289948
289836
  var FINGERPRINT_SALT = "59cf53e54c78";
289949
289837
  var init_fingerprint = () => {};
@@ -289985,7 +289873,7 @@ async function sideQuery(opts) {
289985
289873
  betas.push(STRUCTURED_OUTPUTS_BETA_HEADER);
289986
289874
  }
289987
289875
  const messageText = extractFirstUserMessageText(messages);
289988
- const fingerprint = computeFingerprint(messageText, "2.3.3");
289876
+ const fingerprint = computeFingerprint(messageText, "2.3.5");
289989
289877
  const attributionHeader = getAttributionHeader(fingerprint);
289990
289878
  const systemBlocks = [
289991
289879
  attributionHeader ? { type: "text", text: attributionHeader } : null,
@@ -297712,7 +297600,7 @@ var init_UserTextMessage = __esm(() => {
297712
297600
  });
297713
297601
 
297714
297602
  // src/components/DiagnosticsDisplay.tsx
297715
- import { relative as relative13 } from "path";
297603
+ import { relative as relative14 } from "path";
297716
297604
  function DiagnosticsDisplay(t0) {
297717
297605
  const $2 = c3(14);
297718
297606
  const {
@@ -297816,7 +297704,7 @@ function _temp34(file_0, fileIndex) {
297816
297704
  children: [
297817
297705
  /* @__PURE__ */ jsx_dev_runtime90.jsxDEV(ThemedText, {
297818
297706
  bold: true,
297819
- children: relative13(getCwd(), file_0.uri.replace("file://", "").replace("_claude_fs_right:", ""))
297707
+ children: relative14(getCwd(), file_0.uri.replace("file://", "").replace("_claude_fs_right:", ""))
297820
297708
  }, undefined, false, undefined, this),
297821
297709
  " ",
297822
297710
  /* @__PURE__ */ jsx_dev_runtime90.jsxDEV(ThemedText, {
@@ -298041,7 +297929,7 @@ var init_UserImageMessage = __esm(() => {
298041
297929
  });
298042
297930
 
298043
297931
  // src/components/messages/AttachmentMessage.tsx
298044
- import { basename as basename16, sep as sep16 } from "path";
297932
+ import { basename as basename17, sep as sep16 } from "path";
298045
297933
  function AttachmentMessage({
298046
297934
  attachment,
298047
297935
  addMargin,
@@ -298291,7 +298179,7 @@ function AttachmentMessage({
298291
298179
  dimColor: true,
298292
298180
  children: /* @__PURE__ */ jsx_dev_runtime92.jsxDEV(FilePathLink, {
298293
298181
  filePath: m3.path,
298294
- children: basename16(m3.path)
298182
+ children: basename17(m3.path)
298295
298183
  }, undefined, false, undefined, this)
298296
298184
  }, undefined, false, undefined, this)
298297
298185
  }, undefined, false, undefined, this),
@@ -298976,7 +298864,7 @@ var init_PrBadge = __esm(() => {
298976
298864
  });
298977
298865
 
298978
298866
  // src/components/messages/CollapsedReadSearchContent.tsx
298979
- import { basename as basename17 } from "path";
298867
+ import { basename as basename18 } from "path";
298980
298868
  function VerboseToolUse(t0) {
298981
298869
  const $2 = c3(24);
298982
298870
  const {
@@ -299237,7 +299125,7 @@ function CollapsedReadSearchContent({
299237
299125
  children: [
299238
299126
  " ⎿ ",
299239
299127
  "Recalled ",
299240
- basename17(m3.path)
299128
+ basename18(m3.path)
299241
299129
  ]
299242
299130
  }, undefined, true, undefined, this),
299243
299131
  /* @__PURE__ */ jsx_dev_runtime94.jsxDEV(ThemedBox_default, {
@@ -299952,7 +299840,7 @@ var init_pillLabel = __esm(() => {
299952
299840
  });
299953
299841
 
299954
299842
  // src/components/messages/SystemTextMessage.tsx
299955
- import { basename as basename18 } from "path";
299843
+ import { basename as basename19 } from "path";
299956
299844
  function SystemTextMessage(t0) {
299957
299845
  const $2 = c3(51);
299958
299846
  const {
@@ -300877,7 +300765,7 @@ function MemoryFileRow(t0) {
300877
300765
  const t4 = !hover;
300878
300766
  let t5;
300879
300767
  if ($2[4] !== path8) {
300880
- t5 = basename18(path8);
300768
+ t5 = basename19(path8);
300881
300769
  $2[4] = path8;
300882
300770
  $2[5] = t5;
300883
300771
  } else {
@@ -303262,11 +303150,11 @@ var init_skillUsageTracking = __esm(() => {
303262
303150
  });
303263
303151
 
303264
303152
  // src/utils/telemetry/pluginTelemetry.ts
303265
- import { createHash as createHash11 } from "crypto";
303153
+ import { createHash as createHash12 } from "crypto";
303266
303154
  import { sep as sep17 } from "path";
303267
303155
  function hashPluginId(name, marketplace) {
303268
303156
  const key = marketplace ? `${name}@${marketplace.toLowerCase()}` : name;
303269
- return createHash11("sha256").update(key + PLUGIN_ID_HASH_SALT).digest("hex").slice(0, 16);
303157
+ return createHash12("sha256").update(key + PLUGIN_ID_HASH_SALT).digest("hex").slice(0, 16);
303270
303158
  }
303271
303159
  function getTelemetryPluginScope(name, marketplace, managedNames) {
303272
303160
  if (marketplace === BUILTIN_MARKETPLACE_NAME2)
@@ -304636,7 +304524,7 @@ var init_types7 = __esm(() => {
304636
304524
 
304637
304525
  // src/tools/TodoWriteTool/prompt.ts
304638
304526
  var PROMPT5, DESCRIPTION10 = "Update the todo list for the current session. To be used proactively and often to track progress and pending tasks. Make sure that at least one task is in_progress at all times. Always provide both content (imperative) and activeForm (present continuous) for each task.";
304639
- var init_prompt14 = __esm(() => {
304527
+ var init_prompt13 = __esm(() => {
304640
304528
  PROMPT5 = `Use this tool to create and manage a structured task list for your current coding session. This helps you track progress, organize complex tasks, and demonstrate thoroughness to the user.
304641
304529
  It also helps the user understand the progress of the task and overall progress of their requests.
304642
304530
 
@@ -304827,7 +304715,7 @@ var init_TodoWriteTool = __esm(() => {
304827
304715
  init_tasks();
304828
304716
  init_types7();
304829
304717
  init_constants3();
304830
- init_prompt14();
304718
+ init_prompt13();
304831
304719
  inputSchema14 = lazySchema(() => z39.strictObject({
304832
304720
  todos: TodoListSchema().describe("The updated todo list")
304833
304721
  }));
@@ -304916,7 +304804,7 @@ var init_types8 = __esm(() => {
304916
304804
  });
304917
304805
 
304918
304806
  // src/services/policyLimits/index.ts
304919
- import { createHash as createHash12 } from "crypto";
304807
+ import { createHash as createHash13 } from "crypto";
304920
304808
  import { readFileSync as fsReadFileSync } from "fs";
304921
304809
  import { unlink as unlink7, writeFile as writeFile11 } from "fs/promises";
304922
304810
  import { join as join62 } from "path";
@@ -304962,7 +304850,7 @@ function sortKeysDeep(obj) {
304962
304850
  function computeChecksum(restrictions) {
304963
304851
  const sorted = sortKeysDeep(restrictions);
304964
304852
  const normalized = jsonStringify(sorted);
304965
- const hash = createHash12("sha256").update(normalized).digest("hex");
304853
+ const hash = createHash13("sha256").update(normalized).digest("hex");
304966
304854
  return `sha256:${hash}`;
304967
304855
  }
304968
304856
  function isPolicyLimitsEligible() {
@@ -306325,7 +306213,7 @@ var init_grove = __esm(() => {
306325
306213
  // src/utils/imagePaste.ts
306326
306214
  import { randomBytes as randomBytes8 } from "crypto";
306327
306215
  import { execa as execa8 } from "execa";
306328
- import { basename as basename19, extname as extname9, isAbsolute as isAbsolute19, join as join63 } from "path";
306216
+ import { basename as basename20, extname as extname9, isAbsolute as isAbsolute20, join as join63 } from "path";
306329
306217
  function getClipboardCommands() {
306330
306218
  const platform2 = process.platform;
306331
306219
  const baseTmpDir = process.env.CLAUDE_CODE_TMPDIR || (platform2 === "win32" ? process.env.TEMP || "C:\\Temp" : "/tmp");
@@ -306462,11 +306350,11 @@ async function tryReadImageFromPath(text) {
306462
306350
  const imagePath = cleanedPath;
306463
306351
  let imageBuffer;
306464
306352
  try {
306465
- if (isAbsolute19(imagePath)) {
306353
+ if (isAbsolute20(imagePath)) {
306466
306354
  imageBuffer = getFsImplementation().readFileBytesSync(imagePath);
306467
306355
  } else {
306468
306356
  const clipboardPath = await getImagePathFromClipboard();
306469
- if (clipboardPath && imagePath === basename19(clipboardPath)) {
306357
+ if (clipboardPath && imagePath === basename20(clipboardPath)) {
306470
306358
  imageBuffer = getFsImplementation().readFileBytesSync(clipboardPath);
306471
306359
  }
306472
306360
  }
@@ -310311,7 +310199,7 @@ var init_types9 = __esm(() => {
310311
310199
  });
310312
310200
 
310313
310201
  // src/services/remoteManagedSettings/index.ts
310314
- import { createHash as createHash13 } from "crypto";
310202
+ import { createHash as createHash14 } from "crypto";
310315
310203
  import { open as open9, unlink as unlink8 } from "fs/promises";
310316
310204
  function initializeRemoteManagedSettingsLoadingPromise() {
310317
310205
  if (loadingCompletePromise2) {
@@ -310349,7 +310237,7 @@ function sortKeysDeep2(obj) {
310349
310237
  function computeChecksumFromSettings(settings) {
310350
310238
  const sorted = sortKeysDeep2(settings);
310351
310239
  const normalized = jsonStringify(sorted);
310352
- const hash = createHash13("sha256").update(normalized).digest("hex");
310240
+ const hash = createHash14("sha256").update(normalized).digest("hex");
310353
310241
  return `sha256:${hash}`;
310354
310242
  }
310355
310243
  function isEligibleForRemoteManagedSettings() {
@@ -310737,7 +310625,7 @@ var init_user = __esm(() => {
310737
310625
  deviceId,
310738
310626
  sessionId: getSessionId(),
310739
310627
  email: getEmail(),
310740
- appVersion: "2.3.3",
310628
+ appVersion: "2.3.5",
310741
310629
  platform: getHostPlatformForAnalytics(),
310742
310630
  organizationUuid,
310743
310631
  accountUuid,
@@ -311802,7 +311690,7 @@ async function initializeBetaTracing(resource) {
311802
311690
  });
311803
311691
  logs.setGlobalLoggerProvider(loggerProvider);
311804
311692
  setLoggerProvider(loggerProvider);
311805
- const eventLogger = logs.getLogger("com.anthropic.claude_code.events", "2.3.3");
311693
+ const eventLogger = logs.getLogger("com.anthropic.claude_code.events", "2.3.5");
311806
311694
  setEventLogger(eventLogger);
311807
311695
  process.on("beforeExit", async () => {
311808
311696
  await loggerProvider?.forceFlush();
@@ -311842,7 +311730,7 @@ async function initializeTelemetry() {
311842
311730
  const platform2 = getPlatform();
311843
311731
  const baseAttributes = {
311844
311732
  [ATTR_SERVICE_NAME4]: "claude-code",
311845
- [ATTR_SERVICE_VERSION4]: "2.3.3"
311733
+ [ATTR_SERVICE_VERSION4]: "2.3.5"
311846
311734
  };
311847
311735
  if (platform2 === "wsl") {
311848
311736
  const wslVersion = getWslVersion();
@@ -311887,7 +311775,7 @@ async function initializeTelemetry() {
311887
311775
  } catch {}
311888
311776
  };
311889
311777
  registerCleanup(shutdownTelemetry2);
311890
- return meterProvider2.getMeter("com.anthropic.claude_code", "2.3.3");
311778
+ return meterProvider2.getMeter("com.anthropic.claude_code", "2.3.5");
311891
311779
  }
311892
311780
  const meterProvider = new MeterProvider4({
311893
311781
  resource,
@@ -311907,7 +311795,7 @@ async function initializeTelemetry() {
311907
311795
  });
311908
311796
  logs.setGlobalLoggerProvider(loggerProvider);
311909
311797
  setLoggerProvider(loggerProvider);
311910
- const eventLogger = logs.getLogger("com.anthropic.claude_code.events", "2.3.3");
311798
+ const eventLogger = logs.getLogger("com.anthropic.claude_code.events", "2.3.5");
311911
311799
  setEventLogger(eventLogger);
311912
311800
  logForDebugging("[3P telemetry] Event logger set successfully");
311913
311801
  process.on("beforeExit", async () => {
@@ -311969,7 +311857,7 @@ Current timeout: ${timeoutMs}ms
311969
311857
  }
311970
311858
  };
311971
311859
  registerCleanup(shutdownTelemetry);
311972
- return meterProvider.getMeter("com.anthropic.claude_code", "2.3.3");
311860
+ return meterProvider.getMeter("com.anthropic.claude_code", "2.3.5");
311973
311861
  }
311974
311862
  async function flushTelemetry() {
311975
311863
  const meterProvider = getMeterProvider();
@@ -312336,7 +312224,7 @@ var init_auth_code_listener = __esm(() => {
312336
312224
  });
312337
312225
 
312338
312226
  // src/services/oauth/crypto.ts
312339
- import { createHash as createHash14, randomBytes as randomBytes9 } from "crypto";
312227
+ import { createHash as createHash15, randomBytes as randomBytes9 } from "crypto";
312340
312228
  function base64URLEncode(buffer) {
312341
312229
  return buffer.toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
312342
312230
  }
@@ -312344,7 +312232,7 @@ function generateCodeVerifier() {
312344
312232
  return base64URLEncode(randomBytes9(32));
312345
312233
  }
312346
312234
  function generateCodeChallenge(verifier) {
312347
- const hash = createHash14("sha256");
312235
+ const hash = createHash15("sha256");
312348
312236
  hash.update(verifier);
312349
312237
  return base64URLEncode(hash.digest());
312350
312238
  }
@@ -313159,7 +313047,7 @@ function detectLinuxGlobPatternWarnings() {
313159
313047
  }
313160
313048
  async function getDoctorDiagnostic() {
313161
313049
  const installationType = await getCurrentInstallationType();
313162
- const version = typeof MACRO !== "undefined" ? "2.3.3" : "unknown";
313050
+ const version = typeof MACRO !== "undefined" ? "2.3.5" : "unknown";
313163
313051
  const installationPath = await getInstallationPath();
313164
313052
  const invokedBinary = getInvokedBinary();
313165
313053
  const multipleInstallations = await detectMultipleInstallations();
@@ -313284,7 +313172,7 @@ function getUserBinDir(options) {
313284
313172
  var init_xdg = () => {};
313285
313173
 
313286
313174
  // src/utils/nativeInstaller/download.ts
313287
- import { createHash as createHash15 } from "crypto";
313175
+ import { createHash as createHash16 } from "crypto";
313288
313176
  import { chmod as chmod5, writeFile as writeFile13 } from "fs/promises";
313289
313177
  import { join as join68 } from "path";
313290
313178
  async function getLatestVersionFromArtifactory(tag = "latest") {
@@ -313470,7 +313358,7 @@ async function downloadAndVerifyBinary(binaryUrl, expectedChecksum, binaryPath,
313470
313358
  ...requestConfig
313471
313359
  });
313472
313360
  clearStallTimer();
313473
- const hash = createHash15("sha256");
313361
+ const hash = createHash16("sha256");
313474
313362
  hash.update(response.data);
313475
313363
  const actualChecksum = hash.digest("hex");
313476
313364
  if (actualChecksum !== expectedChecksum) {
@@ -313588,7 +313476,7 @@ var init_download = __esm(() => {
313588
313476
  });
313589
313477
 
313590
313478
  // src/utils/nativeInstaller/pidLock.ts
313591
- import { basename as basename20, join as join69 } from "path";
313479
+ import { basename as basename21, join as join69 } from "path";
313592
313480
  function isPidBasedLockingEnabled() {
313593
313481
  const envVar = process.env.ENABLE_PID_BASED_VERSION_LOCKING;
313594
313482
  if (isEnvTruthy(envVar)) {
@@ -313688,7 +313576,7 @@ function writeLockFile(lockFilePath, content) {
313688
313576
  }
313689
313577
  async function tryAcquireLock(versionPath, lockFilePath) {
313690
313578
  const fs4 = getFsImplementation();
313691
- const versionName = basename20(versionPath);
313579
+ const versionName = basename21(versionPath);
313692
313580
  if (isLockActive(lockFilePath)) {
313693
313581
  const existingContent = readLockContent(lockFilePath);
313694
313582
  logForDebugging(`Cannot acquire lock for ${versionName} - held by PID ${existingContent?.pid}`);
@@ -313837,7 +313725,7 @@ import {
313837
313725
  writeFile as writeFile14
313838
313726
  } from "fs/promises";
313839
313727
  import { homedir as homedir19 } from "os";
313840
- import { basename as basename21, delimiter as delimiter3, dirname as dirname31, join as join70, resolve as resolve28 } from "path";
313728
+ import { basename as basename22, delimiter as delimiter3, dirname as dirname31, join as join70, resolve as resolve28 } from "path";
313841
313729
  function getPlatform2() {
313842
313730
  const os6 = env3.platform;
313843
313731
  const arch = process.arch === "x64" ? "x64" : process.arch === "arm64" ? "arm64" : null;
@@ -314100,8 +313988,8 @@ async function updateLatest(channelOrVersion, forceReinstall = false) {
314100
313988
  const maxVersion = await getMaxVersion();
314101
313989
  if (maxVersion && gt(version, maxVersion)) {
314102
313990
  logForDebugging(`Native installer: maxVersion ${maxVersion} is set, capping update from ${version} to ${maxVersion}`);
314103
- if (gte("2.3.3", maxVersion)) {
314104
- logForDebugging(`Native installer: current version ${"2.3.3"} is already at or above maxVersion ${maxVersion}, skipping update`);
313991
+ if (gte("2.3.5", maxVersion)) {
313992
+ logForDebugging(`Native installer: current version ${"2.3.5"} is already at or above maxVersion ${maxVersion}, skipping update`);
314105
313993
  logEvent("tengu_native_update_skipped_max_version", {
314106
313994
  latency_ms: Date.now() - startTime,
314107
313995
  max_version: maxVersion,
@@ -314112,7 +314000,7 @@ async function updateLatest(channelOrVersion, forceReinstall = false) {
314112
314000
  version = maxVersion;
314113
314001
  }
314114
314002
  }
314115
- if (!forceReinstall && version === "2.3.3" && await versionIsAvailable(version) && await isPossibleLocalClawdBinary(executablePath)) {
314003
+ if (!forceReinstall && version === "2.3.5" && await versionIsAvailable(version) && await isPossibleLocalClawdBinary(executablePath)) {
314116
314004
  logForDebugging(`Found ${version} at ${executablePath}, skipping install`);
314117
314005
  logEvent("tengu_native_update_complete", {
314118
314006
  latency_ms: Date.now() - startTime,
@@ -314430,7 +314318,7 @@ async function getVersionFromSymlink(symlinkPath) {
314430
314318
  return null;
314431
314319
  }
314432
314320
  function getLockFilePathFromVersionPath(dirs, versionPath) {
314433
- const versionName = basename21(versionPath);
314321
+ const versionName = basename22(versionPath);
314434
314322
  return join70(dirs.locks, `${versionName}.lock`);
314435
314323
  }
314436
314324
  async function lockCurrentVersion() {
@@ -323305,7 +323193,7 @@ var init_sessionIngress = __esm(() => {
323305
323193
  });
323306
323194
 
323307
323195
  // src/utils/conversationRecovery.ts
323308
- import { relative as relative14 } from "path";
323196
+ import { relative as relative15 } from "path";
323309
323197
  function migrateLegacyAttachmentTypes(message) {
323310
323198
  if (message.type !== "attachment") {
323311
323199
  return message;
@@ -323317,7 +323205,7 @@ function migrateLegacyAttachmentTypes(message) {
323317
323205
  attachment: {
323318
323206
  ...attachment,
323319
323207
  type: "file",
323320
- displayPath: relative14(getCwd(), attachment.filename)
323208
+ displayPath: relative15(getCwd(), attachment.filename)
323321
323209
  }
323322
323210
  };
323323
323211
  }
@@ -323327,7 +323215,7 @@ function migrateLegacyAttachmentTypes(message) {
323327
323215
  attachment: {
323328
323216
  ...attachment,
323329
323217
  type: "directory",
323330
- displayPath: relative14(getCwd(), attachment.path)
323218
+ displayPath: relative15(getCwd(), attachment.path)
323331
323219
  }
323332
323220
  };
323333
323221
  }
@@ -323338,7 +323226,7 @@ function migrateLegacyAttachmentTypes(message) {
323338
323226
  ...message,
323339
323227
  attachment: {
323340
323228
  ...attachment,
323341
- displayPath: relative14(getCwd(), path8)
323229
+ displayPath: relative15(getCwd(), path8)
323342
323230
  }
323343
323231
  };
323344
323232
  }
@@ -323884,11 +323772,11 @@ var init_filesApi = __esm(() => {
323884
323772
  });
323885
323773
 
323886
323774
  // src/utils/tempfile.ts
323887
- import { createHash as createHash16, randomUUID as randomUUID13 } from "crypto";
323775
+ import { createHash as createHash17, randomUUID as randomUUID13 } from "crypto";
323888
323776
  import { tmpdir as tmpdir4 } from "os";
323889
323777
  import { join as join73 } from "path";
323890
323778
  function generateTempFilePath(prefix = "claude-prompt", extension2 = ".md", options) {
323891
- const id = options?.contentHash ? createHash16("sha256").update(options.contentHash).digest("hex").slice(0, 16) : randomUUID13();
323779
+ const id = options?.contentHash ? createHash17("sha256").update(options.contentHash).digest("hex").slice(0, 16) : randomUUID13();
323892
323780
  return join73(tmpdir4(), `${prefix}-${id}${extension2}`);
323893
323781
  }
323894
323782
  var init_tempfile = () => {};
@@ -326880,7 +326768,7 @@ Usage notes:
326880
326768
 
326881
326769
  ${forkEnabled ? forkExamples : currentExamples}`;
326882
326770
  }
326883
- var init_prompt15 = __esm(() => {
326771
+ var init_prompt14 = __esm(() => {
326884
326772
  init_auth2();
326885
326773
  init_embeddedTools();
326886
326774
  init_envUtils();
@@ -326947,7 +326835,7 @@ var init_AgentTool = __esm(() => {
326947
326835
  init_constants3();
326948
326836
  init_forkSubagent();
326949
326837
  init_loadAgentsDir();
326950
- init_prompt15();
326838
+ init_prompt14();
326951
326839
  init_runAgent();
326952
326840
  init_UI11();
326953
326841
  jsx_dev_runtime134 = __toESM(require_jsx_dev_runtime(), 1);
@@ -333216,9 +333104,9 @@ var require_URL2 = __commonJS((exports, module) => {
333216
333104
  s2 += "#" + this.fragment;
333217
333105
  return s2;
333218
333106
  },
333219
- resolve: function(relative15) {
333107
+ resolve: function(relative16) {
333220
333108
  var base = this;
333221
- var r2 = new URL3(relative15);
333109
+ var r2 = new URL3(relative16);
333222
333110
  var t2 = new URL3;
333223
333111
  if (r2.scheme !== undefined) {
333224
333112
  t2.scheme = r2.scheme;
@@ -345740,7 +345628,7 @@ To complete your request, I need to fetch content from the redirected URL. Pleas
345740
345628
 
345741
345629
  // src/utils/listSessionsImpl.ts
345742
345630
  import { readdir as readdir11, stat as stat25 } from "fs/promises";
345743
- import { basename as basename23, join as join74 } from "path";
345631
+ import { basename as basename24, join as join74 } from "path";
345744
345632
  async function listCandidates(projectDir, doStat, projectPath) {
345745
345633
  let names;
345746
345634
  try {
@@ -346213,7 +346101,7 @@ var BRIEF_TOOL_NAME2 = "SendUserMessage", LEGACY_BRIEF_TOOL_NAME2 = "Brief", DES
346213
346101
  \`message\` supports markdown. \`attachments\` takes file paths (absolute or cwd-relative) for images, diffs, logs.
346214
346102
 
346215
346103
  \`status\` labels intent: 'normal' when replying to what they just asked; 'proactive' when you're initiating — a scheduled task finished, a blocker surfaced during background work, you need input on something they haven't asked about. Set it honestly; downstream routing uses it.`, BRIEF_PROACTIVE_SECTION;
346216
- var init_prompt16 = __esm(() => {
346104
+ var init_prompt15 = __esm(() => {
346217
346105
  BRIEF_PROACTIVE_SECTION = `## Talking to the user
346218
346106
 
346219
346107
  ${BRIEF_TOOL_NAME2} is where your replies go. Text outside it is visible if the user expands the detail view, but most won't — assume unread. Anything you want them to actually see goes through ${BRIEF_TOOL_NAME2}. The failure mode: the real answer lives in plain text while ${BRIEF_TOOL_NAME2} just says "done!" — they see "done!" and miss everything.
@@ -346409,7 +346297,7 @@ var init_BriefTool = __esm(() => {
346409
346297
  init_envUtils();
346410
346298
  init_stringUtils();
346411
346299
  init_attachments();
346412
- init_prompt16();
346300
+ init_prompt15();
346413
346301
  init_UI15();
346414
346302
  inputSchema19 = lazySchema(() => z52.strictObject({
346415
346303
  message: z52.string().describe("The message for the user. Supports markdown formatting."),
@@ -347661,7 +347549,7 @@ var init_inProcessTeammateHelpers = __esm(() => {
347661
347549
 
347662
347550
  // src/tools/ExitPlanModeTool/prompt.ts
347663
347551
  var ASK_USER_QUESTION_TOOL_NAME2 = "AskUserQuestion", EXIT_PLAN_MODE_V2_TOOL_PROMPT;
347664
- var init_prompt17 = __esm(() => {
347552
+ var init_prompt16 = __esm(() => {
347665
347553
  EXIT_PLAN_MODE_V2_TOOL_PROMPT = `Use this tool when you are in plan mode and have finished writing your plan to the plan file and are ready for user approval.
347666
347554
 
347667
347555
  ## How This Tool Works
@@ -347837,7 +347725,7 @@ var init_ExitPlanModeTool = __esm(() => {
347837
347725
  init_teammate();
347838
347726
  init_teammateMailbox();
347839
347727
  init_constants3();
347840
- init_prompt17();
347728
+ init_prompt16();
347841
347729
  init_UI17();
347842
347730
  allowedPromptSchema = lazySchema(() => z55.object({
347843
347731
  tool: z55.enum(["Bash"]).describe("The tool this prompt applies to"),
@@ -348434,7 +348322,7 @@ ${annotation.preview}`);
348434
348322
  });
348435
348323
 
348436
348324
  // src/tools/LSPTool/formatters.ts
348437
- import { relative as relative15 } from "path";
348325
+ import { relative as relative16 } from "path";
348438
348326
  function formatUri2(uri, cwd2) {
348439
348327
  if (!uri) {
348440
348328
  logForDebugging("formatUri called with undefined URI - indicates malformed LSP server response", { level: "warn" });
@@ -348451,7 +348339,7 @@ function formatUri2(uri, cwd2) {
348451
348339
  logForDebugging(`Failed to decode LSP URI '${uri}': ${errorMsg}. Using un-decoded path: ${filePath}`, { level: "warn" });
348452
348340
  }
348453
348341
  if (cwd2) {
348454
- const relativePath = relative15(cwd2, filePath).replaceAll("\\", "/");
348342
+ const relativePath = relative16(cwd2, filePath).replaceAll("\\", "/");
348455
348343
  if (relativePath.length < filePath.length && !relativePath.startsWith("../../")) {
348456
348344
  return relativePath;
348457
348345
  }
@@ -349877,7 +349765,7 @@ function getEnterPlanModeToolPrompt() {
349877
349765
  return process.env.USER_TYPE === "ant" ? getEnterPlanModeToolPromptAnt() : getEnterPlanModeToolPromptExternal();
349878
349766
  }
349879
349767
  var WHAT_HAPPENS_SECTION;
349880
- var init_prompt18 = __esm(() => {
349768
+ var init_prompt17 = __esm(() => {
349881
349769
  init_planMode();
349882
349770
  init_prompt7();
349883
349771
  WHAT_HAPPENS_SECTION = `## What Happens in Plan Mode
@@ -349956,7 +349844,7 @@ var init_EnterPlanModeTool = __esm(() => {
349956
349844
  init_PermissionUpdate();
349957
349845
  init_permissionSetup();
349958
349846
  init_planMode();
349959
- init_prompt18();
349847
+ init_prompt17();
349960
349848
  init_UI19();
349961
349849
  inputSchema26 = lazySchema(() => z60.strictObject({}));
349962
349850
  outputSchema22 = lazySchema(() => z60.object({
@@ -350043,10 +349931,10 @@ import {
350043
349931
  } from "crypto";
350044
349932
  import { existsSync as existsSync6, mkdirSync as mkdirSync5, readFileSync as readFileSync10, writeFileSync as writeFileSync3 } from "fs";
350045
349933
  import { homedir as homedir21 } from "os";
350046
- import { basename as basename24, join as join76, resolve as resolve29 } from "path";
349934
+ import { basename as basename25, join as join76, resolve as resolve29 } from "path";
350047
349935
  function getProjectId() {
350048
349936
  const root2 = getProjectRoot();
350049
- return basename24(resolve29(root2)).toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "").slice(0, 64) || "default";
349937
+ return basename25(resolve29(root2)).toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "").slice(0, 64) || "default";
350050
349938
  }
350051
349939
  function getSecretsFile() {
350052
349940
  return join76(getProjectRoot(), ".localclawd", "secrets.enc");
@@ -351907,6 +351795,7 @@ var SUPPORTED_SETTINGS;
351907
351795
  var init_supportedSettings = __esm(() => {
351908
351796
  init_config();
351909
351797
  init_configConstants();
351798
+ init_context();
351910
351799
  init_modelOptions();
351911
351800
  init_validateModel();
351912
351801
  init_theme();
@@ -351936,9 +351825,20 @@ var init_supportedSettings = __esm(() => {
351936
351825
  options: NOTIFICATION_CHANNELS
351937
351826
  },
351938
351827
  autoCompactEnabled: {
351939
- source: "global",
351828
+ source: "project",
351940
351829
  type: "boolean",
351941
- description: "Auto-compact when context is full"
351830
+ description: "Auto-compact when this project approaches its context limit",
351831
+ formatOnRead: (v2) => typeof v2 === "boolean" ? v2 : getGlobalConfig().autoCompactEnabled
351832
+ },
351833
+ compactContextWindowTokens: {
351834
+ source: "project",
351835
+ type: "number",
351836
+ description: "Project-local context window cap used for usage and compaction thresholds",
351837
+ coerceOnWrite: (v2) => {
351838
+ const parsed = typeof v2 === "number" ? Number.isFinite(v2) ? Math.trunc(v2) : null : parseContextWindowString(String(v2));
351839
+ return parsed ? { value: parsed } : { error: "compactContextWindowTokens requires a value like 200k, 1m, or 131072." };
351840
+ },
351841
+ formatOnRead: (v2) => formatCompactContextWindowOption(typeof v2 === "number" ? v2 : undefined)
351942
351842
  },
351943
351843
  autoMemoryEnabled: {
351944
351844
  source: "settings",
@@ -352024,7 +351924,8 @@ var init_supportedSettings = __esm(() => {
352024
351924
  // src/tools/ConfigTool/prompt.ts
352025
351925
  function generatePrompt() {
352026
351926
  const globalSettings = [];
352027
- const projectSettings = [];
351927
+ const userSettings = [];
351928
+ const projectLocalSettings = [];
352028
351929
  for (const [key, config] of Object.entries(SUPPORTED_SETTINGS)) {
352029
351930
  if (key === "model")
352030
351931
  continue;
@@ -352036,12 +351937,16 @@ function generatePrompt() {
352036
351937
  line += `: ${options.map((o) => `"${o}"`).join(", ")}`;
352037
351938
  } else if (config.type === "boolean") {
352038
351939
  line += `: true/false`;
351940
+ } else if (config.type === "number") {
351941
+ line += `: number`;
352039
351942
  }
352040
351943
  line += ` - ${config.description}`;
352041
351944
  if (config.source === "global") {
352042
351945
  globalSettings.push(line);
351946
+ } else if (config.source === "project") {
351947
+ projectLocalSettings.push(line);
352043
351948
  } else {
352044
- projectSettings.push(line);
351949
+ userSettings.push(line);
352045
351950
  }
352046
351951
  }
352047
351952
  const modelSection = generateModelSection();
@@ -352061,8 +351966,12 @@ The following settings are available for you to change:
352061
351966
  ${globalSettings.join(`
352062
351967
  `)}
352063
351968
 
352064
- ### Project Settings (stored in settings.json)
352065
- ${projectSettings.join(`
351969
+ ### User Settings (stored in settings.json)
351970
+ ${userSettings.join(`
351971
+ `)}
351972
+
351973
+ ### Project-Local Settings (stored per project)
351974
+ ${projectLocalSettings.join(`
352066
351975
  `)}
352067
351976
 
352068
351977
  ${modelSection}
@@ -352092,7 +352001,7 @@ ${lines.join(`
352092
352001
  }
352093
352002
  }
352094
352003
  var DESCRIPTION14 = "Get or set localclawd configuration settings.";
352095
- var init_prompt19 = __esm(() => {
352004
+ var init_prompt18 = __esm(() => {
352096
352005
  init_modelOptions();
352097
352006
  init_voiceModeEnabled();
352098
352007
  init_supportedSettings();
@@ -352189,8 +352098,7 @@ function getValue2(source, path10) {
352189
352098
  return;
352190
352099
  return config[key];
352191
352100
  }
352192
- const settings = getInitialSettings();
352193
- let current = settings;
352101
+ let current = source === "project" ? getCurrentProjectConfig() : getInitialSettings();
352194
352102
  for (const key of path10) {
352195
352103
  if (current && typeof current === "object" && key in current) {
352196
352104
  current = current[key];
@@ -352218,7 +352126,7 @@ var init_ConfigTool = __esm(() => {
352218
352126
  init_log2();
352219
352127
  init_settings2();
352220
352128
  init_slowOperations();
352221
- init_prompt19();
352129
+ init_prompt18();
352222
352130
  init_supportedSettings();
352223
352131
  init_UI23();
352224
352132
  inputSchema30 = lazySchema(() => z65.strictObject({
@@ -352319,9 +352227,23 @@ var init_ConfigTool = __esm(() => {
352319
352227
  };
352320
352228
  }
352321
352229
  let finalValue = value;
352230
+ if (config.coerceOnWrite) {
352231
+ const result = config.coerceOnWrite(finalValue);
352232
+ if ("error" in result) {
352233
+ return {
352234
+ data: {
352235
+ success: false,
352236
+ operation: "set",
352237
+ setting,
352238
+ error: result.error
352239
+ }
352240
+ };
352241
+ }
352242
+ finalValue = result.value;
352243
+ }
352322
352244
  if (config.type === "boolean") {
352323
- if (typeof value === "string") {
352324
- const lower2 = value.toLowerCase().trim();
352245
+ if (typeof finalValue === "string") {
352246
+ const lower2 = finalValue.toLowerCase().trim();
352325
352247
  if (lower2 === "true")
352326
352248
  finalValue = true;
352327
352249
  else if (lower2 === "false")
@@ -352338,6 +352260,21 @@ var init_ConfigTool = __esm(() => {
352338
352260
  };
352339
352261
  }
352340
352262
  }
352263
+ if (config.type === "number") {
352264
+ if (typeof finalValue === "string" && finalValue.trim()) {
352265
+ finalValue = Number(finalValue);
352266
+ }
352267
+ if (typeof finalValue !== "number" || !Number.isFinite(finalValue)) {
352268
+ return {
352269
+ data: {
352270
+ success: false,
352271
+ operation: "set",
352272
+ setting,
352273
+ error: `${setting} requires a finite number.`
352274
+ }
352275
+ };
352276
+ }
352277
+ }
352341
352278
  const options = getOptionsForSetting(setting);
352342
352279
  if (options && !options.includes(String(finalValue))) {
352343
352280
  return {
@@ -352382,6 +352319,23 @@ var init_ConfigTool = __esm(() => {
352382
352319
  return prev;
352383
352320
  return { ...prev, [key]: finalValue };
352384
352321
  });
352322
+ } else if (config.source === "project") {
352323
+ const key = path10[0];
352324
+ if (!key) {
352325
+ return {
352326
+ data: {
352327
+ success: false,
352328
+ operation: "set",
352329
+ setting,
352330
+ error: "Invalid setting path"
352331
+ }
352332
+ };
352333
+ }
352334
+ saveCurrentProjectConfig((prev) => {
352335
+ if (prev[key] === finalValue)
352336
+ return prev;
352337
+ return { ...prev, [key]: finalValue };
352338
+ });
352385
352339
  } else {
352386
352340
  const update = buildNestedObject(path10, finalValue);
352387
352341
  const result = updateSettingsForSource("userSettings", update);
@@ -352515,7 +352469,7 @@ ${teammateTips}- Check TaskList first to avoid creating duplicate tasks
352515
352469
  `;
352516
352470
  }
352517
352471
  var DESCRIPTION15 = "Create a new task in the task list";
352518
- var init_prompt20 = __esm(() => {
352472
+ var init_prompt19 = __esm(() => {
352519
352473
  init_agentSwarmsEnabled();
352520
352474
  });
352521
352475
 
@@ -352527,7 +352481,7 @@ var init_TaskCreateTool = __esm(() => {
352527
352481
  init_hooks5();
352528
352482
  init_tasks();
352529
352483
  init_teammate();
352530
- init_prompt20();
352484
+ init_prompt19();
352531
352485
  inputSchema31 = lazySchema(() => z66.strictObject({
352532
352486
  subject: z66.string().describe("A brief title for the task"),
352533
352487
  description: z66.string().describe("What needs to be done"),
@@ -353129,7 +353083,7 @@ Use TaskGet with a specific task ID to view full details including description a
353129
353083
  ${teammateWorkflow}`;
353130
353084
  }
353131
353085
  var DESCRIPTION18 = "List all tasks in the task list";
353132
- var init_prompt21 = __esm(() => {
353086
+ var init_prompt20 = __esm(() => {
353133
353087
  init_agentSwarmsEnabled();
353134
353088
  });
353135
353089
 
@@ -353139,7 +353093,7 @@ var inputSchema34, outputSchema30, TaskListTool;
353139
353093
  var init_TaskListTool = __esm(() => {
353140
353094
  init_Tool();
353141
353095
  init_tasks();
353142
- init_prompt21();
353096
+ init_prompt20();
353143
353097
  inputSchema34 = lazySchema(() => z69.strictObject({}));
353144
353098
  outputSchema30 = lazySchema(() => z69.object({
353145
353099
  tasks: z69.array(z69.object({
@@ -357677,11 +357631,14 @@ var init_memoryTypes = __esm(() => {
357677
357631
 
357678
357632
  // src/memdir/memoryScan.ts
357679
357633
  import { readdir as readdir13 } from "fs/promises";
357680
- import { basename as basename25, join as join81 } from "path";
357634
+ import { basename as basename26, join as join81 } from "path";
357635
+ function isTurnMemoryPath(relativePath) {
357636
+ return /(^|[/\\])turns[/\\]/.test(relativePath);
357637
+ }
357681
357638
  async function scanMemoryFiles(memoryDir, signal) {
357682
357639
  try {
357683
357640
  const entries = await readdir13(memoryDir, { recursive: true });
357684
- const mdFiles = entries.filter((f3) => f3.endsWith(".md") && basename25(f3) !== "MEMORY.md");
357641
+ const mdFiles = entries.filter((f3) => f3.endsWith(".md") && basename26(f3) !== "MEMORY.md");
357685
357642
  const headerResults = await Promise.allSettled(mdFiles.map(async (relativePath) => {
357686
357643
  const filePath = join81(memoryDir, relativePath);
357687
357644
  const { content, mtimeMs } = await readFileInRange(filePath, 0, FRONTMATTER_MAX_LINES, undefined, signal);
@@ -357695,7 +357652,10 @@ async function scanMemoryFiles(memoryDir, signal) {
357695
357652
  tags: parseTags(frontmatter.tags)
357696
357653
  };
357697
357654
  }));
357698
- return headerResults.filter((r2) => r2.status === "fulfilled").map((r2) => r2.value).sort((a, b3) => b3.mtimeMs - a.mtimeMs).slice(0, MAX_MEMORY_FILES);
357655
+ const sorted = headerResults.filter((r2) => r2.status === "fulfilled").map((r2) => r2.value).sort((a, b3) => b3.mtimeMs - a.mtimeMs);
357656
+ const curated = sorted.filter((memory) => !isTurnMemoryPath(memory.filename)).slice(0, MAX_CURATED_MEMORY_FILES);
357657
+ const turnMemories = sorted.filter((memory) => isTurnMemoryPath(memory.filename)).slice(0, MAX_TURN_MEMORY_FILES);
357658
+ return [...curated, ...turnMemories].sort((a, b3) => b3.mtimeMs - a.mtimeMs).slice(0, MAX_MEMORY_FILES);
357699
357659
  } catch {
357700
357660
  return [];
357701
357661
  }
@@ -357708,7 +357668,7 @@ function formatMemoryManifest(memories) {
357708
357668
  }).join(`
357709
357669
  `);
357710
357670
  }
357711
- var MAX_MEMORY_FILES = 200, FRONTMATTER_MAX_LINES = 30;
357671
+ var MAX_MEMORY_FILES = 240, MAX_CURATED_MEMORY_FILES = 200, MAX_TURN_MEMORY_FILES = 80, FRONTMATTER_MAX_LINES = 30;
357712
357672
  var init_memoryScan = __esm(() => {
357713
357673
  init_frontmatterParser();
357714
357674
  init_readFileInRange();
@@ -358547,7 +358507,7 @@ __export(exports_embedding, {
358547
358507
  cosine: () => cosine
358548
358508
  });
358549
358509
  import { mkdir as mkdir22, readFile as readFile29, writeFile as writeFile22 } from "fs/promises";
358550
- import { createHash as createHash17 } from "crypto";
358510
+ import { createHash as createHash18 } from "crypto";
358551
358511
  import { join as join82 } from "path";
358552
358512
  async function loadCache2() {
358553
358513
  if (_cache)
@@ -358568,7 +358528,7 @@ async function saveCache(cache3) {
358568
358528
  await writeFile22(CACHE_PATH, JSON.stringify(cache3), "utf-8");
358569
358529
  }
358570
358530
  function hashText(text) {
358571
- return createHash17("sha256").update(text).digest("hex");
358531
+ return createHash18("sha256").update(text).digest("hex");
358572
358532
  }
358573
358533
  function evictIfNeeded(cache3) {
358574
358534
  while (cache3.order.length > MAX_CACHE_ENTRIES) {
@@ -359162,7 +359122,7 @@ var init_findRelevantMemories = __esm(() => {
359162
359122
  // src/memdir/turnMemory.ts
359163
359123
  import { randomUUID as randomUUID17 } from "crypto";
359164
359124
  import { mkdir as mkdir26, readdir as readdir15, readFile as readFile33, rm as rm4, stat as stat29, writeFile as writeFile26 } from "fs/promises";
359165
- import { basename as basename26, dirname as dirname33, join as join86, relative as relative16 } from "path";
359125
+ import { basename as basename27, dirname as dirname33, join as join86, relative as relative17 } from "path";
359166
359126
  function truncate4(text, maxChars) {
359167
359127
  const cleaned = text.replace(/\s+/g, " ").trim();
359168
359128
  if (cleaned.length <= maxChars)
@@ -359233,6 +359193,22 @@ async function writeConfig(config) {
359233
359193
  await writeFile26(configPath, `${JSON.stringify({ ...config, updatedAt: new Date().toISOString() }, null, 2)}
359234
359194
  `, "utf8");
359235
359195
  }
359196
+ async function countFilesUnder(dir) {
359197
+ let fileCount = 0;
359198
+ let bytes = 0;
359199
+ try {
359200
+ const entries = await readdir15(dir, { recursive: true });
359201
+ await Promise.all(entries.map(async (entry) => {
359202
+ const path10 = join86(dir, entry);
359203
+ const info = await stat29(path10).catch(() => null);
359204
+ if (!info?.isFile())
359205
+ return;
359206
+ fileCount++;
359207
+ bytes += info.size;
359208
+ }));
359209
+ } catch {}
359210
+ return { fileCount, bytes };
359211
+ }
359236
359212
  async function setProjectMemoryEnabled(enabled) {
359237
359213
  await writeConfig({ enabled });
359238
359214
  }
@@ -359248,24 +359224,20 @@ async function clearProjectMemory() {
359248
359224
  }
359249
359225
  async function getProjectMemoryStatus() {
359250
359226
  const memoryDir = getAutoMemPath();
359251
- let fileCount = 0;
359252
- let bytes = 0;
359253
- try {
359254
- const entries = await readdir15(memoryDir, { recursive: true });
359255
- await Promise.all(entries.map(async (entry) => {
359256
- const path10 = join86(memoryDir, entry);
359257
- const info = await stat29(path10).catch(() => null);
359258
- if (!info?.isFile())
359259
- return;
359260
- fileCount++;
359261
- bytes += info.size;
359262
- }));
359263
- } catch {}
359227
+ const directoryMemoryDir = getDirectoryMemoryPath();
359228
+ const [total, directory] = await Promise.all([
359229
+ countFilesUnder(memoryDir),
359230
+ countFilesUnder(directoryMemoryDir)
359231
+ ]);
359264
359232
  return {
359265
359233
  enabled: isAutoMemoryEnabled(),
359266
359234
  memoryDir,
359267
- fileCount,
359268
- bytes
359235
+ directoryKey: getDirectoryMemoryKey(),
359236
+ directoryMemoryDir,
359237
+ fileCount: total.fileCount,
359238
+ bytes: total.bytes,
359239
+ directoryFileCount: directory.fileCount,
359240
+ directoryBytes: directory.bytes
359269
359241
  };
359270
359242
  }
359271
359243
  async function saveTurnMemory(params) {
@@ -359283,10 +359255,12 @@ async function saveTurnMemory(params) {
359283
359255
  }
359284
359256
  const now2 = new Date;
359285
359257
  const iso2 = now2.toISOString();
359258
+ const cwd2 = getOriginalCwd();
359259
+ const directoryKey = getDirectoryMemoryKey(cwd2);
359286
359260
  const id = `${iso2.replace(/[:.]/g, "-")}-${randomUUID17().slice(0, 8)}`;
359287
359261
  const tags = tagsFor(`${userText} ${assistantText} ${summary}`);
359288
359262
  const filename = `${id}-${slugify2(summary)}.md`;
359289
- const dir = join86(getAutoMemPath(), TURN_MEMORY_DIR);
359263
+ const dir = join86(getDirectoryMemoryPath(cwd2), TURN_MEMORY_DIR);
359290
359264
  const path10 = join86(dir, filename);
359291
359265
  const description = summary;
359292
359266
  const frontmatter = [
@@ -359294,6 +359268,10 @@ async function saveTurnMemory(params) {
359294
359268
  `name: ${yamlQuote(`Turn ${iso2}`)}`,
359295
359269
  `description: ${yamlQuote(description)}`,
359296
359270
  "type: project",
359271
+ "scope: directory",
359272
+ `directory_key: ${yamlQuote(directoryKey)}`,
359273
+ `cwd: ${yamlQuote(cwd2)}`,
359274
+ `project_root: ${yamlQuote(getMemoryBaseDir())}`,
359297
359275
  tags.length > 0 ? `tags: [${tags.map(yamlQuote).join(", ")}]` : "tags: []",
359298
359276
  "---",
359299
359277
  ""
@@ -359305,6 +359283,10 @@ async function saveTurnMemory(params) {
359305
359283
  "## User Request",
359306
359284
  userText || "(No user text captured.)",
359307
359285
  "",
359286
+ "## Directory",
359287
+ `- cwd: ${cwd2}`,
359288
+ `- memory key: ${directoryKey}`,
359289
+ "",
359308
359290
  "## What Was Done",
359309
359291
  assistantText || summary,
359310
359292
  ""
@@ -359321,8 +359303,8 @@ async function searchProjectMemory(query2) {
359321
359303
  const selected = relevant.length > 0 ? relevant.slice(0, MAX_SEARCH_RESULTS) : (await scanMemoryFiles(memoryDir, controller.signal)).slice(0, MAX_SEARCH_RESULTS).map((memory) => ({ path: memory.filePath, mtimeMs: memory.mtimeMs }));
359322
359304
  return Promise.all(selected.map(async (item) => {
359323
359305
  const content = await readFile33(item.path, "utf8").catch(() => "");
359324
- const title = basename26(item.path);
359325
- const rel = relative16(memoryDir, item.path);
359306
+ const title = basename27(item.path);
359307
+ const rel = relative17(memoryDir, item.path);
359326
359308
  const summary = content.split(`
359327
359309
  `).filter((line) => line.trim() && !line.startsWith("---") && !line.includes(": ")).slice(0, 4).join(" ");
359328
359310
  return `${rel || title}: ${truncate4(summary, 240)}`;
@@ -359330,6 +359312,7 @@ async function searchProjectMemory(query2) {
359330
359312
  }
359331
359313
  var TURN_MEMORY_DIR = "turns", MAX_FIELD_CHARS = 2000, MAX_SUMMARY_CHARS = 260, MAX_SEARCH_RESULTS = 8;
359332
359314
  var init_turnMemory = __esm(() => {
359315
+ init_state();
359333
359316
  init_messages3();
359334
359317
  init_paths();
359335
359318
  init_findRelevantMemories();
@@ -360299,7 +360282,7 @@ var init_query2 = __esm(() => {
360299
360282
  init_model();
360300
360283
  init_tokens();
360301
360284
  init_context();
360302
- init_prompt11();
360285
+ init_prompt10();
360303
360286
  init_postSamplingHooks();
360304
360287
  init_hooks5();
360305
360288
  init_dumpPrompts();
@@ -360387,7 +360370,7 @@ function getAnthropicEnvMetadata() {
360387
360370
  function getBuildAgeMinutes() {
360388
360371
  if (false)
360389
360372
  ;
360390
- const buildTime = new Date("2026-05-10T20:16:44.115Z").getTime();
360373
+ const buildTime = new Date("2026-06-03T02:51:00.215Z").getTime();
360391
360374
  if (isNaN(buildTime))
360392
360375
  return;
360393
360376
  return Math.floor((Date.now() - buildTime) / 60000);
@@ -361402,10 +361385,10 @@ var init_promptSuggestion = __esm(() => {
361402
361385
  });
361403
361386
 
361404
361387
  // src/utils/generatedFiles.ts
361405
- import { basename as basename27, extname as extname11, posix as posix6, sep as sep19 } from "path";
361388
+ import { basename as basename28, extname as extname11, posix as posix6, sep as sep19 } from "path";
361406
361389
  function isGeneratedFile(filePath) {
361407
361390
  const normalizedPath = posix6.sep + filePath.split(sep19).join(posix6.sep).replace(/^\/+/, "");
361408
- const fileName = basename27(filePath).toLowerCase();
361391
+ const fileName = basename28(filePath).toLowerCase();
361409
361392
  const ext = extname11(filePath).toLowerCase();
361410
361393
  if (EXCLUDED_FILENAMES.has(fileName)) {
361411
361394
  return true;
@@ -361529,9 +361512,9 @@ __export(exports_commitAttribution, {
361529
361512
  buildSurfaceKey: () => buildSurfaceKey,
361530
361513
  attributionRestoreStateFromLog: () => attributionRestoreStateFromLog
361531
361514
  });
361532
- import { createHash as createHash18, randomUUID as randomUUID19 } from "crypto";
361515
+ import { createHash as createHash19, randomUUID as randomUUID19 } from "crypto";
361533
361516
  import { stat as stat30 } from "fs/promises";
361534
- import { isAbsolute as isAbsolute20, join as join87, relative as relative17, sep as sep20 } from "path";
361517
+ import { isAbsolute as isAbsolute21, join as join87, relative as relative18, sep as sep20 } from "path";
361535
361518
  function getAttributionRepoRoot() {
361536
361519
  const cwd2 = getCwd();
361537
361520
  return findGitRoot(cwd2) ?? getOriginalCwd();
@@ -361582,12 +361565,12 @@ function buildSurfaceKey(surface, model) {
361582
361565
  return `${surface}/${getCanonicalName(model)}`;
361583
361566
  }
361584
361567
  function computeContentHash(content) {
361585
- return createHash18("sha256").update(content).digest("hex");
361568
+ return createHash19("sha256").update(content).digest("hex");
361586
361569
  }
361587
361570
  function normalizeFilePath(filePath) {
361588
361571
  const fs5 = getFsImplementation();
361589
361572
  const cwd2 = getAttributionRepoRoot();
361590
- if (!isAbsolute20(filePath)) {
361573
+ if (!isAbsolute21(filePath)) {
361591
361574
  return filePath;
361592
361575
  }
361593
361576
  let resolvedPath = filePath;
@@ -361599,15 +361582,15 @@ function normalizeFilePath(filePath) {
361599
361582
  resolvedCwd = fs5.realpathSync(cwd2);
361600
361583
  } catch {}
361601
361584
  if (resolvedPath.startsWith(resolvedCwd + sep20) || resolvedPath === resolvedCwd) {
361602
- return relative17(resolvedCwd, resolvedPath).replaceAll(sep20, "/");
361585
+ return relative18(resolvedCwd, resolvedPath).replaceAll(sep20, "/");
361603
361586
  }
361604
361587
  if (filePath.startsWith(cwd2 + sep20) || filePath === cwd2) {
361605
- return relative17(cwd2, filePath).replaceAll(sep20, "/");
361588
+ return relative18(cwd2, filePath).replaceAll(sep20, "/");
361606
361589
  }
361607
361590
  return filePath;
361608
361591
  }
361609
361592
  function expandFilePath(filePath) {
361610
- if (isAbsolute20(filePath)) {
361593
+ if (isAbsolute21(filePath)) {
361611
361594
  return filePath;
361612
361595
  }
361613
361596
  return join87(getAttributionRepoRoot(), filePath);
@@ -363784,7 +363767,7 @@ var init_queryHelpers = __esm(() => {
363784
363767
  import { randomUUID as randomUUID20 } from "crypto";
363785
363768
  import { rm as rm5 } from "fs";
363786
363769
  import { appendFile as appendFile3, copyFile as copyFile5, mkdir as mkdir27 } from "fs/promises";
363787
- import { dirname as dirname34, isAbsolute as isAbsolute21, join as join88, relative as relative18 } from "path";
363770
+ import { dirname as dirname34, isAbsolute as isAbsolute22, join as join88, relative as relative19 } from "path";
363788
363771
  function safeRemoveOverlay(overlayPath) {
363789
363772
  rm5(overlayPath, { recursive: true, force: true, maxRetries: 3, retryDelay: 100 }, () => {});
363790
363773
  }
@@ -364035,8 +364018,8 @@ async function startSpeculation(suggestionText, context5, setAppState, isPipelin
364035
364018
  const pathKey = "notebook_path" in input ? "notebook_path" : ("path" in input) ? "path" : "file_path";
364036
364019
  const filePath = input[pathKey];
364037
364020
  if (filePath) {
364038
- const rel = relative18(cwd2, filePath);
364039
- if (isAbsolute21(rel) || rel.startsWith("..")) {
364021
+ const rel = relative19(cwd2, filePath);
364022
+ if (isAbsolute22(rel) || rel.startsWith("..")) {
364040
364023
  if (isWriteTool) {
364041
364024
  logForDebugging(`[Speculation] Denied ${tool.name}: path outside cwd: ${filePath}`);
364042
364025
  return denySpeculation("Write outside cwd not allowed during speculation", "speculation_write_outside_root");
@@ -365533,7 +365516,7 @@ function getSimplePrompt() {
365533
365516
  ].join(`
365534
365517
  `);
365535
365518
  }
365536
- var init_prompt22 = __esm(() => {
365519
+ var init_prompt21 = __esm(() => {
365537
365520
  init_prompts2();
365538
365521
  init_attribution();
365539
365522
  init_embeddedTools();
@@ -365984,7 +365967,7 @@ var init_BashTool = __esm(() => {
365984
365967
  init_gitOperationTracking();
365985
365968
  init_bashPermissions();
365986
365969
  init_commandSemantics2();
365987
- init_prompt22();
365970
+ init_prompt21();
365988
365971
  init_readOnlyValidation2();
365989
365972
  init_sedEditParser();
365990
365973
  init_shouldUseSandbox();
@@ -369631,7 +369614,7 @@ var init_messages3 = __esm(() => {
369631
369614
  });
369632
369615
 
369633
369616
  // src/services/vcr.ts
369634
- import { createHash as createHash19, randomUUID as randomUUID22 } from "crypto";
369617
+ import { createHash as createHash20, randomUUID as randomUUID22 } from "crypto";
369635
369618
  import { mkdir as mkdir28, readFile as readFile34, writeFile as writeFile27 } from "fs/promises";
369636
369619
  import { dirname as dirname35, join as join89 } from "path";
369637
369620
  function shouldUseVCR() {
@@ -369645,7 +369628,7 @@ async function withFixture(input, fixtureName, f3) {
369645
369628
  if (!shouldUseVCR()) {
369646
369629
  return await f3();
369647
369630
  }
369648
- const hash = createHash19("sha1").update(jsonStringify(input)).digest("hex").slice(0, 12);
369631
+ const hash = createHash20("sha1").update(jsonStringify(input)).digest("hex").slice(0, 12);
369649
369632
  const filename = join89(process.env.CLAUDE_CODE_TEST_FIXTURES_ROOT ?? getCwd(), `fixtures/${fixtureName}-${hash}.json`);
369650
369633
  try {
369651
369634
  const cached2 = jsonParse(await readFile34(filename, { encoding: "utf8" }));
@@ -369680,7 +369663,7 @@ async function withVCR(messages, f3) {
369680
369663
  return true;
369681
369664
  }));
369682
369665
  const dehydratedInput = mapMessages(messagesForAPI.map((_2) => _2.message.content), dehydrateValue);
369683
- const filename = join89(process.env.CLAUDE_CODE_TEST_FIXTURES_ROOT ?? getCwd(), `fixtures/${dehydratedInput.map((_2) => createHash19("sha1").update(jsonStringify(_2)).digest("hex").slice(0, 6)).join("-")}.json`);
369666
+ const filename = join89(process.env.CLAUDE_CODE_TEST_FIXTURES_ROOT ?? getCwd(), `fixtures/${dehydratedInput.map((_2) => createHash20("sha1").update(jsonStringify(_2)).digest("hex").slice(0, 6)).join("-")}.json`);
369684
369667
  try {
369685
369668
  const cached2 = jsonParse(await readFile34(filename, { encoding: "utf8" }));
369686
369669
  cached2.output.forEach(addCachedCostToTotalSessionCost);
@@ -371683,7 +371666,7 @@ function isHumanTurn(m3) {
371683
371666
 
371684
371667
  // src/utils/attachments.ts
371685
371668
  import { readdir as readdir18, stat as stat33 } from "fs/promises";
371686
- import { dirname as dirname36, parse as parse7, relative as relative19, resolve as resolve30 } from "path";
371669
+ import { dirname as dirname36, parse as parse7, relative as relative20, resolve as resolve30 } from "path";
371687
371670
  import { randomUUID as randomUUID24 } from "crypto";
371688
371671
  async function getAttachments(input, toolUseContext, ideSelection, queuedCommands, messages, querySource, options) {
371689
371672
  if (isEnvTruthy(process.env.CLAUDE_CODE_DISABLE_ATTACHMENTS) || isEnvTruthy(process.env.CLAUDE_CODE_SIMPLE)) {
@@ -372048,7 +372031,7 @@ async function getSelectedLinesFromIDE(ideSelection, toolUseContext) {
372048
372031
  lineEnd: ideSelection.lineStart + ideSelection.lineCount - 1,
372049
372032
  filename: ideSelection.filePath,
372050
372033
  content: ideSelection.text,
372051
- displayPath: relative19(getCwd(), ideSelection.filePath)
372034
+ displayPath: relative20(getCwd(), ideSelection.filePath)
372052
372035
  }
372053
372036
  ];
372054
372037
  }
@@ -372087,7 +372070,7 @@ function memoryFilesToAttachments(memoryFiles, toolUseContext, triggerFilePath)
372087
372070
  type: "nested_memory",
372088
372071
  path: memoryFile.path,
372089
372072
  content: memoryFile,
372090
- displayPath: relative19(getCwd(), memoryFile.path)
372073
+ displayPath: relative20(getCwd(), memoryFile.path)
372091
372074
  });
372092
372075
  toolUseContext.loadedNestedMemoryPaths?.add(memoryFile.path);
372093
372076
  toolUseContext.readFileState.set(memoryFile.path, {
@@ -372183,7 +372166,7 @@ async function processAtMentionedFiles(input, toolUseContext) {
372183
372166
  type: "directory",
372184
372167
  path: absoluteFilename,
372185
372168
  content: stdout,
372186
- displayPath: relative19(getCwd(), absoluteFilename)
372169
+ displayPath: relative20(getCwd(), absoluteFilename)
372187
372170
  };
372188
372171
  } catch {
372189
372172
  return null;
@@ -372351,9 +372334,9 @@ async function getRelevantMemoryAttachments(input, agents, readFileState, recent
372351
372334
  const agentDef = agents.find((def) => def.agentType === agentType);
372352
372335
  return agentDef?.memory ? [getAgentMemoryDir(agentType, agentDef.memory)] : [];
372353
372336
  });
372354
- const dirs = memoryDirs.length > 0 ? memoryDirs : [getAutoMemPath()];
372337
+ const dirs = memoryDirs.length > 0 ? memoryDirs : [getDirectoryMemoryPath(), getAutoMemPath()];
372355
372338
  const allResults = await Promise.all(dirs.map((dir) => findRelevantMemories(input, dir, signal, recentTools, alreadySurfaced).catch(() => [])));
372356
- const selected = allResults.flat().filter((m3) => !readFileState.has(m3.path) && !alreadySurfaced.has(m3.path)).slice(0, 5);
372339
+ const selected = [...new Map(allResults.flat().map((memory) => [memory.path, memory])).values()].filter((m3) => !readFileState.has(m3.path) && !alreadySurfaced.has(m3.path)).slice(0, 5);
372357
372340
  const memories = await readMemoriesForSurfacing(selected, signal);
372358
372341
  if (memories.length === 0) {
372359
372342
  return [];
@@ -372529,7 +372512,7 @@ async function getDynamicSkillAttachments(toolUseContext) {
372529
372512
  type: "dynamic_skill",
372530
372513
  skillDir,
372531
372514
  skillNames,
372532
- displayPath: relative19(getCwd(), skillDir)
372515
+ displayPath: relative20(getCwd(), skillDir)
372533
372516
  });
372534
372517
  }
372535
372518
  }
@@ -372716,7 +372699,7 @@ async function tryGetPDFReference(filename) {
372716
372699
  filename,
372717
372700
  pageCount: effectivePageCount,
372718
372701
  fileSize: stats.size,
372719
- displayPath: relative19(getCwd(), filename)
372702
+ displayPath: relative20(getCwd(), filename)
372720
372703
  };
372721
372704
  }
372722
372705
  } catch {}
@@ -372756,7 +372739,7 @@ async function generateFileAttachment(filename, toolUseContext, successEventName
372756
372739
  return {
372757
372740
  type: "already_read_file",
372758
372741
  filename,
372759
- displayPath: relative19(getCwd(), filename),
372742
+ displayPath: relative20(getCwd(), filename),
372760
372743
  content: {
372761
372744
  type: "text",
372762
372745
  file: {
@@ -372784,7 +372767,7 @@ async function generateFileAttachment(filename, toolUseContext, successEventName
372784
372767
  return {
372785
372768
  type: "compact_file_reference",
372786
372769
  filename,
372787
- displayPath: relative19(getCwd(), filename)
372770
+ displayPath: relative20(getCwd(), filename)
372788
372771
  };
372789
372772
  }
372790
372773
  const appState2 = toolUseContext.getAppState();
@@ -372804,7 +372787,7 @@ async function generateFileAttachment(filename, toolUseContext, successEventName
372804
372787
  filename,
372805
372788
  content: result.data,
372806
372789
  truncated: true,
372807
- displayPath: relative19(getCwd(), filename)
372790
+ displayPath: relative20(getCwd(), filename)
372808
372791
  };
372809
372792
  } catch {
372810
372793
  logEvent(errorEventName, {});
@@ -372822,7 +372805,7 @@ async function generateFileAttachment(filename, toolUseContext, successEventName
372822
372805
  type: "file",
372823
372806
  filename,
372824
372807
  content: result.data,
372825
- displayPath: relative19(getCwd(), filename)
372808
+ displayPath: relative20(getCwd(), filename)
372826
372809
  };
372827
372810
  } catch (error5) {
372828
372811
  if (error5 instanceof MaxFileReadTokenExceededError || error5 instanceof FileTooLargeError) {
@@ -373247,7 +373230,7 @@ var init_attachments2 = __esm(() => {
373247
373230
  init_file();
373248
373231
  init_loadAgentsDir();
373249
373232
  init_constants3();
373250
- init_prompt15();
373233
+ init_prompt14();
373251
373234
  init_permissions2();
373252
373235
  init_auth2();
373253
373236
  init_mcpStringUtils();
@@ -373301,22 +373284,22 @@ var init_attachments2 = __esm(() => {
373301
373284
  });
373302
373285
 
373303
373286
  // src/utils/plugins/loadPluginCommands.ts
373304
- import { basename as basename29, dirname as dirname37, join as join92 } from "path";
373287
+ import { basename as basename30, dirname as dirname37, join as join92 } from "path";
373305
373288
  function isSkillFile2(filePath) {
373306
- return /^skill\.md$/i.test(basename29(filePath));
373289
+ return /^skill\.md$/i.test(basename30(filePath));
373307
373290
  }
373308
373291
  function getCommandNameFromFile(filePath, baseDir, pluginName) {
373309
373292
  const isSkill = isSkillFile2(filePath);
373310
373293
  if (isSkill) {
373311
373294
  const skillDirectory = dirname37(filePath);
373312
373295
  const parentOfSkillDir = dirname37(skillDirectory);
373313
- const commandBaseName = basename29(skillDirectory);
373296
+ const commandBaseName = basename30(skillDirectory);
373314
373297
  const relativePath = parentOfSkillDir.startsWith(baseDir) ? parentOfSkillDir.slice(baseDir.length).replace(/^\//, "") : "";
373315
373298
  const namespace = relativePath ? relativePath.split("/").join(":") : "";
373316
373299
  return namespace ? `${pluginName}:${namespace}:${commandBaseName}` : `${pluginName}:${commandBaseName}`;
373317
373300
  } else {
373318
373301
  const fileDirectory = dirname37(filePath);
373319
- const commandBaseName = basename29(filePath).replace(/\.md$/, "");
373302
+ const commandBaseName = basename30(filePath).replace(/\.md$/, "");
373320
373303
  const relativePath = fileDirectory.startsWith(baseDir) ? fileDirectory.slice(baseDir.length).replace(/^\//, "") : "";
373321
373304
  const namespace = relativePath ? relativePath.split("/").join(":") : "";
373322
373305
  return namespace ? `${pluginName}:${namespace}:${commandBaseName}` : `${pluginName}:${commandBaseName}`;
@@ -373353,7 +373336,7 @@ function transformPluginSkillFiles(files) {
373353
373336
  if (skillFiles.length > 0) {
373354
373337
  const skillFile = skillFiles[0];
373355
373338
  if (skillFiles.length > 1) {
373356
- logForDebugging(`Multiple skill files found in ${dir}, using ${basename29(skillFile.filePath)}`);
373339
+ logForDebugging(`Multiple skill files found in ${dir}, using ${basename30(skillFile.filePath)}`);
373357
373340
  }
373358
373341
  result.push(skillFile);
373359
373342
  } else {
@@ -373500,7 +373483,7 @@ async function loadSkillsFromDirectory(skillsPath, pluginName, sourceName, plugi
373500
373483
  }
373501
373484
  try {
373502
373485
  const { frontmatter, content: markdownContent } = parseFrontmatter(directSkillContent, directSkillPath);
373503
- const skillName = `${pluginName}:${basename29(skillsPath)}`;
373486
+ const skillName = `${pluginName}:${basename30(skillsPath)}`;
373504
373487
  const file = {
373505
373488
  filePath: directSkillPath,
373506
373489
  baseDir: dirname37(directSkillPath),
@@ -373646,7 +373629,7 @@ var init_loadPluginCommands = __esm(() => {
373646
373629
  }
373647
373630
  }
373648
373631
  if (!commandName) {
373649
- commandName = `${plugin.name}:${basename29(commandPath).replace(/\.md$/, "")}`;
373632
+ commandName = `${plugin.name}:${basename30(commandPath).replace(/\.md$/, "")}`;
373650
373633
  }
373651
373634
  const finalFrontmatter = metadataOverride ? {
373652
373635
  ...frontmatter,
@@ -373790,7 +373773,7 @@ import {
373790
373773
  writeFile as writeFile28
373791
373774
  } from "fs/promises";
373792
373775
  import { tmpdir as tmpdir6 } from "os";
373793
- import { basename as basename30, dirname as dirname38, join as join93 } from "path";
373776
+ import { basename as basename31, dirname as dirname38, join as join93 } from "path";
373794
373777
  function isPluginZipCacheEnabled() {
373795
373778
  return isEnvTruthy(process.env.CLAUDE_CODE_PLUGIN_USE_ZIP_CACHE);
373796
373779
  }
@@ -373855,7 +373838,7 @@ async function cleanupSessionPluginCache() {
373855
373838
  async function atomicWriteToZipCache(targetPath, data) {
373856
373839
  const dir = dirname38(targetPath);
373857
373840
  await getFsImplementation().mkdir(dir);
373858
- const tmpName = `.${basename30(targetPath)}.tmp.${randomBytes12(4).toString("hex")}`;
373841
+ const tmpName = `.${basename31(targetPath)}.tmp.${randomBytes12(4).toString("hex")}`;
373859
373842
  const tmpPath = join93(dir, tmpName);
373860
373843
  try {
373861
373844
  if (typeof data === "string") {
@@ -374560,7 +374543,7 @@ var init_officialMarketplaceGcs = __esm(() => {
374560
374543
 
374561
374544
  // src/utils/plugins/marketplaceManager.ts
374562
374545
  import { writeFile as writeFile31 } from "fs/promises";
374563
- import { basename as basename31, dirname as dirname40, isAbsolute as isAbsolute22, join as join96, resolve as resolve32, sep as sep22 } from "path";
374546
+ import { basename as basename32, dirname as dirname40, isAbsolute as isAbsolute23, join as join96, resolve as resolve32, sep as sep22 } from "path";
374564
374547
  function getKnownMarketplacesFile() {
374565
374548
  return join96(getPluginsDirectory(), "known_marketplaces.json");
374566
374549
  }
@@ -375141,7 +375124,7 @@ Technical details: ${error5.message}`);
375141
375124
  });
375142
375125
  }
375143
375126
  function getCachePathForSource(source) {
375144
- const tempName = source.source === "github" ? source.repo.replace("/", "-") : source.source === "npm" ? source.package.replace("@", "").replace("/", "-") : source.source === "file" ? basename31(source.path).replace(".json", "") : source.source === "directory" ? basename31(source.path) : "temp_" + Date.now();
375127
+ const tempName = source.source === "github" ? source.repo.replace("/", "-") : source.source === "npm" ? source.package.replace("@", "").replace("/", "-") : source.source === "file" ? basename32(source.path).replace(".json", "") : source.source === "directory" ? basename32(source.path) : "temp_" + Date.now();
375145
375128
  return tempName;
375146
375129
  }
375147
375130
  async function parseFileWithSchema(filePath, schema) {
@@ -375314,7 +375297,7 @@ Technical details: ${errorMsg}`);
375314
375297
  }
375315
375298
  async function addMarketplaceSource(source, onProgress) {
375316
375299
  let resolvedSource = source;
375317
- if (isLocalMarketplaceSource(source) && !isAbsolute22(source.path)) {
375300
+ if (isLocalMarketplaceSource(source) && !isAbsolute23(source.path)) {
375318
375301
  resolvedSource = { ...source, path: resolve32(source.path) };
375319
375302
  }
375320
375303
  if (!isSourceAllowedByPolicy(resolvedSource)) {
@@ -375726,7 +375709,7 @@ var init_marketplaceManager = __esm(() => {
375726
375709
  if (!entry) {
375727
375710
  throw new Error(`Marketplace '${name}' not found in configuration. Available marketplaces: ${Object.keys(config).join(", ")}`);
375728
375711
  }
375729
- if (isLocalMarketplaceSource(entry.source) && !isAbsolute22(entry.source.path)) {
375712
+ if (isLocalMarketplaceSource(entry.source) && !isAbsolute23(entry.source.path)) {
375730
375713
  throw new Error(`Marketplace "${name}" has a relative source path (${entry.source.path}) ` + `in known_marketplaces.json — this is stale state from an older ` + `localclawd version. Run 'claude marketplace remove ${name}' and ` + `re-add it from the original project directory.`);
375731
375714
  }
375732
375715
  try {
@@ -376271,7 +376254,7 @@ var init_managedPlugins = __esm(() => {
376271
376254
  });
376272
376255
 
376273
376256
  // src/utils/plugins/pluginVersioning.ts
376274
- import { createHash as createHash20 } from "crypto";
376257
+ import { createHash as createHash21 } from "crypto";
376275
376258
  async function calculatePluginVersion(pluginId, source, manifest, installPath, providedVersion, gitCommitSha) {
376276
376259
  if (manifest?.version) {
376277
376260
  logForDebugging(`Using manifest version for ${pluginId}: ${manifest.version}`);
@@ -376285,7 +376268,7 @@ async function calculatePluginVersion(pluginId, source, manifest, installPath, p
376285
376268
  const shortSha = gitCommitSha.substring(0, 12);
376286
376269
  if (typeof source === "object" && source.source === "git-subdir") {
376287
376270
  const normPath = source.path.replace(/\\/g, "/").replace(/^\.\//, "").replace(/\/+$/, "");
376288
- const pathHash = createHash20("sha256").update(normPath).digest("hex").substring(0, 8);
376271
+ const pathHash = createHash21("sha256").update(normPath).digest("hex").substring(0, 8);
376289
376272
  const v2 = `${shortSha}-${pathHash}`;
376290
376273
  logForDebugging(`Using git-subdir SHA+path version for ${pluginId}: ${v2} (path=${normPath})`);
376291
376274
  return v2;
@@ -376574,7 +376557,7 @@ import {
376574
376557
  stat as stat36,
376575
376558
  symlink as symlink3
376576
376559
  } from "fs/promises";
376577
- import { basename as basename32, dirname as dirname43, join as join99, relative as relative20, resolve as resolve34, sep as sep24 } from "path";
376560
+ import { basename as basename33, dirname as dirname43, join as join99, relative as relative21, resolve as resolve34, sep as sep24 } from "path";
376578
376561
  function getPluginCachePath() {
376579
376562
  return join99(getPluginsDirectory(), "cache");
376580
376563
  }
@@ -376644,9 +376627,9 @@ async function copyDir(src, dest) {
376644
376627
  }
376645
376628
  const srcPrefix = resolvedSrc.endsWith(sep24) ? resolvedSrc : resolvedSrc + sep24;
376646
376629
  if (resolvedTarget.startsWith(srcPrefix) || resolvedTarget === resolvedSrc) {
376647
- const targetRelativeToSrc = relative20(resolvedSrc, resolvedTarget);
376630
+ const targetRelativeToSrc = relative21(resolvedSrc, resolvedTarget);
376648
376631
  const destTargetPath = join99(dest, targetRelativeToSrc);
376649
- const relativeLinkPath = relative20(dirname43(destPath), destTargetPath);
376632
+ const relativeLinkPath = relative21(dirname43(destPath), destTargetPath);
376650
376633
  await symlink3(relativeLinkPath, destPath);
376651
376634
  } else {
376652
376635
  await symlink3(resolvedTarget, destPath);
@@ -377939,7 +377922,7 @@ async function loadSessionOnlyPlugins(sessionPluginPaths) {
377939
377922
  });
377940
377923
  continue;
377941
377924
  }
377942
- const dirName = basename32(resolvedPath);
377925
+ const dirName = basename33(resolvedPath);
377943
377926
  const { plugin, errors: pluginErrors } = await createPluginFromPath(resolvedPath, `${dirName}@inline`, true, dirName);
377944
377927
  plugin.source = `${plugin.name}@inline`;
377945
377928
  plugin.repository = `${plugin.name}@inline`;
@@ -378111,7 +378094,7 @@ var init_pluginLoader = __esm(() => {
378111
378094
  });
378112
378095
 
378113
378096
  // src/utils/plugins/loadPluginOutputStyles.ts
378114
- import { basename as basename33 } from "path";
378097
+ import { basename as basename34 } from "path";
378115
378098
  async function loadOutputStylesFromDirectory(outputStylesPath, pluginName, loadedPaths) {
378116
378099
  const styles5 = [];
378117
378100
  await walkPluginMarkdown(outputStylesPath, async (fullPath) => {
@@ -378129,7 +378112,7 @@ async function loadOutputStyleFromFile(filePath, pluginName, loadedPaths) {
378129
378112
  try {
378130
378113
  const content = await fs5.readFile(filePath, { encoding: "utf-8" });
378131
378114
  const { frontmatter, content: markdownContent } = parseFrontmatter(content, filePath);
378132
- const fileName = basename33(filePath, ".md");
378115
+ const fileName = basename34(filePath, ".md");
378133
378116
  const baseStyleName = frontmatter.name || fileName;
378134
378117
  const name = `${pluginName}:${baseStyleName}`;
378135
378118
  const description = coerceDescriptionToString(frontmatter.description, name) ?? extractDescriptionFromMarkdown(markdownContent, `Output style from ${pluginName} plugin`);
@@ -378210,7 +378193,7 @@ var init_loadPluginOutputStyles = __esm(() => {
378210
378193
  });
378211
378194
 
378212
378195
  // src/outputStyles/loadOutputStylesDir.ts
378213
- import { basename as basename34 } from "path";
378196
+ import { basename as basename35 } from "path";
378214
378197
  var getOutputStyleDirStyles;
378215
378198
  var init_loadOutputStylesDir = __esm(() => {
378216
378199
  init_memoize();
@@ -378224,7 +378207,7 @@ var init_loadOutputStylesDir = __esm(() => {
378224
378207
  const markdownFiles = await loadMarkdownFilesForSubdir("output-styles", cwd2);
378225
378208
  const styles5 = markdownFiles.map(({ filePath, frontmatter, content, source }) => {
378226
378209
  try {
378227
- const fileName = basename34(filePath);
378210
+ const fileName = basename35(filePath);
378228
378211
  const styleName = fileName.replace(/\.md$/, "");
378229
378212
  const name = frontmatter["name"] || styleName;
378230
378213
  const description = coerceDescriptionToString(frontmatter["description"], styleName) ?? extractDescriptionFromMarkdown(content, `Custom ${styleName} output style`);
@@ -378868,7 +378851,7 @@ var init_prompts2 = __esm(() => {
378868
378851
  init_betas2();
378869
378852
  init_forkSubagent();
378870
378853
  init_systemPromptSections();
378871
- init_prompt11();
378854
+ init_prompt10();
378872
378855
  init_xml();
378873
378856
  init_debug();
378874
378857
  init_thinkharder();
@@ -378885,7 +378868,7 @@ function isFeedbackSurveyDisabled() {
378885
378868
  }
378886
378869
 
378887
378870
  // src/utils/api.ts
378888
- import { createHash as createHash21 } from "crypto";
378871
+ import { createHash as createHash22 } from "crypto";
378889
378872
  function filterSwarmFieldsFromSchema(toolName, schema) {
378890
378873
  const fieldsToRemove = SWARM_FIELDS_BY_TOOL[toolName];
378891
378874
  if (!fieldsToRemove || fieldsToRemove.length === 0) {
@@ -378975,7 +378958,7 @@ function logAPIPrefix(systemPrompt) {
378975
378958
  logEvent("tengu_sysprompt_block", {
378976
378959
  snippet: firstSystemPrompt?.slice(0, 20),
378977
378960
  length: firstSystemPrompt?.length ?? 0,
378978
- hash: firstSystemPrompt ? createHash21("sha256").update(firstSystemPrompt).digest("hex") : ""
378961
+ hash: firstSystemPrompt ? createHash22("sha256").update(firstSystemPrompt).digest("hex") : ""
378979
378962
  });
378980
378963
  }
378981
378964
  function splitSysPromptPrefix(systemPrompt, options) {
@@ -382547,7 +382530,7 @@ var init_permissions2 = __esm(() => {
382547
382530
  });
382548
382531
 
382549
382532
  // src/utils/permissions/permissionSetup.ts
382550
- import { relative as relative21 } from "path";
382533
+ import { relative as relative22 } from "path";
382551
382534
  import { resolve as resolve35 } from "path";
382552
382535
  function isDangerousBashPermission(toolName, ruleContent) {
382553
382536
  if (toolName !== BASH_TOOL_NAME) {
@@ -382651,7 +382634,7 @@ function formatPermissionSource(source) {
382651
382634
  if (SETTING_SOURCES.includes(source)) {
382652
382635
  const filePath = getSettingsFilePathForSource(source);
382653
382636
  if (filePath) {
382654
- const relativePath = relative21(getCwd(), filePath);
382637
+ const relativePath = relative22(getCwd(), filePath);
382655
382638
  return relativePath.length < filePath.length ? relativePath : filePath;
382656
382639
  }
382657
382640
  }
@@ -384273,14 +384256,14 @@ var init_terminalSetup = __esm(() => {
384273
384256
  });
384274
384257
 
384275
384258
  // src/utils/pasteStore.ts
384276
- import { createHash as createHash22 } from "crypto";
384259
+ import { createHash as createHash23 } from "crypto";
384277
384260
  import { mkdir as mkdir32, readdir as readdir22, readFile as readFile40, stat as stat38, unlink as unlink15, writeFile as writeFile33 } from "fs/promises";
384278
384261
  import { join as join105 } from "path";
384279
384262
  function getPasteStoreDir() {
384280
384263
  return join105(getClaudeConfigHomeDir(), PASTE_STORE_DIR);
384281
384264
  }
384282
384265
  function hashPastedText(content) {
384283
- return createHash22("sha256").update(content).digest("hex").slice(0, 16);
384266
+ return createHash23("sha256").update(content).digest("hex").slice(0, 16);
384284
384267
  }
384285
384268
  function getPastePath(hash) {
384286
384269
  return join105(getPasteStoreDir(), `${hash}.txt`);
@@ -386086,7 +386069,7 @@ var init_renderPlaceholder = __esm(() => {
386086
386069
  });
386087
386070
 
386088
386071
  // src/hooks/usePasteHandler.ts
386089
- import { basename as basename35 } from "path";
386072
+ import { basename as basename36 } from "path";
386090
386073
  function usePasteHandler({
386091
386074
  onPaste,
386092
386075
  onInput,
@@ -386137,7 +386120,7 @@ function usePasteHandler({
386137
386120
  const validImages = results.filter((r2) => r2 !== null);
386138
386121
  if (validImages.length > 0) {
386139
386122
  for (const imageData of validImages) {
386140
- const filename = basename35(imageData.path);
386123
+ const filename = basename36(imageData.path);
386141
386124
  onImagePaste2(imageData.base64, imageData.mediaType, filename, imageData.dimensions, imageData.path);
386142
386125
  }
386143
386126
  const nonImageLines = lines.filter((line) => !isImageFilePath(line));
@@ -386740,7 +386723,7 @@ var init_TextInput = __esm(() => {
386740
386723
  });
386741
386724
 
386742
386725
  // src/utils/suggestions/directoryCompletion.ts
386743
- import { basename as basename36, dirname as dirname46, join as join107, sep as sep25 } from "path";
386726
+ import { basename as basename37, dirname as dirname46, join as join107, sep as sep25 } from "path";
386744
386727
  function parsePartialPath(partialPath, basePath) {
386745
386728
  if (!partialPath) {
386746
386729
  const directory2 = basePath || getCwd();
@@ -386751,7 +386734,7 @@ function parsePartialPath(partialPath, basePath) {
386751
386734
  return { directory: resolved, prefix: "" };
386752
386735
  }
386753
386736
  const directory = dirname46(resolved);
386754
- const prefix = basename36(partialPath);
386737
+ const prefix = basename37(partialPath);
386755
386738
  return { directory, prefix };
386756
386739
  }
386757
386740
  async function scanDirectory(dirPath) {
@@ -388416,7 +388399,7 @@ function Feedback({
388416
388399
  platform: env3.platform,
388417
388400
  gitRepo: envInfo.isGit,
388418
388401
  terminal: env3.terminal,
388419
- version: "2.3.3",
388402
+ version: "2.3.5",
388420
388403
  transcript: normalizeMessagesForAPI(messages),
388421
388404
  errors: sanitizedErrors,
388422
388405
  lastApiRequest: getLastAPIRequest(),
@@ -388608,7 +388591,7 @@ function Feedback({
388608
388591
  ", ",
388609
388592
  env3.terminal,
388610
388593
  ", v",
388611
- "2.3.3"
388594
+ "2.3.5"
388612
388595
  ]
388613
388596
  }, undefined, true, undefined, this)
388614
388597
  ]
@@ -388714,7 +388697,7 @@ ${sanitizedDescription}
388714
388697
  ` + `**Environment Info**
388715
388698
  ` + `- Platform: ${env3.platform}
388716
388699
  ` + `- Terminal: ${env3.terminal}
388717
- ` + `- Version: ${"2.3.3"}
388700
+ ` + `- Version: ${"2.3.5"}
388718
388701
  ` + `- Feedback ID: ${feedbackId}
388719
388702
  ` + `
388720
388703
  **Errors**
@@ -391323,7 +391306,7 @@ function buildPrimarySection() {
391323
391306
  }, undefined, false, undefined, this);
391324
391307
  return [{
391325
391308
  label: "Version",
391326
- value: "2.3.3"
391309
+ value: "2.3.5"
391327
391310
  }, {
391328
391311
  label: "Session name",
391329
391312
  value: nameValue
@@ -394542,7 +394525,9 @@ function Config({
394542
394525
  const [, setTheme] = useTheme();
394543
394526
  const themeSetting = useThemeSetting();
394544
394527
  const [globalConfig, setGlobalConfig] = import_react104.useState(getGlobalConfig());
394528
+ const [projectConfig, setProjectConfig] = import_react104.useState(getCurrentProjectConfig());
394545
394529
  const initialConfig = React54.useRef(getGlobalConfig());
394530
+ const initialProjectConfig = React54.useRef(getCurrentProjectConfig());
394546
394531
  const [settingsData, setSettingsData] = import_react104.useState(getInitialSettings());
394547
394532
  const initialSettingsData = React54.useRef(getInitialSettings());
394548
394533
  const [currentOutputStyle, setCurrentOutputStyle] = import_react104.useState(settingsData?.outputStyle || DEFAULT_OUTPUT_STYLE_NAME);
@@ -394670,15 +394655,15 @@ function Config({
394670
394655
  {
394671
394656
  id: "autoCompactEnabled",
394672
394657
  label: "Auto-compact",
394673
- value: globalConfig.autoCompactEnabled,
394658
+ value: projectConfig.autoCompactEnabled ?? globalConfig.autoCompactEnabled,
394674
394659
  type: "boolean",
394675
394660
  onChange(autoCompactEnabled) {
394676
- saveGlobalConfig((current_0) => ({
394661
+ saveCurrentProjectConfig((current_0) => ({
394677
394662
  ...current_0,
394678
394663
  autoCompactEnabled
394679
394664
  }));
394680
- setGlobalConfig({
394681
- ...getGlobalConfig(),
394665
+ setProjectConfig({
394666
+ ...getCurrentProjectConfig(),
394682
394667
  autoCompactEnabled
394683
394668
  });
394684
394669
  logEvent("tengu_auto_compact_setting_changed", {
@@ -394689,17 +394674,17 @@ function Config({
394689
394674
  {
394690
394675
  id: "compactContextWindowTokens",
394691
394676
  label: "Compact context window",
394692
- value: formatCompactContextWindowOption(globalConfig.compactContextWindowTokens),
394677
+ value: formatCompactContextWindowOption(projectConfig.compactContextWindowTokens),
394693
394678
  options: [formatCompactContextWindowOption(undefined), ...COMPACT_CONTEXT_WINDOW_CHOICES.map(formatCompactContextWindowOption)],
394694
394679
  type: "enum",
394695
394680
  onChange(value) {
394696
394681
  const compactContextWindowTokens = COMPACT_CONTEXT_WINDOW_CHOICES.find((tokens) => formatCompactContextWindowOption(tokens) === value);
394697
- saveGlobalConfig((current_0) => ({
394682
+ saveCurrentProjectConfig((current_0) => ({
394698
394683
  ...current_0,
394699
394684
  compactContextWindowTokens
394700
394685
  }));
394701
- setGlobalConfig({
394702
- ...getGlobalConfig(),
394686
+ setProjectConfig({
394687
+ ...getCurrentProjectConfig(),
394703
394688
  compactContextWindowTokens
394704
394689
  });
394705
394690
  logEvent("tengu_compact_context_window_changed", {
@@ -395247,8 +395232,8 @@ function Config({
395247
395232
  id: "showExternalIncludesDialog",
395248
395233
  label: "External LOCALCLAWD.md includes",
395249
395234
  value: (() => {
395250
- const projectConfig = getCurrentProjectConfig();
395251
- if (projectConfig.hasClaudeMdExternalIncludesApproved) {
395235
+ const projectConfig2 = getCurrentProjectConfig();
395236
+ if (projectConfig2.hasClaudeMdExternalIncludesApproved) {
395252
395237
  return "true";
395253
395238
  } else {
395254
395239
  return "false";
@@ -395397,11 +395382,11 @@ function Config({
395397
395382
  if (globalConfig.autoInstallIdeExtension !== initialConfig.current.autoInstallIdeExtension) {
395398
395383
  formattedChanges.push(`${globalConfig.autoInstallIdeExtension ? "Enabled" : "Disabled"} auto-install IDE extension`);
395399
395384
  }
395400
- if (globalConfig.autoCompactEnabled !== initialConfig.current.autoCompactEnabled) {
395401
- formattedChanges.push(`${globalConfig.autoCompactEnabled ? "Enabled" : "Disabled"} auto-compact`);
395385
+ if (projectConfig.autoCompactEnabled !== initialProjectConfig.current.autoCompactEnabled) {
395386
+ formattedChanges.push(`${projectConfig.autoCompactEnabled ?? globalConfig.autoCompactEnabled ? "Enabled" : "Disabled"} auto-compact`);
395402
395387
  }
395403
- if (globalConfig.compactContextWindowTokens !== initialConfig.current.compactContextWindowTokens) {
395404
- formattedChanges.push(`Set compact context window to ${source_default.bold(formatCompactContextWindowOption(globalConfig.compactContextWindowTokens))}`);
395388
+ if (projectConfig.compactContextWindowTokens !== initialProjectConfig.current.compactContextWindowTokens) {
395389
+ formattedChanges.push(`Set compact context window to ${source_default.bold(formatCompactContextWindowOption(projectConfig.compactContextWindowTokens))}`);
395405
395390
  }
395406
395391
  if (globalConfig.respectGitignore !== initialConfig.current.respectGitignore) {
395407
395392
  formattedChanges.push(`${globalConfig.respectGitignore ? "Enabled" : "Disabled"} respect .gitignore in file picker`);
@@ -396004,7 +395989,7 @@ function Config({
396004
395989
  }
396005
395990
  }, undefined, false, undefined, this)
396006
395991
  }, undefined, false, undefined, this) : showSubmenu === "ChannelDowngrade" ? /* @__PURE__ */ jsx_dev_runtime176.jsxDEV(ChannelDowngradeDialog, {
396007
- currentVersion: "2.3.3",
395992
+ currentVersion: "2.3.5",
396008
395993
  onChoice: (choice) => {
396009
395994
  setShowSubmenu(null);
396010
395995
  setTabsHidden(false);
@@ -396016,7 +396001,7 @@ function Config({
396016
396001
  autoUpdatesChannel: "stable"
396017
396002
  };
396018
396003
  if (choice === "stay") {
396019
- newSettings.minimumVersion = "2.3.3";
396004
+ newSettings.minimumVersion = "2.3.5";
396020
396005
  }
396021
396006
  updateSettingsForSource("userSettings", newSettings);
396022
396007
  setSettingsData((prev_27) => ({
@@ -402422,12 +402407,12 @@ var call19 = async (onDone, _context, args) => {
402422
402407
  const destArg = parts.slice(1).join(" ");
402423
402408
  const srcPath = srcName.includes("/") || srcName.includes("\\") ? srcName : join113(defaultOutputDir, srcName);
402424
402409
  const { copyFile: copyFile9, rename: rename7 } = await import("fs/promises");
402425
- const { basename: basename37 } = await import("path");
402410
+ const { basename: basename38 } = await import("path");
402426
402411
  let destPath;
402427
402412
  if (!destArg) {
402428
- destPath = join113(projectRoot, basename37(srcName));
402413
+ destPath = join113(projectRoot, basename38(srcName));
402429
402414
  } else if (!destArg.includes("/") && !destArg.includes("\\") && !destArg.includes(".")) {
402430
- destPath = join113(projectRoot, destArg, basename37(srcName));
402415
+ destPath = join113(projectRoot, destArg, basename38(srcName));
402431
402416
  } else {
402432
402417
  destPath = destArg.startsWith(".") || !destArg.includes(":") && !destArg.startsWith("/") ? join113(projectRoot, destArg) : destArg;
402433
402418
  }
@@ -403431,7 +403416,7 @@ function createEmptyState() {
403431
403416
 
403432
403417
  // src/services/director/directorMemoryOps.ts
403433
403418
  import { mkdir as mkdir38, readdir as readdir24, readFile as readFile45, stat as stat40, writeFile as writeFile40 } from "fs/promises";
403434
- import { basename as basename37, join as join117, resolve as resolve37 } from "path";
403419
+ import { basename as basename38, join as join117, resolve as resolve37 } from "path";
403435
403420
  function setDirectorProjectRoot(projectPath) {
403436
403421
  _projectStateDir = join117(projectPath, ".localclawd");
403437
403422
  }
@@ -403461,7 +403446,7 @@ async function saveDirectorState(state) {
403461
403446
  await writeFile40(join117(_projectStateDir, "director-memory.json"), JSON.stringify(state, null, 2), "utf-8");
403462
403447
  }
403463
403448
  function slugify4(path12) {
403464
- return basename37(resolve37(path12)).toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
403449
+ return basename38(resolve37(path12)).toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
403465
403450
  }
403466
403451
  async function detectGitRemote(projectPath) {
403467
403452
  try {
@@ -403486,11 +403471,11 @@ async function detectDescription(projectPath) {
403486
403471
  if (firstLine)
403487
403472
  return firstLine.trim().slice(0, 120);
403488
403473
  } catch {}
403489
- return basename37(resolve37(projectPath));
403474
+ return basename38(resolve37(projectPath));
403490
403475
  }
403491
403476
  function generateTags(project) {
403492
403477
  const tags = [];
403493
- const name = basename37(resolve37(project.path));
403478
+ const name = basename38(resolve37(project.path));
403494
403479
  tags.push(name.toLowerCase());
403495
403480
  const words = project.description.toLowerCase().split(/\W+/).filter((w2) => w2.length > 3);
403496
403481
  tags.push(...words.slice(0, 5));
@@ -405334,14 +405319,53 @@ function parseFocus(args) {
405334
405319
  function extractLastAssistantText(messages) {
405335
405320
  for (let i3 = messages.length - 1;i3 >= 0; i3--) {
405336
405321
  const msg = messages[i3];
405337
- if (msg.role !== "assistant")
405322
+ const role = msg.message?.role ?? msg.role;
405323
+ if (role !== "assistant" && msg.type !== "assistant")
405338
405324
  continue;
405339
- const blocks = Array.isArray(msg.content) ? msg.content : [];
405325
+ const content = msg.message?.content ?? msg.content;
405326
+ if (typeof content === "string") {
405327
+ return content;
405328
+ }
405329
+ const blocks = Array.isArray(content) ? content : [];
405340
405330
  return blocks.filter((b3) => b3.type === "text").map((b3) => b3.text ?? "").join(`
405341
405331
  `);
405342
405332
  }
405343
405333
  return "";
405344
405334
  }
405335
+ function hasCompactBoundaryAfterLastAssistant(messages) {
405336
+ let lastAssistantIndex = -1;
405337
+ let lastCompactBoundaryIndex = -1;
405338
+ for (let i3 = 0;i3 < messages.length; i3++) {
405339
+ const msg = messages[i3];
405340
+ const role = msg.message?.role ?? msg.role;
405341
+ if (role === "assistant" || msg.type === "assistant") {
405342
+ lastAssistantIndex = i3;
405343
+ }
405344
+ if (msg.type === "system" && msg.subtype === "compact_boundary") {
405345
+ lastCompactBoundaryIndex = i3;
405346
+ }
405347
+ }
405348
+ return lastCompactBoundaryIndex >= 0 && lastCompactBoundaryIndex > lastAssistantIndex;
405349
+ }
405350
+ function queuedKeepGoingCommand(value) {
405351
+ return typeof value === "string" && /^\/(keepgoing|kg|continue)(\s|$)/i.test(value.trim());
405352
+ }
405353
+ function scheduleKeepGoingResume(command3) {
405354
+ try {
405355
+ removeByFilter((cmd) => queuedKeepGoingCommand(cmd.value));
405356
+ const timer = setTimeout(() => {
405357
+ try {
405358
+ removeByFilter((cmd) => queuedKeepGoingCommand(cmd.value));
405359
+ enqueue({ value: command3, mode: "prompt", isMeta: true, priority: "later" });
405360
+ } catch (error5) {
405361
+ logKgCrash(error5, "resume-enqueue");
405362
+ }
405363
+ }, RECOVERY_REQUEUE_DELAY_MS);
405364
+ timer.unref?.();
405365
+ } catch (error5) {
405366
+ logKgCrash(error5, "resume-schedule");
405367
+ }
405368
+ }
405345
405369
  async function synthesizeNextDirective(focus) {
405346
405370
  try {
405347
405371
  const cacheSafeParams = getLastCacheSafeParams();
@@ -405533,9 +405557,8 @@ function logKgCrash(error5, context7) {
405533
405557
  const msg = error5 instanceof Error ? error5.stack ?? error5.message : String(error5);
405534
405558
  try {
405535
405559
  const { appendFileSync: appendFileSync3, mkdirSync: mkdirSync6 } = __require("fs");
405536
- const { homedir: homedir26 } = __require("os");
405537
405560
  const { join: join119 } = __require("path");
405538
- const dir = join119(homedir26(), ".claude");
405561
+ const dir = getClaudeConfigHomeDir();
405539
405562
  mkdirSync6(dir, { recursive: true });
405540
405563
  appendFileSync3(join119(dir, "crash.log"), `[${new Date().toISOString()}] keepgoing ${context7}: ${msg}
405541
405564
  `);
@@ -405574,15 +405597,18 @@ async function callInner3(onDone, context7, args) {
405574
405597
  }
405575
405598
  }));
405576
405599
  let lastText = "";
405600
+ let compactBoundaryAfterLastAssistant = false;
405577
405601
  try {
405578
405602
  context7.setMessages((prev) => {
405579
- lastText = extractLastAssistantText(prev);
405603
+ const transcript = prev;
405604
+ lastText = extractLastAssistantText(transcript);
405605
+ compactBoundaryAfterLastAssistant = hasCompactBoundaryAfterLastAssistant(transcript);
405580
405606
  return prev;
405581
405607
  });
405582
405608
  } catch (e2) {
405583
405609
  logKgCrash(e2, "extractLastAssistantText");
405584
405610
  }
405585
- const contextCompacted = lastText === NO_CONTENT_MESSAGE || lastText.trim() === "";
405611
+ const contextCompacted = lastText === NO_CONTENT_MESSAGE || compactBoundaryAfterLastAssistant;
405586
405612
  if (!contextCompacted) {
405587
405613
  const extracted = extractSelfDirective(lastText);
405588
405614
  const synthesized = lastText.trim() && sessionRound >= 1 ? await synthesizeNextDirective(focus) : "";
@@ -405595,7 +405621,7 @@ async function callInner3(onDone, context7, args) {
405595
405621
  sessionSelfDirective = preview ? `Continue from where you left off: ${preview.slice(0, 200)}` : "Continue with the next most important task.";
405596
405622
  }
405597
405623
  } else {
405598
- sessionSelfDirective = "";
405624
+ sessionSelfDirective = "Context was compacted or the last model response had no content. Reconstruct the current state from the compact summary, git status, active files, and recent tests, then continue the highest-value remaining work without waiting for the user.";
405599
405625
  }
405600
405626
  if (lastText.trim() && lastText !== NO_CONTENT_MESSAGE) {
405601
405627
  const preview = lastText.slice(0, 1200);
@@ -405645,7 +405671,8 @@ Round ${finalRound} · stopped via /stop`;
405645
405671
  const nextCmd = "/keepgoing";
405646
405672
  const handleReady = () => {
405647
405673
  try {
405648
- enqueue({ value: nextCmd, mode: "prompt", isMeta: true });
405674
+ removeByFilter((cmd) => queuedKeepGoingCommand(cmd.value));
405675
+ enqueue({ value: nextCmd, mode: "prompt", isMeta: true, priority: "later" });
405649
405676
  onDone(undefined, {
405650
405677
  display: "system",
405651
405678
  shouldQuery: true,
@@ -405653,8 +405680,9 @@ Round ${finalRound} · stopped via /stop`;
405653
405680
  });
405654
405681
  } catch (e2) {
405655
405682
  logKgCrash(e2, "handleReady");
405683
+ scheduleKeepGoingResume(nextCmd);
405656
405684
  try {
405657
- onDone(`⚠ keepgoing recovered from internal error`, { display: "system" });
405685
+ onDone(`⚠ keepgoing recovered from internal error and will continue`, { display: "system" });
405658
405686
  } catch {}
405659
405687
  }
405660
405688
  };
@@ -405667,16 +405695,23 @@ Round ${finalRound} · stopped via /stop`;
405667
405695
  onReady: handleReady
405668
405696
  }, undefined, false, undefined, this);
405669
405697
  }
405670
- var React58, jsx_dev_runtime196, sessionRound = 0, sessionFocus = "", sessionOriginalMode = "default", sessionSelfDirective = "", call22 = async (onDone, context7, args) => {
405698
+ var React58, jsx_dev_runtime196, sessionRound = 0, sessionFocus = "", sessionOriginalMode = "default", sessionSelfDirective = "", RECOVERY_REQUEUE_DELAY_MS = 1500, call22 = async (onDone, context7, args) => {
405671
405699
  try {
405672
405700
  return await callInner3(onDone, context7, args);
405673
405701
  } catch (error5) {
405674
405702
  logKgCrash(error5, "call");
405675
405703
  const msg = error5 instanceof Error ? error5.message : String(error5);
405676
- try {
405677
- enqueue({ value: "/keepgoing", mode: "prompt", isMeta: true });
405678
- } catch {}
405679
- onDone(`⚠ keepgoing error (restarting): ${msg}`, { display: "system" });
405704
+ const fallbackFocus = sessionFocus || parseFocus(args ?? "");
405705
+ const command3 = fallbackFocus ? `/keepgoing ${fallbackFocus}` : "/keepgoing";
405706
+ scheduleKeepGoingResume(command3);
405707
+ context7.setAppState((prev) => ({
405708
+ ...prev,
405709
+ toolPermissionContext: {
405710
+ ...prev.toolPermissionContext,
405711
+ mode: "bypassPermissions"
405712
+ }
405713
+ }));
405714
+ onDone(`keepgoing recovered from an internal error and will continue: ${msg}`, { display: "system" });
405680
405715
  return null;
405681
405716
  }
405682
405717
  };
@@ -405691,6 +405726,7 @@ var init_keepgoing = __esm(() => {
405691
405726
  init_messageQueueManager();
405692
405727
  init_forkedAgent();
405693
405728
  init_messages3();
405729
+ init_envUtils();
405694
405730
  React58 = __toESM(require_react(), 1);
405695
405731
  jsx_dev_runtime196 = __toESM(require_jsx_dev_runtime(), 1);
405696
405732
  });
@@ -409321,7 +409357,7 @@ var init_daytona_run2 = __esm(() => {
409321
409357
 
409322
409358
  // src/services/skills/skillPortable.ts
409323
409359
  import { readdir as readdir30, readFile as readFile52, writeFile as writeFile47, mkdir as mkdir45, stat as stat46 } from "fs/promises";
409324
- import { join as join127, basename as basename38, extname as extname13, resolve as resolve38 } from "path";
409360
+ import { join as join127, basename as basename39, extname as extname13, resolve as resolve38 } from "path";
409325
409361
  function parseFrontmatter2(raw) {
409326
409362
  const m3 = raw.match(/^---\s*\n([\s\S]*?)\n---\s*\n?([\s\S]*)$/);
409327
409363
  if (!m3)
@@ -409426,7 +409462,7 @@ async function importSkill(filePath) {
409426
409462
  const { meta, body } = parseFrontmatter2(raw);
409427
409463
  let name = typeof meta.name === "string" ? meta.name : "";
409428
409464
  if (!name) {
409429
- name = basename38(filePath, extname13(filePath));
409465
+ name = basename39(filePath, extname13(filePath));
409430
409466
  }
409431
409467
  name = name.toLowerCase().replace(/[^a-z0-9-]+/g, "-").replace(/^-|-$/g, "").slice(0, 48);
409432
409468
  if (!name)
@@ -410207,7 +410243,7 @@ __export(exports_webuiServer, {
410207
410243
  });
410208
410244
  import { createServer as createServer5 } from "http";
410209
410245
  import { mkdir as mkdir48, readdir as readdir31, readFile as readFile55, writeFile as writeFile50 } from "fs/promises";
410210
- import { createHash as createHash23 } from "crypto";
410246
+ import { createHash as createHash24 } from "crypto";
410211
410247
  import { join as join130 } from "path";
410212
410248
  function getWebuiPort() {
410213
410249
  return _boundPort;
@@ -410323,7 +410359,7 @@ function handleUpgrade(req, socket) {
410323
410359
  socket.destroy();
410324
410360
  return;
410325
410361
  }
410326
- const accept = createHash23("sha1").update(key + WS_GUID).digest("base64");
410362
+ const accept = createHash24("sha1").update(key + WS_GUID).digest("base64");
410327
410363
  socket.write(`HTTP/1.1 101 Switching Protocols\r
410328
410364
  ` + `Upgrade: websocket\r
410329
410365
  ` + `Connection: Upgrade\r
@@ -411004,7 +411040,7 @@ var init_windows_setup2 = __esm(() => {
411004
411040
  import { createServer as createServer6 } from "http";
411005
411041
  import { readFile as readFile56, writeFile as writeFile51, mkdir as mkdir49, readdir as readdir32, stat as stat48 } from "fs/promises";
411006
411042
  import { spawn as spawn12 } from "child_process";
411007
- import { join as join131, resolve as resolvePath, relative as relative24 } from "path";
411043
+ import { join as join131, resolve as resolvePath, relative as relative25 } from "path";
411008
411044
  async function handleRead(p) {
411009
411045
  try {
411010
411046
  const raw = await readFile56(p.path, "utf-8");
@@ -411131,7 +411167,7 @@ async function handleGlob(p) {
411131
411167
  const re2 = globToRegex(p.pattern);
411132
411168
  const all4 = [];
411133
411169
  await walk(cwd2, all4, 1e4);
411134
- const matches = all4.map((f3) => relative24(cwd2, f3).replace(/\\/g, "/")).filter((f3) => re2.test(f3));
411170
+ const matches = all4.map((f3) => relative25(cwd2, f3).replace(/\\/g, "/")).filter((f3) => re2.test(f3));
411135
411171
  return { ok: true, data: matches };
411136
411172
  } catch (e2) {
411137
411173
  return { ok: false, error: String(e2) };
@@ -411149,7 +411185,7 @@ async function handleGrep(p) {
411149
411185
  for (const f3 of files) {
411150
411186
  if (out.length >= max2)
411151
411187
  break;
411152
- if (globRe && !globRe.test(relative24(root2, f3).replace(/\\/g, "/")))
411188
+ if (globRe && !globRe.test(relative25(root2, f3).replace(/\\/g, "/")))
411153
411189
  continue;
411154
411190
  let content;
411155
411191
  try {
@@ -411795,7 +411831,7 @@ async function autoDetectProviderContextWindow() {
411795
411831
  return;
411796
411832
  _detected = true;
411797
411833
  try {
411798
- const configured = getGlobalConfig().compactContextWindowTokens;
411834
+ const configured = getCurrentProjectConfig().compactContextWindowTokens;
411799
411835
  if (configured && configured > 0) {
411800
411836
  setLocalProviderContextWindow(configured);
411801
411837
  logForDebugging(`[context] Using persisted context window: ${configured} tokens`);
@@ -411814,8 +411850,11 @@ async function autoDetectProviderContextWindow() {
411814
411850
  }
411815
411851
  if (detected && detected > 0) {
411816
411852
  setLocalProviderContextWindow(detected);
411817
- saveGlobalConfig((c5) => ({ ...c5, compactContextWindowTokens: detected }));
411818
- logForDebugging(`[context] Auto-detected context window from ${provider}: ${detected} tokens (persisted)`);
411853
+ saveCurrentProjectConfig((c5) => ({
411854
+ ...c5,
411855
+ compactContextWindowTokens: detected
411856
+ }));
411857
+ logForDebugging(`[context] Auto-detected context window from ${provider}: ${detected} tokens (persisted for project)`);
411819
411858
  }
411820
411859
  } catch (err2) {
411821
411860
  logForDebugging(`[context] Auto-detect context window failed (non-fatal): ${err2}`);
@@ -411848,7 +411887,11 @@ function barLine(used, total, width = 40) {
411848
411887
  return `[${"█".repeat(filled)}${" ".repeat(empty)}] ${Math.round(pct * 100)}%`;
411849
411888
  }
411850
411889
  function applySize(parsed, model, onDone) {
411851
- saveGlobalConfig((c5) => ({ ...c5, compactContextWindowTokens: parsed }));
411890
+ saveCurrentProjectConfig((c5) => ({ ...c5, compactContextWindowTokens: parsed }));
411891
+ saveGlobalConfig((c5) => {
411892
+ const { compactContextWindowTokens: _legacy, ...rest } = c5;
411893
+ return rest;
411894
+ });
411852
411895
  setLocalProviderContextWindow(parsed);
411853
411896
  onDone([
411854
411897
  `Context window set to ${fmtTokens(parsed)} tokens.`,
@@ -411880,15 +411923,16 @@ var call51 = async (onDone, context7, args) => {
411880
411923
  return applySize(parsed, model, onDone);
411881
411924
  }
411882
411925
  if (sub === "reset") {
411926
+ saveCurrentProjectConfig((c5) => {
411927
+ const { compactContextWindowTokens: _drop, ...rest } = c5;
411928
+ return rest;
411929
+ });
411883
411930
  saveGlobalConfig((c5) => {
411884
411931
  const { compactContextWindowTokens: _drop, ...rest } = c5;
411885
411932
  return rest;
411886
411933
  });
411887
411934
  setLocalProviderContextWindow(null);
411888
411935
  resetContextWindowDetection();
411889
- const hadEnv = process.env.LOCALCLAWD_MAX_CONTEXT_TOKENS || process.env.CLAUDE_CODE_MAX_CONTEXT_TOKENS;
411890
- delete process.env.LOCALCLAWD_MAX_CONTEXT_TOKENS;
411891
- delete process.env.CLAUDE_CODE_MAX_CONTEXT_TOKENS;
411892
411936
  await autoDetectProviderContextWindow();
411893
411937
  const detected = getLocalProviderContextWindow();
411894
411938
  const effective = getContextWindowForModel(model);
@@ -411898,9 +411942,6 @@ var call51 = async (onDone, context7, args) => {
411898
411942
  `Effective window: ${fmtTokens(getEffectiveContextWindowSize(model))} (minus output reservation).`,
411899
411943
  `Auto-compact threshold: ${fmtTokens(getAutoCompactThreshold(model))}.`
411900
411944
  ];
411901
- if (hadEnv) {
411902
- lines2.push("", "Note: LOCALCLAWD_MAX_CONTEXT_TOKENS / CLAUDE_CODE_MAX_CONTEXT_TOKENS were set in this", "process and have been cleared for this session. Unset them in your shell to make it", "permanent.");
411903
- }
411904
411945
  onDone(lines2.join(`
411905
411946
  `), { display: "system" });
411906
411947
  return null;
@@ -411909,7 +411950,7 @@ var call51 = async (onDone, context7, args) => {
411909
411950
  const toggle = parts[1]?.toLowerCase();
411910
411951
  if (toggle === "on" || toggle === "off") {
411911
411952
  const enable = toggle === "on";
411912
- saveGlobalConfig((c5) => ({ ...c5, autoCompactEnabled: enable }));
411953
+ saveCurrentProjectConfig((c5) => ({ ...c5, autoCompactEnabled: enable }));
411913
411954
  onDone(`Auto-compact ${enable ? "enabled" : "disabled"}.`, { display: "system" });
411914
411955
  return null;
411915
411956
  }
@@ -411919,7 +411960,7 @@ var call51 = async (onDone, context7, args) => {
411919
411960
  const totalWindow = getContextWindowForModel(model);
411920
411961
  const effectiveWindow = getEffectiveContextWindowSize(model);
411921
411962
  const autoCompactThreshold = getAutoCompactThreshold(model);
411922
- const persisted = getGlobalConfig().compactContextWindowTokens;
411963
+ const persisted = getCurrentProjectConfig().compactContextWindowTokens;
411923
411964
  const detectedFromProvider = getLocalProviderContextWindow();
411924
411965
  const tokenUsage = tokenCountWithEstimation(context7.messages);
411925
411966
  const autoCompact = isAutoCompactEnabled();
@@ -412261,12 +412302,12 @@ var init_MemoryFileSelector = __esm(() => {
412261
412302
 
412262
412303
  // src/components/memory/MemoryUpdateNotification.tsx
412263
412304
  import { homedir as homedir30 } from "os";
412264
- import { relative as relative25 } from "path";
412305
+ import { relative as relative26 } from "path";
412265
412306
  function getRelativeMemoryPath(path12) {
412266
412307
  const homeDir = homedir30();
412267
412308
  const cwd2 = getCwd();
412268
412309
  const relativeToHome = path12.startsWith(homeDir) ? "~" + path12.slice(homeDir.length) : null;
412269
- const relativeToCwd = path12.startsWith(cwd2) ? "./" + relative25(cwd2, path12) : null;
412310
+ const relativeToCwd = path12.startsWith(cwd2) ? "./" + relative26(cwd2, path12) : null;
412270
412311
  if (relativeToHome && relativeToCwd) {
412271
412312
  return relativeToHome.length <= relativeToCwd.length ? relativeToHome : relativeToCwd;
412272
412313
  }
@@ -412284,12 +412325,12 @@ import {
412284
412325
  spawn as spawn13,
412285
412326
  spawnSync as spawnSync8
412286
412327
  } from "child_process";
412287
- import { basename as basename39 } from "path";
412328
+ import { basename as basename40 } from "path";
412288
412329
  function isCommandAvailable3(command3) {
412289
412330
  return !!whichSync(command3);
412290
412331
  }
412291
412332
  function classifyGuiEditor(editor) {
412292
- const base = basename39(editor.split(" ")[0] ?? "");
412333
+ const base = basename40(editor.split(" ")[0] ?? "");
412293
412334
  return GUI_EDITORS.find((g2) => base.includes(g2));
412294
412335
  }
412295
412336
  function guiGotoArgv(guiFamily, filePath, line) {
@@ -412326,7 +412367,7 @@ function openFileInExternalEditor(filePath, line) {
412326
412367
  const inkInstance = instances_default.get(process.stdout);
412327
412368
  if (!inkInstance)
412328
412369
  return false;
412329
- const useGotoLine = line && PLUS_N_EDITORS.test(basename39(base));
412370
+ const useGotoLine = line && PLUS_N_EDITORS.test(basename40(base));
412330
412371
  inkInstance.enterAlternateScreen();
412331
412372
  try {
412332
412373
  const syncOpts = { stdio: "inherit" };
@@ -412523,7 +412564,7 @@ async function runMemoryControlCommand(args) {
412523
412564
  const [command3 = "status", ...rest] = args.trim().split(/\s+/);
412524
412565
  if (command3 === "on" || command3 === "enable") {
412525
412566
  await setProjectMemoryEnabled(true);
412526
- return "Project memory is on. Future turns will be saved in .localclawd/memory/.";
412567
+ return "Project memory is on. Future turns will be saved under .localclawd/memory/directories/<current-directory>.";
412527
412568
  }
412528
412569
  if (command3 === "off" || command3 === "disable") {
412529
412570
  await setProjectMemoryEnabled(false);
@@ -412545,9 +412586,11 @@ async function runMemoryControlCommand(args) {
412545
412586
  const status = await getProjectMemoryStatus();
412546
412587
  return [
412547
412588
  `Project memory: ${status.enabled ? "on" : "off"}`,
412548
- `Path: ${status.memoryDir}`,
412549
- `Files: ${status.fileCount}`,
412550
- `Size: ${formatBytes(status.bytes)}`
412589
+ `Project path: ${status.memoryDir}`,
412590
+ `Current directory key: ${status.directoryKey}`,
412591
+ `Current directory path: ${status.directoryMemoryDir}`,
412592
+ `Files: ${status.fileCount} total; ${status.directoryFileCount} in current directory memory`,
412593
+ `Size: ${formatBytes(status.bytes)} total; ${formatBytes(status.directoryBytes)} in current directory memory`
412551
412594
  ].join(`
412552
412595
  `);
412553
412596
  }
@@ -413535,7 +413578,7 @@ function Help(t0) {
413535
413578
  let t6;
413536
413579
  if ($2[31] !== tabs) {
413537
413580
  t6 = /* @__PURE__ */ jsx_dev_runtime218.jsxDEV(Tabs, {
413538
- title: `localclawd v${"2.3.3"}`,
413581
+ title: `localclawd v${"2.3.5"}`,
413539
413582
  color: "professionalBlue",
413540
413583
  defaultTab: "general",
413541
413584
  children: tabs
@@ -416233,7 +416276,7 @@ var init_channelPermissions = __esm(() => {
416233
416276
  });
416234
416277
 
416235
416278
  // src/services/mcp/useManageMCPConnections.ts
416236
- import { basename as basename40 } from "path";
416279
+ import { basename as basename41 } from "path";
416237
416280
  function getErrorKey(error5) {
416238
416281
  const plugin = "plugin" in error5 ? error5.plugin : "no-plugin";
416239
416282
  return `${error5.type}:${error5.source}:${plugin}`;
@@ -416610,7 +416653,7 @@ function useManageMCPConnections(dynamicMcpConfig, isStrictMcpConfig = false) {
416610
416653
  else if (serverConfig.scope === "claudeai")
416611
416654
  counts.claudeai++;
416612
416655
  if (process.env.USER_TYPE === "ant" && !isMcpServerDisabled(name) && (serverConfig.type === undefined || serverConfig.type === "stdio") && "command" in serverConfig) {
416613
- stdioCommands.push(basename40(serverConfig.command));
416656
+ stdioCommands.push(basename41(serverConfig.command));
416614
416657
  }
416615
416658
  }
416616
416659
  logEvent("tengu_mcp_servers", {
@@ -430797,7 +430840,7 @@ function getRecentReleaseNotes(currentVersion, previousVersion, changelogContent
430797
430840
  }
430798
430841
  return [];
430799
430842
  }
430800
- async function checkForReleaseNotes(lastSeenVersion, currentVersion = "2.3.3") {
430843
+ async function checkForReleaseNotes(lastSeenVersion, currentVersion = "2.3.5") {
430801
430844
  if (process.env.USER_TYPE === "ant") {
430802
430845
  const changelog = MACRO.VERSION_CHANGELOG;
430803
430846
  if (changelog) {
@@ -430824,7 +430867,7 @@ async function checkForReleaseNotes(lastSeenVersion, currentVersion = "2.3.3") {
430824
430867
  releaseNotes
430825
430868
  };
430826
430869
  }
430827
- function checkForReleaseNotesSync(lastSeenVersion, currentVersion = "2.3.3") {
430870
+ function checkForReleaseNotesSync(lastSeenVersion, currentVersion = "2.3.5") {
430828
430871
  if (process.env.USER_TYPE === "ant") {
430829
430872
  const changelog = MACRO.VERSION_CHANGELOG;
430830
430873
  if (changelog) {
@@ -430981,7 +431024,7 @@ function getRecentActivitySync() {
430981
431024
  return cachedActivity;
430982
431025
  }
430983
431026
  function getLogoDisplayData() {
430984
- const version = process.env.DEMO_VERSION ?? "2.3.3";
431027
+ const version = process.env.DEMO_VERSION ?? "2.3.5";
430985
431028
  const serverUrl = getDirectConnectServerUrl();
430986
431029
  const displayPath = process.env.DEMO_VERSION ? "/code/claude" : getDisplayPath(getCwd());
430987
431030
  const cwd2 = serverUrl ? `${displayPath} in ${serverUrl.replace(/^https?:\/\//, "")}` : displayPath;
@@ -432081,7 +432124,7 @@ function Logo() {
432081
432124
  if ($2[2] === Symbol.for("react.memo_cache_sentinel")) {
432082
432125
  t2 = () => {
432083
432126
  const currentConfig = getGlobalConfig();
432084
- if (currentConfig.lastReleaseNotesSeen === "2.3.3") {
432127
+ if (currentConfig.lastReleaseNotesSeen === "2.3.5") {
432085
432128
  return;
432086
432129
  }
432087
432130
  saveGlobalConfig(_temp325);
@@ -432740,12 +432783,12 @@ function Logo() {
432740
432783
  return t41;
432741
432784
  }
432742
432785
  function _temp325(current) {
432743
- if (current.lastReleaseNotesSeen === "2.3.3") {
432786
+ if (current.lastReleaseNotesSeen === "2.3.5") {
432744
432787
  return current;
432745
432788
  }
432746
432789
  return {
432747
432790
  ...current,
432748
- lastReleaseNotesSeen: "2.3.3"
432791
+ lastReleaseNotesSeen: "2.3.5"
432749
432792
  };
432750
432793
  }
432751
432794
  function _temp240(s_0) {
@@ -433301,7 +433344,7 @@ var init_nullRenderingAttachments = __esm(() => {
433301
433344
  });
433302
433345
 
433303
433346
  // src/utils/statusNoticeDefinitions.tsx
433304
- import { relative as relative26 } from "path";
433347
+ import { relative as relative27 } from "path";
433305
433348
  function getActiveNotices(context7) {
433306
433349
  return statusNoticeDefinitions.filter((notice) => notice.isActive(context7));
433307
433350
  }
@@ -433325,7 +433368,7 @@ var init_statusNoticeDefinitions = __esm(() => {
433325
433368
  const largeMemoryFiles = getLargeMemoryFiles(ctx2.memoryFiles);
433326
433369
  return /* @__PURE__ */ jsx_dev_runtime260.jsxDEV(jsx_dev_runtime260.Fragment, {
433327
433370
  children: largeMemoryFiles.map((file) => {
433328
- const displayPath = file.path.startsWith(getCwd()) ? relative26(getCwd(), file.path) : file.path;
433371
+ const displayPath = file.path.startsWith(getCwd()) ? relative27(getCwd(), file.path) : file.path;
433329
433372
  return /* @__PURE__ */ jsx_dev_runtime260.jsxDEV(ThemedBox_default, {
433330
433373
  flexDirection: "row",
433331
433374
  children: [
@@ -456704,13 +456747,13 @@ var exports_files2 = {};
456704
456747
  __export(exports_files2, {
456705
456748
  call: () => call78
456706
456749
  });
456707
- import { relative as relative27 } from "path";
456750
+ import { relative as relative28 } from "path";
456708
456751
  async function call78(_args, context7) {
456709
456752
  const files = context7.readFileState ? cacheKeys(context7.readFileState) : [];
456710
456753
  if (files.length === 0) {
456711
456754
  return { type: "text", value: "No files in context" };
456712
456755
  }
456713
- const fileList = files.map((file) => relative27(getCwd(), file)).join(`
456756
+ const fileList = files.map((file) => relative28(getCwd(), file)).join(`
456714
456757
  `);
456715
456758
  return { type: "text", value: `Files in context:
456716
456759
  ${fileList}` };
@@ -463204,7 +463247,7 @@ async function captureMemoryDiagnostics(trigger, dumpNumber = 0) {
463204
463247
  smapsRollup,
463205
463248
  platform: process.platform,
463206
463249
  nodeVersion: process.version,
463207
- ccVersion: "2.3.3"
463250
+ ccVersion: "2.3.5"
463208
463251
  };
463209
463252
  }
463210
463253
  async function performHeapDump(trigger = "manual", dumpNumber = 0) {
@@ -463789,7 +463832,7 @@ var init_bridge_kick = __esm(() => {
463789
463832
  var call86 = async () => {
463790
463833
  return {
463791
463834
  type: "text",
463792
- value: `${"2.3.3"} (built ${"2026-05-10T20:16:44.115Z"})`
463835
+ value: `${"2.3.5"} (built ${"2026-06-03T02:51:00.215Z"})`
463793
463836
  };
463794
463837
  }, version, version_default;
463795
463838
  var init_version = __esm(() => {
@@ -464957,7 +465000,7 @@ var exports_sandbox_toggle = {};
464957
465000
  __export(exports_sandbox_toggle, {
464958
465001
  call: () => call87
464959
465002
  });
464960
- import { relative as relative28 } from "path";
465003
+ import { relative as relative29 } from "path";
464961
465004
  async function call87(onDone, _context, args) {
464962
465005
  const settings = getSettings_DEPRECATED();
464963
465006
  const themeName = settings.theme || "light";
@@ -464999,7 +465042,7 @@ async function call87(onDone, _context, args) {
464999
465042
  const cleanPattern = commandPattern.replace(/^["']|["']$/g, "");
465000
465043
  addToExcludedCommands(cleanPattern);
465001
465044
  const localSettingsPath = getSettingsFilePathForSource("localSettings");
465002
- const relativePath = localSettingsPath ? relative28(getCwdState(), localSettingsPath) : ".claude/settings.local.json";
465045
+ const relativePath = localSettingsPath ? relative29(getCwdState(), localSettingsPath) : ".claude/settings.local.json";
465003
465046
  const message = color("success", themeName)(`Added "${cleanPattern}" to excluded commands in ${relativePath}`);
465004
465047
  onDone(message);
465005
465048
  return null;
@@ -465157,7 +465200,7 @@ var init_advisor2 = __esm(() => {
465157
465200
  // src/skills/bundledSkills.ts
465158
465201
  import { constants as fsConstants4 } from "fs";
465159
465202
  import { mkdir as mkdir55, open as open13 } from "fs/promises";
465160
- import { dirname as dirname54, isAbsolute as isAbsolute23, join as join145, normalize as normalize12, sep as pathSep2 } from "path";
465203
+ import { dirname as dirname54, isAbsolute as isAbsolute24, join as join145, normalize as normalize12, sep as pathSep2 } from "path";
465161
465204
  function registerBundledSkill(definition) {
465162
465205
  const { files: files2 } = definition;
465163
465206
  let skillRoot;
@@ -465244,7 +465287,7 @@ async function safeWriteFile(p, content) {
465244
465287
  }
465245
465288
  function resolveSkillFilePath(baseDir, relPath) {
465246
465289
  const normalized = normalize12(relPath);
465247
- if (isAbsolute23(normalized) || normalized.split(pathSep2).includes("..") || normalized.split("/").includes("..")) {
465290
+ if (isAbsolute24(normalized) || normalized.split(pathSep2).includes("..") || normalized.split("/").includes("..")) {
465248
465291
  throw new Error(`bundled skill file path escapes skill dir: ${relPath}`);
465249
465292
  }
465250
465293
  return join145(baseDir, normalized);
@@ -468212,7 +468255,7 @@ var init_screenshotClipboard = __esm(() => {
468212
468255
 
468213
468256
  // src/utils/stats.ts
468214
468257
  import { open as open15 } from "fs/promises";
468215
- import { basename as basename43, join as join150, sep as sep30 } from "path";
468258
+ import { basename as basename44, join as join150, sep as sep30 } from "path";
468216
468259
  async function processSessionFiles(sessionFiles, options = {}) {
468217
468260
  const { fromDate, toDate } = options;
468218
468261
  const fs6 = getFsImplementation();
@@ -468270,7 +468313,7 @@ async function processSessionFiles(sessionFiles, options = {}) {
468270
468313
  logForDebugging(`Failed to read session file ${sessionFile}: ${errorMessage(error5)}`);
468271
468314
  continue;
468272
468315
  }
468273
- const sessionId = basename43(sessionFile, ".jsonl");
468316
+ const sessionId = basename44(sessionFile, ".jsonl");
468274
468317
  const messages = [];
468275
468318
  for (const entry of entries) {
468276
468319
  if (isTranscriptMessage(entry)) {
@@ -471733,7 +471776,7 @@ function generateHtmlReport(data, insights) {
471733
471776
  </html>`;
471734
471777
  }
471735
471778
  function buildExportData(data, insights, facets, remoteStats) {
471736
- const version2 = typeof MACRO !== "undefined" ? "2.3.3" : "unknown";
471779
+ const version2 = typeof MACRO !== "undefined" ? "2.3.5" : "unknown";
471737
471780
  const remote_hosts_collected = remoteStats?.hosts.filter((h2) => h2.sessionCount > 0).map((h2) => h2.name);
471738
471781
  const facets_summary = {
471739
471782
  total: facets.size,
@@ -473111,7 +473154,7 @@ import {
473111
473154
  unlink as unlink22,
473112
473155
  writeFile as writeFile61
473113
473156
  } from "fs/promises";
473114
- import { basename as basename44, dirname as dirname56, join as join152 } from "path";
473157
+ import { basename as basename45, dirname as dirname56, join as join152 } from "path";
473115
473158
  function isTranscriptMessage(entry) {
473116
473159
  return entry.type === "user" || entry.type === "assistant" || entry.type === "attachment" || entry.type === "system";
473117
473160
  }
@@ -475545,7 +475588,7 @@ async function getSessionFilesWithMtime(projectDir) {
475545
475588
  for (const dirent of dirents) {
475546
475589
  if (!dirent.isFile() || !dirent.name.endsWith(".jsonl"))
475547
475590
  continue;
475548
- const sessionId = validateUuid2(basename44(dirent.name, ".jsonl"));
475591
+ const sessionId = validateUuid2(basename45(dirent.name, ".jsonl"));
475549
475592
  if (!sessionId)
475550
475593
  continue;
475551
475594
  candidates.push({ sessionId, filePath: join152(projectDir, dirent.name) });
@@ -475932,7 +475975,7 @@ var init_sessionStorage = __esm(() => {
475932
475975
  init_settings2();
475933
475976
  init_slowOperations();
475934
475977
  init_uuid();
475935
- VERSION6 = typeof MACRO !== "undefined" ? "2.3.3" : "unknown";
475978
+ VERSION6 = typeof MACRO !== "undefined" ? "2.3.5" : "unknown";
475936
475979
  MAX_TOMBSTONE_REWRITE_BYTES = 50 * 1024 * 1024;
475937
475980
  SKIP_FIRST_PROMPT_PATTERN = /^(?:\s*<[a-z][\w-]*[\s>]|\[Request interrupted by user[^\]]*\])/;
475938
475981
  EPHEMERAL_PROGRESS_TYPES = new Set([
@@ -476089,14 +476132,14 @@ function buildMemoryLines(displayName, memoryDir, extraGuidelines, skipIndex = f
476089
476132
  return lines;
476090
476133
  }
476091
476134
  function buildMemoryPrompt(params) {
476092
- const { displayName, memoryDir, extraGuidelines } = params;
476135
+ const { displayName, memoryDir, extraGuidelines, skipIndex = false } = params;
476093
476136
  const fs6 = getFsImplementation();
476094
476137
  const entrypoint = memoryDir + ENTRYPOINT_NAME;
476095
476138
  let entrypointContent = "";
476096
476139
  try {
476097
476140
  entrypointContent = fs6.readFileSync(entrypoint, { encoding: "utf-8" });
476098
476141
  } catch {}
476099
- const lines = buildMemoryLines(displayName, memoryDir, extraGuidelines);
476142
+ const lines = buildMemoryLines(displayName, memoryDir, extraGuidelines, skipIndex);
476100
476143
  if (entrypointContent.trim()) {
476101
476144
  const t2 = truncateEntrypointContent(entrypointContent);
476102
476145
  const memoryType = displayName === AUTO_MEM_DISPLAY_NAME ? "auto" : "agent";
@@ -476427,14 +476470,14 @@ function pathInWorkingPath(path15, workingPath) {
476427
476470
  const normalizedWorkingPath = absoluteWorkingPath.replace(/^\/private\/var\//, "/var/").replace(/^\/private\/tmp(\/|$)/, "/tmp$1");
476428
476471
  const caseNormalizedPath = normalizeCaseForComparison(normalizedPath);
476429
476472
  const caseNormalizedWorkingPath = normalizeCaseForComparison(normalizedWorkingPath);
476430
- const relative29 = relativePath(caseNormalizedWorkingPath, caseNormalizedPath);
476431
- if (relative29 === "") {
476473
+ const relative30 = relativePath(caseNormalizedWorkingPath, caseNormalizedPath);
476474
+ if (relative30 === "") {
476432
476475
  return true;
476433
476476
  }
476434
- if (containsPathTraversal(relative29)) {
476477
+ if (containsPathTraversal(relative30)) {
476435
476478
  return false;
476436
476479
  }
476437
- return !posix8.isAbsolute(relative29);
476480
+ return !posix8.isAbsolute(relative30);
476438
476481
  }
476439
476482
  function rootPathForSource(source) {
476440
476483
  switch (source) {
@@ -477063,7 +477106,7 @@ var init_filesystem = __esm(() => {
477063
477106
  });
477064
477107
  getBundledSkillsRoot = memoize_default(function getBundledSkillsRoot2() {
477065
477108
  const nonce = randomBytes20(16).toString("hex");
477066
- return join154(getClaudeTempDir(), "bundled-skills", "2.3.3", nonce);
477109
+ return join154(getClaudeTempDir(), "bundled-skills", "2.3.5", nonce);
477067
477110
  });
477068
477111
  getResolvedWorkingDirPaths = memoize_default(getPathsForPermissionCheck);
477069
477112
  });
@@ -478493,7 +478536,7 @@ __export(exports_hooks2, {
478493
478536
  executeConfigChangeHooks: () => executeConfigChangeHooks,
478494
478537
  createBaseHookInput: () => createBaseHookInput
478495
478538
  });
478496
- import { basename as basename45 } from "path";
478539
+ import { basename as basename46 } from "path";
478497
478540
  import { spawn as spawn14 } from "child_process";
478498
478541
  import { randomUUID as randomUUID31 } from "crypto";
478499
478542
  function getSessionEndHookTimeoutMs() {
@@ -479324,7 +479367,7 @@ async function getMatchingHooks(appState, sessionId, hookEvent, hookInput, tools
479324
479367
  matchQuery = hookInput.load_reason;
479325
479368
  break;
479326
479369
  case "FileChanged":
479327
- matchQuery = basename45(hookInput.file_path);
479370
+ matchQuery = basename46(hookInput.file_path);
479328
479371
  break;
479329
479372
  default:
479330
479373
  break;
@@ -481354,7 +481397,7 @@ import {
481354
481397
  symlink as symlink5,
481355
481398
  utimes as utimes2
481356
481399
  } from "fs/promises";
481357
- import { basename as basename46, dirname as dirname57, join as join156 } from "path";
481400
+ import { basename as basename47, dirname as dirname57, join as join156 } from "path";
481358
481401
  function validateWorktreeSlug(slug) {
481359
481402
  if (slug.length > MAX_WORKTREE_SLUG_LENGTH) {
481360
481403
  throw new Error(`Invalid worktree name: must be ${MAX_WORKTREE_SLUG_LENGTH} characters or fewer (got ${slug.length})`);
@@ -481397,7 +481440,7 @@ function restoreWorktreeSession(session2) {
481397
481440
  currentWorktreeSession = session2;
481398
481441
  }
481399
481442
  function generateTmuxSessionName(repoPath, branch2) {
481400
- const repoName = basename46(repoPath);
481443
+ const repoName = basename47(repoPath);
481401
481444
  const combined = `${repoName}_${branch2}`;
481402
481445
  return combined.replace(/[/.]/g, "_");
481403
481446
  }
@@ -481973,7 +482016,7 @@ async function execIntoTmuxWorktree(args) {
481973
482016
  error: `Error: ${errorMessage(error5)}`
481974
482017
  };
481975
482018
  }
481976
- repoName = basename46(findCanonicalGitRoot(getCwd()) ?? getCwd());
482019
+ repoName = basename47(findCanonicalGitRoot(getCwd()) ?? getCwd());
481977
482020
  console.log(`Using worktree via hook: ${worktreeDir}`);
481978
482021
  } else {
481979
482022
  const repoRoot = findCanonicalGitRoot(getCwd());
@@ -481983,7 +482026,7 @@ async function execIntoTmuxWorktree(args) {
481983
482026
  error: "Error: --worktree requires a git repository"
481984
482027
  };
481985
482028
  }
481986
- repoName = basename46(repoRoot);
482029
+ repoName = basename47(repoRoot);
481987
482030
  worktreeDir = worktreePathFor(repoRoot, worktreeName);
481988
482031
  try {
481989
482032
  const result = await getOrCreateWorktree(repoRoot, worktreeName, prNumber !== null ? { prNumber } : undefined);
@@ -486300,7 +486343,7 @@ function buildSystemInitMessage(inputs) {
486300
486343
  slash_commands: inputs.commands.filter((c5) => c5.userInvocable !== false).map((c5) => c5.name),
486301
486344
  apiKeySource: getAnthropicApiKeyWithSource().source,
486302
486345
  betas: getSdkBetas(),
486303
- claude_code_version: "2.3.3",
486346
+ claude_code_version: "2.3.5",
486304
486347
  output_style: outputStyle2,
486305
486348
  agents: inputs.agents.map((agent) => agent.agentType),
486306
486349
  skills: inputs.skills.filter((s2) => s2.userInvocable !== false).map((skill) => skill.name),
@@ -492250,7 +492293,7 @@ var init_FileEditToolDiff = __esm(() => {
492250
492293
 
492251
492294
  // src/hooks/useDiffInIDE.ts
492252
492295
  import { randomUUID as randomUUID34 } from "crypto";
492253
- import { basename as basename48 } from "path";
492296
+ import { basename as basename49 } from "path";
492254
492297
  function useDiffInIDE({
492255
492298
  onChange,
492256
492299
  toolUseContext,
@@ -492261,7 +492304,7 @@ function useDiffInIDE({
492261
492304
  const isUnmounted = import_react197.useRef(false);
492262
492305
  const [hasError, setHasError] = import_react197.useState(false);
492263
492306
  const sha = import_react197.useMemo(() => randomUUID34().slice(0, 6), []);
492264
- const tabName = import_react197.useMemo(() => `✻ [localclawd] ${basename48(filePath)} (${sha}) ⧉`, [filePath, sha]);
492307
+ const tabName = import_react197.useMemo(() => `✻ [localclawd] ${basename49(filePath)} (${sha}) ⧉`, [filePath, sha]);
492265
492308
  const shouldShowDiffInIDE = hasAccessToIDEExtensionDiffFeature(toolUseContext.options.mcpClients) && getGlobalConfig().diffTool === "auto" && !filePath.endsWith(".ipynb");
492266
492309
  const ideName = getConnectedIdeName(toolUseContext.options.mcpClients) ?? "IDE";
492267
492310
  async function showDiff() {
@@ -492442,7 +492485,7 @@ var init_useDiffInIDE = __esm(() => {
492442
492485
  });
492443
492486
 
492444
492487
  // src/components/ShowInIDEPrompt.tsx
492445
- import { basename as basename49, relative as relative29 } from "path";
492488
+ import { basename as basename50, relative as relative30 } from "path";
492446
492489
  function ShowInIDEPrompt(t0) {
492447
492490
  const $2 = c3(36);
492448
492491
  const {
@@ -492480,7 +492523,7 @@ function ShowInIDEPrompt(t0) {
492480
492523
  if ($2[2] !== symlinkTarget) {
492481
492524
  t2 = symlinkTarget && /* @__PURE__ */ jsx_dev_runtime377.jsxDEV(ThemedText, {
492482
492525
  color: "warning",
492483
- children: relative29(getCwd(), symlinkTarget).startsWith("..") ? `This will modify ${symlinkTarget} (outside working directory) via a symlink` : `Symlink target: ${symlinkTarget}`
492526
+ children: relative30(getCwd(), symlinkTarget).startsWith("..") ? `This will modify ${symlinkTarget} (outside working directory) via a symlink` : `Symlink target: ${symlinkTarget}`
492484
492527
  }, undefined, false, undefined, this);
492485
492528
  $2[2] = symlinkTarget;
492486
492529
  $2[3] = t2;
@@ -492499,7 +492542,7 @@ function ShowInIDEPrompt(t0) {
492499
492542
  }
492500
492543
  let t4;
492501
492544
  if ($2[5] !== filePath) {
492502
- t4 = basename49(filePath);
492545
+ t4 = basename50(filePath);
492503
492546
  $2[5] = filePath;
492504
492547
  $2[6] = t4;
492505
492548
  } else {
@@ -492659,7 +492702,7 @@ var init_ShowInIDEPrompt = __esm(() => {
492659
492702
 
492660
492703
  // src/components/permissions/FilePermissionDialog/permissionOptions.tsx
492661
492704
  import { homedir as homedir35 } from "os";
492662
- import { basename as basename50, join as join158, sep as sep33 } from "path";
492705
+ import { basename as basename51, join as join158, sep as sep33 } from "path";
492663
492706
  function isInClaudeFolder(filePath) {
492664
492707
  const absolutePath = expandPath(filePath);
492665
492708
  const claudeFolderPath = expandPath(`${getOriginalCwd()}/.claude`);
@@ -492741,7 +492784,7 @@ function getFilePermissionOptions({
492741
492784
  }
492742
492785
  } else {
492743
492786
  const dirPath = getDirectoryForPath(filePath);
492744
- const dirName = basename50(dirPath) || "this directory";
492787
+ const dirName = basename51(dirPath) || "this directory";
492745
492788
  if (operationType === "read") {
492746
492789
  sessionLabel = /* @__PURE__ */ jsx_dev_runtime378.jsxDEV(ThemedText, {
492747
492790
  children: [
@@ -493044,7 +493087,7 @@ var init_useFilePermissionDialog = __esm(() => {
493044
493087
  });
493045
493088
 
493046
493089
  // src/components/permissions/FilePermissionDialog/FilePermissionDialog.tsx
493047
- import { relative as relative30 } from "path";
493090
+ import { relative as relative31 } from "path";
493048
493091
  function FilePermissionDialog({
493049
493092
  toolUseConfirm,
493050
493093
  toolUseContext,
@@ -493151,7 +493194,7 @@ function FilePermissionDialog({
493151
493194
  noInputMode
493152
493195
  }, undefined, false, undefined, this);
493153
493196
  }
493154
- const isSymlinkOutsideCwd = symlinkTarget != null && relative30(getCwd(), symlinkTarget).startsWith("..");
493197
+ const isSymlinkOutsideCwd = symlinkTarget != null && relative31(getCwd(), symlinkTarget).startsWith("..");
493155
493198
  const symlinkWarning = symlinkTarget ? /* @__PURE__ */ jsx_dev_runtime379.jsxDEV(ThemedBox_default, {
493156
493199
  paddingX: 1,
493157
493200
  marginBottom: 1,
@@ -493238,7 +493281,7 @@ var init_FilePermissionDialog = __esm(() => {
493238
493281
  });
493239
493282
 
493240
493283
  // src/components/permissions/SedEditPermissionRequest/SedEditPermissionRequest.tsx
493241
- import { basename as basename51, relative as relative31 } from "path";
493284
+ import { basename as basename52, relative as relative32 } from "path";
493242
493285
  function SedEditPermissionRequest(t0) {
493243
493286
  const $2 = c3(9);
493244
493287
  let props;
@@ -493406,7 +493449,7 @@ function SedEditPermissionRequestInner(t0) {
493406
493449
  const t8 = props.onReject;
493407
493450
  let t9;
493408
493451
  if ($2[14] !== filePath) {
493409
- t9 = relative31(getCwd(), filePath);
493452
+ t9 = relative32(getCwd(), filePath);
493410
493453
  $2[14] = filePath;
493411
493454
  $2[15] = t9;
493412
493455
  } else {
@@ -493414,7 +493457,7 @@ function SedEditPermissionRequestInner(t0) {
493414
493457
  }
493415
493458
  let t10;
493416
493459
  if ($2[16] !== filePath) {
493417
- t10 = basename51(filePath);
493460
+ t10 = basename52(filePath);
493418
493461
  $2[16] = filePath;
493419
493462
  $2[17] = t10;
493420
493463
  } else {
@@ -493624,7 +493667,7 @@ var init_useShellPermissionFeedback = __esm(() => {
493624
493667
  });
493625
493668
 
493626
493669
  // src/components/permissions/shellPermissionHelpers.tsx
493627
- import { basename as basename52, sep as sep34 } from "path";
493670
+ import { basename as basename53, sep as sep34 } from "path";
493628
493671
  function commandListDisplay(commands) {
493629
493672
  switch (commands.length) {
493630
493673
  case 0:
@@ -493675,7 +493718,7 @@ function commandListDisplayTruncated(commands) {
493675
493718
  function formatPathList(paths2) {
493676
493719
  if (paths2.length === 0)
493677
493720
  return "";
493678
- const names = paths2.map((p) => basename52(p) || p);
493721
+ const names = paths2.map((p) => basename53(p) || p);
493679
493722
  if (names.length === 1) {
493680
493723
  return /* @__PURE__ */ jsx_dev_runtime381.jsxDEV(ThemedText, {
493681
493724
  children: [
@@ -493741,7 +493784,7 @@ function generateShellSuggestionsLabel(suggestions, shellToolName, commandTransf
493741
493784
  if (hasReadPaths && !hasDirectories && !hasCommands) {
493742
493785
  if (readPaths.length === 1) {
493743
493786
  const firstPath = readPaths[0];
493744
- const dirName = basename52(firstPath) || firstPath;
493787
+ const dirName = basename53(firstPath) || firstPath;
493745
493788
  return /* @__PURE__ */ jsx_dev_runtime381.jsxDEV(ThemedText, {
493746
493789
  children: [
493747
493790
  "Yes, allow reading from ",
@@ -493765,7 +493808,7 @@ function generateShellSuggestionsLabel(suggestions, shellToolName, commandTransf
493765
493808
  if (hasDirectories && !hasReadPaths && !hasCommands) {
493766
493809
  if (directories.length === 1) {
493767
493810
  const firstDir = directories[0];
493768
- const dirName = basename52(firstDir) || firstDir;
493811
+ const dirName = basename53(firstDir) || firstDir;
493769
493812
  return /* @__PURE__ */ jsx_dev_runtime381.jsxDEV(ThemedText, {
493770
493813
  children: [
493771
493814
  "Yes, and always allow access to ",
@@ -495996,7 +496039,7 @@ function createSingleEditDiffConfig(filePath, oldString, newString, replaceAll)
495996
496039
  }
495997
496040
 
495998
496041
  // src/components/permissions/FileEditPermissionRequest/FileEditPermissionRequest.tsx
495999
- import { basename as basename53, relative as relative32 } from "path";
496042
+ import { basename as basename54, relative as relative33 } from "path";
496000
496043
  function FileEditPermissionRequest(props) {
496001
496044
  const $2 = c3(51);
496002
496045
  const parseInput = _temp168;
@@ -496033,13 +496076,13 @@ function FileEditPermissionRequest(props) {
496033
496076
  t7 = props.onReject;
496034
496077
  t8 = props.workerBadge;
496035
496078
  t9 = "Edit file";
496036
- t10 = relative32(getCwd(), file_path);
496079
+ t10 = relative33(getCwd(), file_path);
496037
496080
  T1 = ThemedText;
496038
496081
  t2 = "Do you want to make this edit to";
496039
496082
  t3 = " ";
496040
496083
  T0 = ThemedText;
496041
496084
  t0 = true;
496042
- t1 = basename53(file_path);
496085
+ t1 = basename54(file_path);
496043
496086
  $2[0] = props.onDone;
496044
496087
  $2[1] = props.onReject;
496045
496088
  $2[2] = props.toolUseConfirm;
@@ -496463,7 +496506,7 @@ var init_FileWriteToolDiff = __esm(() => {
496463
496506
  });
496464
496507
 
496465
496508
  // src/components/permissions/FileWritePermissionRequest/FileWritePermissionRequest.tsx
496466
- import { basename as basename54, relative as relative33 } from "path";
496509
+ import { basename as basename55, relative as relative34 } from "path";
496467
496510
  function FileWritePermissionRequest(props) {
496468
496511
  const $2 = c3(30);
496469
496512
  const parseInput = _temp171;
@@ -496522,7 +496565,7 @@ function FileWritePermissionRequest(props) {
496522
496565
  const t7 = fileExists ? "Overwrite file" : "Create file";
496523
496566
  let t8;
496524
496567
  if ($2[5] !== file_path) {
496525
- t8 = relative33(getCwd(), file_path);
496568
+ t8 = relative34(getCwd(), file_path);
496526
496569
  $2[5] = file_path;
496527
496570
  $2[6] = t8;
496528
496571
  } else {
@@ -496530,7 +496573,7 @@ function FileWritePermissionRequest(props) {
496530
496573
  }
496531
496574
  let t9;
496532
496575
  if ($2[7] !== file_path) {
496533
- t9 = basename54(file_path);
496576
+ t9 = basename55(file_path);
496534
496577
  $2[7] = file_path;
496535
496578
  $2[8] = t9;
496536
496579
  } else {
@@ -496652,7 +496695,7 @@ var init_FileWritePermissionRequest = __esm(() => {
496652
496695
  });
496653
496696
 
496654
496697
  // src/components/permissions/NotebookEditPermissionRequest/NotebookEditToolDiff.tsx
496655
- import { relative as relative34 } from "path";
496698
+ import { relative as relative35 } from "path";
496656
496699
  function NotebookEditToolDiff(props) {
496657
496700
  const $2 = c3(5);
496658
496701
  let t0;
@@ -496795,7 +496838,7 @@ function NotebookEditToolDiffInner(t0) {
496795
496838
  }
496796
496839
  let t4;
496797
496840
  if ($2[11] !== notebook_path || $2[12] !== verbose) {
496798
- t4 = verbose ? notebook_path : relative34(getCwd(), notebook_path);
496841
+ t4 = verbose ? notebook_path : relative35(getCwd(), notebook_path);
496799
496842
  $2[11] = notebook_path;
496800
496843
  $2[12] = verbose;
496801
496844
  $2[13] = t4;
@@ -496933,7 +496976,7 @@ var init_NotebookEditToolDiff = __esm(() => {
496933
496976
  });
496934
496977
 
496935
496978
  // src/components/permissions/NotebookEditPermissionRequest/NotebookEditPermissionRequest.tsx
496936
- import { basename as basename55 } from "path";
496979
+ import { basename as basename56 } from "path";
496937
496980
  function NotebookEditPermissionRequest(props) {
496938
496981
  const $2 = c3(52);
496939
496982
  const parseInput = _temp175;
@@ -496977,7 +497020,7 @@ function NotebookEditPermissionRequest(props) {
496977
497020
  t4 = " ";
496978
497021
  T0 = ThemedText;
496979
497022
  t0 = true;
496980
- t1 = basename55(notebook_path);
497023
+ t1 = basename56(notebook_path);
496981
497024
  $2[0] = props.onDone;
496982
497025
  $2[1] = props.onReject;
496983
497026
  $2[2] = props.toolUseConfirm;
@@ -500457,7 +500500,7 @@ var init_useVoiceEnabled = __esm(() => {
500457
500500
  function getSemverPart(version2) {
500458
500501
  return `${import_semver10.major(version2, { loose: true })}.${import_semver10.minor(version2, { loose: true })}.${import_semver10.patch(version2, { loose: true })}`;
500459
500502
  }
500460
- function useUpdateNotification(updatedVersion, initialVersion = "2.3.3") {
500503
+ function useUpdateNotification(updatedVersion, initialVersion = "2.3.5") {
500461
500504
  const [lastNotifiedSemver, setLastNotifiedSemver] = import_react214.useState(() => getSemverPart(initialVersion));
500462
500505
  if (!updatedVersion) {
500463
500506
  return null;
@@ -500497,7 +500540,7 @@ function AutoUpdater({
500497
500540
  return;
500498
500541
  }
500499
500542
  if (false) {}
500500
- const currentVersion = "2.3.3";
500543
+ const currentVersion = "2.3.5";
500501
500544
  const channel = getInitialSettings()?.autoUpdatesChannel ?? "latest";
500502
500545
  let latestVersion = await getLatestVersion(channel);
500503
500546
  const isDisabled = isAutoUpdaterDisabled();
@@ -500708,12 +500751,12 @@ function NativeAutoUpdater({
500708
500751
  logEvent("tengu_native_auto_updater_start", {});
500709
500752
  try {
500710
500753
  const maxVersion = await getMaxVersion();
500711
- if (maxVersion && gt("2.3.3", maxVersion)) {
500754
+ if (maxVersion && gt("2.3.5", maxVersion)) {
500712
500755
  const msg = await getMaxVersionMessage();
500713
500756
  setMaxVersionIssue(msg ?? "affects your version");
500714
500757
  }
500715
500758
  const result = await installLatest(channel);
500716
- const currentVersion = "2.3.3";
500759
+ const currentVersion = "2.3.5";
500717
500760
  const latencyMs = Date.now() - startTime;
500718
500761
  if (result.lockFailed) {
500719
500762
  logEvent("tengu_native_auto_updater_lock_contention", {
@@ -500848,17 +500891,17 @@ function PackageManagerAutoUpdater(t0) {
500848
500891
  const maxVersion = await getMaxVersion();
500849
500892
  if (maxVersion && latest && gt(latest, maxVersion)) {
500850
500893
  logForDebugging(`PackageManagerAutoUpdater: maxVersion ${maxVersion} is set, capping update from ${latest} to ${maxVersion}`);
500851
- if (gte("2.3.3", maxVersion)) {
500852
- logForDebugging(`PackageManagerAutoUpdater: current version ${"2.3.3"} is already at or above maxVersion ${maxVersion}, skipping update`);
500894
+ if (gte("2.3.5", maxVersion)) {
500895
+ logForDebugging(`PackageManagerAutoUpdater: current version ${"2.3.5"} is already at or above maxVersion ${maxVersion}, skipping update`);
500853
500896
  setUpdateAvailable(false);
500854
500897
  return;
500855
500898
  }
500856
500899
  latest = maxVersion;
500857
500900
  }
500858
- const hasUpdate = latest && !gte("2.3.3", latest) && !shouldSkipVersion(latest);
500901
+ const hasUpdate = latest && !gte("2.3.5", latest) && !shouldSkipVersion(latest);
500859
500902
  setUpdateAvailable(!!hasUpdate);
500860
500903
  if (hasUpdate) {
500861
- logForDebugging(`PackageManagerAutoUpdater: Update available ${"2.3.3"} -> ${latest}`);
500904
+ logForDebugging(`PackageManagerAutoUpdater: Update available ${"2.3.5"} -> ${latest}`);
500862
500905
  }
500863
500906
  };
500864
500907
  $2[0] = t1;
@@ -500892,7 +500935,7 @@ function PackageManagerAutoUpdater(t0) {
500892
500935
  wrap: "truncate",
500893
500936
  children: [
500894
500937
  "currentVersion: ",
500895
- "2.3.3"
500938
+ "2.3.5"
500896
500939
  ]
500897
500940
  }, undefined, true, undefined, this);
500898
500941
  $2[3] = verbose;
@@ -501044,7 +501087,7 @@ var init_AutoUpdaterWrapper = __esm(() => {
501044
501087
  });
501045
501088
 
501046
501089
  // src/components/IdeStatusIndicator.tsx
501047
- import { basename as basename56 } from "path";
501090
+ import { basename as basename57 } from "path";
501048
501091
  function IdeStatusIndicator(t0) {
501049
501092
  const $2 = c3(7);
501050
501093
  const {
@@ -501084,7 +501127,7 @@ function IdeStatusIndicator(t0) {
501084
501127
  if (ideSelection.filePath) {
501085
501128
  let t1;
501086
501129
  if ($2[3] !== ideSelection.filePath) {
501087
- t1 = basename56(ideSelection.filePath);
501130
+ t1 = basename57(ideSelection.filePath);
501088
501131
  $2[3] = ideSelection.filePath;
501089
501132
  $2[4] = t1;
501090
501133
  } else {
@@ -504305,7 +504348,7 @@ var init_slackChannelSuggestions = __esm(() => {
504305
504348
  });
504306
504349
 
504307
504350
  // src/hooks/unifiedSuggestions.ts
504308
- import { basename as basename57 } from "path";
504351
+ import { basename as basename58 } from "path";
504309
504352
  function createSuggestionFromSource(source) {
504310
504353
  switch (source.type) {
504311
504354
  case "file":
@@ -504367,7 +504410,7 @@ async function generateUnifiedSuggestions(query2, mcpResources, agents2, showOnE
504367
504410
  displayText: suggestion.displayText,
504368
504411
  description: suggestion.description,
504369
504412
  path: suggestion.displayText,
504370
- filename: basename57(suggestion.displayText),
504413
+ filename: basename58(suggestion.displayText),
504371
504414
  score: suggestion.metadata?.score
504372
504415
  }));
504373
504416
  const mcpSources = Object.values(mcpResources).flat().map((resource) => ({
@@ -505587,7 +505630,7 @@ var init_AutoModeOptInDialog = __esm(() => {
505587
505630
  });
505588
505631
 
505589
505632
  // src/components/BridgeDialog.tsx
505590
- import { basename as basename58 } from "path";
505633
+ import { basename as basename59 } from "path";
505591
505634
  function BridgeDialog(t0) {
505592
505635
  const $2 = c3(87);
505593
505636
  const {
@@ -505610,7 +505653,7 @@ function BridgeDialog(t0) {
505610
505653
  const [branchName, setBranchName] = import_react229.useState("");
505611
505654
  let t1;
505612
505655
  if ($2[0] === Symbol.for("react.memo_cache_sentinel")) {
505613
- t1 = basename58(getOriginalCwd());
505656
+ t1 = basename59(getOriginalCwd());
505614
505657
  $2[0] = t1;
505615
505658
  } else {
505616
505659
  t1 = $2[0];
@@ -508452,7 +508495,7 @@ function buildStatusLineCommandInput(permissionMode, exceedsHalfContext, setting
508452
508495
  project_dir: getOriginalCwd(),
508453
508496
  added_dirs: addedDirs
508454
508497
  },
508455
- version: "2.3.3",
508498
+ version: "2.3.5",
508456
508499
  output_style: {
508457
508500
  name: outputStyleName
508458
508501
  },
@@ -518382,7 +518425,7 @@ __export(exports_asciicast, {
518382
518425
  _resetRecordingStateForTesting: () => _resetRecordingStateForTesting
518383
518426
  });
518384
518427
  import { appendFile as appendFile6, rename as rename10 } from "fs/promises";
518385
- import { basename as basename59, dirname as dirname58, join as join161 } from "path";
518428
+ import { basename as basename60, dirname as dirname58, join as join161 } from "path";
518386
518429
  function getRecordFilePath() {
518387
518430
  if (recordingState.filePath !== null) {
518388
518431
  return recordingState.filePath;
@@ -518428,8 +518471,8 @@ async function renameRecordingForSession() {
518428
518471
  return;
518429
518472
  }
518430
518473
  await recorder?.flush();
518431
- const oldName = basename59(oldPath);
518432
- const newName = basename59(newPath);
518474
+ const oldName = basename60(oldPath);
518475
+ const newName = basename60(newPath);
518433
518476
  try {
518434
518477
  await rename10(oldPath, newPath);
518435
518478
  recordingState.filePath = newPath;
@@ -520024,7 +520067,7 @@ async function submitTranscriptShare(messages, trigger, appearanceId) {
520024
520067
  } catch {}
520025
520068
  const data = {
520026
520069
  trigger,
520027
- version: "2.3.3",
520070
+ version: "2.3.5",
520028
520071
  platform: process.platform,
520029
520072
  transcript,
520030
520073
  subagentTranscripts: Object.keys(subagentTranscripts).length > 0 ? subagentTranscripts : undefined,
@@ -520642,7 +520685,6 @@ var init_sessionMemoryCompact = __esm(() => {
520642
520685
  init_sessionMemoryUtils();
520643
520686
  init_compact();
520644
520687
  init_microCompact();
520645
- init_prompt10();
520646
520688
  DEFAULT_SM_COMPACT_CONFIG = {
520647
520689
  minTokens: 1e4,
520648
520690
  minTextBlockMessages: 5,
@@ -522294,7 +522336,7 @@ var init_tipRegistry = __esm(() => {
522294
522336
  init_DesktopUpsellStartup();
522295
522337
  init_color();
522296
522338
  init_shortcutFormat();
522297
- init_prompt12();
522339
+ init_prompt11();
522298
522340
  init_auth2();
522299
522341
  init_concurrentSessions();
522300
522342
  init_config();
@@ -525518,7 +525560,7 @@ var init_usePluginAutoupdateNotification = __esm(() => {
525518
525560
  });
525519
525561
 
525520
525562
  // src/utils/plugins/reconciler.ts
525521
- import { isAbsolute as isAbsolute24, resolve as resolve43 } from "path";
525563
+ import { isAbsolute as isAbsolute25, resolve as resolve43 } from "path";
525522
525564
  function diffMarketplaces(declared, materialized, opts) {
525523
525565
  const missing = [];
525524
525566
  const sourceChanged = [];
@@ -525626,7 +525668,7 @@ async function reconcileMarketplaces(opts) {
525626
525668
  return { installed, updated, failed, upToDate: diff2.upToDate, skipped };
525627
525669
  }
525628
525670
  function normalizeSource(source, projectRoot) {
525629
- if ((source.source === "directory" || source.source === "file") && !isAbsolute24(source.path)) {
525671
+ if ((source.source === "directory" || source.source === "file") && !isAbsolute25(source.path)) {
525630
525672
  const base = projectRoot ?? getOriginalCwd();
525631
525673
  const canonicalRoot = findCanonicalGitRoot(base);
525632
525674
  return {
@@ -531072,7 +531114,7 @@ var init_REPL = __esm(() => {
531072
531114
  init_ExitPlanModePermissionRequest();
531073
531115
  init_permissionSetup();
531074
531116
  init_filesystem();
531075
- init_prompt11();
531117
+ init_prompt10();
531076
531118
  init_bashPermissions();
531077
531119
  init_config();
531078
531120
  init_billing();
@@ -536997,7 +537039,7 @@ function appendToLog(path17, message) {
536997
537039
  cwd: getFsImplementation().cwd(),
536998
537040
  userType: process.env.USER_TYPE,
536999
537041
  sessionId: getSessionId(),
537000
- version: "2.3.3"
537042
+ version: "2.3.5"
537001
537043
  };
537002
537044
  getLogWriter(path17).write(messageWithTimestamp);
537003
537045
  }
@@ -537256,7 +537298,7 @@ To attach: ${source_default.bold(`tmux attach -t ${tmuxSessionName}`)}`));
537256
537298
  startToolRpcServer();
537257
537299
  startScheduler();
537258
537300
  initSecretStore();
537259
- const persistedCtx = getGlobalConfig().compactContextWindowTokens;
537301
+ const persistedCtx = getCurrentProjectConfig().compactContextWindowTokens;
537260
537302
  if (persistedCtx && persistedCtx > 0) {
537261
537303
  logForDebugging(`[context] Using configured context window: ${persistedCtx} tokens`);
537262
537304
  } else if (isLocalLLMProviderEnabled()) {
@@ -540490,7 +540532,7 @@ var init_idleTimeout = __esm(() => {
540490
540532
  // src/bridge/inboundAttachments.ts
540491
540533
  import { randomUUID as randomUUID50 } from "crypto";
540492
540534
  import { mkdir as mkdir62, writeFile as writeFile65 } from "fs/promises";
540493
- import { basename as basename60, join as join168 } from "path";
540535
+ import { basename as basename61, join as join168 } from "path";
540494
540536
  import { z as z95 } from "zod/v4";
540495
540537
  function debug3(msg) {
540496
540538
  logForDebugging(`[bridge:inbound-attach] ${msg}`);
@@ -540503,7 +540545,7 @@ function extractInboundAttachments(msg) {
540503
540545
  return parsed.success ? parsed.data : [];
540504
540546
  }
540505
540547
  function sanitizeFileName(name) {
540506
- const base = basename60(name).replace(/[^a-zA-Z0-9._-]/g, "_");
540548
+ const base = basename61(name).replace(/[^a-zA-Z0-9._-]/g, "_");
540507
540549
  return base || "attachment";
540508
540550
  }
540509
540551
  function uploadsDir() {
@@ -540796,8 +540838,8 @@ async function getEnvLessBridgeConfig() {
540796
540838
  }
540797
540839
  async function checkEnvLessBridgeMinVersion() {
540798
540840
  const cfg = await getEnvLessBridgeConfig();
540799
- if (cfg.min_version && lt("2.3.3", cfg.min_version)) {
540800
- return `Your version of localclawd (${"2.3.3"}) is too old for Remote Control.
540841
+ if (cfg.min_version && lt("2.3.5", cfg.min_version)) {
540842
+ return `Your version of localclawd (${"2.3.5"}) is too old for Remote Control.
540801
540843
  Version ${cfg.min_version} or higher is required. Run \`localclawd update\` to update.`;
540802
540844
  }
540803
540845
  return null;
@@ -541269,7 +541311,7 @@ async function initBridgeCore(params) {
541269
541311
  const rawApi = createBridgeApiClient({
541270
541312
  baseUrl,
541271
541313
  getAccessToken,
541272
- runnerVersion: "2.3.3",
541314
+ runnerVersion: "2.3.5",
541273
541315
  onDebug: logForDebugging,
541274
541316
  onAuth401,
541275
541317
  getTrustedDeviceToken
@@ -546988,7 +547030,7 @@ async function startMCPServer(cwd3, debug4, verbose) {
546988
547030
  setCwd(cwd3);
546989
547031
  const server = new Server({
546990
547032
  name: "claude/tengu",
546991
- version: "2.3.3"
547033
+ version: "2.3.5"
546992
547034
  }, {
546993
547035
  capabilities: {
546994
547036
  tools: {}
@@ -547541,7 +547583,7 @@ __export(exports_plugins, {
547541
547583
  VALID_UPDATE_SCOPES: () => VALID_UPDATE_SCOPES,
547542
547584
  VALID_INSTALLABLE_SCOPES: () => VALID_INSTALLABLE_SCOPES
547543
547585
  });
547544
- import { basename as basename61, dirname as dirname65 } from "path";
547586
+ import { basename as basename62, dirname as dirname65 } from "path";
547545
547587
  function handleMarketplaceError(error5, action2) {
547546
547588
  logError(error5);
547547
547589
  cliError(`${figures_default.cross} Failed to ${action2}: ${errorMessage(error5)}`);
@@ -547575,7 +547617,7 @@ async function pluginValidateHandler(manifestPath, options) {
547575
547617
  let contentResults = [];
547576
547618
  if (result.fileType === "plugin") {
547577
547619
  const manifestDir = dirname65(result.filePath);
547578
- if (basename61(manifestDir) === ".claude-plugin") {
547620
+ if (basename62(manifestDir) === ".claude-plugin") {
547579
547621
  contentResults = await validatePluginContents(dirname65(manifestDir));
547580
547622
  for (const r2 of contentResults) {
547581
547623
  console.log(`Validating ${r2.fileType}: ${r2.filePath}
@@ -548069,7 +548111,7 @@ function WelcomeLogo() {
548069
548111
  dimColor: true,
548070
548112
  children: [
548071
548113
  "v",
548072
- "2.3.3"
548114
+ "2.3.5"
548073
548115
  ]
548074
548116
  }, undefined, true, undefined, this)
548075
548117
  ]
@@ -548260,7 +548302,7 @@ __export(exports_update, {
548260
548302
  });
548261
548303
  async function update() {
548262
548304
  logEvent("tengu_update_check", {});
548263
- writeToStdout(`Current version: ${"2.3.3"}
548305
+ writeToStdout(`Current version: ${"2.3.5"}
548264
548306
  `);
548265
548307
  const channel = getInitialSettings()?.autoUpdatesChannel ?? "latest";
548266
548308
  writeToStdout(`Checking for updates to ${channel} version...
@@ -548335,8 +548377,8 @@ async function update() {
548335
548377
  writeToStdout(`localclawd is managed by Homebrew.
548336
548378
  `);
548337
548379
  const latest = await getLatestVersion(channel);
548338
- if (latest && !gte("2.3.3", latest)) {
548339
- writeToStdout(`Update available: ${"2.3.3"} → ${latest}
548380
+ if (latest && !gte("2.3.5", latest)) {
548381
+ writeToStdout(`Update available: ${"2.3.5"} → ${latest}
548340
548382
  `);
548341
548383
  writeToStdout(`
548342
548384
  `);
@@ -548352,8 +548394,8 @@ async function update() {
548352
548394
  writeToStdout(`localclawd is managed by winget.
548353
548395
  `);
548354
548396
  const latest = await getLatestVersion(channel);
548355
- if (latest && !gte("2.3.3", latest)) {
548356
- writeToStdout(`Update available: ${"2.3.3"} → ${latest}
548397
+ if (latest && !gte("2.3.5", latest)) {
548398
+ writeToStdout(`Update available: ${"2.3.5"} → ${latest}
548357
548399
  `);
548358
548400
  writeToStdout(`
548359
548401
  `);
@@ -548367,8 +548409,8 @@ async function update() {
548367
548409
  writeToStdout(`localclawd is managed by apk.
548368
548410
  `);
548369
548411
  const latest = await getLatestVersion(channel);
548370
- if (latest && !gte("2.3.3", latest)) {
548371
- writeToStdout(`Update available: ${"2.3.3"} → ${latest}
548412
+ if (latest && !gte("2.3.5", latest)) {
548413
+ writeToStdout(`Update available: ${"2.3.5"} → ${latest}
548372
548414
  `);
548373
548415
  writeToStdout(`
548374
548416
  `);
@@ -548433,11 +548475,11 @@ async function update() {
548433
548475
  `);
548434
548476
  await gracefulShutdown(1);
548435
548477
  }
548436
- if (result.latestVersion === "2.3.3") {
548437
- writeToStdout(source_default.green(`localclawd is up to date (${"2.3.3"})`) + `
548478
+ if (result.latestVersion === "2.3.5") {
548479
+ writeToStdout(source_default.green(`localclawd is up to date (${"2.3.5"})`) + `
548438
548480
  `);
548439
548481
  } else {
548440
- writeToStdout(source_default.green(`Successfully updated from ${"2.3.3"} to version ${result.latestVersion}`) + `
548482
+ writeToStdout(source_default.green(`Successfully updated from ${"2.3.5"} to version ${result.latestVersion}`) + `
548441
548483
  `);
548442
548484
  await regenerateCompletionCache();
548443
548485
  }
@@ -548497,12 +548539,12 @@ async function update() {
548497
548539
  `);
548498
548540
  await gracefulShutdown(1);
548499
548541
  }
548500
- if (latestVersion === "2.3.3") {
548501
- writeToStdout(source_default.green(`localclawd is up to date (${"2.3.3"})`) + `
548542
+ if (latestVersion === "2.3.5") {
548543
+ writeToStdout(source_default.green(`localclawd is up to date (${"2.3.5"})`) + `
548502
548544
  `);
548503
548545
  await gracefulShutdown(0);
548504
548546
  }
548505
- writeToStdout(`New version available: ${latestVersion} (current: ${"2.3.3"})
548547
+ writeToStdout(`New version available: ${latestVersion} (current: ${"2.3.5"})
548506
548548
  `);
548507
548549
  writeToStdout(`Installing update...
548508
548550
  `);
@@ -548547,7 +548589,7 @@ async function update() {
548547
548589
  logForDebugging(`update: Installation status: ${status2}`);
548548
548590
  switch (status2) {
548549
548591
  case "success":
548550
- writeToStdout(source_default.green(`Successfully updated from ${"2.3.3"} to version ${latestVersion}`) + `
548592
+ writeToStdout(source_default.green(`Successfully updated from ${"2.3.5"} to version ${latestVersion}`) + `
548551
548593
  `);
548552
548594
  await regenerateCompletionCache();
548553
548595
  break;
@@ -549789,7 +549831,7 @@ Run with --debug for more details.
549789
549831
  }
549790
549832
  }
549791
549833
  logForDiagnosticsNoPII("info", "started", {
549792
- version: "2.3.3",
549834
+ version: "2.3.5",
549793
549835
  is_native_binary: isInBundledMode()
549794
549836
  });
549795
549837
  registerCleanup(async () => {
@@ -550573,7 +550615,7 @@ Usage: localclawd --remote "your task description"`, () => gracefulShutdown(1));
550573
550615
  pendingHookMessages
550574
550616
  }, renderAndRun);
550575
550617
  }
550576
- }).version("2.3.3 (localclawd)", "-v, --version", "Output the version number");
550618
+ }).version("2.3.5 (localclawd)", "-v, --version", "Output the version number");
550577
550619
  program2.option("-w, --worktree [name]", "Create a new git worktree for this session (optionally specify a name)");
550578
550620
  program2.option("--tmux", "Create a tmux session for the worktree (requires --worktree). Uses iTerm2 native panes when available; use --tmux=classic for traditional tmux.");
550579
550621
  if (canUserConfigureAdvisor()) {
@@ -551087,7 +551129,7 @@ if (false) {}
551087
551129
  async function main2() {
551088
551130
  const args = process.argv.slice(2);
551089
551131
  if (args.length === 1 && (args[0] === "--version" || args[0] === "-v" || args[0] === "-V")) {
551090
- console.log(`${"2.3.3"} (localclawd)`);
551132
+ console.log(`${"2.3.5"} (localclawd)`);
551091
551133
  return;
551092
551134
  }
551093
551135
  const {
@@ -551178,4 +551220,4 @@ localclawd crashed: ${msg}
551178
551220
  process.exit(1);
551179
551221
  });
551180
551222
 
551181
- //# debugId=0B0FA34AFD16289164756E2164756E21
551223
+ //# debugId=842A682EBF63408664756E2164756E21