@letta-ai/letta-code 0.27.2 → 0.27.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/letta.js CHANGED
@@ -3694,6 +3694,7 @@ class SettingsManager {
3694
3694
  if (this.initialized)
3695
3695
  return;
3696
3696
  const settingsPath = this.getSettingsPath();
3697
+ let shouldRollbackAutoConversationTitles = false;
3697
3698
  try {
3698
3699
  if (!exists(settingsPath)) {
3699
3700
  this.settings = { ...DEFAULT_SETTINGS };
@@ -3709,6 +3710,12 @@ class SettingsManager {
3709
3710
  delete loadedSettingsRaw.reflectionBehavior;
3710
3711
  this.markDirty("reflectionBehavior");
3711
3712
  }
3713
+ shouldRollbackAutoConversationTitles = loadedSettingsRaw.autoConversationTitlesRollbackApplied !== true;
3714
+ if (shouldRollbackAutoConversationTitles) {
3715
+ loadedSettingsRaw.autoConversationTitles = false;
3716
+ loadedSettingsRaw.autoConversationTitlesRollbackApplied = true;
3717
+ this.markDirty("autoConversationTitles", "autoConversationTitlesRollbackApplied");
3718
+ }
3712
3719
  this.settings = {
3713
3720
  ...DEFAULT_SETTINGS,
3714
3721
  ...loadedSettingsRaw
@@ -3718,6 +3725,11 @@ class SettingsManager {
3718
3725
  }
3719
3726
  }
3720
3727
  this.initialized = true;
3728
+ if (shouldRollbackAutoConversationTitles) {
3729
+ try {
3730
+ await this.persistSettings();
3731
+ } catch {}
3732
+ }
3721
3733
  await this.checkSecretsSupport();
3722
3734
  if (!isSubagentProcess()) {
3723
3735
  await this.migrateTokensToSecrets();
@@ -4787,7 +4799,9 @@ class SettingsManager {
4787
4799
  pinned: updates.pinned !== undefined ? updates.pinned : existing.pinned,
4788
4800
  memfs: updates.memfs !== undefined ? updates.memfs : existing.memfs,
4789
4801
  toolset: updates.toolset !== undefined ? updates.toolset : existing.toolset,
4790
- systemPromptPreset: updates.systemPromptPreset !== undefined ? updates.systemPromptPreset : existing.systemPromptPreset
4802
+ systemPromptPreset: updates.systemPromptPreset !== undefined ? updates.systemPromptPreset : existing.systemPromptPreset,
4803
+ systemPromptHash: updates.systemPromptHash !== undefined ? updates.systemPromptHash ?? undefined : existing.systemPromptHash,
4804
+ systemPromptVersion: updates.systemPromptVersion !== undefined ? updates.systemPromptVersion ?? undefined : existing.systemPromptVersion
4791
4805
  };
4792
4806
  if (!updated.pinned)
4793
4807
  delete updated.pinned;
@@ -4797,6 +4811,10 @@ class SettingsManager {
4797
4811
  delete updated.toolset;
4798
4812
  if (!updated.systemPromptPreset)
4799
4813
  delete updated.systemPromptPreset;
4814
+ if (!updated.systemPromptHash)
4815
+ delete updated.systemPromptHash;
4816
+ if (!updated.systemPromptVersion)
4817
+ delete updated.systemPromptVersion;
4800
4818
  if (!updated.baseUrl)
4801
4819
  delete updated.baseUrl;
4802
4820
  agents[idx] = updated;
@@ -4804,7 +4822,9 @@ class SettingsManager {
4804
4822
  const newAgent = {
4805
4823
  agentId,
4806
4824
  baseUrl: normalizedBaseUrl,
4807
- ...updates
4825
+ ...updates,
4826
+ systemPromptHash: updates.systemPromptHash ?? undefined,
4827
+ systemPromptVersion: updates.systemPromptVersion ?? undefined
4808
4828
  };
4809
4829
  if (!newAgent.pinned)
4810
4830
  delete newAgent.pinned;
@@ -4814,6 +4834,10 @@ class SettingsManager {
4814
4834
  delete newAgent.toolset;
4815
4835
  if (!newAgent.systemPromptPreset)
4816
4836
  delete newAgent.systemPromptPreset;
4837
+ if (!newAgent.systemPromptHash)
4838
+ delete newAgent.systemPromptHash;
4839
+ if (!newAgent.systemPromptVersion)
4840
+ delete newAgent.systemPromptVersion;
4817
4841
  if (!newAgent.baseUrl)
4818
4842
  delete newAgent.baseUrl;
4819
4843
  agents.push(newAgent);
@@ -4839,11 +4863,39 @@ class SettingsManager {
4839
4863
  getSystemPromptPreset(agentId) {
4840
4864
  return this.getAgentSettings(agentId)?.systemPromptPreset;
4841
4865
  }
4866
+ getSystemPromptHash(agentId) {
4867
+ return this.getAgentSettings(agentId)?.systemPromptHash;
4868
+ }
4869
+ getSystemPromptVersion(agentId) {
4870
+ return this.getAgentSettings(agentId)?.systemPromptVersion;
4871
+ }
4842
4872
  setSystemPromptPreset(agentId, preset) {
4843
- this.upsertAgentSettings(agentId, { systemPromptPreset: preset });
4873
+ this.upsertAgentSettings(agentId, {
4874
+ systemPromptPreset: preset,
4875
+ systemPromptHash: null,
4876
+ systemPromptVersion: null
4877
+ });
4878
+ }
4879
+ setManagedSystemPrompt(agentId, prompt) {
4880
+ this.upsertAgentSettings(agentId, {
4881
+ systemPromptPreset: prompt.preset,
4882
+ systemPromptHash: prompt.hash,
4883
+ systemPromptVersion: prompt.version
4884
+ });
4885
+ }
4886
+ setSystemPromptCustom(agentId) {
4887
+ this.upsertAgentSettings(agentId, {
4888
+ systemPromptPreset: "custom",
4889
+ systemPromptHash: null,
4890
+ systemPromptVersion: null
4891
+ });
4844
4892
  }
4845
4893
  clearSystemPromptPreset(agentId) {
4846
- this.upsertAgentSettings(agentId, { systemPromptPreset: "" });
4894
+ this.upsertAgentSettings(agentId, {
4895
+ systemPromptPreset: "",
4896
+ systemPromptHash: null,
4897
+ systemPromptVersion: null
4898
+ });
4847
4899
  }
4848
4900
  hasLocalLettaDir(workingDirectory = process.cwd()) {
4849
4901
  const dirPath = join3(workingDirectory, ".letta");
@@ -5001,7 +5053,8 @@ var init_settings_manager = __esm(() => {
5001
5053
  enableSleeptime: false,
5002
5054
  conversationSwitchAlertEnabled: false,
5003
5055
  sessionContextEnabled: true,
5004
- autoConversationTitles: true,
5056
+ autoConversationTitles: false,
5057
+ autoConversationTitlesRollbackApplied: true,
5005
5058
  autoSwapOnQuotaLimit: true,
5006
5059
  includeWorktreeTool: true,
5007
5060
  recentModels: [],
@@ -5024,7 +5077,7 @@ var package_default;
5024
5077
  var init_package = __esm(() => {
5025
5078
  package_default = {
5026
5079
  name: "@letta-ai/letta-code",
5027
- version: "0.27.2",
5080
+ version: "0.27.3",
5028
5081
  description: "Letta Code is a CLI tool for interacting with stateful Letta agents from the terminal.",
5029
5082
  type: "module",
5030
5083
  packageManager: "bun@1.3.0",
@@ -5249,10 +5302,10 @@ var init_constants = __esm(() => {
5249
5302
  function getConversationTitleSettings() {
5250
5303
  try {
5251
5304
  return {
5252
- enabled: settingsManager.getSettings().autoConversationTitles !== false
5305
+ enabled: settingsManager.getSettings().autoConversationTitles === true
5253
5306
  };
5254
5307
  } catch {
5255
- return { enabled: true };
5308
+ return { enabled: false };
5256
5309
  }
5257
5310
  }
5258
5311
  function setConversationTitleSettings(enabled) {
@@ -143845,6 +143898,177 @@ var init_prompt_assets = __esm(() => {
143845
143898
  ];
143846
143899
  });
143847
143900
 
143901
+ // src/agent/system-prompt-versioning.ts
143902
+ var exports_system_prompt_versioning = {};
143903
+ __export(exports_system_prompt_versioning, {
143904
+ scheduleManagedSystemPromptUpdate: () => scheduleManagedSystemPromptUpdate,
143905
+ recordManagedSystemPrompt: () => recordManagedSystemPrompt,
143906
+ hashSystemPrompt: () => hashSystemPrompt,
143907
+ getMemoryPromptModeForAgent: () => getMemoryPromptModeForAgent,
143908
+ decideManagedSystemPromptUpdate: () => decideManagedSystemPromptUpdate
143909
+ });
143910
+ import { createHash } from "node:crypto";
143911
+ function hashSystemPrompt(content) {
143912
+ const digest = createHash("sha256").update(content).digest("base64url");
143913
+ return `${SYSTEM_PROMPT_HASH_PREFIX}${digest}`;
143914
+ }
143915
+ function managedPrompt(preset, memoryMode, content = buildSystemPrompt(preset, memoryMode)) {
143916
+ return {
143917
+ preset,
143918
+ hash: hashSystemPrompt(content),
143919
+ version: getVersion()
143920
+ };
143921
+ }
143922
+ function recordManagedSystemPrompt(agentId, preset, memoryMode, content) {
143923
+ if (!settingsManager.isReady) {
143924
+ return;
143925
+ }
143926
+ settingsManager.setManagedSystemPrompt(agentId, managedPrompt(preset, memoryMode, content));
143927
+ }
143928
+ function getMemoryPromptModeForAgent(agentId) {
143929
+ const backend = getBackend();
143930
+ if (backend.capabilities.localMemfs) {
143931
+ return "local-memfs";
143932
+ }
143933
+ return settingsManager.isReady && settingsManager.isMemfsEnabled(agentId) ? "memfs" : "standard";
143934
+ }
143935
+ function isLettaCodePrimaryAgent(agent2) {
143936
+ const tags = agent2.tags ?? [];
143937
+ return tags.includes("origin:letta-code") && !tags.includes("role:subagent");
143938
+ }
143939
+ function findMatchingCurrentPreset(systemPrompt, memoryMode) {
143940
+ for (const preset of SYSTEM_PROMPTS) {
143941
+ if (buildSystemPrompt(preset.id, memoryMode) === systemPrompt) {
143942
+ return preset.id;
143943
+ }
143944
+ }
143945
+ return;
143946
+ }
143947
+ function isValidHash(hash4) {
143948
+ return !!hash4 && hash4.startsWith(SYSTEM_PROMPT_HASH_PREFIX);
143949
+ }
143950
+ function decideManagedSystemPromptUpdate(input) {
143951
+ const { agent: agent2, memoryMode, storedPreset, storedHash, storedVersion } = input;
143952
+ const currentSystemPrompt = agent2.system ?? "";
143953
+ const currentHash = hashSystemPrompt(currentSystemPrompt);
143954
+ const currentVersion = getVersion();
143955
+ if (storedPreset === "custom") {
143956
+ return { kind: "noop", reason: "system prompt is marked custom" };
143957
+ }
143958
+ if (storedPreset) {
143959
+ if (!isKnownPreset(storedPreset)) {
143960
+ return { kind: "clear", reason: "stored preset is no longer known" };
143961
+ }
143962
+ if (storedHash) {
143963
+ if (!isValidHash(storedHash)) {
143964
+ return { kind: "clear", reason: "stored prompt hash is invalid" };
143965
+ }
143966
+ if (currentHash !== storedHash) {
143967
+ return {
143968
+ kind: "custom",
143969
+ reason: "agent prompt differs from stored managed prompt hash"
143970
+ };
143971
+ }
143972
+ const nextSystemPrompt = buildSystemPrompt(storedPreset, memoryMode);
143973
+ const nextPrompt = managedPrompt(storedPreset, memoryMode, nextSystemPrompt);
143974
+ if (nextPrompt.hash !== storedHash) {
143975
+ return {
143976
+ kind: "update",
143977
+ nextSystemPrompt,
143978
+ prompt: nextPrompt,
143979
+ reason: "managed prompt content changed for current Letta Code version"
143980
+ };
143981
+ }
143982
+ if (storedVersion !== currentVersion) {
143983
+ return { kind: "track", prompt: nextPrompt };
143984
+ }
143985
+ return { kind: "noop", reason: "managed prompt is current" };
143986
+ }
143987
+ const expectedCurrentPrompt = buildSystemPrompt(storedPreset, memoryMode);
143988
+ if (currentSystemPrompt === expectedCurrentPrompt) {
143989
+ return {
143990
+ kind: "track",
143991
+ prompt: managedPrompt(storedPreset, memoryMode, currentSystemPrompt)
143992
+ };
143993
+ }
143994
+ return {
143995
+ kind: "custom",
143996
+ reason: "legacy preset tracking exists but prompt content was modified"
143997
+ };
143998
+ }
143999
+ if (!isLettaCodePrimaryAgent(agent2)) {
144000
+ return { kind: "noop", reason: "agent is not a primary Letta Code agent" };
144001
+ }
144002
+ const matchingPreset = findMatchingCurrentPreset(currentSystemPrompt, memoryMode);
144003
+ if (!matchingPreset) {
144004
+ return {
144005
+ kind: "custom",
144006
+ reason: "legacy Letta Code agent prompt does not match a current preset"
144007
+ };
144008
+ }
144009
+ return {
144010
+ kind: "track",
144011
+ prompt: managedPrompt(matchingPreset, memoryMode, currentSystemPrompt)
144012
+ };
144013
+ }
144014
+ function scheduleManagedSystemPromptUpdate({
144015
+ agent: agent2,
144016
+ memoryMode,
144017
+ onUpdated
144018
+ }) {
144019
+ if (!settingsManager.isReady) {
144020
+ return;
144021
+ }
144022
+ const decision = decideManagedSystemPromptUpdate({
144023
+ agent: agent2,
144024
+ memoryMode,
144025
+ storedPreset: settingsManager.getSystemPromptPreset(agent2.id),
144026
+ storedHash: settingsManager.getSystemPromptHash(agent2.id),
144027
+ storedVersion: settingsManager.getSystemPromptVersion(agent2.id)
144028
+ });
144029
+ if (decision.kind === "noop") {
144030
+ debugLog("startup", `System prompt version check noop: ${decision.reason}`);
144031
+ return;
144032
+ }
144033
+ if (decision.kind === "track") {
144034
+ settingsManager.setManagedSystemPrompt(agent2.id, decision.prompt);
144035
+ debugLog("startup", `Tracking managed system prompt ${decision.prompt.preset}@${decision.prompt.version}`);
144036
+ return;
144037
+ }
144038
+ if (decision.kind === "custom") {
144039
+ settingsManager.setSystemPromptCustom(agent2.id);
144040
+ debugLog("startup", `Marked system prompt custom: ${decision.reason}`);
144041
+ return;
144042
+ }
144043
+ if (decision.kind === "clear") {
144044
+ settingsManager.clearSystemPromptPreset(agent2.id);
144045
+ debugLog("startup", `Cleared system prompt metadata: ${decision.reason}`);
144046
+ return;
144047
+ }
144048
+ getBackend().updateAgent(agent2.id, {
144049
+ system: decision.nextSystemPrompt
144050
+ }).then(async () => {
144051
+ settingsManager.setManagedSystemPrompt(agent2.id, decision.prompt);
144052
+ debugLog("startup", `Updated managed system prompt ${decision.prompt.preset}@${decision.prompt.version}: ${decision.reason}`);
144053
+ if (onUpdated) {
144054
+ const updatedAgent = await getBackend().retrieveAgent(agent2.id, {
144055
+ include: ["agent.secrets", "agent.tools", "agent.tags"]
144056
+ });
144057
+ onUpdated(updatedAgent);
144058
+ }
144059
+ }).catch((error54) => {
144060
+ debugWarn("startup", `Failed to update managed system prompt for ${agent2.id}: ${error54 instanceof Error ? error54.message : String(error54)}`);
144061
+ });
144062
+ }
144063
+ var SYSTEM_PROMPT_HASH_PREFIX = "sha256:";
144064
+ var init_system_prompt_versioning = __esm(() => {
144065
+ init_backend2();
144066
+ init_settings_manager();
144067
+ init_debug();
144068
+ init_version();
144069
+ init_prompt_assets();
144070
+ });
144071
+
143848
144072
  // src/agent/modify.ts
143849
144073
  var exports_modify = {};
143850
144074
  __export(exports_modify, {
@@ -144070,6 +144294,7 @@ async function updateAgentSystemPromptRaw(agentId, systemPromptContent) {
144070
144294
  async function updateAgentSystemPrompt(agentId, systemPromptId) {
144071
144295
  try {
144072
144296
  const { isKnownPreset: isKnownPreset2, resolveAndBuildSystemPrompt: resolveAndBuildSystemPrompt2 } = await Promise.resolve().then(() => (init_prompt_assets(), exports_prompt_assets));
144297
+ const { recordManagedSystemPrompt: recordManagedSystemPrompt2 } = await Promise.resolve().then(() => (init_system_prompt_versioning(), exports_system_prompt_versioning));
144073
144298
  const { settingsManager: settingsManager2 } = await Promise.resolve().then(() => (init_settings_manager(), exports_settings_manager));
144074
144299
  const backend = getBackend();
144075
144300
  const memoryMode = backend.capabilities.localMemfs ? "local-memfs" : settingsManager2.isReady && settingsManager2.isMemfsEnabled(agentId) ? "memfs" : "standard";
@@ -144085,7 +144310,7 @@ async function updateAgentSystemPrompt(agentId, systemPromptId) {
144085
144310
  }
144086
144311
  if (settingsManager2.isReady) {
144087
144312
  if (isKnownPreset2(systemPromptId)) {
144088
- settingsManager2.setSystemPromptPreset(agentId, systemPromptId);
144313
+ recordManagedSystemPrompt2(agentId, systemPromptId, memoryMode, systemPromptContent);
144089
144314
  } else {
144090
144315
  settingsManager2.clearSystemPromptPreset(agentId);
144091
144316
  }
@@ -144110,10 +144335,33 @@ async function updateAgentSystemPromptMemfs(agentId, enableMemfs) {
144110
144335
  try {
144111
144336
  const { settingsManager: settingsManager2 } = await Promise.resolve().then(() => (init_settings_manager(), exports_settings_manager));
144112
144337
  const { isKnownPreset: isKnownPreset2, buildSystemPrompt: buildSystemPrompt2 } = await Promise.resolve().then(() => (init_prompt_assets(), exports_prompt_assets));
144338
+ const { hashSystemPrompt: hashSystemPrompt2, recordManagedSystemPrompt: recordManagedSystemPrompt2 } = await Promise.resolve().then(() => (init_system_prompt_versioning(), exports_system_prompt_versioning));
144113
144339
  const newMode = enableMemfs ? getBackend().capabilities.localMemfs ? "local-memfs" : "memfs" : "standard";
144114
144340
  const storedPreset = settingsManager2.isReady ? settingsManager2.getSystemPromptPreset(agentId) : undefined;
144341
+ const storedHash = settingsManager2.isReady ? settingsManager2.getSystemPromptHash(agentId) : undefined;
144115
144342
  let nextSystemPrompt;
144116
144343
  if (storedPreset && isKnownPreset2(storedPreset)) {
144344
+ const agent2 = await getBackend().retrieveAgent(agentId);
144345
+ const currentSystemPrompt = agent2.system || "";
144346
+ if (storedHash && hashSystemPrompt2(currentSystemPrompt) !== storedHash) {
144347
+ if (settingsManager2.isReady) {
144348
+ settingsManager2.setSystemPromptCustom(agentId);
144349
+ }
144350
+ return {
144351
+ success: true,
144352
+ message: "Custom system prompt left unchanged for memory mode"
144353
+ };
144354
+ }
144355
+ if (!storedHash && settingsManager2.isReady) {
144356
+ const currentMode = settingsManager2.isMemfsEnabled(agentId) ? getBackend().capabilities.localMemfs ? "local-memfs" : "memfs" : "standard";
144357
+ if (currentSystemPrompt !== buildSystemPrompt2(storedPreset, currentMode)) {
144358
+ settingsManager2.setSystemPromptCustom(agentId);
144359
+ return {
144360
+ success: true,
144361
+ message: "Custom system prompt left unchanged for memory mode"
144362
+ };
144363
+ }
144364
+ }
144117
144365
  nextSystemPrompt = buildSystemPrompt2(storedPreset, newMode);
144118
144366
  } else {
144119
144367
  const agent2 = await getBackend().retrieveAgent(agentId);
@@ -144122,6 +144370,9 @@ async function updateAgentSystemPromptMemfs(agentId, enableMemfs) {
144122
144370
  await getBackend().updateAgent(agentId, {
144123
144371
  system: nextSystemPrompt
144124
144372
  });
144373
+ if (storedPreset && isKnownPreset2(storedPreset)) {
144374
+ recordManagedSystemPrompt2(agentId, storedPreset, newMode, nextSystemPrompt);
144375
+ }
144125
144376
  return {
144126
144377
  success: true,
144127
144378
  message: enableMemfs ? "System prompt updated for memfs memory mode" : "System prompt updated for standard memory mode"
@@ -161566,6 +161817,8 @@ var init_session2 = __esm(() => {
161566
161817
  });
161567
161818
 
161568
161819
  // src/tools/impl/shell-launchers.ts
161820
+ import { existsSync as existsSync13 } from "node:fs";
161821
+ import { delimiter, isAbsolute as isAbsolute3, join as join14 } from "node:path";
161569
161822
  function isValidEnvAlias(name) {
161570
161823
  return /^[A-Za-z_][A-Za-z0-9_]*$/.test(name);
161571
161824
  }
@@ -161662,6 +161915,56 @@ function shellCommandFlag(shellName, login) {
161662
161915
  }
161663
161916
  return "-c";
161664
161917
  }
161918
+ function pathEnvValue(env3) {
161919
+ return env3.PATH ?? env3.Path ?? env3.path ?? "";
161920
+ }
161921
+ function pathExtValue(env3) {
161922
+ return env3.PATHEXT ?? env3.PathExt ?? ".COM;.EXE;.BAT;.CMD";
161923
+ }
161924
+ function hasPathSeparator(executable) {
161925
+ return executable.includes("/") || executable.includes("\\");
161926
+ }
161927
+ function hasFileExtension(executable) {
161928
+ const basename11 = executable.split(/[\\/]/).pop() ?? executable;
161929
+ return /\.[^.]+$/.test(basename11);
161930
+ }
161931
+ function resolveExecutablePath(executable, env3) {
161932
+ if (isAbsolute3(executable) || hasPathSeparator(executable)) {
161933
+ return existsSync13(executable) ? executable : null;
161934
+ }
161935
+ const pathDelimiter = process.platform === "win32" ? ";" : delimiter;
161936
+ const pathEntries = pathEnvValue(env3).split(pathDelimiter).filter(Boolean);
161937
+ const executableNames = [executable];
161938
+ if (process.platform === "win32" && !hasFileExtension(executable)) {
161939
+ for (const extension of pathExtValue(env3).split(";").filter(Boolean)) {
161940
+ executableNames.push(`${executable}${extension}`);
161941
+ }
161942
+ }
161943
+ for (const entry of pathEntries) {
161944
+ for (const name of executableNames) {
161945
+ const candidate = join14(entry, name);
161946
+ if (existsSync13(candidate)) {
161947
+ return candidate;
161948
+ }
161949
+ }
161950
+ }
161951
+ return null;
161952
+ }
161953
+ function selectAvailableShellLauncher(launchers, env3 = process.env) {
161954
+ if (process.platform !== "win32") {
161955
+ return launchers[0];
161956
+ }
161957
+ for (const launcher of launchers) {
161958
+ const executable = launcher[0];
161959
+ if (!executable)
161960
+ continue;
161961
+ const resolvedExecutable = resolveExecutablePath(executable, env3);
161962
+ if (resolvedExecutable) {
161963
+ return [resolvedExecutable, ...launcher.slice(1)];
161964
+ }
161965
+ }
161966
+ return launchers.at(-1);
161967
+ }
161665
161968
  function unixLaunchers(command, login) {
161666
161969
  const trimmed = command.trim();
161667
161970
  if (!trimmed)
@@ -166028,14 +166331,14 @@ function rebuildCachedLauncher(command, secretEnv) {
166028
166331
  });
166029
166332
  return launchers.find((launcher) => launcher[0]?.toLowerCase() === cachedExecutable) ?? null;
166030
166333
  }
166031
- function getBackgroundLauncher(command, secretEnv) {
166334
+ function getBackgroundLauncher(command, env3, secretEnv) {
166032
166335
  const cachedLauncher = rebuildCachedLauncher(command, secretEnv);
166033
166336
  if (cachedLauncher)
166034
166337
  return cachedLauncher;
166035
166338
  const launchers = buildShellLaunchers(command, {
166036
166339
  powershellEnvAliases: secretEnv ? Object.keys(secretEnv) : undefined
166037
166340
  });
166038
- return launchers[0] || [];
166341
+ return selectAvailableShellLauncher(launchers, env3) || [];
166039
166342
  }
166040
166343
  async function spawnCommand(command, options3) {
166041
166344
  const env3 = options3.secretEnv ? { ...options3.env, ...options3.secretEnv } : options3.env;
@@ -166153,7 +166456,7 @@ async function bash(args) {
166153
166456
  const bgCommand = withStrictShellPrelude(command, bgEnv);
166154
166457
  const bashId = getNextBashId();
166155
166458
  const outputFile = createBackgroundOutputFile(bashId);
166156
- const launcher = getBackgroundLauncher(bgCommand, secretEnv);
166459
+ const launcher = getBackgroundLauncher(bgCommand, bgEnv, secretEnv);
166157
166460
  const [executable, ...launcherArgs] = launcher;
166158
166461
  if (!executable) {
166159
166462
  return {
@@ -166570,7 +166873,7 @@ var init_create_goal = __esm(() => {
166570
166873
  });
166571
166874
 
166572
166875
  // src/websocket/listener/remote-settings.ts
166573
- import { existsSync as existsSync14, readFileSync as readFileSync14 } from "node:fs";
166876
+ import { existsSync as existsSync15, readFileSync as readFileSync14 } from "node:fs";
166574
166877
  import { mkdir as mkdir6, writeFile as writeFile9 } from "node:fs/promises";
166575
166878
  import { homedir as homedir11 } from "node:os";
166576
166879
  import path10 from "node:path";
@@ -166584,7 +166887,7 @@ function loadRemoteSettings() {
166584
166887
  let loaded = {};
166585
166888
  try {
166586
166889
  const settingsPath = getRemoteSettingsPath();
166587
- if (existsSync14(settingsPath)) {
166890
+ if (existsSync15(settingsPath)) {
166588
166891
  const raw = readFileSync14(settingsPath, "utf-8");
166589
166892
  const parsed = JSON.parse(raw);
166590
166893
  loaded = parsed;
@@ -166593,7 +166896,7 @@ function loadRemoteSettings() {
166593
166896
  if (loaded.cwdMap) {
166594
166897
  const validCwdMap = {};
166595
166898
  for (const [key, value] of Object.entries(loaded.cwdMap)) {
166596
- if (typeof value === "string" && existsSync14(value)) {
166899
+ if (typeof value === "string" && existsSync15(value)) {
166597
166900
  validCwdMap[key] = value;
166598
166901
  }
166599
166902
  }
@@ -166620,13 +166923,13 @@ function saveRemoteSettings(updates) {
166620
166923
  function loadLegacyCwdCache() {
166621
166924
  try {
166622
166925
  const legacyPath = path10.join(homedir11(), ".letta", "cwd-cache.json");
166623
- if (!existsSync14(legacyPath))
166926
+ if (!existsSync15(legacyPath))
166624
166927
  return {};
166625
166928
  const raw = readFileSync14(legacyPath, "utf-8");
166626
166929
  const parsed = JSON.parse(raw);
166627
166930
  const result = {};
166628
166931
  for (const [key, value] of Object.entries(parsed)) {
166629
- if (typeof value === "string" && existsSync14(value)) {
166932
+ if (typeof value === "string" && existsSync15(value)) {
166630
166933
  result[key] = value;
166631
166934
  }
166632
166935
  }
@@ -167160,8 +167463,8 @@ var init_memory_runtime = __esm(() => {
167160
167463
  });
167161
167464
 
167162
167465
  // src/utils/system-prompt-size.ts
167163
- import { existsSync as existsSync15, readdirSync as readdirSync4, readFileSync as readFileSync15 } from "node:fs";
167164
- import { join as join16 } from "node:path";
167466
+ import { existsSync as existsSync16, readdirSync as readdirSync4, readFileSync as readFileSync15 } from "node:fs";
167467
+ import { join as join17 } from "node:path";
167165
167468
  function estimateSystemTokens(text) {
167166
167469
  return Math.ceil(Buffer.byteLength(text, "utf8") / SYSTEM_PROMPT_BYTES_PER_TOKEN);
167167
167470
  }
@@ -167169,7 +167472,7 @@ function normalizePath(value) {
167169
167472
  return value.replaceAll("\\", "/");
167170
167473
  }
167171
167474
  function walkMarkdownFiles(dir) {
167172
- if (!existsSync15(dir)) {
167475
+ if (!existsSync16(dir)) {
167173
167476
  return [];
167174
167477
  }
167175
167478
  const out = [];
@@ -167178,7 +167481,7 @@ function walkMarkdownFiles(dir) {
167178
167481
  if (entry.name.startsWith(".")) {
167179
167482
  continue;
167180
167483
  }
167181
- const full = join16(dir, entry.name);
167484
+ const full = join17(dir, entry.name);
167182
167485
  if (entry.isDirectory()) {
167183
167486
  out.push(...walkMarkdownFiles(full));
167184
167487
  continue;
@@ -167190,8 +167493,8 @@ function walkMarkdownFiles(dir) {
167190
167493
  return out;
167191
167494
  }
167192
167495
  function estimateSystemPromptSize(memoryDir) {
167193
- const systemDir = join16(memoryDir, "system");
167194
- if (!existsSync15(systemDir)) {
167496
+ const systemDir = join17(memoryDir, "system");
167497
+ if (!existsSync16(systemDir)) {
167195
167498
  return { total: 0, files: [] };
167196
167499
  }
167197
167500
  const files = walkMarkdownFiles(systemDir).sort();
@@ -168741,7 +169044,7 @@ var init_edit2 = __esm(() => {
168741
169044
  });
168742
169045
 
168743
169046
  // src/tools/impl/shell.ts
168744
- import { existsSync as existsSync16, statSync as statSync4 } from "node:fs";
169047
+ import { existsSync as existsSync17, statSync as statSync4 } from "node:fs";
168745
169048
  import * as path14 from "node:path";
168746
169049
  function resolveShellWorkdir(workdir) {
168747
169050
  const defaultCwd = getCurrentWorkingDirectory();
@@ -168844,7 +169147,7 @@ function arraysEqual(a, b) {
168844
169147
  }
168845
169148
  function isUsableDirectory(candidate) {
168846
169149
  try {
168847
- return existsSync16(candidate) && statSync4(candidate).isDirectory();
169150
+ return existsSync17(candidate) && statSync4(candidate).isDirectory();
168848
169151
  } catch {
168849
169152
  return false;
168850
169153
  }
@@ -168911,8 +169214,6 @@ var init_shell = __esm(() => {
168911
169214
 
168912
169215
  // src/tools/impl/exec-command.ts
168913
169216
  import { spawn as spawn6 } from "node:child_process";
168914
- import { existsSync as existsSync17 } from "node:fs";
168915
- import { delimiter as delimiter2, isAbsolute as isAbsolute6, join as join17 } from "node:path";
168916
169217
  function createAbortError() {
168917
169218
  const error54 = new Error("The operation was aborted");
168918
169219
  error54.name = "AbortError";
@@ -169102,56 +169403,6 @@ function buildExecLaunchers(args) {
169102
169403
  powershellEnvAliases: envAliases
169103
169404
  });
169104
169405
  }
169105
- function pathEnvValue(env3) {
169106
- return env3.PATH ?? env3.Path ?? env3.path ?? "";
169107
- }
169108
- function pathExtValue(env3) {
169109
- return env3.PATHEXT ?? env3.PathExt ?? ".COM;.EXE;.BAT;.CMD";
169110
- }
169111
- function hasPathSeparator(executable) {
169112
- return executable.includes("/") || executable.includes("\\");
169113
- }
169114
- function hasFileExtension(executable) {
169115
- const basename12 = executable.split(/[\\/]/).pop() ?? executable;
169116
- return /\.[^.]+$/.test(basename12);
169117
- }
169118
- function resolveExecutablePath(executable, env3) {
169119
- if (isAbsolute6(executable) || hasPathSeparator(executable)) {
169120
- return existsSync17(executable) ? executable : null;
169121
- }
169122
- const pathDelimiter = process.platform === "win32" ? ";" : delimiter2;
169123
- const pathEntries = pathEnvValue(env3).split(pathDelimiter).filter(Boolean);
169124
- const executableNames = [executable];
169125
- if (process.platform === "win32" && !hasFileExtension(executable)) {
169126
- for (const extension of pathExtValue(env3).split(";").filter(Boolean)) {
169127
- executableNames.push(`${executable}${extension}`);
169128
- }
169129
- }
169130
- for (const entry of pathEntries) {
169131
- for (const name of executableNames) {
169132
- const candidate = join17(entry, name);
169133
- if (existsSync17(candidate)) {
169134
- return candidate;
169135
- }
169136
- }
169137
- }
169138
- return null;
169139
- }
169140
- function selectExecLauncher(launchers, env3) {
169141
- if (process.platform !== "win32") {
169142
- return launchers[0];
169143
- }
169144
- for (const launcher of launchers) {
169145
- const executable = launcher[0];
169146
- if (!executable)
169147
- continue;
169148
- const resolvedExecutable = resolveExecutablePath(executable, env3);
169149
- if (resolvedExecutable) {
169150
- return [resolvedExecutable, ...launcher.slice(1)];
169151
- }
169152
- }
169153
- return launchers.at(-1);
169154
- }
169155
169406
  function buildPtyEnv(env3) {
169156
169407
  const ptyEnv = {};
169157
169408
  for (const [key, value] of Object.entries(env3)) {
@@ -169336,7 +169587,7 @@ async function startExecSession(args) {
169336
169587
  const cwd = resolveShellWorkdir(args.workdir);
169337
169588
  const env3 = { ...getShellEnv(), ...args.secretEnv ?? {} };
169338
169589
  const launchers = buildExecLaunchers(args);
169339
- const launcher = selectExecLauncher(launchers, env3);
169590
+ const launcher = selectAvailableShellLauncher(launchers, env3);
169340
169591
  if (!launcher) {
169341
169592
  throw new Error("Command must be a non-empty string");
169342
169593
  }
@@ -175071,7 +175322,7 @@ var require_libvips = __commonJS((exports, module3) => {
175071
175322
  SPDX-License-Identifier: Apache-2.0
175072
175323
  */
175073
175324
  var { spawnSync } = __require("node:child_process");
175074
- var { createHash } = __require("node:crypto");
175325
+ var { createHash: createHash2 } = __require("node:crypto");
175075
175326
  var semverCoerce = require_coerce();
175076
175327
  var semverGreaterThanOrEqualTo = require_gte();
175077
175328
  var semverSatisfies = require_satisfies();
@@ -175159,7 +175410,7 @@ var require_libvips = __commonJS((exports, module3) => {
175159
175410
  }
175160
175411
  return false;
175161
175412
  };
175162
- var sha512 = (s2) => createHash("sha512").update(s2).digest("hex");
175413
+ var sha512 = (s2) => createHash2("sha512").update(s2).digest("hex");
175163
175414
  var yarnLocator = () => {
175164
175415
  try {
175165
175416
  const identHash = sha512(`imgsharp-libvips-${buildPlatformArch()}`);
@@ -192954,7 +193205,7 @@ __export(exports_loader, {
192954
193205
  loadPermissions: () => loadPermissions,
192955
193206
  getUserSettingsPaths: () => getUserSettingsPaths
192956
193207
  });
192957
- import { createHash } from "node:crypto";
193208
+ import { createHash as createHash2 } from "node:crypto";
192958
193209
  import { readFileSync as readFileSync17, statSync as statSync5, watch as watch2 } from "node:fs";
192959
193210
  import { homedir as homedir12 } from "node:os";
192960
193211
  import { dirname as dirname14, join as join24, resolve as resolve25 } from "node:path";
@@ -192985,7 +193236,7 @@ function getFileSignature(path26) {
192985
193236
  exists: true,
192986
193237
  mtimeMs: stat9.mtimeMs,
192987
193238
  size: stat9.size,
192988
- hash: createHash("sha256").update(readFileSync17(path26)).digest("hex")
193239
+ hash: createHash2("sha256").update(readFileSync17(path26)).digest("hex")
192989
193240
  };
192990
193241
  } catch {
192991
193242
  return { exists: false };
@@ -204098,11 +204349,11 @@ var init_local_model_config = __esm(() => {
204098
204349
 
204099
204350
  // src/backend/local/system-prompt-compilation.ts
204100
204351
  import { execFileSync as execFileSync2 } from "node:child_process";
204101
- import { createHash as createHash2 } from "node:crypto";
204352
+ import { createHash as createHash3 } from "node:crypto";
204102
204353
  import { existsSync as existsSync26 } from "node:fs";
204103
204354
  import { basename as basename13, dirname as dirname17, relative as relative4 } from "node:path";
204104
204355
  function hashString(value) {
204105
- return createHash2("sha256").update(value).digest("hex");
204356
+ return createHash3("sha256").update(value).digest("hex");
204106
204357
  }
204107
204358
  function hashRawSystemPrompt(systemPrompt) {
204108
204359
  return hashString(systemPrompt);
@@ -243373,9 +243624,9 @@ async function createAgent(nameOrOptions = DEFAULT_AGENT_NAME, model, embeddingM
243373
243624
  }
243374
243625
  if (!isSubagent && settingsManager.isReady) {
243375
243626
  if (options3.systemPromptCustom) {
243376
- settingsManager.setSystemPromptPreset(fullAgent.id, "custom");
243627
+ settingsManager.setSystemPromptCustom(fullAgent.id);
243377
243628
  } else if (isKnownPreset(options3.systemPromptPreset ?? "default")) {
243378
- settingsManager.setSystemPromptPreset(fullAgent.id, options3.systemPromptPreset ?? "default");
243629
+ recordManagedSystemPrompt(fullAgent.id, options3.systemPromptPreset ?? "default", memMode, systemPromptContent);
243379
243630
  }
243380
243631
  }
243381
243632
  const provenance = {
@@ -243395,6 +243646,7 @@ var init_create6 = __esm(() => {
243395
243646
  init_model();
243396
243647
  init_modify();
243397
243648
  init_prompt_assets();
243649
+ init_system_prompt_versioning();
243398
243650
  });
243399
243651
 
243400
243652
  // src/agent/personality.ts
@@ -255134,6 +255386,7 @@ function markIncompleteToolsAsCancelled(b3, setInterruptedFlag = true, reason =
255134
255386
  let anyToolsCancelled = false;
255135
255387
  for (const [id2, line] of b3.byId.entries()) {
255136
255388
  if (line.kind === "tool_call" && line.phase !== "finished") {
255389
+ debugLog("accumulator", `[ORPHANED_TOOL] name=${line.name ?? "?"} phase=${line.phase} diagnosis=${diagnoseOrphanedTool(line, b3)} reason=${reason}`);
255137
255390
  const updatedLine = {
255138
255391
  ...line,
255139
255392
  phase: "finished",
@@ -255149,6 +255402,33 @@ function markIncompleteToolsAsCancelled(b3, setInterruptedFlag = true, reason =
255149
255402
  }
255150
255403
  return anyToolsCancelled;
255151
255404
  }
255405
+ function removeIncompleteTools(b3) {
255406
+ let anyToolsRemoved = false;
255407
+ for (const [id2, line] of b3.byId.entries()) {
255408
+ if (line.kind === "tool_call" && line.phase !== "finished") {
255409
+ debugLog("accumulator", `[REMOVED_ORPHANED_TOOL] name=${line.name ?? "?"} phase=${line.phase} diagnosis=${diagnoseOrphanedTool(line, b3)} toolCallId=${line.toolCallId ?? "?"}`);
255410
+ b3.byId.delete(id2);
255411
+ b3.order = b3.order.filter((oid) => oid !== id2);
255412
+ if (line.toolCallId) {
255413
+ b3.toolCallIdToLineId.delete(line.toolCallId);
255414
+ b3.serverToolCalls.delete(line.toolCallId);
255415
+ }
255416
+ anyToolsRemoved = true;
255417
+ }
255418
+ }
255419
+ return anyToolsRemoved;
255420
+ }
255421
+ function diagnoseOrphanedTool(line, b3) {
255422
+ const isTrackedAsServerTool = line.toolCallId ? b3.serverToolCalls.has(line.toolCallId) : false;
255423
+ if (line.phase === "streaming") {
255424
+ return isTrackedAsServerTool ? "server_tool_missing_return" : "client_tool_missing_approval_request";
255425
+ }
255426
+ if (line.phase === "ready")
255427
+ return "approval_pending_at_stream_end";
255428
+ if (line.phase === "running")
255429
+ return "execution_incomplete_at_stream_end";
255430
+ return "unknown_phase";
255431
+ }
255152
255432
  function getStringProp(obj, key2) {
255153
255433
  const v2 = obj[key2];
255154
255434
  return typeof v2 === "string" ? v2 : undefined;
@@ -256340,7 +256620,15 @@ async function drainStream(stream5, buffers, refresh, abortSignal, onFirstMessag
256340
256620
  stopReason = "error";
256341
256621
  }
256342
256622
  if (stopReason === "cancelled") {
256343
- markIncompleteToolsAsCancelled(buffers, true, "user_interrupt");
256623
+ const hadOrphanedTools = markIncompleteToolsAsCancelled(buffers, true, "user_interrupt");
256624
+ if (hadOrphanedTools) {
256625
+ debugWarn("drainStream", "cancelled had orphaned tool calls (see [ORPHANED_TOOL] logs for diagnosis)");
256626
+ }
256627
+ } else if (stopReason === "end_turn") {
256628
+ const hadOrphanedTools = removeIncompleteTools(buffers);
256629
+ if (hadOrphanedTools) {
256630
+ debugWarn("drainStream", "end_turn had orphaned tool calls (see [REMOVED_ORPHANED_TOOL] logs)");
256631
+ }
256344
256632
  }
256345
256633
  if (stopReason !== "error") {
256346
256634
  markCurrentLineAsFinished(buffers);
@@ -262322,6 +262610,45 @@ function trackListenerUserInput(messages, modelId) {
262322
262610
  telemetry.trackUserInput(inputText, "user", modelId);
262323
262611
  }
262324
262612
  }
262613
+ function buildInboundUserTranscriptLines(messages) {
262614
+ const lines = [];
262615
+ for (const message of messages) {
262616
+ if (!("role" in message) || message.role !== "user") {
262617
+ continue;
262618
+ }
262619
+ if (!("content" in message)) {
262620
+ continue;
262621
+ }
262622
+ const text2 = extractTelemetryInputText(message.content);
262623
+ if (text2.length === 0) {
262624
+ continue;
262625
+ }
262626
+ const otid = "otid" in message && typeof message.otid === "string" ? message.otid : undefined;
262627
+ const id2 = otid ? `user-${otid}` : `user-${crypto.randomUUID()}`;
262628
+ lines.push({
262629
+ kind: "user",
262630
+ id: id2,
262631
+ text: text2,
262632
+ otid
262633
+ });
262634
+ }
262635
+ return lines;
262636
+ }
262637
+ function seedInboundUserTranscriptLines(buffers, lines) {
262638
+ for (const line of lines) {
262639
+ if (line.kind !== "user") {
262640
+ continue;
262641
+ }
262642
+ if (buffers.byId.has(line.id)) {
262643
+ continue;
262644
+ }
262645
+ buffers.byId.set(line.id, line);
262646
+ buffers.order.push(line.id);
262647
+ if (line.otid) {
262648
+ buffers.userLineIdByOtid.set(line.otid, line.id);
262649
+ }
262650
+ }
262651
+ }
262325
262652
  function escapeTaskNotificationSummary(summary) {
262326
262653
  return summary.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
262327
262654
  }
@@ -262485,6 +262812,7 @@ async function handleIncomingMessage(msg, socket, runtime, onStatusChange, conne
262485
262812
  ...m4,
262486
262813
  otid: "client_message_id" in m4 && typeof m4.client_message_id === "string" ? m4.client_message_id : crypto.randomUUID()
262487
262814
  } : m4));
262815
+ const inboundUserTranscriptLines = buildInboundUserTranscriptLines(messagesToSend);
262488
262816
  const firstMessage = normalizedMessages[0];
262489
262817
  const isApprovalMessage = firstMessage && "type" in firstMessage && firstMessage.type === "approval" && "approvals" in firstMessage;
262490
262818
  let cachedAgent = null;
@@ -262590,6 +262918,7 @@ async function handleIncomingMessage(msg, socket, runtime, onStatusChange, conne
262590
262918
  let runIdSent = false;
262591
262919
  let runId;
262592
262920
  const buffers = createBuffers(agentId);
262921
+ seedInboundUserTranscriptLines(buffers, inboundUserTranscriptLines);
262593
262922
  while (true) {
262594
262923
  runIdSent = false;
262595
262924
  let latestErrorText = null;
@@ -439966,7 +440295,7 @@ Additional information: BADCLIENT: Bad error code, ${badCode} not found in range
439966
440295
  });
439967
440296
 
439968
440297
  // src/extensions/extension-engine.ts
439969
- import { createHash as createHash3 } from "node:crypto";
440298
+ import { createHash as createHash4 } from "node:crypto";
439970
440299
  import {
439971
440300
  existsSync as existsSync46,
439972
440301
  mkdirSync as mkdirSync33,
@@ -440179,7 +440508,7 @@ function prepareExtensionForImport(extensionPath, source2) {
440179
440508
  function createImportableExtensionPath(extensionPath, cacheDirectory) {
440180
440509
  ensureExtensionCache(cacheDirectory);
440181
440510
  const source2 = readFileSync32(extensionPath, "utf8");
440182
- const hash4 = createHash3("sha256").update(source2).digest("hex").slice(0, 16);
440511
+ const hash4 = createHash4("sha256").update(source2).digest("hex").slice(0, 16);
440183
440512
  const extension = path34.extname(extensionPath);
440184
440513
  const importableSource = prepareExtensionForImport(extensionPath, source2);
440185
440514
  const baseName = path34.basename(extensionPath, extension).replace(/[^a-zA-Z0-9_-]/g, "-");
@@ -440937,17 +441266,19 @@ function hasExtensionSources(options3) {
440937
441266
  return resolveLocalExtensionSources(options3).some((source2) => source2.files.length > 0);
440938
441267
  }
440939
441268
  function createExtensionAdapter(options3) {
440940
- if (options3.disabled) {
440941
- disableExtensionsForProcess();
440942
- }
440943
- if (options3.disabled || areExtensionsDisabled()) {
440944
- return createDisabledExtensionAdapter(options3);
440945
- }
440946
441269
  const {
441270
+ disabled,
440947
441271
  getBackend: resolveBackend,
440948
441272
  initialContext,
440949
441273
  ...engineOptions
440950
441274
  } = options3;
441275
+ const alreadyDisabled = areExtensionsDisabled();
441276
+ if (disabled || alreadyDisabled) {
441277
+ if (!alreadyDisabled) {
441278
+ disableExtensionsForProcess();
441279
+ }
441280
+ return createDisabledExtensionAdapter({ initialContext });
441281
+ }
440951
441282
  let context3 = initialContext;
440952
441283
  let disposed = false;
440953
441284
  const initialHasExtensionSources = hasExtensionSources(engineOptions);
@@ -440961,7 +441292,7 @@ function createExtensionAdapter(options3) {
440961
441292
  const getContext3 = () => context3;
440962
441293
  const engine4 = createExtensionEngine({
440963
441294
  ...engineOptions,
440964
- ...resolveBackend ? { getBackend: getBackend2 } : {},
441295
+ getBackend: getBackend2,
440965
441296
  getContext: getContext3
440966
441297
  });
440967
441298
  const events = {
@@ -441005,9 +441336,9 @@ function createExtensionAdapter(options3) {
441005
441336
  debugLog("extensions", "failed to load %s: %s", loadError.path, loadError.error.message);
441006
441337
  }
441007
441338
  for (const diagnostic of nextRegistry.diagnostics) {
441008
- if (diagnostic.phase !== "command.override")
441009
- continue;
441010
- debugLog("extensions", "%s", diagnostic.error.message);
441339
+ if (diagnostic.phase === "command.override") {
441340
+ debugLog("extensions", "%s", diagnostic.error.message);
441341
+ }
441011
441342
  }
441012
441343
  loadState = {
441013
441344
  hadStatuslineRenderer: Boolean(nextRegistry.ui.statuslineRenderer),
@@ -442086,7 +442417,7 @@ In headless mode, use:
442086
442417
  }
442087
442418
  agent2 = result.agent;
442088
442419
  if (settingsManager.isReady) {
442089
- settingsManager.setSystemPromptPreset(agent2.id, "custom");
442420
+ settingsManager.setSystemPromptCustom(agent2.id);
442090
442421
  }
442091
442422
  if (result.skills && result.skills.length > 0) {
442092
442423
  const { getAgentSkillsDir: getAgentSkillsDir3 } = await Promise.resolve().then(() => (init_skills3(), exports_skills2));
@@ -442295,26 +442626,11 @@ Current session AGENT_ID=${process.env.AGENT_ID}; --backend local switches to a
442295
442626
  agent2 = result.agent;
442296
442627
  }
442297
442628
  if (isResumingAgent && !systemPromptPreset) {
442298
- let storedPreset = settingsManager.getSystemPromptPreset(agent2.id);
442299
- if (!storedPreset && agent2.tags?.includes("origin:letta-code") && !agent2.tags?.includes("role:subagent")) {
442300
- storedPreset = "custom";
442301
- settingsManager.setSystemPromptPreset(agent2.id, storedPreset);
442302
- }
442303
- if (storedPreset && storedPreset !== "custom") {
442304
- const { buildSystemPrompt: rebuildPrompt, isKnownPreset: isKnown } = await Promise.resolve().then(() => (init_prompt_assets(), exports_prompt_assets));
442305
- if (isKnown(storedPreset)) {
442306
- const memoryMode = settingsManager.isMemfsEnabled(agent2.id) ? "memfs" : "standard";
442307
- const expected = rebuildPrompt(storedPreset, memoryMode);
442308
- if (agent2.system !== expected) {
442309
- await backend4.updateAgent(agent2.id, { system: expected });
442310
- agent2 = await backend4.retrieveAgent(agent2.id, {
442311
- include: ["agent.secrets", "agent.tools", "agent.tags"]
442312
- });
442313
- }
442314
- } else {
442315
- settingsManager.clearSystemPromptPreset(agent2.id);
442316
- }
442317
- }
442629
+ const { getMemoryPromptModeForAgent: getMemoryPromptModeForAgent2, scheduleManagedSystemPromptUpdate: scheduleManagedSystemPromptUpdate2 } = await Promise.resolve().then(() => (init_system_prompt_versioning(), exports_system_prompt_versioning));
442630
+ scheduleManagedSystemPromptUpdate2({
442631
+ agent: agent2,
442632
+ memoryMode: getMemoryPromptModeForAgent2(agent2.id)
442633
+ });
442318
442634
  }
442319
442635
  const startupAgentId = agent2.id;
442320
442636
  clearPersistedClientToolRules(startupAgentId, agent2).then((cleanup) => {
@@ -502285,9 +502601,9 @@ async function createAgent2(nameOrOptions = DEFAULT_AGENT_NAME, model, embedding
502285
502601
  }
502286
502602
  if (!isSubagent && settingsManager.isReady) {
502287
502603
  if (options3.systemPromptCustom) {
502288
- settingsManager.setSystemPromptPreset(fullAgent.id, "custom");
502604
+ settingsManager.setSystemPromptCustom(fullAgent.id);
502289
502605
  } else if (isKnownPreset(options3.systemPromptPreset ?? "default")) {
502290
- settingsManager.setSystemPromptPreset(fullAgent.id, options3.systemPromptPreset ?? "default");
502606
+ recordManagedSystemPrompt(fullAgent.id, options3.systemPromptPreset ?? "default", memMode, systemPromptContent);
502291
502607
  }
502292
502608
  }
502293
502609
  const provenance = {
@@ -502307,6 +502623,7 @@ var init_create9 = __esm(() => {
502307
502623
  init_model();
502308
502624
  init_modify();
502309
502625
  init_prompt_assets();
502626
+ init_system_prompt_versioning();
502310
502627
  });
502311
502628
 
502312
502629
  // src/agent/import.ts
@@ -502990,6 +503307,177 @@ var init_secrets_store2 = __esm(() => {
502990
503307
  SECRETS_CACHE_KEY2 = Symbol.for("@letta/secretsCache");
502991
503308
  });
502992
503309
 
503310
+ // src/agent/system-prompt-versioning.ts
503311
+ var exports_system_prompt_versioning2 = {};
503312
+ __export(exports_system_prompt_versioning2, {
503313
+ scheduleManagedSystemPromptUpdate: () => scheduleManagedSystemPromptUpdate2,
503314
+ recordManagedSystemPrompt: () => recordManagedSystemPrompt2,
503315
+ hashSystemPrompt: () => hashSystemPrompt2,
503316
+ getMemoryPromptModeForAgent: () => getMemoryPromptModeForAgent2,
503317
+ decideManagedSystemPromptUpdate: () => decideManagedSystemPromptUpdate2
503318
+ });
503319
+ import { createHash as createHash5 } from "node:crypto";
503320
+ function hashSystemPrompt2(content) {
503321
+ const digest = createHash5("sha256").update(content).digest("base64url");
503322
+ return `${SYSTEM_PROMPT_HASH_PREFIX2}${digest}`;
503323
+ }
503324
+ function managedPrompt2(preset, memoryMode, content = buildSystemPrompt(preset, memoryMode)) {
503325
+ return {
503326
+ preset,
503327
+ hash: hashSystemPrompt2(content),
503328
+ version: getVersion()
503329
+ };
503330
+ }
503331
+ function recordManagedSystemPrompt2(agentId, preset, memoryMode, content) {
503332
+ if (!settingsManager.isReady) {
503333
+ return;
503334
+ }
503335
+ settingsManager.setManagedSystemPrompt(agentId, managedPrompt2(preset, memoryMode, content));
503336
+ }
503337
+ function getMemoryPromptModeForAgent2(agentId) {
503338
+ const backend4 = getBackend();
503339
+ if (backend4.capabilities.localMemfs) {
503340
+ return "local-memfs";
503341
+ }
503342
+ return settingsManager.isReady && settingsManager.isMemfsEnabled(agentId) ? "memfs" : "standard";
503343
+ }
503344
+ function isLettaCodePrimaryAgent2(agent2) {
503345
+ const tags = agent2.tags ?? [];
503346
+ return tags.includes("origin:letta-code") && !tags.includes("role:subagent");
503347
+ }
503348
+ function findMatchingCurrentPreset2(systemPrompt, memoryMode) {
503349
+ for (const preset of SYSTEM_PROMPTS) {
503350
+ if (buildSystemPrompt(preset.id, memoryMode) === systemPrompt) {
503351
+ return preset.id;
503352
+ }
503353
+ }
503354
+ return;
503355
+ }
503356
+ function isValidHash2(hash4) {
503357
+ return !!hash4 && hash4.startsWith(SYSTEM_PROMPT_HASH_PREFIX2);
503358
+ }
503359
+ function decideManagedSystemPromptUpdate2(input) {
503360
+ const { agent: agent2, memoryMode, storedPreset, storedHash, storedVersion } = input;
503361
+ const currentSystemPrompt = agent2.system ?? "";
503362
+ const currentHash = hashSystemPrompt2(currentSystemPrompt);
503363
+ const currentVersion = getVersion();
503364
+ if (storedPreset === "custom") {
503365
+ return { kind: "noop", reason: "system prompt is marked custom" };
503366
+ }
503367
+ if (storedPreset) {
503368
+ if (!isKnownPreset(storedPreset)) {
503369
+ return { kind: "clear", reason: "stored preset is no longer known" };
503370
+ }
503371
+ if (storedHash) {
503372
+ if (!isValidHash2(storedHash)) {
503373
+ return { kind: "clear", reason: "stored prompt hash is invalid" };
503374
+ }
503375
+ if (currentHash !== storedHash) {
503376
+ return {
503377
+ kind: "custom",
503378
+ reason: "agent prompt differs from stored managed prompt hash"
503379
+ };
503380
+ }
503381
+ const nextSystemPrompt = buildSystemPrompt(storedPreset, memoryMode);
503382
+ const nextPrompt = managedPrompt2(storedPreset, memoryMode, nextSystemPrompt);
503383
+ if (nextPrompt.hash !== storedHash) {
503384
+ return {
503385
+ kind: "update",
503386
+ nextSystemPrompt,
503387
+ prompt: nextPrompt,
503388
+ reason: "managed prompt content changed for current Letta Code version"
503389
+ };
503390
+ }
503391
+ if (storedVersion !== currentVersion) {
503392
+ return { kind: "track", prompt: nextPrompt };
503393
+ }
503394
+ return { kind: "noop", reason: "managed prompt is current" };
503395
+ }
503396
+ const expectedCurrentPrompt = buildSystemPrompt(storedPreset, memoryMode);
503397
+ if (currentSystemPrompt === expectedCurrentPrompt) {
503398
+ return {
503399
+ kind: "track",
503400
+ prompt: managedPrompt2(storedPreset, memoryMode, currentSystemPrompt)
503401
+ };
503402
+ }
503403
+ return {
503404
+ kind: "custom",
503405
+ reason: "legacy preset tracking exists but prompt content was modified"
503406
+ };
503407
+ }
503408
+ if (!isLettaCodePrimaryAgent2(agent2)) {
503409
+ return { kind: "noop", reason: "agent is not a primary Letta Code agent" };
503410
+ }
503411
+ const matchingPreset = findMatchingCurrentPreset2(currentSystemPrompt, memoryMode);
503412
+ if (!matchingPreset) {
503413
+ return {
503414
+ kind: "custom",
503415
+ reason: "legacy Letta Code agent prompt does not match a current preset"
503416
+ };
503417
+ }
503418
+ return {
503419
+ kind: "track",
503420
+ prompt: managedPrompt2(matchingPreset, memoryMode, currentSystemPrompt)
503421
+ };
503422
+ }
503423
+ function scheduleManagedSystemPromptUpdate2({
503424
+ agent: agent2,
503425
+ memoryMode,
503426
+ onUpdated
503427
+ }) {
503428
+ if (!settingsManager.isReady) {
503429
+ return;
503430
+ }
503431
+ const decision = decideManagedSystemPromptUpdate2({
503432
+ agent: agent2,
503433
+ memoryMode,
503434
+ storedPreset: settingsManager.getSystemPromptPreset(agent2.id),
503435
+ storedHash: settingsManager.getSystemPromptHash(agent2.id),
503436
+ storedVersion: settingsManager.getSystemPromptVersion(agent2.id)
503437
+ });
503438
+ if (decision.kind === "noop") {
503439
+ debugLog("startup", `System prompt version check noop: ${decision.reason}`);
503440
+ return;
503441
+ }
503442
+ if (decision.kind === "track") {
503443
+ settingsManager.setManagedSystemPrompt(agent2.id, decision.prompt);
503444
+ debugLog("startup", `Tracking managed system prompt ${decision.prompt.preset}@${decision.prompt.version}`);
503445
+ return;
503446
+ }
503447
+ if (decision.kind === "custom") {
503448
+ settingsManager.setSystemPromptCustom(agent2.id);
503449
+ debugLog("startup", `Marked system prompt custom: ${decision.reason}`);
503450
+ return;
503451
+ }
503452
+ if (decision.kind === "clear") {
503453
+ settingsManager.clearSystemPromptPreset(agent2.id);
503454
+ debugLog("startup", `Cleared system prompt metadata: ${decision.reason}`);
503455
+ return;
503456
+ }
503457
+ getBackend().updateAgent(agent2.id, {
503458
+ system: decision.nextSystemPrompt
503459
+ }).then(async () => {
503460
+ settingsManager.setManagedSystemPrompt(agent2.id, decision.prompt);
503461
+ debugLog("startup", `Updated managed system prompt ${decision.prompt.preset}@${decision.prompt.version}: ${decision.reason}`);
503462
+ if (onUpdated) {
503463
+ const updatedAgent = await getBackend().retrieveAgent(agent2.id, {
503464
+ include: ["agent.secrets", "agent.tools", "agent.tags"]
503465
+ });
503466
+ onUpdated(updatedAgent);
503467
+ }
503468
+ }).catch((error54) => {
503469
+ debugWarn("startup", `Failed to update managed system prompt for ${agent2.id}: ${error54 instanceof Error ? error54.message : String(error54)}`);
503470
+ });
503471
+ }
503472
+ var SYSTEM_PROMPT_HASH_PREFIX2 = "sha256:";
503473
+ var init_system_prompt_versioning2 = __esm(() => {
503474
+ init_backend2();
503475
+ init_settings_manager();
503476
+ init_debug();
503477
+ init_version();
503478
+ init_prompt_assets();
503479
+ });
503480
+
502993
503481
  // src/index.ts
502994
503482
  import { hostname as hostname7 } from "os";
502995
503483
 
@@ -504089,6 +504577,7 @@ async function updateAgentSystemPromptRaw2(agentId, systemPromptContent) {
504089
504577
  async function updateAgentSystemPrompt2(agentId, systemPromptId) {
504090
504578
  try {
504091
504579
  const { isKnownPreset: isKnownPreset2, resolveAndBuildSystemPrompt: resolveAndBuildSystemPrompt2 } = await Promise.resolve().then(() => (init_prompt_assets(), exports_prompt_assets));
504580
+ const { recordManagedSystemPrompt: recordManagedSystemPrompt2 } = await Promise.resolve().then(() => (init_system_prompt_versioning(), exports_system_prompt_versioning));
504092
504581
  const { settingsManager: settingsManager2 } = await Promise.resolve().then(() => (init_settings_manager(), exports_settings_manager));
504093
504582
  const backend3 = getBackend();
504094
504583
  const memoryMode = backend3.capabilities.localMemfs ? "local-memfs" : settingsManager2.isReady && settingsManager2.isMemfsEnabled(agentId) ? "memfs" : "standard";
@@ -504104,7 +504593,7 @@ async function updateAgentSystemPrompt2(agentId, systemPromptId) {
504104
504593
  }
504105
504594
  if (settingsManager2.isReady) {
504106
504595
  if (isKnownPreset2(systemPromptId)) {
504107
- settingsManager2.setSystemPromptPreset(agentId, systemPromptId);
504596
+ recordManagedSystemPrompt2(agentId, systemPromptId, memoryMode, systemPromptContent);
504108
504597
  } else {
504109
504598
  settingsManager2.clearSystemPromptPreset(agentId);
504110
504599
  }
@@ -511590,7 +512079,8 @@ var DEFAULT_SETTINGS2 = {
511590
512079
  enableSleeptime: false,
511591
512080
  conversationSwitchAlertEnabled: false,
511592
512081
  sessionContextEnabled: true,
511593
- autoConversationTitles: true,
512082
+ autoConversationTitles: false,
512083
+ autoConversationTitlesRollbackApplied: true,
511594
512084
  autoSwapOnQuotaLimit: true,
511595
512085
  includeWorktreeTool: true,
511596
512086
  recentModels: [],
@@ -511745,6 +512235,7 @@ class SettingsManager2 {
511745
512235
  if (this.initialized)
511746
512236
  return;
511747
512237
  const settingsPath = this.getSettingsPath();
512238
+ let shouldRollbackAutoConversationTitles = false;
511748
512239
  try {
511749
512240
  if (!exists(settingsPath)) {
511750
512241
  this.settings = { ...DEFAULT_SETTINGS2 };
@@ -511760,6 +512251,12 @@ class SettingsManager2 {
511760
512251
  delete loadedSettingsRaw.reflectionBehavior;
511761
512252
  this.markDirty("reflectionBehavior");
511762
512253
  }
512254
+ shouldRollbackAutoConversationTitles = loadedSettingsRaw.autoConversationTitlesRollbackApplied !== true;
512255
+ if (shouldRollbackAutoConversationTitles) {
512256
+ loadedSettingsRaw.autoConversationTitles = false;
512257
+ loadedSettingsRaw.autoConversationTitlesRollbackApplied = true;
512258
+ this.markDirty("autoConversationTitles", "autoConversationTitlesRollbackApplied");
512259
+ }
511763
512260
  this.settings = {
511764
512261
  ...DEFAULT_SETTINGS2,
511765
512262
  ...loadedSettingsRaw
@@ -511769,6 +512266,11 @@ class SettingsManager2 {
511769
512266
  }
511770
512267
  }
511771
512268
  this.initialized = true;
512269
+ if (shouldRollbackAutoConversationTitles) {
512270
+ try {
512271
+ await this.persistSettings();
512272
+ } catch {}
512273
+ }
511772
512274
  await this.checkSecretsSupport();
511773
512275
  if (!isSubagentProcess3()) {
511774
512276
  await this.migrateTokensToSecrets();
@@ -512838,7 +513340,9 @@ class SettingsManager2 {
512838
513340
  pinned: updates.pinned !== undefined ? updates.pinned : existing.pinned,
512839
513341
  memfs: updates.memfs !== undefined ? updates.memfs : existing.memfs,
512840
513342
  toolset: updates.toolset !== undefined ? updates.toolset : existing.toolset,
512841
- systemPromptPreset: updates.systemPromptPreset !== undefined ? updates.systemPromptPreset : existing.systemPromptPreset
513343
+ systemPromptPreset: updates.systemPromptPreset !== undefined ? updates.systemPromptPreset : existing.systemPromptPreset,
513344
+ systemPromptHash: updates.systemPromptHash !== undefined ? updates.systemPromptHash ?? undefined : existing.systemPromptHash,
513345
+ systemPromptVersion: updates.systemPromptVersion !== undefined ? updates.systemPromptVersion ?? undefined : existing.systemPromptVersion
512842
513346
  };
512843
513347
  if (!updated.pinned)
512844
513348
  delete updated.pinned;
@@ -512848,6 +513352,10 @@ class SettingsManager2 {
512848
513352
  delete updated.toolset;
512849
513353
  if (!updated.systemPromptPreset)
512850
513354
  delete updated.systemPromptPreset;
513355
+ if (!updated.systemPromptHash)
513356
+ delete updated.systemPromptHash;
513357
+ if (!updated.systemPromptVersion)
513358
+ delete updated.systemPromptVersion;
512851
513359
  if (!updated.baseUrl)
512852
513360
  delete updated.baseUrl;
512853
513361
  agents[idx] = updated;
@@ -512855,7 +513363,9 @@ class SettingsManager2 {
512855
513363
  const newAgent = {
512856
513364
  agentId,
512857
513365
  baseUrl: normalizedBaseUrl,
512858
- ...updates
513366
+ ...updates,
513367
+ systemPromptHash: updates.systemPromptHash ?? undefined,
513368
+ systemPromptVersion: updates.systemPromptVersion ?? undefined
512859
513369
  };
512860
513370
  if (!newAgent.pinned)
512861
513371
  delete newAgent.pinned;
@@ -512865,6 +513375,10 @@ class SettingsManager2 {
512865
513375
  delete newAgent.toolset;
512866
513376
  if (!newAgent.systemPromptPreset)
512867
513377
  delete newAgent.systemPromptPreset;
513378
+ if (!newAgent.systemPromptHash)
513379
+ delete newAgent.systemPromptHash;
513380
+ if (!newAgent.systemPromptVersion)
513381
+ delete newAgent.systemPromptVersion;
512868
513382
  if (!newAgent.baseUrl)
512869
513383
  delete newAgent.baseUrl;
512870
513384
  agents.push(newAgent);
@@ -512890,11 +513404,39 @@ class SettingsManager2 {
512890
513404
  getSystemPromptPreset(agentId) {
512891
513405
  return this.getAgentSettings(agentId)?.systemPromptPreset;
512892
513406
  }
513407
+ getSystemPromptHash(agentId) {
513408
+ return this.getAgentSettings(agentId)?.systemPromptHash;
513409
+ }
513410
+ getSystemPromptVersion(agentId) {
513411
+ return this.getAgentSettings(agentId)?.systemPromptVersion;
513412
+ }
512893
513413
  setSystemPromptPreset(agentId, preset) {
512894
- this.upsertAgentSettings(agentId, { systemPromptPreset: preset });
513414
+ this.upsertAgentSettings(agentId, {
513415
+ systemPromptPreset: preset,
513416
+ systemPromptHash: null,
513417
+ systemPromptVersion: null
513418
+ });
513419
+ }
513420
+ setManagedSystemPrompt(agentId, prompt) {
513421
+ this.upsertAgentSettings(agentId, {
513422
+ systemPromptPreset: prompt.preset,
513423
+ systemPromptHash: prompt.hash,
513424
+ systemPromptVersion: prompt.version
513425
+ });
513426
+ }
513427
+ setSystemPromptCustom(agentId) {
513428
+ this.upsertAgentSettings(agentId, {
513429
+ systemPromptPreset: "custom",
513430
+ systemPromptHash: null,
513431
+ systemPromptVersion: null
513432
+ });
512895
513433
  }
512896
513434
  clearSystemPromptPreset(agentId) {
512897
- this.upsertAgentSettings(agentId, { systemPromptPreset: "" });
513435
+ this.upsertAgentSettings(agentId, {
513436
+ systemPromptPreset: "",
513437
+ systemPromptHash: null,
513438
+ systemPromptVersion: null
513439
+ });
512898
513440
  }
512899
513441
  hasLocalLettaDir(workingDirectory = process.cwd()) {
512900
513442
  const dirPath = join42(workingDirectory, ".letta");
@@ -514837,7 +515379,7 @@ Error: ${message}`);
514837
515379
  blocks: []
514838
515380
  });
514839
515381
  if (settingsManager2.isReady) {
514840
- settingsManager2.setSystemPromptPreset(agent2.id, "custom");
515382
+ settingsManager2.setSystemPromptCustom(agent2.id);
514841
515383
  }
514842
515384
  if (result.skills && result.skills.length > 0) {
514843
515385
  const { getAgentSkillsDir: getAgentSkillsDir3 } = await Promise.resolve().then(() => (init_skills4(), exports_skills3));
@@ -514890,6 +515432,7 @@ Error: ${message}`);
514890
515432
  skillsDirectory: skillsDirectory2,
514891
515433
  parallelToolCalls: true,
514892
515434
  systemPromptPreset: systemPromptPreset2,
515435
+ systemPromptCustom: systemCustom,
514893
515436
  memoryPromptMode: effectiveMemoryMode,
514894
515437
  initBlocks: initBlocks2,
514895
515438
  baseTools: baseTools2
@@ -515072,26 +515615,6 @@ Error: ${message}`);
515072
515615
  } catch (error54) {
515073
515616
  Promise.resolve().then(() => (init_debug2(), exports_debug2)).then(({ debugLog: debugLog5 }) => debugLog5("secrets", `Failed to init secrets: ${error54 instanceof Error ? error54.message : String(error54)}`));
515074
515617
  }
515075
- if (resuming && !systemPromptPreset2) {
515076
- let storedPreset = settingsManager2.getSystemPromptPreset(agent2.id);
515077
- if (!storedPreset && agent2.tags?.includes("origin:letta-code") && !agent2.tags?.includes("role:subagent")) {
515078
- storedPreset = "custom";
515079
- settingsManager2.setSystemPromptPreset(agent2.id, storedPreset);
515080
- }
515081
- if (storedPreset && storedPreset !== "custom") {
515082
- const { buildSystemPrompt: rebuildPrompt, isKnownPreset: isKnown } = await Promise.resolve().then(() => (init_prompt_assets2(), exports_prompt_assets2));
515083
- if (isKnown(storedPreset)) {
515084
- const memoryMode = settingsManager2.isMemfsEnabled(agent2.id) ? "memfs" : "standard";
515085
- const expected = rebuildPrompt(storedPreset, memoryMode);
515086
- if (agent2.system !== expected) {
515087
- await backend4.updateAgent(agent2.id, { system: expected });
515088
- agent2 = await backend4.retrieveAgent(agent2.id);
515089
- }
515090
- } else {
515091
- settingsManager2.clearSystemPromptPreset(agent2.id);
515092
- }
515093
- }
515094
- }
515095
515618
  if (shouldPersistSessionState2()) {
515096
515619
  settingsManager2.persistSession(agent2.id, conversationIdToUse);
515097
515620
  }
@@ -515101,6 +515624,19 @@ Error: ${message}`);
515101
515624
  setConversationId2(conversationIdToUse);
515102
515625
  markMilestone2("TUI_READY");
515103
515626
  setLoadingState("ready");
515627
+ if (resuming && !systemPromptPreset2) {
515628
+ const {
515629
+ getMemoryPromptModeForAgent: getMemoryPromptModeForAgent3,
515630
+ scheduleManagedSystemPromptUpdate: scheduleManagedSystemPromptUpdate3
515631
+ } = await Promise.resolve().then(() => (init_system_prompt_versioning2(), exports_system_prompt_versioning2));
515632
+ scheduleManagedSystemPromptUpdate3({
515633
+ agent: agent2,
515634
+ memoryMode: getMemoryPromptModeForAgent3(agent2.id),
515635
+ onUpdated: (updatedAgent) => {
515636
+ setAgentState(updatedAgent);
515637
+ }
515638
+ });
515639
+ }
515104
515640
  }
515105
515641
  init().catch((err) => {
515106
515642
  trackCliBoundaryError("tui_initialization_failed", err, "tui_app_initialization");
@@ -515250,4 +515786,4 @@ Error during initialization: ${message}`);
515250
515786
  }
515251
515787
  main2();
515252
515788
 
515253
- //# debugId=B61A22FCE77950DE64756E2164756E21
515789
+ //# debugId=1C963C23C659C5D164756E2164756E21