@google/gemini-cli 0.36.0-preview.7 → 0.37.0-preview.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/bundle/{chunk-NYCY3Q2B.js → chunk-3TN4SOLW.js} +6652 -4181
  2. package/bundle/{chunk-S2IQOR7T.js → chunk-7UZ4Y32N.js} +214 -66
  3. package/bundle/{chunk-2RCLDWUX.js → chunk-A62NZYIK.js} +8052 -2969
  4. package/bundle/{chunk-VA3P26WZ.js → chunk-LEK5YYAR.js} +6296 -4095
  5. package/bundle/{chunk-MYI75E6G.js → chunk-R5X4CMUM.js} +233 -70
  6. package/bundle/{chunk-EHC7O4TG.js → chunk-TJ76C6AA.js} +16848 -9497
  7. package/bundle/chunk-U4FACSVX.js +30 -0
  8. package/bundle/{chunk-APAYS2LE.js → chunk-ULC3DHVX.js} +8052 -2969
  9. package/bundle/{chunk-YTGZ6CSI.js → chunk-XX7JYMTE.js} +8106 -3035
  10. package/bundle/{core-BHH4RB6L.js → core-5OME6LT4.js} +58 -4
  11. package/bundle/{dist-SWQPYLLV.js → core-CUCGSGCA.js} +58 -4
  12. package/bundle/{devtoolsService-STAWBGOY.js → devtoolsService-4FIYD6OW.js} +20 -3
  13. package/bundle/{devtoolsService-GJALET3B.js → devtoolsService-IDLWLZFQ.js} +21 -5
  14. package/bundle/{devtoolsService-4QGIZO5B.js → devtoolsService-TVWW3DBW.js} +20 -3
  15. package/bundle/{dist-YOBWJF52.js → dist-YWCADMDD.js} +58 -4
  16. package/bundle/docs/CONTRIBUTING.md +10 -7
  17. package/bundle/docs/assets/theme-tokyonight-dark.png +0 -0
  18. package/bundle/docs/changelogs/index.md +24 -0
  19. package/bundle/docs/changelogs/latest.md +366 -459
  20. package/bundle/docs/changelogs/preview.md +362 -356
  21. package/bundle/docs/cli/acp-mode.md +126 -0
  22. package/bundle/docs/cli/cli-reference.md +1 -1
  23. package/bundle/docs/cli/notifications.md +5 -5
  24. package/bundle/docs/cli/plan-mode.md +12 -8
  25. package/bundle/docs/cli/sandbox.md +1 -1
  26. package/bundle/docs/cli/settings.md +14 -13
  27. package/bundle/docs/cli/themes.md +5 -0
  28. package/bundle/docs/core/index.md +2 -2
  29. package/bundle/docs/core/subagents.md +134 -23
  30. package/bundle/docs/get-started/gemini-3.md +1 -1
  31. package/bundle/docs/get-started/index.md +127 -1
  32. package/bundle/docs/ide-integration/index.md +99 -24
  33. package/bundle/docs/index.md +0 -2
  34. package/bundle/docs/redirects.json +1 -0
  35. package/bundle/docs/reference/commands.md +1 -3
  36. package/bundle/docs/reference/configuration.md +183 -92
  37. package/bundle/docs/reference/keyboard-shortcuts.md +14 -6
  38. package/bundle/docs/reference/policy-engine.md +16 -30
  39. package/bundle/docs/reference/tools.md +56 -23
  40. package/bundle/docs/resources/quota-and-pricing.md +23 -9
  41. package/bundle/docs/sidebar.json +11 -4
  42. package/bundle/docs/tools/planning.md +6 -4
  43. package/bundle/events-CLX3JQHP.js +12 -0
  44. package/bundle/gemini.js +342 -52
  45. package/bundle/{interactiveCli-YJFA3P4G.js → interactiveCli-4WFWOVAQ.js} +5079 -4022
  46. package/bundle/{interactiveCli-MEBWWWE7.js → interactiveCli-4ZZ72DR3.js} +5079 -4022
  47. package/bundle/{interactiveCli-B6Y3UISW.js → interactiveCli-6SIGBRWS.js} +5292 -4252
  48. package/bundle/{memoryDiscovery-BQGYT4OD.js → memoryDiscovery-NS2EGHYH.js} +3 -1
  49. package/bundle/{memoryDiscovery-FCEPFZ3M.js → memoryDiscovery-VL3OH25S.js} +3 -1
  50. package/bundle/node_modules/@google/gemini-cli-devtools/dist/client/main.js +26 -19
  51. package/bundle/node_modules/@google/gemini-cli-devtools/dist/src/_client-assets.d.ts +1 -1
  52. package/bundle/node_modules/@google/gemini-cli-devtools/dist/src/_client-assets.js +1 -1
  53. package/bundle/node_modules/@google/gemini-cli-devtools/dist/src/_client-assets.js.map +1 -1
  54. package/bundle/node_modules/@google/gemini-cli-devtools/dist/src/index.js +35 -1
  55. package/bundle/node_modules/@google/gemini-cli-devtools/dist/src/index.js.map +1 -1
  56. package/bundle/node_modules/@google/gemini-cli-devtools/package.json +1 -1
  57. package/bundle/{oauth2-provider-TIKPJAVU.js → oauth2-provider-HGHECKPY.js} +2 -2
  58. package/bundle/{oauth2-provider-IGY3DL3D.js → oauth2-provider-TYBJKXSJ.js} +2 -2
  59. package/bundle/{oauth2-provider-DLPX23GY.js → oauth2-provider-YYRJ44X5.js} +73 -39
  60. package/bundle/policies/discovered.toml +7 -0
  61. package/bundle/policies/non-interactive.toml +7 -0
  62. package/bundle/policies/plan.toml +25 -0
  63. package/bundle/policies/read-only.toml +6 -0
  64. package/bundle/policies/sandbox-default.toml +3 -2
  65. package/bundle/policies/write.toml +21 -0
  66. package/bundle/policies/yolo.toml +1 -1
  67. package/package.json +1 -1
  68. package/bundle/chunk-GDBDMLKR.js +0 -354180
  69. package/bundle/chunk-QTVUHTZR.js +0 -93293
  70. package/bundle/devtoolsService-Q6LGZKTJ.js +0 -854
  71. package/bundle/dist-YHAAIIZP.js +0 -1886
  72. package/bundle/docs/get-started/examples.md +0 -141
  73. package/bundle/interactiveCli-HYY2W6AF.js +0 -49298
  74. package/bundle/oauth2-provider-MKUXMD5I.js +0 -237
