@google/gemini-cli 0.36.0 → 0.37.0-preview.1

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 (74) hide show
  1. package/bundle/{chunk-UNM3DGTG.js → chunk-33B2YA3V.js} +711 -240
  2. package/bundle/{chunk-2OFO4ODK.js → chunk-43UUP7VO.js} +6717 -4203
  3. package/bundle/{chunk-MYI75E6G.js → chunk-5OOT636U.js} +262 -92
  4. package/bundle/{chunk-GHJNEZXJ.js → chunk-BLL44IGV.js} +777 -294
  5. package/bundle/{chunk-S2IQOR7T.js → chunk-JS5WSGB2.js} +243 -88
  6. package/bundle/{chunk-QVTX2M5J.js → chunk-PPWUMHZT.js} +6355 -4117
  7. package/bundle/chunk-TSSVZ7RZ.js +98376 -0
  8. package/bundle/chunk-U4FACSVX.js +30 -0
  9. package/bundle/{chunk-VB55KQW3.js → chunk-VSXV53B7.js} +11735 -14377
  10. package/bundle/{chunk-EAXTBDLN.js → chunk-WZB27TDF.js} +711 -240
  11. package/bundle/chunk-ZB4UQCX5.js +356418 -0
  12. package/bundle/{core-6V2OYDRU.js → core-RMRIZ3E5.js} +60 -4
  13. package/bundle/{devtoolsService-ZKU2HLK2.js → devtoolsService-2ULAA43E.js} +20 -3
  14. package/bundle/{devtoolsService-UL6JE436.js → devtoolsService-AWVCG2N2.js} +22 -4
  15. package/bundle/devtoolsService-IWSTJYRB.js +871 -0
  16. package/bundle/{devtoolsService-QTW7GHQP.js → devtoolsService-SZYXXACN.js} +20 -3
  17. package/bundle/{core-BMLL5RF4.js → dist-4FKFY6XB.js} +60 -4
  18. package/bundle/{dist-PYC2JXAJ.js → dist-PRDBNGX2.js} +60 -4
  19. package/bundle/dist-TCCEQJDV.js +1942 -0
  20. package/bundle/docs/CONTRIBUTING.md +10 -7
  21. package/bundle/docs/assets/theme-tokyonight-dark.png +0 -0
  22. package/bundle/docs/changelogs/index.md +24 -0
  23. package/bundle/docs/changelogs/latest.md +366 -459
  24. package/bundle/docs/changelogs/preview.md +362 -356
  25. package/bundle/docs/cli/acp-mode.md +126 -0
  26. package/bundle/docs/cli/cli-reference.md +1 -1
  27. package/bundle/docs/cli/notifications.md +5 -5
  28. package/bundle/docs/cli/plan-mode.md +22 -11
  29. package/bundle/docs/cli/sandbox.md +1 -1
  30. package/bundle/docs/cli/settings.md +14 -13
  31. package/bundle/docs/cli/themes.md +5 -0
  32. package/bundle/docs/core/index.md +2 -2
  33. package/bundle/docs/core/subagents.md +134 -23
  34. package/bundle/docs/get-started/gemini-3.md +1 -1
  35. package/bundle/docs/get-started/index.md +127 -1
  36. package/bundle/docs/ide-integration/index.md +99 -24
  37. package/bundle/docs/index.md +0 -2
  38. package/bundle/docs/redirects.json +1 -0
  39. package/bundle/docs/reference/commands.md +1 -3
  40. package/bundle/docs/reference/configuration.md +182 -91
  41. package/bundle/docs/reference/keyboard-shortcuts.md +14 -6
  42. package/bundle/docs/reference/policy-engine.md +36 -31
  43. package/bundle/docs/reference/tools.md +56 -23
  44. package/bundle/docs/resources/quota-and-pricing.md +23 -9
  45. package/bundle/docs/sidebar.json +11 -4
  46. package/bundle/docs/tools/planning.md +6 -4
  47. package/bundle/events-CLX3JQHP.js +12 -0
  48. package/bundle/gemini.js +342 -52
  49. package/bundle/{interactiveCli-VLQHRXHU.js → interactiveCli-24VGI5NV.js} +5066 -4010
  50. package/bundle/{interactiveCli-A6HZ2TDO.js → interactiveCli-D2MTTARB.js} +5066 -4010
  51. package/bundle/{interactiveCli-DWMSDCKV.js → interactiveCli-DX76MWWT.js} +5296 -4223
  52. package/bundle/interactiveCli-VNDJAKWG.js +50355 -0
  53. package/bundle/{memoryDiscovery-BQGYT4OD.js → memoryDiscovery-A265O6ML.js} +3 -1
  54. package/bundle/{memoryDiscovery-FCEPFZ3M.js → memoryDiscovery-H6J7KIH2.js} +3 -1
  55. package/bundle/node_modules/@google/gemini-cli-devtools/dist/client/main.js +26 -19
  56. package/bundle/node_modules/@google/gemini-cli-devtools/dist/src/_client-assets.d.ts +1 -1
  57. package/bundle/node_modules/@google/gemini-cli-devtools/dist/src/_client-assets.js +1 -1
  58. package/bundle/node_modules/@google/gemini-cli-devtools/dist/src/_client-assets.js.map +1 -1
  59. package/bundle/node_modules/@google/gemini-cli-devtools/dist/src/index.js +35 -1
  60. package/bundle/node_modules/@google/gemini-cli-devtools/dist/src/index.js.map +1 -1
  61. package/bundle/node_modules/@google/gemini-cli-devtools/package.json +1 -1
  62. package/bundle/{oauth2-provider-5ENESIRQ.js → oauth2-provider-FZUTS3SV.js} +2 -2
  63. package/bundle/{oauth2-provider-CAKFQRQV.js → oauth2-provider-K25DXIWC.js} +2 -2
  64. package/bundle/{oauth2-provider-RVED6DAZ.js → oauth2-provider-N73M7SQI.js} +39 -73
  65. package/bundle/oauth2-provider-RMDEEXSP.js +237 -0
  66. package/bundle/policies/discovered.toml +7 -0
  67. package/bundle/policies/non-interactive.toml +7 -0
  68. package/bundle/policies/plan.toml +25 -0
  69. package/bundle/policies/read-only.toml +6 -0
  70. package/bundle/policies/sandbox-default.toml +3 -2
  71. package/bundle/policies/write.toml +21 -0
  72. package/bundle/policies/yolo.toml +1 -1
  73. package/package.json +1 -1
  74. package/bundle/docs/get-started/examples.md +0 -141
@@ -40759,26 +40759,6 @@ function getApiKeyFromEnv() {
40759
40759
  return envGoogleApiKey || envGeminiApiKey || void 0;
40760
40760
  }
40761
40761
 
40762
- // packages/core/dist/src/confirmation-bus/types.js
40763
- var MessageBusType;
40764
- (function(MessageBusType2) {
40765
- MessageBusType2["TOOL_CONFIRMATION_REQUEST"] = "tool-confirmation-request";
40766
- MessageBusType2["TOOL_CONFIRMATION_RESPONSE"] = "tool-confirmation-response";
40767
- MessageBusType2["TOOL_POLICY_REJECTION"] = "tool-policy-rejection";
40768
- MessageBusType2["TOOL_EXECUTION_SUCCESS"] = "tool-execution-success";
40769
- MessageBusType2["TOOL_EXECUTION_FAILURE"] = "tool-execution-failure";
40770
- MessageBusType2["UPDATE_POLICY"] = "update-policy";
40771
- MessageBusType2["TOOL_CALLS_UPDATE"] = "tool-calls-update";
40772
- MessageBusType2["ASK_USER_REQUEST"] = "ask-user-request";
40773
- MessageBusType2["ASK_USER_RESPONSE"] = "ask-user-response";
40774
- })(MessageBusType || (MessageBusType = {}));
40775
- var QuestionType;
40776
- (function(QuestionType2) {
40777
- QuestionType2["CHOICE"] = "choice";
40778
- QuestionType2["TEXT"] = "text";
40779
- QuestionType2["YESNO"] = "yesno";
40780
- })(QuestionType || (QuestionType = {}));
40781
-
40782
40762
  // packages/core/dist/src/policy/types.js
40783
40763
  var PolicyDecision;
40784
40764
  (function(PolicyDecision2) {
@@ -40807,6 +40787,12 @@ var ApprovalMode;
40807
40787
  ApprovalMode2["YOLO"] = "yolo";
40808
40788
  ApprovalMode2["PLAN"] = "plan";
40809
40789
  })(ApprovalMode || (ApprovalMode = {}));
40790
+ var MODES_BY_PERMISSIVENESS = [
40791
+ ApprovalMode.PLAN,
40792
+ ApprovalMode.DEFAULT,
40793
+ ApprovalMode.AUTO_EDIT,
40794
+ ApprovalMode.YOLO
40795
+ ];
40810
40796
  var InProcessCheckerType;
40811
40797
  (function(InProcessCheckerType2) {
40812
40798
  InProcessCheckerType2["ALLOWED_PATH"] = "allowed-path";
@@ -40817,6 +40803,27 @@ var ALWAYS_ALLOW_PRIORITY_FRACTION = 950;
40817
40803
  var ALWAYS_ALLOW_PRIORITY_OFFSET = ALWAYS_ALLOW_PRIORITY_FRACTION / 1e3;
40818
40804
  var PRIORITY_YOLO_ALLOW_ALL = 998;
40819
40805
 
40806
+ // packages/core/dist/src/confirmation-bus/types.js
40807
+ var MessageBusType;
40808
+ (function(MessageBusType2) {
40809
+ MessageBusType2["TOOL_CONFIRMATION_REQUEST"] = "tool-confirmation-request";
40810
+ MessageBusType2["TOOL_CONFIRMATION_RESPONSE"] = "tool-confirmation-response";
40811
+ MessageBusType2["TOOL_POLICY_REJECTION"] = "tool-policy-rejection";
40812
+ MessageBusType2["TOOL_EXECUTION_SUCCESS"] = "tool-execution-success";
40813
+ MessageBusType2["TOOL_EXECUTION_FAILURE"] = "tool-execution-failure";
40814
+ MessageBusType2["UPDATE_POLICY"] = "update-policy";
40815
+ MessageBusType2["TOOL_CALLS_UPDATE"] = "tool-calls-update";
40816
+ MessageBusType2["ASK_USER_REQUEST"] = "ask-user-request";
40817
+ MessageBusType2["ASK_USER_RESPONSE"] = "ask-user-response";
40818
+ MessageBusType2["SUBAGENT_ACTIVITY"] = "subagent-activity";
40819
+ })(MessageBusType || (MessageBusType = {}));
40820
+ var QuestionType;
40821
+ (function(QuestionType2) {
40822
+ QuestionType2["CHOICE"] = "choice";
40823
+ QuestionType2["TEXT"] = "text";
40824
+ QuestionType2["YESNO"] = "yesno";
40825
+ })(QuestionType || (QuestionType = {}));
40826
+
40820
40827
  // packages/core/dist/src/tools/tools.js
40821
40828
  function isBackgroundExecutionData(data) {
40822
40829
  if (typeof data !== "object" || data === null) {
@@ -40986,6 +40993,11 @@ var BaseToolInvocation = class {
40986
40993
  }
40987
40994
  });
40988
40995
  }
40996
+ toJSON() {
40997
+ return {
40998
+ params: this.params
40999
+ };
41000
+ }
40989
41001
  };
40990
41002
  var DeclarativeTool = class {
40991
41003
  name;
@@ -41025,6 +41037,15 @@ var DeclarativeTool = class {
41025
41037
  }
41026
41038
  return cloned;
41027
41039
  }
41040
+ toJSON() {
41041
+ return {
41042
+ name: this.name,
41043
+ displayName: this.displayName,
41044
+ description: this.description,
41045
+ kind: this.kind,
41046
+ parameterSchema: this.parameterSchema
41047
+ };
41048
+ }
41028
41049
  get isReadOnly() {
41029
41050
  return READ_ONLY_KINDS.includes(this.kind);
41030
41051
  }