@@ -40796,6 +40796,7 @@ var MessageBusType = /* @__PURE__ */ ((MessageBusType2) => {
40796
40796
  MessageBusType2["TOOL_CALLS_UPDATE"] = "tool-calls-update";
40797
40797
  MessageBusType2["ASK_USER_REQUEST"] = "ask-user-request";
40798
40798
  MessageBusType2["ASK_USER_RESPONSE"] = "ask-user-response";
40799
+ MessageBusType2["SUBAGENT_ACTIVITY"] = "subagent-activity";
40799
40800
  return MessageBusType2;
40800
40801
  })(MessageBusType || {});
40801
40802
  var QuestionType = /* @__PURE__ */ ((QuestionType2) => {
@@ -41012,6 +41013,11 @@ var BaseToolInvocation = class {
41012
41013
  }
41013
41014
  });
41014
41015
  }
41016
+ toJSON() {
41017
+ return {
41018
+ params: this.params
41019
+ };
41020
+ }
41015
41021
  };
41016
41022
  var DeclarativeTool = class {
41017
41023
  constructor(name, displayName, description, kind, parameterSchema, messageBus, isOutputMarkdown = true, canUpdateOutput = false, extensionName, extensionId) {
@@ -41041,6 +41047,15 @@ var DeclarativeTool = class {
41041
41047
  }
41042
41048
  return cloned;
41043
41049
  }
41050
+ toJSON() {
41051
+ return {
41052
+ name: this.name,
41053
+ displayName: this.displayName,
41054
+ description: this.description,
41055
+ kind: this.kind,
41056
+ parameterSchema: this.parameterSchema
41057
+ };
41058
+ }
41044
41059
  get isReadOnly() {
41045
41060
  return READ_ONLY_KINDS.includes(this.kind);
41046
41061
  }
@@ -41261,6 +41276,7 @@ function isStructuredToolResult(obj) {
41261
41276
  var hasSummary = (res) => isStructuredToolResult(res);
41262
41277
  var isGrepResult = (res) => isStructuredToolResult(res) && "matches" in res && Array.isArray(res.matches);
41263
41278
  var isListResult = (res) => isStructuredToolResult(res) && "files" in res && Array.isArray(res.files);
41279
+ var isReadManyFilesResult = (res) => isListResult(res) && "include" in res;
41264
41280
  var isFileDiff = (res) => typeof res === "object" && res !== null && "fileDiff" in res && "fileName" in res && "filePath" in res;
41265
41281
  var ToolConfirmationOutcome = /* @__PURE__ */ ((ToolConfirmationOutcome2) => {
41266
41282
  ToolConfirmationOutcome2["ProceedOnce"] = "proceed_once";
@@ -42019,6 +42035,10 @@ var Storage = class _Storage {
42019
42035
  const historyDir = path6.join(_Storage.getGlobalGeminiDir(), "history");
42020
42036
  return path6.join(historyDir, identifier);
42021
42037
  }
42038
+ getProjectMemoryDir() {
42039
+ const identifier = this.getProjectIdentifier();
42040
+ return path6.join(_Storage.getGlobalGeminiDir(), "memory", identifier);
42041
+ }
42022
42042
  getWorkspaceSettingsPath() {
42023
42043
  return path6.join(this.getGeminiDir(), "settings.json");
42024
42044
  }
@@ -43247,6 +43267,7 @@ var READ_MANY_PARAM_RECURSIVE = "recursive";
43247
43267
  var READ_MANY_PARAM_USE_DEFAULT_EXCLUDES = "useDefaultExcludes";
43248
43268
  var MEMORY_TOOL_NAME = "save_memory";
43249
43269
  var MEMORY_PARAM_FACT = "fact";
43270
+ var MEMORY_PARAM_SCOPE = "scope";
43250
43271
  var GET_INTERNAL_DOCS_TOOL_NAME = "get_internal_docs";
43251
43272
  var DOCS_PARAM_PATH = "path";
43252
43273
  var ACTIVATE_SKILL_TOOL_NAME = "activate_skill";
@@ -43266,6 +43287,11 @@ var EXIT_PLAN_PARAM_PLAN_FILENAME = "plan_filename";
43266
43287
  var ENTER_PLAN_MODE_TOOL_NAME = "enter_plan_mode";
43267
43288
  var PLAN_MODE_PARAM_REASON = "reason";
43268
43289
  var PARAM_ADDITIONAL_PERMISSIONS = "additional_permissions";
43290
+ var UPDATE_TOPIC_TOOL_NAME = "update_topic";
43291
+ var UPDATE_TOPIC_DISPLAY_NAME = "Update Topic Context";
43292
+ var TOPIC_PARAM_TITLE = "title";
43293
+ var TOPIC_PARAM_SUMMARY = "summary";
43294
+ var TOPIC_PARAM_STRATEGIC_INTENT = "strategic_intent";
43269
43295
 
43270
43296
  // packages/core/src/tools/definitions/dynamic-declaration-helpers.ts
43271
43297
  import * as os4 from "node:os";
@@ -48687,7 +48713,7 @@ function getShellDeclaration(enableInteractiveShell, enableEfficiency, enableToo
48687
48713
  function getExitPlanModeDeclaration() {
48688
48714
  return {
48689
48715
  name: EXIT_PLAN_MODE_TOOL_NAME,
48690
- 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.",
48716
+ 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.",
48691
48717
  parametersJsonSchema: {
48692
48718
  type: "object",
48693
48719
  required: [EXIT_PLAN_PARAM_PLAN_FILENAME],
@@ -48718,6 +48744,30 @@ function getActivateSkillDeclaration(skillNames) {
48718
48744
  parametersJsonSchema: zodToJsonSchema(schema)
48719
48745
  };
48720
48746
  }
48747
+ function getUpdateTopicDeclaration() {
48748
+ return {
48749
+ name: UPDATE_TOPIC_TOOL_NAME,
48750
+ description: "Manages your narrative flow. Include `title` and `summary` only when starting a new Chapter (logical phase) or shifting strategic intent.",
48751
+ parametersJsonSchema: {
48752
+ type: "object",
48753
+ properties: {
48754
+ [TOPIC_PARAM_TITLE]: {
48755
+ type: "string",
48756
+ description: "The title of the new topic or chapter."
48757
+ },
48758
+ [TOPIC_PARAM_SUMMARY]: {
48759
+ type: "string",
48760
+ 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."
48761
+ },
48762
+ [TOPIC_PARAM_STRATEGIC_INTENT]: {
48763
+ type: "string",
48764
+ description: "A mandatory one-sentence statement of your immediate intent."
48765
+ }
48766
+ },
48767
+ required: [TOPIC_PARAM_STRATEGIC_INTENT]
48768
+ }
48769
+ };
48770
+ }
48721
48771
 
48722
48772
  // packages/core/src/tools/definitions/model-family-sets/default-legacy.ts
48723
48773
  var DEFAULT_LEGACY_SET = {
@@ -49091,19 +49141,24 @@ Use this tool when the user's query implies needing the content of several files
49091
49141
  save_memory: {
49092
49142
  name: MEMORY_TOOL_NAME,
49093
49143
  description: `
49094
- Saves concise global user context (preferences, facts) for use across ALL workspaces.
49144
+ Saves concise user context (preferences, facts) for use across future sessions.
49095
49145
 
49096
- ### CRITICAL: GLOBAL CONTEXT ONLY
49097
- 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.
49146
+ Supports two scopes:
49147
+ - **global** (default): Cross-project preferences loaded in every workspace. Use for "Remember X" or clear personal facts.
49148
+ - **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.
49098
49149
 
49099
- - Use for "Remember X" or clear personal facts.
49100
- - Do NOT use for session context.`,
49150
+ Do NOT use for session-specific context or temporary data.`,
49101
49151
  parametersJsonSchema: {
49102
49152
  type: "object",
49103
49153
  properties: {
49104
49154
  [MEMORY_PARAM_FACT]: {
49105
49155
  type: "string",
49106
49156
  description: "The specific fact or piece of information to remember. Should be a clear, self-contained statement."
49157
+ },
49158
+ [MEMORY_PARAM_SCOPE]: {
49159
+ type: "string",
49160
+ enum: ["global", "project"],
49161
+ 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."
49107
49162
  }
49108
49163
  },
49109
49164
  required: [MEMORY_PARAM_FACT],
@@ -49661,13 +49716,18 @@ Use this tool when the user's query implies needing the content of several files
49661
49716
  },
49662
49717
  save_memory: {
49663
49718
  name: MEMORY_TOOL_NAME,
49664
- 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.`,
49719
+ 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.`,
49665
49720
  parametersJsonSchema: {
49666
49721
  type: "object",
49667
49722
  properties: {
49668
49723
  [MEMORY_PARAM_FACT]: {
49669
49724
  type: "string",
49670
- description: "A concise, global fact or preference (e.g., 'I prefer using tabs'). Do not include local paths or project-specific names."
49725
+ description: "A concise fact or preference to remember. Should be a clear, self-contained statement."
49726
+ },
49727
+ [MEMORY_PARAM_SCOPE]: {
49728
+ type: "string",
49729
+ enum: ["global", "project"],
49730
+ 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."
49671
49731
  }
49672
49732
  },
49673
49733
  required: [MEMORY_PARAM_FACT],
@@ -49870,7 +49930,8 @@ The agent did not use the todo list because this task could be completed by a ti
49870
49930
  }
49871
49931
  },
49872
49932
  exit_plan_mode: () => getExitPlanModeDeclaration(),
49873
- activate_skill: (skillNames) => getActivateSkillDeclaration(skillNames)
49933
+ activate_skill: (skillNames) => getActivateSkillDeclaration(skillNames),
49934
+ update_topic: getUpdateTopicDeclaration()
49874
49935
  };
49875
49936
 
49876
49937
  // packages/core/src/tools/definitions/coreTools.ts
@@ -50477,7 +50538,8 @@ var ALL_BUILTIN_TOOL_NAMES = [
50477
50538
  TRACKER_VISUALIZE_TOOL_NAME,
50478
50539
  GET_INTERNAL_DOCS_TOOL_NAME,
50479
50540
  ENTER_PLAN_MODE_TOOL_NAME,
50480
- EXIT_PLAN_MODE_TOOL_NAME
50541
+ EXIT_PLAN_MODE_TOOL_NAME,
50542
+ UPDATE_TOPIC_TOOL_NAME
50481
50543
  ];
50482
50544
  var PLAN_MODE_TOOLS = [
50483
50545
  GLOB_TOOL_NAME,
@@ -50488,6 +50550,7 @@ var PLAN_MODE_TOOLS = [
50488
50550
  ASK_USER_TOOL_NAME,
50489
50551
  ACTIVATE_SKILL_TOOL_NAME,
50490
50552
  GET_INTERNAL_DOCS_TOOL_NAME,
50553
+ UPDATE_TOPIC_TOOL_NAME,
50491
50554
  "codebase_investigator",
50492
50555
  "cli_help"
50493
50556
  ];
@@ -50573,6 +50636,9 @@ function getAllGeminiMdFilenames() {
50573
50636
  function getGlobalMemoryFilePath() {
50574
50637
  return path7.join(Storage.getGlobalGeminiDir(), getCurrentGeminiMdFilename());
50575
50638
  }
50639
+ function getProjectMemoryFilePath(storage) {
50640
+ return path7.join(storage.getProjectMemoryDir(), getCurrentGeminiMdFilename());
50641
+ }
50576
50642
  function ensureNewlineSeparation(currentContent) {
50577
50643
  if (currentContent.length === 0) return "";
50578
50644
  if (currentContent.endsWith("\n\n") || currentContent.endsWith("\r\n\r\n"))
@@ -50581,9 +50647,9 @@ function ensureNewlineSeparation(currentContent) {
50581
50647
  return "\n";
50582
50648
  return "\n\n";
50583
50649
  }
50584
- async function readMemoryFileContent() {
50650
+ async function readMemoryFileContent(filePath) {
50585
50651
  try {
50586
- return await fs8.readFile(getGlobalMemoryFilePath(), "utf-8");
50652
+ return await fs8.readFile(filePath, "utf-8");
50587
50653
  } catch (err) {
50588
50654
  const error = err;
50589
50655
  if (!(error instanceof Error) || error.code !== "ENOENT") throw err;
@@ -50622,20 +50688,28 @@ ${afterSectionMarker}`.trimEnd() + "\n";
50622
50688
  var MemoryToolInvocation = class _MemoryToolInvocation extends BaseToolInvocation {
50623
50689
  static allowlist = /* @__PURE__ */ new Set();
50624
50690
  proposedNewContent;
50625
- constructor(params, messageBus, toolName, displayName) {
50691
+ storage;
50692
+ constructor(params, messageBus, toolName, displayName, storage) {
50626
50693
  super(params, messageBus, toolName, displayName);
50694
+ this.storage = storage;
50695
+ }
50696
+ getMemoryFilePath() {
50697
+ if (this.params.scope === "project" && this.storage) {
50698
+ return getProjectMemoryFilePath(this.storage);
50699
+ }
50700
+ return getGlobalMemoryFilePath();
50627
50701
  }
50628
50702
  getDescription() {
50629
- const memoryFilePath = getGlobalMemoryFilePath();
50703
+ const memoryFilePath = this.getMemoryFilePath();
50630
50704
  return `in ${tildeifyPath(memoryFilePath)}`;
50631
50705
  }
50632
50706
  async getConfirmationDetails(_abortSignal) {
50633
- const memoryFilePath = getGlobalMemoryFilePath();
50707
+ const memoryFilePath = this.getMemoryFilePath();
50634
50708
  const allowlistKey = memoryFilePath;
50635
50709
  if (_MemoryToolInvocation.allowlist.has(allowlistKey)) {
50636
50710
  return false;
50637
50711
  }
50638
- const currentContent = await readMemoryFileContent();
50712
+ const currentContent = await readMemoryFileContent(memoryFilePath);
50639
50713
  const { fact, modified_by_user, modified_content } = this.params;
50640
50714
  const contentForDiff = modified_by_user && modified_content !== void 0 ? modified_content : computeNewContent(currentContent, fact);
50641
50715
  this.proposedNewContent = contentForDiff;
@@ -50666,6 +50740,7 @@ var MemoryToolInvocation = class _MemoryToolInvocation extends BaseToolInvocatio
50666
50740
  }
50667
50741
  async execute(_signal) {
50668
50742
  const { fact, modified_by_user, modified_content } = this.params;
50743
+ const memoryFilePath = this.getMemoryFilePath();
50669
50744
  try {
50670
50745
  let contentToWrite;
50671
50746
  let successMessage;
@@ -50675,16 +50750,16 @@ var MemoryToolInvocation = class _MemoryToolInvocation extends BaseToolInvocatio
50675
50750
  successMessage = `Okay, I've updated the memory file with your modifications.`;
50676
50751
  } else {
50677
50752
  if (this.proposedNewContent === void 0) {
50678
- const currentContent = await readMemoryFileContent();
50753
+ const currentContent = await readMemoryFileContent(memoryFilePath);
50679
50754
  this.proposedNewContent = computeNewContent(currentContent, fact);
50680
50755
  }
50681
50756
  contentToWrite = this.proposedNewContent;
50682
50757
  successMessage = `Okay, I've remembered that: "${sanitizedFact}"`;
50683
50758
  }
50684
- await fs8.mkdir(path7.dirname(getGlobalMemoryFilePath()), {
50759
+ await fs8.mkdir(path7.dirname(memoryFilePath), {
50685
50760
  recursive: true
50686
50761
  });
50687
- await fs8.writeFile(getGlobalMemoryFilePath(), contentToWrite, "utf-8");
50762
+ await fs8.writeFile(memoryFilePath, contentToWrite, "utf-8");
50688
50763
  return {
50689
50764
  llmContent: JSON.stringify({
50690
50765
  success: true,
@@ -50710,7 +50785,8 @@ var MemoryToolInvocation = class _MemoryToolInvocation extends BaseToolInvocatio
50710
50785
  };
50711
50786
  var MemoryTool = class _MemoryTool extends BaseDeclarativeTool {
50712
50787
  static Name = MEMORY_TOOL_NAME;
50713
- constructor(messageBus) {
50788
+ storage;
50789
+ constructor(messageBus, storage) {
50714
50790
  super(
50715
50791
  _MemoryTool.Name,
50716
50792
  "SaveMemory",
@@ -50721,11 +50797,21 @@ var MemoryTool = class _MemoryTool extends BaseDeclarativeTool {
50721
50797
  true,
50722
50798
  false
50723
50799
  );
50800
+ this.storage = storage;
50801
+ }
50802
+ resolveMemoryFilePath(params) {
50803
+ if (params.scope === "project" && this.storage) {
50804
+ return getProjectMemoryFilePath(this.storage);
50805
+ }
50806
+ return getGlobalMemoryFilePath();
50724
50807
  }
50725
50808
  validateToolParamValues(params) {
50726
50809
  if (params.fact.trim() === "") {
50727
50810
  return 'Parameter "fact" must be a non-empty string.';
50728
50811
  }
50812
+ if (params.scope === "project" && !this.storage) {
50813
+ return "Project-level memory is not available: storage is not initialized.";
50814
+ }
50729
50815
  return null;
50730
50816
  }
50731
50817
  createInvocation(params, messageBus, toolName, displayName) {
@@ -50733,7 +50819,8 @@ var MemoryTool = class _MemoryTool extends BaseDeclarativeTool {
50733
50819
  params,
50734
50820
  messageBus,
50735
50821
  toolName ?? this.name,
50736
- displayName ?? this.displayName
50822
+ displayName ?? this.displayName,
50823
+ this.storage
50737
50824
  );
50738
50825
  }
50739
50826
  getSchema(modelId) {
@@ -50741,10 +50828,11 @@ var MemoryTool = class _MemoryTool extends BaseDeclarativeTool {
50741
50828
  }
50742
50829
  getModifyContext(_abortSignal) {
50743
50830
  return {
50744
- getFilePath: (_params) => getGlobalMemoryFilePath(),
50745
- getCurrentContent: async (_params) => readMemoryFileContent(),
50831
+ getFilePath: (params) => this.resolveMemoryFilePath(params),
50832
+ getCurrentContent: async (params) => readMemoryFileContent(this.resolveMemoryFilePath(params)),
50746
50833
  getProposedContent: async (params) => {
50747
- const currentContent = await readMemoryFileContent();
50834
+ const filePath = this.resolveMemoryFilePath(params);
50835
+ const currentContent = await readMemoryFileContent(filePath);
50748
50836
  const { fact, modified_by_user, modified_content } = params;
50749
50837
  return modified_by_user && modified_content !== void 0 ? modified_content : computeNewContent(currentContent, fact);
50750
50838
  },
@@ -50768,14 +50856,22 @@ var logger2 = {
50768
50856
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
50769
50857
  error: (...args) => debugLogger.error("[ERROR] [ImportProcessor]", ...args)
50770
50858
  };
50771
- async function findProjectRoot(startDir) {
50859
+ async function findProjectRoot(startDir, boundaryMarkers = [".git"]) {
50860
+ if (boundaryMarkers.length === 0) {
50861
+ return path8.resolve(startDir);
50862
+ }
50772
50863
  let currentDir = path8.resolve(startDir);
50773
50864
  while (true) {
50774
- const gitPath = path8.join(currentDir, ".git");
50775
- try {
50776
- await fs9.access(gitPath);
50777
- return currentDir;
50778
- } catch {
50865
+ for (const marker of boundaryMarkers) {
50866
+ if (path8.isAbsolute(marker) || marker.includes("..")) {
50867
+ continue;
50868
+ }
50869
+ const markerPath = path8.join(currentDir, marker);
50870
+ try {
50871
+ await fs9.access(markerPath);
50872
+ return currentDir;
50873
+ } catch {
50874
+ }
50779
50875
  }
50780
50876
  const parentDir = path8.dirname(currentDir);
50781
50877
  if (parentDir === currentDir) {
@@ -50836,9 +50932,9 @@ async function processImports(content, basePath, debugMode = false, importState
50836
50932
  processedFiles: /* @__PURE__ */ new Set(),
50837
50933
  maxDepth: 5,
50838
50934
  currentDepth: 0
50839
- }, projectRoot, importFormat = "tree") {
50935
+ }, projectRoot, importFormat = "tree", boundaryMarkers = [".git"]) {
50840
50936
  if (!projectRoot) {
50841
- projectRoot = await findProjectRoot(basePath);
50937
+ projectRoot = await findProjectRoot(basePath, boundaryMarkers);
50842
50938
  }
50843
50939
  if (importState.currentDepth >= importState.maxDepth) {
50844
50940
  if (debugMode) {
@@ -50944,7 +51040,8 @@ ${f.content.trim()}
50944
51040
  debugMode,
50945
51041
  newImportState,
50946
51042
  projectRoot,
50947
- importFormat
51043
+ importFormat,
51044
+ boundaryMarkers
50948
51045
  );
50949
51046
  result += `<!-- Imported from: ${importPath} -->
50950
51047
  ${imported.content}
@@ -51362,47 +51459,56 @@ function getErrorMessage(error) {
51362
51459
  }
51363
51460
  function getErrorType(error) {
51364
51461
  if (!(error instanceof Error)) return "unknown";
51365
- return error.name === "Error" ? error.constructor?.name ?? "Error" : error.name;
51462
+ const name = error.name && error.name !== "Error" ? error.name : error.constructor?.name ?? "Error";
51463
+ return name.replace(/^_+/, "");
51366
51464
  }
51367
51465
  var FatalError = class extends Error {
51368
51466
  constructor(message, exitCode) {
51369
51467
  super(message);
51370
51468
  this.exitCode = exitCode;
51469
+ this.name = "FatalError";
51371
51470
  }
51372
51471
  };
51373
51472
  var FatalAuthenticationError = class extends FatalError {
51374
51473
  constructor(message) {
51375
51474
  super(message, 41);
51475
+ this.name = "FatalAuthenticationError";
51376
51476
  }
51377
51477
  };
51378
51478
  var FatalInputError = class extends FatalError {
51379
51479
  constructor(message) {
51380
51480
  super(message, 42);
51481
+ this.name = "FatalInputError";
51381
51482
  }
51382
51483
  };
51383
51484
  var FatalSandboxError = class extends FatalError {
51384
51485
  constructor(message) {
51385
51486
  super(message, 44);
51487
+ this.name = "FatalSandboxError";
51386
51488
  }
51387
51489
  };
51388
51490
  var FatalConfigError = class extends FatalError {
51389
51491
  constructor(message) {
51390
51492
  super(message, 52);
51493
+ this.name = "FatalConfigError";
51391
51494
  }
51392
51495
  };
51393
51496
  var FatalTurnLimitedError = class extends FatalError {
51394
51497
  constructor(message) {
51395
51498
  super(message, 53);
51499
+ this.name = "FatalTurnLimitedError";
51396
51500
  }
51397
51501
  };
51398
51502
  var FatalToolExecutionError = class extends FatalError {
51399
51503
  constructor(message) {
51400
51504
  super(message, 54);
51505
+ this.name = "FatalToolExecutionError";
51401
51506
  }
51402
51507
  };
51403
51508
  var FatalCancellationError = class extends FatalError {
51404
51509
  constructor(message) {
51405
51510
  super(message, 130);
51511
+ this.name = "FatalCancellationError";
51406
51512
  }
51407
51513
  };
51408
51514
  var CanceledError = class extends Error {
@@ -51412,6 +51518,10 @@ var CanceledError = class extends Error {
51412
51518
  }
51413
51519
  };
51414
51520
  var ForbiddenError = class extends Error {
51521
+ constructor(message) {
51522
+ super(message);
51523
+ this.name = "ForbiddenError";
51524
+ }
51415
51525
  };
51416
51526
  var AccountSuspendedError = class extends ForbiddenError {
51417
51527
  appealUrl;
@@ -51424,8 +51534,16 @@ var AccountSuspendedError = class extends ForbiddenError {
51424
51534
  }
51425
51535
  };
51426
51536
  var UnauthorizedError = class extends Error {
51537
+ constructor(message) {
51538
+ super(message);
51539
+ this.name = "UnauthorizedError";
51540
+ }
51427
51541
  };
51428
51542
  var BadRequestError = class extends Error {
51543
+ constructor(message) {
51544
+ super(message);
51545
+ this.name = "BadRequestError";
51546
+ }
51429
51547
  };
51430
51548
  var ChangeAuthRequestedError = class extends Error {
51431
51549
  constructor() {
@@ -51507,7 +51625,7 @@ function isAuthenticationError(error) {
51507
51625
  return true;
51508
51626
  }
51509
51627
  }
51510
- if (error instanceof Error && error.constructor.name === "UnauthorizedError") {
51628
+ if (error instanceof Error && error.name === "UnauthorizedError") {
51511
51629
  return true;
51512
51630
  }
51513
51631
  if (error instanceof UnauthorizedError) {
@@ -51606,27 +51724,35 @@ async function deduplicatePathsByFileIdentity(filePaths) {
51606
51724
  identityMap: pathToIdentityMap
51607
51725
  };
51608
51726
  }
51609
- async function findProjectRoot2(startDir) {
51727
+ async function findProjectRoot2(startDir, boundaryMarkers = [".git"]) {
51728
+ if (boundaryMarkers.length === 0) {
51729
+ return null;
51730
+ }
51610
51731
  let currentDir = normalizePath(startDir);
51611
51732
  while (true) {
51612
- const gitPath = path9.join(currentDir, ".git");
51613
- try {
51614
- await fs10.access(gitPath);
51615
- return currentDir;
51616
- } catch (error) {
51617
- const isENOENT = typeof error === "object" && error !== null && "code" in error && // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
51618
- error.code === "ENOENT";
51619
- const isTestEnv = process.env["NODE_ENV"] === "test" || process.env["VITEST"];
51620
- if (!isENOENT && !isTestEnv) {
51621
- if (typeof error === "object" && error !== null && "code" in error) {
51622
- const fsError = error;
51623
- logger3.warn(
51624
- `Error checking for .git at ${gitPath}: ${fsError.message}`
51625
- );
51626
- } else {
51627
- logger3.warn(
51628
- `Non-standard error checking for .git at ${gitPath}: ${String(error)}`
51629
- );
51733
+ for (const marker of boundaryMarkers) {
51734
+ if (path9.isAbsolute(marker) || marker.includes("..")) {
51735
+ continue;
51736
+ }
51737
+ const markerPath = path9.join(currentDir, marker);
51738
+ try {
51739
+ await fs10.access(markerPath);
51740
+ return currentDir;
51741
+ } catch (error) {
51742
+ const isENOENT = typeof error === "object" && error !== null && "code" in error && // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
51743
+ error.code === "ENOENT";
51744
+ const isTestEnv = process.env["NODE_ENV"] === "test" || process.env["VITEST"];
51745
+ if (!isENOENT && !isTestEnv) {
51746
+ if (typeof error === "object" && error !== null && "code" in error) {
51747
+ const fsError = error;
51748
+ logger3.warn(
51749
+ `Error checking for ${marker} at ${markerPath}: ${fsError.message}`
51750
+ );
51751
+ } else {
51752
+ logger3.warn(
51753
+ `Non-standard error checking for ${marker} at ${markerPath}: ${String(error)}`
51754
+ );
51755
+ }
51630
51756
  }
51631
51757
  }
51632
51758
  }
@@ -51637,7 +51763,7 @@ async function findProjectRoot2(startDir) {
51637
51763
  currentDir = parentDir;
51638
51764
  }
51639
51765
  }
51640
- async function getGeminiMdFilePathsInternal(currentWorkingDirectory, includeDirectoriesToReadGemini, userHomePath, fileService, folderTrust, fileFilteringOptions, maxDirs) {
51766
+ async function getGeminiMdFilePathsInternal(currentWorkingDirectory, includeDirectoriesToReadGemini, userHomePath, fileService, folderTrust, fileFilteringOptions, maxDirs, boundaryMarkers = [".git"]) {
51641
51767
  const dirs = /* @__PURE__ */ new Set([
51642
51768
  ...includeDirectoriesToReadGemini,
51643
51769
  currentWorkingDirectory
@@ -51655,7 +51781,8 @@ async function getGeminiMdFilePathsInternal(currentWorkingDirectory, includeDire
51655
51781
  fileService,
51656
51782
  folderTrust,
51657
51783
  fileFilteringOptions,
51658
- maxDirs
51784
+ maxDirs,
51785
+ boundaryMarkers
51659
51786
  )
51660
51787
  );
51661
51788
  const batchResults = await Promise.allSettled(batchPromises);
@@ -51675,7 +51802,7 @@ async function getGeminiMdFilePathsInternal(currentWorkingDirectory, includeDire
51675
51802
  project: Array.from(projectPaths)
51676
51803
  };
51677
51804
  }
51678
- async function getGeminiMdFilePathsInternalForEachDir(dir, userHomePath, fileService, folderTrust, fileFilteringOptions, maxDirs) {
51805
+ async function getGeminiMdFilePathsInternalForEachDir(dir, userHomePath, fileService, folderTrust, fileFilteringOptions, maxDirs, boundaryMarkers = [".git"]) {
51679
51806
  const globalPaths = /* @__PURE__ */ new Set();
51680
51807
  const projectPaths = /* @__PURE__ */ new Set();
51681
51808
  const geminiMdFilenames = getAllGeminiMdFilenames();
@@ -51703,7 +51830,7 @@ async function getGeminiMdFilePathsInternalForEachDir(dir, userHomePath, fileSer
51703
51830
  "starting from CWD:",
51704
51831
  resolvedCwd
51705
51832
  );
51706
- const projectRoot = await findProjectRoot2(resolvedCwd);
51833
+ const projectRoot = await findProjectRoot2(resolvedCwd, boundaryMarkers);
51707
51834
  debugLogger.debug(
51708
51835
  "[DEBUG] [MemoryDiscovery] Determined project root:",
51709
51836
  projectRoot ?? "None"
@@ -51752,7 +51879,7 @@ async function getGeminiMdFilePathsInternalForEachDir(dir, userHomePath, fileSer
51752
51879
  project: Array.from(projectPaths)
51753
51880
  };
51754
51881
  }
51755
- async function readGeminiMdFiles(filePaths, importFormat = "tree") {
51882
+ async function readGeminiMdFiles(filePaths, importFormat = "tree", boundaryMarkers = [".git"]) {
51756
51883
  const CONCURRENT_LIMIT = 20;
51757
51884
  const results = [];
51758
51885
  for (let i = 0; i < filePaths.length; i += CONCURRENT_LIMIT) {
@@ -51767,7 +51894,8 @@ async function readGeminiMdFiles(filePaths, importFormat = "tree") {
51767
51894
  false,
51768
51895
  void 0,
51769
51896
  void 0,
51770
- importFormat
51897
+ importFormat,
51898
+ boundaryMarkers
51771
51899
  );
51772
51900
  debugLogger.debug(
51773
51901
  "[DEBUG] [MemoryDiscovery] Successfully read and processed imports:",
@@ -51835,15 +51963,34 @@ async function getGlobalMemoryPaths() {
51835
51963
  (p) => p !== null
51836
51964
  );
51837
51965
  }
51966
+ async function getUserProjectMemoryPaths(projectMemoryDir) {
51967
+ const geminiMdFilenames = getAllGeminiMdFilenames();
51968
+ const accessChecks = geminiMdFilenames.map(async (filename) => {
51969
+ const memoryPath = normalizePath(path9.join(projectMemoryDir, filename));
51970
+ try {
51971
+ await fs10.access(memoryPath, fsSync2.constants.R_OK);
51972
+ debugLogger.debug(
51973
+ "[DEBUG] [MemoryDiscovery] Found user project memory file:",
51974
+ memoryPath
51975
+ );
51976
+ return memoryPath;
51977
+ } catch {
51978
+ return null;
51979
+ }
51980
+ });
51981
+ return (await Promise.all(accessChecks)).filter(
51982
+ (p) => p !== null
51983
+ );
51984
+ }
51838
51985
  function getExtensionMemoryPaths(extensionLoader) {
51839
51986
  const extensionPaths = extensionLoader.getExtensions().filter((ext) => ext.isActive).flatMap((ext) => ext.contextFiles).map((p) => normalizePath(p));
51840
51987
  return Array.from(new Set(extensionPaths)).sort();
51841
51988
  }
51842
- async function getEnvironmentMemoryPaths(trustedRoots) {
51989
+ async function getEnvironmentMemoryPaths(trustedRoots, boundaryMarkers = [".git"]) {
51843
51990
  const allPaths = /* @__PURE__ */ new Set();
51844
51991
  const traversalPromises = trustedRoots.map(async (root) => {
51845
51992
  const resolvedRoot = normalizePath(root);
51846
- const gitRoot = await findProjectRoot2(resolvedRoot);
51993
+ const gitRoot = await findProjectRoot2(resolvedRoot, boundaryMarkers);
51847
51994
  const ceiling = gitRoot ? normalizePath(gitRoot) : resolvedRoot;
51848
51995
  debugLogger.debug(
51849
51996
  "[DEBUG] [MemoryDiscovery] Loading environment memory for trusted root:",
@@ -51864,7 +52011,8 @@ function categorizeAndConcatenate(paths, contentsMap) {
51864
52011
  return {
51865
52012
  global: getConcatenated(paths.global),
51866
52013
  extension: getConcatenated(paths.extension),
51867
- project: getConcatenated(paths.project)
52014
+ project: getConcatenated(paths.project),
52015
+ userProjectMemory: getConcatenated(paths.userProjectMemory ?? [])
51868
52016
  };
51869
52017
  }
51870
52018
  async function findUpwardGeminiFiles(startDir, stopDir) {
@@ -51904,7 +52052,7 @@ async function findUpwardGeminiFiles(startDir, stopDir) {
51904
52052
  }
51905
52053
  return upwardPaths;
51906
52054
  }
51907
- async function loadServerHierarchicalMemory(currentWorkingDirectory, includeDirectoriesToReadGemini, fileService, extensionLoader, folderTrust, importFormat = "tree", fileFilteringOptions, maxDirs = 200) {
52055
+ async function loadServerHierarchicalMemory(currentWorkingDirectory, includeDirectoriesToReadGemini, fileService, extensionLoader, folderTrust, importFormat = "tree", fileFilteringOptions, maxDirs = 200, boundaryMarkers = [".git"]) {
51908
52056
  const realCwd = normalizePath(
51909
52057
  await fs10.realpath(path9.resolve(currentWorkingDirectory))
51910
52058
  );
@@ -51925,7 +52073,8 @@ async function loadServerHierarchicalMemory(currentWorkingDirectory, includeDire
51925
52073
  fileService,
51926
52074
  folderTrust,
51927
52075
  fileFilteringOptions || DEFAULT_MEMORY_FILE_FILTERING_OPTIONS,
51928
- maxDirs
52076
+ maxDirs,
52077
+ boundaryMarkers
51929
52078
  ),
51930
52079
  Promise.resolve(getExtensionMemoryPaths(extensionLoader))
51931
52080
  ]);
@@ -51959,7 +52108,11 @@ async function loadServerHierarchicalMemory(currentWorkingDirectory, includeDire
51959
52108
  filePaths: []
51960
52109
  };
51961
52110
  }
51962
- const allContents = await readGeminiMdFiles(allFilePaths, importFormat);
52111
+ const allContents = await readGeminiMdFiles(
52112
+ allFilePaths,
52113
+ importFormat,
52114
+ boundaryMarkers
52115
+ );
51963
52116
  const contentsMap = new Map(allContents.map((c) => [c.filePath, c]));
51964
52117
  const hierarchicalMemory = categorizeAndConcatenate(
51965
52118
  {
@@ -51984,7 +52137,8 @@ async function refreshServerHierarchicalMemory(config) {
51984
52137
  config.isTrustedFolder(),
51985
52138
  config.getImportFormat(),
51986
52139
  config.getFileFilteringOptions(),
51987
- config.getDiscoveryMaxDirs()
52140
+ config.getDiscoveryMaxDirs(),
52141
+ config.getMemoryBoundaryMarkers()
51988
52142
  );
51989
52143
  const mcpInstructions = config.getMcpClientManager()?.getMcpInstructions() || "";
51990
52144
  const finalMemory = {
@@ -51997,7 +52151,7 @@ async function refreshServerHierarchicalMemory(config) {
51997
52151
  coreEvents.emit("memory-changed" /* MemoryChanged */, { fileCount: result.fileCount });
51998
52152
  return result;
51999
52153
  }
52000
- async function loadJitSubdirectoryMemory(targetPath, trustedRoots, alreadyLoadedPaths, alreadyLoadedIdentities) {
52154
+ async function loadJitSubdirectoryMemory(targetPath, trustedRoots, alreadyLoadedPaths, alreadyLoadedIdentities, boundaryMarkers = [".git"]) {
52001
52155
  const resolvedTarget = normalizePath(targetPath);
52002
52156
  let bestRoot = null;
52003
52157
  for (const root of trustedRoots) {
@@ -52017,7 +52171,7 @@ async function loadJitSubdirectoryMemory(targetPath, trustedRoots, alreadyLoaded
52017
52171
  );
52018
52172
  return { files: [], fileIdentities: [] };
52019
52173
  }
52020
- const gitRoot = await findProjectRoot2(bestRoot);
52174
+ const gitRoot = await findProjectRoot2(bestRoot, boundaryMarkers);
52021
52175
  const resolvedCeiling = gitRoot ? normalizePath(gitRoot) : bestRoot;
52022
52176
  debugLogger.debug(
52023
52177
  "[DEBUG] [MemoryDiscovery] Loading JIT memory for",
@@ -52079,7 +52233,7 @@ async function loadJitSubdirectoryMemory(targetPath, trustedRoots, alreadyLoaded
52079
52233
  "[DEBUG] [MemoryDiscovery] Found new JIT memory files:",
52080
52234
  JSON.stringify(newPaths)
52081
52235
  );
52082
- const contents = await readGeminiMdFiles(newPaths, "tree");
52236
+ const contents = await readGeminiMdFiles(newPaths, "tree", boundaryMarkers);
52083
52237
  return {
52084
52238
  files: contents.filter((item) => item.content !== null).map((item) => ({
52085
52239
  path: item.filePath,
@@ -52137,6 +52291,7 @@ export {
52137
52291
  hasSummary,
52138
52292
  isGrepResult,
52139
52293
  isListResult,
52294
+ isReadManyFilesResult,
52140
52295
  isFileDiff,
52141
52296
  ToolConfirmationOutcome,
52142
52297
  Kind,
@@ -52263,7 +52418,13 @@ export {
52263
52418
  ENTER_PLAN_MODE_TOOL_NAME,
52264
52419
  PLAN_MODE_PARAM_REASON,
52265
52420
  PARAM_ADDITIONAL_PERMISSIONS,
52421
+ UPDATE_TOPIC_TOOL_NAME,
52422
+ UPDATE_TOPIC_DISPLAY_NAME,
52423
+ TOPIC_PARAM_TITLE,
52424
+ TOPIC_PARAM_SUMMARY,
52425
+ TOPIC_PARAM_STRATEGIC_INTENT,
52266
52426
  zodToJsonSchema,
52427
+ getUpdateTopicDeclaration,
52267
52428
  REFERENCE_CONTENT_START,
52268
52429
  REFERENCE_CONTENT_END,
52269
52430
  DEFAULT_MAX_LINES_TEXT_FILE,
@@ -52328,6 +52489,7 @@ export {
52328
52489
  getCurrentGeminiMdFilename,
52329
52490
  getAllGeminiMdFilenames,
52330
52491
  getGlobalMemoryFilePath,
52492
+ getProjectMemoryFilePath,
52331
52493
  MemoryTool,
52332
52494
  parseGoogleApiError,
52333
52495
  isNodeError,
@@ -52366,6 +52528,7 @@ export {
52366
52528
  readGeminiMdFiles,
52367
52529
  concatenateInstructions,
52368
52530
  getGlobalMemoryPaths,
52531
+ getUserProjectMemoryPaths,
52369
52532
  getExtensionMemoryPaths,
52370
52533
  getEnvironmentMemoryPaths,
52371
52534
  categorizeAndConcatenate,