@@ -41235,6 +41256,7 @@ function isStructuredToolResult(obj) {
41235
41256
  var hasSummary = (res) => isStructuredToolResult(res);
41236
41257
  var isGrepResult = (res) => isStructuredToolResult(res) && "matches" in res && Array.isArray(res.matches);
41237
41258
  var isListResult = (res) => isStructuredToolResult(res) && "files" in res && Array.isArray(res.files);
41259
+ var isReadManyFilesResult = (res) => isListResult(res) && "include" in res;
41238
41260
  var isFileDiff = (res) => typeof res === "object" && res !== null && "fileDiff" in res && "fileName" in res && "filePath" in res;
41239
41261
  var ToolConfirmationOutcome;
41240
41262
  (function(ToolConfirmationOutcome2) {
@@ -41971,6 +41993,10 @@ var Storage = class _Storage {
41971
41993
  const historyDir = path6.join(_Storage.getGlobalGeminiDir(), "history");
41972
41994
  return path6.join(historyDir, identifier);
41973
41995
  }
41996
+ getProjectMemoryDir() {
41997
+ const identifier = this.getProjectIdentifier();
41998
+ return path6.join(_Storage.getGlobalGeminiDir(), "memory", identifier);
41999
+ }
41974
42000
  getWorkspaceSettingsPath() {
41975
42001
  return path6.join(this.getGeminiDir(), "settings.json");
41976
42002
  }
@@ -43168,6 +43194,7 @@ var READ_MANY_PARAM_RECURSIVE = "recursive";
43168
43194
  var READ_MANY_PARAM_USE_DEFAULT_EXCLUDES = "useDefaultExcludes";
43169
43195
  var MEMORY_TOOL_NAME = "save_memory";
43170
43196
  var MEMORY_PARAM_FACT = "fact";
43197
+ var MEMORY_PARAM_SCOPE = "scope";
43171
43198
  var GET_INTERNAL_DOCS_TOOL_NAME = "get_internal_docs";
43172
43199
  var DOCS_PARAM_PATH = "path";
43173
43200
  var ACTIVATE_SKILL_TOOL_NAME = "activate_skill";
@@ -43187,6 +43214,11 @@ var EXIT_PLAN_PARAM_PLAN_FILENAME = "plan_filename";
43187
43214
  var ENTER_PLAN_MODE_TOOL_NAME = "enter_plan_mode";
43188
43215
  var PLAN_MODE_PARAM_REASON = "reason";
43189
43216
  var PARAM_ADDITIONAL_PERMISSIONS = "additional_permissions";
43217
+ var UPDATE_TOPIC_TOOL_NAME = "update_topic";
43218
+ var UPDATE_TOPIC_DISPLAY_NAME = "Update Topic Context";
43219
+ var TOPIC_PARAM_TITLE = "title";
43220
+ var TOPIC_PARAM_SUMMARY = "summary";
43221
+ var TOPIC_PARAM_STRATEGIC_INTENT = "strategic_intent";
43190
43222
 
43191
43223
  // packages/core/dist/src/tools/definitions/dynamic-declaration-helpers.js
43192
43224
  import * as os4 from "node:os";
@@ -48605,7 +48637,7 @@ function getShellDeclaration(enableInteractiveShell, enableEfficiency, enableToo
48605
48637
  function getExitPlanModeDeclaration() {
48606
48638
  return {
48607
48639
  name: EXIT_PLAN_MODE_TOOL_NAME,
48608
- description: "Finalizes the planning phase and transitions to implementation by presenting the plan for user approval. This tool MUST be used to exit Plan Mode before any source code edits can be performed. Call this whenever a plan is ready or the user requests implementation.",
48640
+ description: "Finalizes the planning phase and transitions to implementation by presenting the plan for formal user approval. You MUST reach an informal agreement with the user in the chat regarding the proposed strategy BEFORE calling this tool. This tool MUST be used to exit Plan Mode before any source code edits can be performed.",
48609
48641
  parametersJsonSchema: {
48610
48642
  type: "object",
48611
48643
  required: [EXIT_PLAN_PARAM_PLAN_FILENAME],
@@ -48636,6 +48668,30 @@ function getActivateSkillDeclaration(skillNames) {
48636
48668
  parametersJsonSchema: zodToJsonSchema(schema)
48637
48669
  };
48638
48670
  }
48671
+ function getUpdateTopicDeclaration() {
48672
+ return {
48673
+ name: UPDATE_TOPIC_TOOL_NAME,
48674
+ description: "Manages your narrative flow. Include `title` and `summary` only when starting a new Chapter (logical phase) or shifting strategic intent.",
48675
+ parametersJsonSchema: {
48676
+ type: "object",
48677
+ properties: {
48678
+ [TOPIC_PARAM_TITLE]: {
48679
+ type: "string",
48680
+ description: "The title of the new topic or chapter."
48681
+ },
48682
+ [TOPIC_PARAM_SUMMARY]: {
48683
+ type: "string",
48684
+ description: "(OPTIONAL) A detailed summary (5-10 sentences) covering both the work completed in the previous topic and the strategic intent of the new topic. This is required when transitioning between topics to maintain continuity."
48685
+ },
48686
+ [TOPIC_PARAM_STRATEGIC_INTENT]: {
48687
+ type: "string",
48688
+ description: "A mandatory one-sentence statement of your immediate intent."
48689
+ }
48690
+ },
48691
+ required: [TOPIC_PARAM_STRATEGIC_INTENT]
48692
+ }
48693
+ };
48694
+ }
48639
48695
 
48640
48696
  // packages/core/dist/src/tools/definitions/model-family-sets/default-legacy.js
48641
48697
  var DEFAULT_LEGACY_SET = {
@@ -49005,19 +49061,24 @@ Use this tool when the user's query implies needing the content of several files
49005
49061
  save_memory: {
49006
49062
  name: MEMORY_TOOL_NAME,
49007
49063
  description: `
49008
- Saves concise global user context (preferences, facts) for use across ALL workspaces.
49064
+ Saves concise user context (preferences, facts) for use across future sessions.
49009
49065
 
49010
- ### CRITICAL: GLOBAL CONTEXT ONLY
49011
- NEVER save workspace-specific context, local paths, or commands (e.g. "The entry point is src/index.js", "The test command is npm test"). These are local to the current workspace and must NOT be saved globally. EXCLUSIVELY for context relevant across ALL workspaces.
49066
+ Supports two scopes:
49067
+ - **global** (default): Cross-project preferences loaded in every workspace. Use for "Remember X" or clear personal facts.
49068
+ - **project**: Facts specific to the current workspace, private to the user (not committed to the repo). Use for local dev setup notes, project-specific workflows, or personal reminders about this codebase.
49012
49069
 
49013
- - Use for "Remember X" or clear personal facts.
49014
- - Do NOT use for session context.`,
49070
+ Do NOT use for session-specific context or temporary data.`,
49015
49071
  parametersJsonSchema: {
49016
49072
  type: "object",
49017
49073
  properties: {
49018
49074
  [MEMORY_PARAM_FACT]: {
49019
49075
  type: "string",
49020
49076
  description: "The specific fact or piece of information to remember. Should be a clear, self-contained statement."
49077
+ },
49078
+ [MEMORY_PARAM_SCOPE]: {
49079
+ type: "string",
49080
+ enum: ["global", "project"],
49081
+ description: "Where to save the memory. 'global' (default) saves to a file loaded in every workspace. 'project' saves to a project-specific file private to the user, not committed to the repo."
49021
49082
  }
49022
49083
  },
49023
49084
  required: [MEMORY_PARAM_FACT],
@@ -49571,13 +49632,18 @@ Use this tool when the user's query implies needing the content of several files
49571
49632
  },
49572
49633
  save_memory: {
49573
49634
  name: MEMORY_TOOL_NAME,
49574
- description: `Persists global preferences or facts across ALL future sessions. Use this for recurring instructions like coding styles or tool aliases. Unlike '${WRITE_FILE_TOOL_NAME}', which is for project-specific files, this appends to a global memory file loaded in every workspace. If you are unsure whether a fact should be remembered globally, ask the user first. CRITICAL: Do not use for session-specific context or temporary data.`,
49635
+ description: `Persists preferences or facts across ALL future sessions. Supports two scopes: 'global' (default) for cross-project preferences loaded in every workspace, and 'project' for facts specific to the current workspace that are private to the user (not committed to the repo). Use 'project' scope for things like local dev setup notes, project-specific workflows, or personal reminders about this codebase. CRITICAL: Do not use for session-specific context or temporary data.`,
49575
49636
  parametersJsonSchema: {
49576
49637
  type: "object",
49577
49638
  properties: {
49578
49639
  [MEMORY_PARAM_FACT]: {
49579
49640
  type: "string",
49580
- description: "A concise, global fact or preference (e.g., 'I prefer using tabs'). Do not include local paths or project-specific names."
49641
+ description: "A concise fact or preference to remember. Should be a clear, self-contained statement."
49642
+ },
49643
+ [MEMORY_PARAM_SCOPE]: {
49644
+ type: "string",
49645
+ enum: ["global", "project"],
49646
+ description: "Where to save the memory. 'global' (default) saves to a file loaded in every workspace. 'project' saves to a project-specific file private to the user, not committed to the repo."
49581
49647
  }
49582
49648
  },
49583
49649
  required: [MEMORY_PARAM_FACT],
@@ -49780,7 +49846,8 @@ The agent did not use the todo list because this task could be completed by a ti
49780
49846
  }
49781
49847
  },
49782
49848
  exit_plan_mode: () => getExitPlanModeDeclaration(),
49783
- activate_skill: (skillNames) => getActivateSkillDeclaration(skillNames)
49849
+ activate_skill: (skillNames) => getActivateSkillDeclaration(skillNames),
49850
+ update_topic: getUpdateTopicDeclaration()
49784
49851
  };
49785
49852
 
49786
49853
  // packages/core/dist/src/tools/definitions/coreTools.js
@@ -50359,7 +50426,8 @@ var ALL_BUILTIN_TOOL_NAMES = [
50359
50426
  TRACKER_VISUALIZE_TOOL_NAME,
50360
50427
  GET_INTERNAL_DOCS_TOOL_NAME,
50361
50428
  ENTER_PLAN_MODE_TOOL_NAME,
50362
- EXIT_PLAN_MODE_TOOL_NAME
50429
+ EXIT_PLAN_MODE_TOOL_NAME,
50430
+ UPDATE_TOPIC_TOOL_NAME
50363
50431
  ];
50364
50432
  var PLAN_MODE_TOOLS = [
50365
50433
  GLOB_TOOL_NAME,
@@ -50370,6 +50438,7 @@ var PLAN_MODE_TOOLS = [
50370
50438
  ASK_USER_TOOL_NAME,
50371
50439
  ACTIVATE_SKILL_TOOL_NAME,
50372
50440
  GET_INTERNAL_DOCS_TOOL_NAME,
50441
+ UPDATE_TOPIC_TOOL_NAME,
50373
50442
  "codebase_investigator",
50374
50443
  "cli_help"
50375
50444
  ];
@@ -50455,6 +50524,9 @@ function getAllGeminiMdFilenames() {
50455
50524
  function getGlobalMemoryFilePath() {
50456
50525
  return path7.join(Storage.getGlobalGeminiDir(), getCurrentGeminiMdFilename());
50457
50526
  }
50527
+ function getProjectMemoryFilePath(storage) {
50528
+ return path7.join(storage.getProjectMemoryDir(), getCurrentGeminiMdFilename());
50529
+ }
50458
50530
  function ensureNewlineSeparation(currentContent) {
50459
50531
  if (currentContent.length === 0)
50460
50532
  return "";
@@ -50464,9 +50536,9 @@ function ensureNewlineSeparation(currentContent) {
50464
50536
  return "\n";
50465
50537
  return "\n\n";
50466
50538
  }
50467
- async function readMemoryFileContent() {
50539
+ async function readMemoryFileContent(filePath) {
50468
50540
  try {
50469
- return await fs8.readFile(getGlobalMemoryFilePath(), "utf-8");
50541
+ return await fs8.readFile(filePath, "utf-8");
50470
50542
  } catch (err) {
50471
50543
  const error = err;
50472
50544
  if (!(error instanceof Error) || error.code !== "ENOENT")
@@ -50503,20 +50575,28 @@ ${afterSectionMarker}`.trimEnd() + "\n";
50503
50575
  var MemoryToolInvocation = class _MemoryToolInvocation extends BaseToolInvocation {
50504
50576
  static allowlist = /* @__PURE__ */ new Set();
50505
50577
  proposedNewContent;
50506
- constructor(params, messageBus, toolName, displayName) {
50578
+ storage;
50579
+ constructor(params, messageBus, toolName, displayName, storage) {
50507
50580
  super(params, messageBus, toolName, displayName);
50581
+ this.storage = storage;
50582
+ }
50583
+ getMemoryFilePath() {
50584
+ if (this.params.scope === "project" && this.storage) {
50585
+ return getProjectMemoryFilePath(this.storage);
50586
+ }
50587
+ return getGlobalMemoryFilePath();
50508
50588
  }
50509
50589
  getDescription() {
50510
- const memoryFilePath = getGlobalMemoryFilePath();
50590
+ const memoryFilePath = this.getMemoryFilePath();
50511
50591
  return `in ${tildeifyPath(memoryFilePath)}`;
50512
50592
  }
50513
50593
  async getConfirmationDetails(_abortSignal) {
50514
- const memoryFilePath = getGlobalMemoryFilePath();
50594
+ const memoryFilePath = this.getMemoryFilePath();
50515
50595
  const allowlistKey = memoryFilePath;
50516
50596
  if (_MemoryToolInvocation.allowlist.has(allowlistKey)) {
50517
50597
  return false;
50518
50598
  }
50519
- const currentContent = await readMemoryFileContent();
50599
+ const currentContent = await readMemoryFileContent(memoryFilePath);
50520
50600
  const { fact, modified_by_user, modified_content } = this.params;
50521
50601
  const contentForDiff = modified_by_user && modified_content !== void 0 ? modified_content : computeNewContent(currentContent, fact);
50522
50602
  this.proposedNewContent = contentForDiff;
@@ -50540,6 +50620,7 @@ var MemoryToolInvocation = class _MemoryToolInvocation extends BaseToolInvocatio
50540
50620
  }
50541
50621
  async execute(_signal) {
50542
50622
  const { fact, modified_by_user, modified_content } = this.params;
50623
+ const memoryFilePath = this.getMemoryFilePath();
50543
50624
  try {
50544
50625
  let contentToWrite;
50545
50626
  let successMessage;
@@ -50549,16 +50630,16 @@ var MemoryToolInvocation = class _MemoryToolInvocation extends BaseToolInvocatio
50549
50630
  successMessage = `Okay, I've updated the memory file with your modifications.`;
50550
50631
  } else {
50551
50632
  if (this.proposedNewContent === void 0) {
50552
- const currentContent = await readMemoryFileContent();
50633
+ const currentContent = await readMemoryFileContent(memoryFilePath);
50553
50634
  this.proposedNewContent = computeNewContent(currentContent, fact);
50554
50635
  }
50555
50636
  contentToWrite = this.proposedNewContent;
50556
50637
  successMessage = `Okay, I've remembered that: "${sanitizedFact}"`;
50557
50638
  }
50558
- await fs8.mkdir(path7.dirname(getGlobalMemoryFilePath()), {
50639
+ await fs8.mkdir(path7.dirname(memoryFilePath), {
50559
50640
  recursive: true
50560
50641
  });
50561
- await fs8.writeFile(getGlobalMemoryFilePath(), contentToWrite, "utf-8");
50642
+ await fs8.writeFile(memoryFilePath, contentToWrite, "utf-8");
50562
50643
  return {
50563
50644
  llmContent: JSON.stringify({
50564
50645
  success: true,
@@ -50584,27 +50665,39 @@ var MemoryToolInvocation = class _MemoryToolInvocation extends BaseToolInvocatio
50584
50665
  };
50585
50666
  var MemoryTool = class _MemoryTool extends BaseDeclarativeTool {
50586
50667
  static Name = MEMORY_TOOL_NAME;
50587
- constructor(messageBus) {
50668
+ storage;
50669
+ constructor(messageBus, storage) {
50588
50670
  super(_MemoryTool.Name, "SaveMemory", MEMORY_DEFINITION.base.description, Kind.Think, MEMORY_DEFINITION.base.parametersJsonSchema, messageBus, true, false);
50671
+ this.storage = storage;
50672
+ }
50673
+ resolveMemoryFilePath(params) {
50674
+ if (params.scope === "project" && this.storage) {
50675
+ return getProjectMemoryFilePath(this.storage);
50676
+ }
50677
+ return getGlobalMemoryFilePath();
50589
50678
  }
50590
50679
  validateToolParamValues(params) {
50591
50680
  if (params.fact.trim() === "") {
50592
50681
  return 'Parameter "fact" must be a non-empty string.';
50593
50682
  }
50683
+ if (params.scope === "project" && !this.storage) {
50684
+ return "Project-level memory is not available: storage is not initialized.";
50685
+ }
50594
50686
  return null;
50595
50687
  }
50596
50688
  createInvocation(params, messageBus, toolName, displayName) {
50597
- return new MemoryToolInvocation(params, messageBus, toolName ?? this.name, displayName ?? this.displayName);
50689
+ return new MemoryToolInvocation(params, messageBus, toolName ?? this.name, displayName ?? this.displayName, this.storage);
50598
50690
  }
50599
50691
  getSchema(modelId) {
50600
50692
  return resolveToolDeclaration(MEMORY_DEFINITION, modelId);
50601
50693
  }
50602
50694
  getModifyContext(_abortSignal) {
50603
50695
  return {
50604
- getFilePath: (_params) => getGlobalMemoryFilePath(),
50605
- getCurrentContent: async (_params) => readMemoryFileContent(),
50696
+ getFilePath: (params) => this.resolveMemoryFilePath(params),
50697
+ getCurrentContent: async (params) => readMemoryFileContent(this.resolveMemoryFilePath(params)),
50606
50698
  getProposedContent: async (params) => {
50607
- const currentContent = await readMemoryFileContent();
50699
+ const filePath = this.resolveMemoryFilePath(params);
50700
+ const currentContent = await readMemoryFileContent(filePath);
50608
50701
  const { fact, modified_by_user, modified_content } = params;
50609
50702
  return modified_by_user && modified_content !== void 0 ? modified_content : computeNewContent(currentContent, fact);
50610
50703
  },
@@ -50628,14 +50721,22 @@ var logger2 = {
50628
50721
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
50629
50722
  error: (...args) => debugLogger.error("[ERROR] [ImportProcessor]", ...args)
50630
50723
  };
50631
- async function findProjectRoot(startDir) {
50724
+ async function findProjectRoot(startDir, boundaryMarkers = [".git"]) {
50725
+ if (boundaryMarkers.length === 0) {
50726
+ return path8.resolve(startDir);
50727
+ }
50632
50728
  let currentDir = path8.resolve(startDir);
50633
50729
  while (true) {
50634
- const gitPath = path8.join(currentDir, ".git");
50635
- try {
50636
- await fs9.access(gitPath);
50637
- return currentDir;
50638
- } catch {
50730
+ for (const marker of boundaryMarkers) {
50731
+ if (path8.isAbsolute(marker) || marker.includes("..")) {
50732
+ continue;
50733
+ }
50734
+ const markerPath = path8.join(currentDir, marker);
50735
+ try {
50736
+ await fs9.access(markerPath);
50737
+ return currentDir;
50738
+ } catch {
50739
+ }
50639
50740
  }
50640
50741
  const parentDir = path8.dirname(currentDir);
50641
50742
  if (parentDir === currentDir) {
@@ -50697,9 +50798,9 @@ async function processImports(content, basePath, debugMode = false, importState
50697
50798
  processedFiles: /* @__PURE__ */ new Set(),
50698
50799
  maxDepth: 5,
50699
50800
  currentDepth: 0
50700
- }, projectRoot, importFormat = "tree") {
50801
+ }, projectRoot, importFormat = "tree", boundaryMarkers = [".git"]) {
50701
50802
  if (!projectRoot) {
50702
- projectRoot = await findProjectRoot(basePath);
50803
+ projectRoot = await findProjectRoot(basePath, boundaryMarkers);
50703
50804
  }
50704
50805
  if (importState.currentDepth >= importState.maxDepth) {
50705
50806
  if (debugMode) {
@@ -50786,7 +50887,7 @@ ${f.content.trim()}
50786
50887
  currentFile: fullPath
50787
50888
  };
50788
50889
  newImportState.processedFiles.add(fullPath);
50789
- const imported = await processImports(fileContent, path8.dirname(fullPath), debugMode, newImportState, projectRoot, importFormat);
50890
+ const imported = await processImports(fileContent, path8.dirname(fullPath), debugMode, newImportState, projectRoot, importFormat, boundaryMarkers);
50790
50891
  result += `<!-- Imported from: ${importPath} -->
50791
50892
  ${imported.content}
50792
50893
  <!-- End of import from: ${importPath} -->`;
@@ -51189,48 +51290,57 @@ function getErrorMessage(error) {
51189
51290
  function getErrorType(error) {
51190
51291
  if (!(error instanceof Error))
51191
51292
  return "unknown";
51192
- return error.name === "Error" ? error.constructor?.name ?? "Error" : error.name;
51293
+ const name = error.name && error.name !== "Error" ? error.name : error.constructor?.name ?? "Error";
51294
+ return name.replace(/^_+/, "");
51193
51295
  }
51194
51296
  var FatalError = class extends Error {
51195
51297
  exitCode;
51196
51298
  constructor(message, exitCode) {
51197
51299
  super(message);
51198
51300
  this.exitCode = exitCode;
51301
+ this.name = "FatalError";
51199
51302
  }
51200
51303
  };
51201
51304
  var FatalAuthenticationError = class extends FatalError {
51202
51305
  constructor(message) {
51203
51306
  super(message, 41);
51307
+ this.name = "FatalAuthenticationError";
51204
51308
  }
51205
51309
  };
51206
51310
  var FatalInputError = class extends FatalError {
51207
51311
  constructor(message) {
51208
51312
  super(message, 42);
51313
+ this.name = "FatalInputError";
51209
51314
  }
51210
51315
  };
51211
51316
  var FatalSandboxError = class extends FatalError {
51212
51317
  constructor(message) {
51213
51318
  super(message, 44);
51319
+ this.name = "FatalSandboxError";
51214
51320
  }
51215
51321
  };
51216
51322
  var FatalConfigError = class extends FatalError {
51217
51323
  constructor(message) {
51218
51324
  super(message, 52);
51325
+ this.name = "FatalConfigError";
51219
51326
  }
51220
51327
  };
51221
51328
  var FatalTurnLimitedError = class extends FatalError {
51222
51329
  constructor(message) {
51223
51330
  super(message, 53);
51331
+ this.name = "FatalTurnLimitedError";
51224
51332
  }
51225
51333
  };
51226
51334
  var FatalToolExecutionError = class extends FatalError {
51227
51335
  constructor(message) {
51228
51336
  super(message, 54);
51337
+ this.name = "FatalToolExecutionError";
51229
51338
  }
51230
51339
  };
51231
51340
  var FatalCancellationError = class extends FatalError {
51232
51341
  constructor(message) {
51233
51342
  super(message, 130);
51343
+ this.name = "FatalCancellationError";
51234
51344
  }
51235
51345
  };
51236
51346
  var CanceledError = class extends Error {
@@ -51240,6 +51350,10 @@ var CanceledError = class extends Error {
51240
51350
  }
51241
51351
  };
51242
51352
  var ForbiddenError = class extends Error {
51353
+ constructor(message) {
51354
+ super(message);
51355
+ this.name = "ForbiddenError";
51356
+ }
51243
51357
  };
51244
51358
  var AccountSuspendedError = class extends ForbiddenError {
51245
51359
  appealUrl;
@@ -51252,8 +51366,16 @@ var AccountSuspendedError = class extends ForbiddenError {
51252
51366
  }
51253
51367
  };
51254
51368
  var UnauthorizedError = class extends Error {
51369
+ constructor(message) {
51370
+ super(message);
51371
+ this.name = "UnauthorizedError";
51372
+ }
51255
51373
  };
51256
51374
  var BadRequestError = class extends Error {
51375
+ constructor(message) {
51376
+ super(message);
51377
+ this.name = "BadRequestError";
51378
+ }
51257
51379
  };
51258
51380
  var ChangeAuthRequestedError = class extends Error {
51259
51381
  constructor() {
@@ -51330,7 +51452,7 @@ function isAuthenticationError(error) {
51330
51452
  return true;
51331
51453
  }
51332
51454
  }
51333
- if (error instanceof Error && error.constructor.name === "UnauthorizedError") {
51455
+ if (error instanceof Error && error.name === "UnauthorizedError") {
51334
51456
  return true;
51335
51457
  }
51336
51458
  if (error instanceof UnauthorizedError) {
@@ -51416,23 +51538,31 @@ async function deduplicatePathsByFileIdentity(filePaths) {
51416
51538
  identityMap: pathToIdentityMap
51417
51539
  };
51418
51540
  }
51419
- async function findProjectRoot2(startDir) {
51541
+ async function findProjectRoot2(startDir, boundaryMarkers = [".git"]) {
51542
+ if (boundaryMarkers.length === 0) {
51543
+ return null;
51544
+ }
51420
51545
  let currentDir = normalizePath(startDir);
51421
51546
  while (true) {
51422
- const gitPath = path9.join(currentDir, ".git");
51423
- try {
51424
- await fs10.access(gitPath);
51425
- return currentDir;
51426
- } catch (error) {
51427
- const isENOENT = typeof error === "object" && error !== null && "code" in error && // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
51428
- error.code === "ENOENT";
51429
- const isTestEnv = process.env["NODE_ENV"] === "test" || process.env["VITEST"];
51430
- if (!isENOENT && !isTestEnv) {
51431
- if (typeof error === "object" && error !== null && "code" in error) {
51432
- const fsError = error;
51433
- logger3.warn(`Error checking for .git at ${gitPath}: ${fsError.message}`);
51434
- } else {
51435
- logger3.warn(`Non-standard error checking for .git at ${gitPath}: ${String(error)}`);
51547
+ for (const marker of boundaryMarkers) {
51548
+ if (path9.isAbsolute(marker) || marker.includes("..")) {
51549
+ continue;
51550
+ }
51551
+ const markerPath = path9.join(currentDir, marker);
51552
+ try {
51553
+ await fs10.access(markerPath);
51554
+ return currentDir;
51555
+ } catch (error) {
51556
+ const isENOENT = typeof error === "object" && error !== null && "code" in error && // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
51557
+ error.code === "ENOENT";
51558
+ const isTestEnv = process.env["NODE_ENV"] === "test" || process.env["VITEST"];
51559
+ if (!isENOENT && !isTestEnv) {
51560
+ if (typeof error === "object" && error !== null && "code" in error) {
51561
+ const fsError = error;
51562
+ logger3.warn(`Error checking for ${marker} at ${markerPath}: ${fsError.message}`);
51563
+ } else {
51564
+ logger3.warn(`Non-standard error checking for ${marker} at ${markerPath}: ${String(error)}`);
51565
+ }
51436
51566
  }
51437
51567
  }
51438
51568
  }
@@ -51443,7 +51573,7 @@ async function findProjectRoot2(startDir) {
51443
51573
  currentDir = parentDir;
51444
51574
  }
51445
51575
  }
51446
- async function getGeminiMdFilePathsInternal(currentWorkingDirectory, includeDirectoriesToReadGemini, userHomePath, fileService, folderTrust, fileFilteringOptions, maxDirs) {
51576
+ async function getGeminiMdFilePathsInternal(currentWorkingDirectory, includeDirectoriesToReadGemini, userHomePath, fileService, folderTrust, fileFilteringOptions, maxDirs, boundaryMarkers = [".git"]) {
51447
51577
  const dirs = /* @__PURE__ */ new Set([
51448
51578
  ...includeDirectoriesToReadGemini,
51449
51579
  currentWorkingDirectory
@@ -51454,7 +51584,7 @@ async function getGeminiMdFilePathsInternal(currentWorkingDirectory, includeDire
51454
51584
  const projectPaths = /* @__PURE__ */ new Set();
51455
51585
  for (let i = 0; i < dirsArray.length; i += CONCURRENT_LIMIT) {
51456
51586
  const batch = dirsArray.slice(i, i + CONCURRENT_LIMIT);
51457
- const batchPromises = batch.map((dir) => getGeminiMdFilePathsInternalForEachDir(dir, userHomePath, fileService, folderTrust, fileFilteringOptions, maxDirs));
51587
+ const batchPromises = batch.map((dir) => getGeminiMdFilePathsInternalForEachDir(dir, userHomePath, fileService, folderTrust, fileFilteringOptions, maxDirs, boundaryMarkers));
51458
51588
  const batchResults = await Promise.allSettled(batchPromises);
51459
51589
  for (const result of batchResults) {
51460
51590
  if (result.status === "fulfilled") {
@@ -51472,7 +51602,7 @@ async function getGeminiMdFilePathsInternal(currentWorkingDirectory, includeDire
51472
51602
  project: Array.from(projectPaths)
51473
51603
  };
51474
51604
  }
51475
- async function getGeminiMdFilePathsInternalForEachDir(dir, userHomePath, fileService, folderTrust, fileFilteringOptions, maxDirs) {
51605
+ async function getGeminiMdFilePathsInternalForEachDir(dir, userHomePath, fileService, folderTrust, fileFilteringOptions, maxDirs, boundaryMarkers = [".git"]) {
51476
51606
  const globalPaths = /* @__PURE__ */ new Set();
51477
51607
  const projectPaths = /* @__PURE__ */ new Set();
51478
51608
  const geminiMdFilenames = getAllGeminiMdFilenames();
@@ -51489,7 +51619,7 @@ async function getGeminiMdFilePathsInternalForEachDir(dir, userHomePath, fileSer
51489
51619
  if (dir && folderTrust) {
51490
51620
  const resolvedCwd = normalizePath(dir);
51491
51621
  debugLogger.debug("[DEBUG] [MemoryDiscovery] Searching for", geminiMdFilename, "starting from CWD:", resolvedCwd);
51492
- const projectRoot = await findProjectRoot2(resolvedCwd);
51622
+ const projectRoot = await findProjectRoot2(resolvedCwd, boundaryMarkers);
51493
51623
  debugLogger.debug("[DEBUG] [MemoryDiscovery] Determined project root:", projectRoot ?? "None");
51494
51624
  const upwardPaths = [];
51495
51625
  let currentDir = resolvedCwd;
@@ -51533,7 +51663,7 @@ async function getGeminiMdFilePathsInternalForEachDir(dir, userHomePath, fileSer
51533
51663
  project: Array.from(projectPaths)
51534
51664
  };
51535
51665
  }
51536
- async function readGeminiMdFiles(filePaths, importFormat = "tree") {
51666
+ async function readGeminiMdFiles(filePaths, importFormat = "tree", boundaryMarkers = [".git"]) {
51537
51667
  const CONCURRENT_LIMIT = 20;
51538
51668
  const results = [];
51539
51669
  for (let i = 0; i < filePaths.length; i += CONCURRENT_LIMIT) {
@@ -51541,7 +51671,7 @@ async function readGeminiMdFiles(filePaths, importFormat = "tree") {
51541
51671
  const batchPromises = batch.map(async (filePath) => {
51542
51672
  try {
51543
51673
  const content = await fs10.readFile(filePath, "utf-8");
51544
- const processedResult = await processImports(content, path9.dirname(filePath), false, void 0, void 0, importFormat);
51674
+ const processedResult = await processImports(content, path9.dirname(filePath), false, void 0, void 0, importFormat, boundaryMarkers);
51545
51675
  debugLogger.debug("[DEBUG] [MemoryDiscovery] Successfully read and processed imports:", filePath, `(Length: ${processedResult.content.length})`);
51546
51676
  return { filePath, content: processedResult.content };
51547
51677
  } catch (error) {
@@ -51593,15 +51723,29 @@ async function getGlobalMemoryPaths() {
51593
51723
  });
51594
51724
  return (await Promise.all(accessChecks)).filter((p) => p !== null);
51595
51725
  }
51726
+ async function getUserProjectMemoryPaths(projectMemoryDir) {
51727
+ const geminiMdFilenames = getAllGeminiMdFilenames();
51728
+ const accessChecks = geminiMdFilenames.map(async (filename) => {
51729
+ const memoryPath = normalizePath(path9.join(projectMemoryDir, filename));
51730
+ try {
51731
+ await fs10.access(memoryPath, fsSync2.constants.R_OK);
51732
+ debugLogger.debug("[DEBUG] [MemoryDiscovery] Found user project memory file:", memoryPath);
51733
+ return memoryPath;
51734
+ } catch {
51735
+ return null;
51736
+ }
51737
+ });
51738
+ return (await Promise.all(accessChecks)).filter((p) => p !== null);
51739
+ }
51596
51740
  function getExtensionMemoryPaths(extensionLoader) {
51597
51741
  const extensionPaths = extensionLoader.getExtensions().filter((ext) => ext.isActive).flatMap((ext) => ext.contextFiles).map((p) => normalizePath(p));
51598
51742
  return Array.from(new Set(extensionPaths)).sort();
51599
51743
  }
51600
- async function getEnvironmentMemoryPaths(trustedRoots) {
51744
+ async function getEnvironmentMemoryPaths(trustedRoots, boundaryMarkers = [".git"]) {
51601
51745
  const allPaths = /* @__PURE__ */ new Set();
51602
51746
  const traversalPromises = trustedRoots.map(async (root) => {
51603
51747
  const resolvedRoot = normalizePath(root);
51604
- const gitRoot = await findProjectRoot2(resolvedRoot);
51748
+ const gitRoot = await findProjectRoot2(resolvedRoot, boundaryMarkers);
51605
51749
  const ceiling = gitRoot ? normalizePath(gitRoot) : resolvedRoot;
51606
51750
  debugLogger.debug("[DEBUG] [MemoryDiscovery] Loading environment memory for trusted root:", resolvedRoot, "(Stopping at", gitRoot ? `git root: ${ceiling})` : `trusted root: ${ceiling} \u2014 no git root found)`);
51607
51751
  return findUpwardGeminiFiles(resolvedRoot, ceiling);
@@ -51615,7 +51759,8 @@ function categorizeAndConcatenate(paths, contentsMap) {
51615
51759
  return {
51616
51760
  global: getConcatenated(paths.global),
51617
51761
  extension: getConcatenated(paths.extension),
51618
- project: getConcatenated(paths.project)
51762
+ project: getConcatenated(paths.project),
51763
+ userProjectMemory: getConcatenated(paths.userProjectMemory ?? [])
51619
51764
  };
51620
51765
  }
51621
51766
  async function findUpwardGeminiFiles(startDir, stopDir) {
@@ -51648,7 +51793,7 @@ async function findUpwardGeminiFiles(startDir, stopDir) {
51648
51793
  }
51649
51794
  return upwardPaths;
51650
51795
  }
51651
- async function loadServerHierarchicalMemory(currentWorkingDirectory, includeDirectoriesToReadGemini, fileService, extensionLoader, folderTrust, importFormat = "tree", fileFilteringOptions, maxDirs = 200) {
51796
+ async function loadServerHierarchicalMemory(currentWorkingDirectory, includeDirectoriesToReadGemini, fileService, extensionLoader, folderTrust, importFormat = "tree", fileFilteringOptions, maxDirs = 200, boundaryMarkers = [".git"]) {
51652
51797
  const realCwd = normalizePath(await fs10.realpath(path9.resolve(currentWorkingDirectory)));
51653
51798
  const realHome = normalizePath(await fs10.realpath(path9.resolve(homedir())));
51654
51799
  const isHomeDirectory = realCwd === realHome;
@@ -51656,7 +51801,7 @@ async function loadServerHierarchicalMemory(currentWorkingDirectory, includeDire
51656
51801
  debugLogger.debug("[DEBUG] [MemoryDiscovery] Loading server hierarchical memory for CWD:", currentWorkingDirectory, `(importFormat: ${importFormat})`);
51657
51802
  const userHomePath = homedir();
51658
51803
  const [discoveryResult, extensionPaths] = await Promise.all([
51659
- getGeminiMdFilePathsInternal(currentWorkingDirectory, includeDirectoriesToReadGemini, userHomePath, fileService, folderTrust, fileFilteringOptions || DEFAULT_MEMORY_FILE_FILTERING_OPTIONS, maxDirs),
51804
+ getGeminiMdFilePathsInternal(currentWorkingDirectory, includeDirectoriesToReadGemini, userHomePath, fileService, folderTrust, fileFilteringOptions || DEFAULT_MEMORY_FILE_FILTERING_OPTIONS, maxDirs, boundaryMarkers),
51660
51805
  Promise.resolve(getExtensionMemoryPaths(extensionLoader))
51661
51806
  ]);
51662
51807
  const allFilePathsStringDeduped = Array.from(/* @__PURE__ */ new Set([
@@ -51681,7 +51826,7 @@ async function loadServerHierarchicalMemory(currentWorkingDirectory, includeDire
51681
51826
  filePaths: []
51682
51827
  };
51683
51828
  }
51684
- const allContents = await readGeminiMdFiles(allFilePaths, importFormat);
51829
+ const allContents = await readGeminiMdFiles(allFilePaths, importFormat, boundaryMarkers);
51685
51830
  const contentsMap = new Map(allContents.map((c) => [c.filePath, c]));
51686
51831
  const hierarchicalMemory = categorizeAndConcatenate({
51687
51832
  global: discoveryResult.global,
@@ -51695,7 +51840,7 @@ async function loadServerHierarchicalMemory(currentWorkingDirectory, includeDire
51695
51840
  };
51696
51841
  }
51697
51842
  async function refreshServerHierarchicalMemory(config) {
51698
- const result = await loadServerHierarchicalMemory(config.getWorkingDir(), config.shouldLoadMemoryFromIncludeDirectories() ? config.getWorkspaceContext().getDirectories() : [], config.getFileService(), config.getExtensionLoader(), config.isTrustedFolder(), config.getImportFormat(), config.getFileFilteringOptions(), config.getDiscoveryMaxDirs());
51843
+ const result = await loadServerHierarchicalMemory(config.getWorkingDir(), config.shouldLoadMemoryFromIncludeDirectories() ? config.getWorkspaceContext().getDirectories() : [], config.getFileService(), config.getExtensionLoader(), config.isTrustedFolder(), config.getImportFormat(), config.getFileFilteringOptions(), config.getDiscoveryMaxDirs(), config.getMemoryBoundaryMarkers());
51699
51844
  const mcpInstructions = config.getMcpClientManager()?.getMcpInstructions() || "";
51700
51845
  const finalMemory = {
51701
51846
  ...result.memoryContent,
@@ -51707,7 +51852,7 @@ async function refreshServerHierarchicalMemory(config) {
51707
51852
  coreEvents.emit(CoreEvent.MemoryChanged, { fileCount: result.fileCount });
51708
51853
  return result;
51709
51854
  }
51710
- async function loadJitSubdirectoryMemory(targetPath, trustedRoots, alreadyLoadedPaths, alreadyLoadedIdentities) {
51855
+ async function loadJitSubdirectoryMemory(targetPath, trustedRoots, alreadyLoadedPaths, alreadyLoadedIdentities, boundaryMarkers = [".git"]) {
51711
51856
  const resolvedTarget = normalizePath(targetPath);
51712
51857
  let bestRoot = null;
51713
51858
  for (const root of trustedRoots) {
@@ -51723,7 +51868,7 @@ async function loadJitSubdirectoryMemory(targetPath, trustedRoots, alreadyLoaded
51723
51868
  debugLogger.debug("[DEBUG] [MemoryDiscovery] JIT memory skipped:", resolvedTarget, "is not in any trusted root.");
51724
51869
  return { files: [], fileIdentities: [] };
51725
51870
  }
51726
- const gitRoot = await findProjectRoot2(bestRoot);
51871
+ const gitRoot = await findProjectRoot2(bestRoot, boundaryMarkers);
51727
51872
  const resolvedCeiling = gitRoot ? normalizePath(gitRoot) : bestRoot;
51728
51873
  debugLogger.debug("[DEBUG] [MemoryDiscovery] Loading JIT memory for", resolvedTarget, `(Trusted root: ${bestRoot}, Ceiling: ${resolvedCeiling}${gitRoot ? " [git root]" : " [trusted root, no git]"})`);
51729
51874
  let startDir = resolvedTarget;
@@ -51774,7 +51919,7 @@ async function loadJitSubdirectoryMemory(targetPath, trustedRoots, alreadyLoaded
51774
51919
  return { files: [], fileIdentities: [] };
51775
51920
  }
51776
51921
  debugLogger.debug("[DEBUG] [MemoryDiscovery] Found new JIT memory files:", JSON.stringify(newPaths));
51777
- const contents = await readGeminiMdFiles(newPaths, "tree");
51922
+ const contents = await readGeminiMdFiles(newPaths, "tree", boundaryMarkers);
51778
51923
  return {
51779
51924
  files: contents.filter((item) => item.content !== null).map((item) => ({
51780
51925
  path: item.filePath,
@@ -51812,16 +51957,17 @@ export {
51812
51957
  EmbedContentResponse,
51813
51958
  ApiError,
51814
51959
  GoogleGenAI,
51815
- MessageBusType,
51816
- QuestionType,
51817
51960
  PolicyDecision,
51818
51961
  getHookSource,
51819
51962
  ApprovalMode,
51963
+ MODES_BY_PERMISSIVENESS,
51820
51964
  InProcessCheckerType,
51821
51965
  PRIORITY_SUBAGENT_TOOL,
51822
51966
  ALWAYS_ALLOW_PRIORITY_FRACTION,
51823
51967
  ALWAYS_ALLOW_PRIORITY_OFFSET,
51824
51968
  PRIORITY_YOLO_ALLOW_ALL,
51969
+ MessageBusType,
51970
+ QuestionType,
51825
51971
  isBackgroundExecutionData,
51826
51972
  BaseToolInvocation,
51827
51973
  DeclarativeTool,
@@ -51832,6 +51978,7 @@ export {
51832
51978
  hasSummary,
51833
51979
  isGrepResult,
51834
51980
  isListResult,
51981
+ isReadManyFilesResult,
51835
51982
  isFileDiff,
51836
51983
  ToolConfirmationOutcome,
51837
51984
  Kind,
@@ -51958,7 +52105,13 @@ export {
51958
52105
  ENTER_PLAN_MODE_TOOL_NAME,
51959
52106
  PLAN_MODE_PARAM_REASON,
51960
52107
  PARAM_ADDITIONAL_PERMISSIONS,
52108
+ UPDATE_TOPIC_TOOL_NAME,
52109
+ UPDATE_TOPIC_DISPLAY_NAME,
52110
+ TOPIC_PARAM_TITLE,
52111
+ TOPIC_PARAM_SUMMARY,
52112
+ TOPIC_PARAM_STRATEGIC_INTENT,
51961
52113
  zodToJsonSchema,
52114
+ getUpdateTopicDeclaration,
51962
52115
  REFERENCE_CONTENT_START,
51963
52116
  REFERENCE_CONTENT_END,
51964
52117
  DEFAULT_MAX_LINES_TEXT_FILE,
@@ -52023,6 +52176,7 @@ export {
52023
52176
  getCurrentGeminiMdFilename,
52024
52177
  getAllGeminiMdFilenames,
52025
52178
  getGlobalMemoryFilePath,
52179
+ getProjectMemoryFilePath,
52026
52180
  MemoryTool,
52027
52181
  parseGoogleApiError,
52028
52182
  isNodeError,
@@ -52061,6 +52215,7 @@ export {
52061
52215
  readGeminiMdFiles,
52062
52216
  concatenateInstructions,
52063
52217
  getGlobalMemoryPaths,
52218
+ getUserProjectMemoryPaths,
52064
52219
  getExtensionMemoryPaths,
52065
52220
  getEnvironmentMemoryPaths,
52066
52221
  categorizeAndConcatenate,