stratagate-dsh 0.3.8 → 0.3.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/dsh-host-resolution.ts","../src/bootstrap.ts"],"sourcesContent":["import { existsSync, readFileSync } from 'node:fs'\r\nimport { createRequire, registerHooks } from 'node:module'\r\nimport { dirname, isAbsolute, join, relative } from 'node:path'\r\nimport { fileURLToPath, pathToFileURL } from 'node:url'\r\n\r\nconst HOST_PACKAGES = [\r\n '@deepseek-ai/cordis',\r\n '@deepseek-ai/dsh-agent-default-model',\r\n '@deepseek-ai/dsh-client-ui-conversation',\r\n '@deepseek-ai/dsh-llm',\r\n '@deepseek-ai/dsh-native-command',\r\n '@deepseek-ai/dsh-session',\r\n '@deepseek-ai/dsh-session-format',\r\n '@deepseek-ai/dsh-session-format-catalog',\r\n '@deepseek-ai/dsh-session-format-v0-to-v1',\r\n '@deepseek-ai/dsh-settings',\r\n '@deepseek-ai/dsh-system-prompt',\r\n '@deepseek-ai/dsh-tools',\r\n '@deepseek-ai/schemastery',\r\n] as const\r\n\r\nconst installedHooks = Symbol.for('stratagate.dsh-host-resolution.v1')\r\n\r\nfunction isWithin(path: string, root: string): boolean {\r\n const child = relative(root, path)\r\n return child === '' || (!child.startsWith('..') && !isAbsolute(child))\r\n}\r\n\r\nfunction profileDirectory(start: string): string | undefined {\r\n let directory = start\r\n for (;;) {\r\n const manifestPath = join(directory, 'package.json')\r\n if (existsSync(manifestPath)) {\r\n try {\r\n const manifest = JSON.parse(readFileSync(manifestPath, 'utf8')) as { dsh?: { profile?: unknown } }\r\n if (manifest.dsh?.profile && typeof manifest.dsh.profile === 'object') return directory\r\n } catch {}\r\n }\r\n const parent = dirname(directory)\r\n if (parent === directory) return undefined\r\n directory = parent\r\n }\r\n}\r\n\r\nfunction hostPackage(specifier: string): boolean {\r\n return HOST_PACKAGES.some((name) => specifier === name || specifier.startsWith(`${name}/`))\r\n}\r\n\r\n/**\r\n * Force only StrataGate's DSH imports through the installation-owned fallback\r\n * created by DSH. The hook neither deletes nor rewrites the profile's package\r\n * tree, and imports belonging to the host or other plugins are untouched.\r\n */\r\nexport function installDshHostResolution(moduleUrl: string): boolean {\r\n const packageDirectory = dirname(dirname(fileURLToPath(moduleUrl)))\r\n const profile = profileDirectory(packageDirectory)\r\n if (!profile) return false\r\n\r\n const globalState = globalThis as typeof globalThis & { [installedHooks]?: Set<string> }\r\n const installed = globalState[installedHooks] ??= new Set<string>()\r\n const key = `${profile}\\u0000${packageDirectory}`\r\n if (installed.has(key)) return true\r\n\r\n const fallbackModules = join(dirname(profile), 'node_modules')\r\n const hostRequire = createRequire(join(fallbackModules, '.stratagate-host-resolution.cjs'))\r\n registerHooks({\r\n resolve(specifier, context, nextResolve) {\r\n const parent = context.parentURL?.startsWith('file:') ? fileURLToPath(context.parentURL) : undefined\r\n if (!hostPackage(specifier) || !parent || !isWithin(parent, packageDirectory)) {\r\n return nextResolve(specifier, context)\r\n }\r\n try {\r\n return { url: pathToFileURL(hostRequire.resolve(specifier)).href, shortCircuit: true }\r\n } catch (cause) {\r\n if (specifier === '@deepseek-ai/dsh-session-format-v0-to-v1'\r\n || specifier === '@deepseek-ai/dsh-session-format-catalog') {\r\n return nextResolve(specifier, context)\r\n }\r\n throw new Error(\r\n `StrataGate cannot resolve host-provided DSH package ${JSON.stringify(specifier)} from ${fallbackModules}. `\r\n + 'Start StrataGate through the DSH profile launcher so the host can prepare its module fallback.',\r\n { cause },\r\n )\r\n }\r\n },\r\n })\r\n installed.add(key)\r\n return true\r\n}\r\n","import { installDshHostResolution } from './dsh-host-resolution.js'\r\n\r\n// DSH prepares its installation-owned module fallback before it imports a\r\n// profile bundle. Install the narrowly-scoped resolver first, then load the\r\n// implementation so stale profile-local peers cannot win ESM resolution.\r\ninstallDshHostResolution(import.meta.url)\r\n\r\n// This file and src/index.ts are separate tsup entries. The runtime path is\r\n// intentionally external so the implementation is instantiated only after\r\n// the resolver above is active.\r\n// @ts-expect-error dist/plugin.js is emitted from src/index.ts during build.\r\nconst plugin = await import('./plugin.js') as typeof import('./index.js')\r\n\r\nexport const name = plugin.name\r\nexport const inject = plugin.inject\r\nexport const STRATAGATE_SETTINGS_NAMESPACE = plugin.STRATAGATE_SETTINGS_NAMESPACE\r\nexport const Config = plugin.Config\r\nexport const apply = plugin.apply\r\nexport type PluginConfig = import('./index.js').PluginConfig\r\n"],"mappings":";AAAA,SAAS,YAAY,oBAAoB;AACzC,SAAS,eAAe,qBAAqB;AAC7C,SAAS,SAAS,YAAY,MAAM,gBAAgB;AACpD,SAAS,eAAe,qBAAqB;AAE7C,IAAM,gBAAgB;AAAA,EACpB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,IAAM,iBAAiB,uBAAO,IAAI,mCAAmC;AAErE,SAAS,SAAS,MAAc,MAAuB;AACrD,QAAM,QAAQ,SAAS,MAAM,IAAI;AACjC,SAAO,UAAU,MAAO,CAAC,MAAM,WAAW,IAAI,KAAK,CAAC,WAAW,KAAK;AACtE;AAEA,SAAS,iBAAiB,OAAmC;AAC3D,MAAI,YAAY;AAChB,aAAS;AACP,UAAM,eAAe,KAAK,WAAW,cAAc;AACnD,QAAI,WAAW,YAAY,GAAG;AAC5B,UAAI;AACF,cAAM,WAAW,KAAK,MAAM,aAAa,cAAc,MAAM,CAAC;AAC9D,YAAI,SAAS,KAAK,WAAW,OAAO,SAAS,IAAI,YAAY,SAAU,QAAO;AAAA,MAChF,QAAQ;AAAA,MAAC;AAAA,IACX;AACA,UAAM,SAAS,QAAQ,SAAS;AAChC,QAAI,WAAW,UAAW,QAAO;AACjC,gBAAY;AAAA,EACd;AACF;AAEA,SAAS,YAAY,WAA4B;AAC/C,SAAO,cAAc,KAAK,CAACA,UAAS,cAAcA,SAAQ,UAAU,WAAW,GAAGA,KAAI,GAAG,CAAC;AAC5F;AAOO,SAAS,yBAAyB,WAA4B;AACnE,QAAM,mBAAmB,QAAQ,QAAQ,cAAc,SAAS,CAAC,CAAC;AAClE,QAAM,UAAU,iBAAiB,gBAAgB;AACjD,MAAI,CAAC,QAAS,QAAO;AAErB,QAAM,cAAc;AACpB,QAAM,YAAY,YAAY,cAAc,MAAM,oBAAI,IAAY;AAClE,QAAM,MAAM,GAAG,OAAO,KAAS,gBAAgB;AAC/C,MAAI,UAAU,IAAI,GAAG,EAAG,QAAO;AAE/B,QAAM,kBAAkB,KAAK,QAAQ,OAAO,GAAG,cAAc;AAC7D,QAAM,cAAc,cAAc,KAAK,iBAAiB,iCAAiC,CAAC;AAC1F,gBAAc;AAAA,IACZ,QAAQ,WAAW,SAAS,aAAa;AACvC,YAAM,SAAS,QAAQ,WAAW,WAAW,OAAO,IAAI,cAAc,QAAQ,SAAS,IAAI;AAC3F,UAAI,CAAC,YAAY,SAAS,KAAK,CAAC,UAAU,CAAC,SAAS,QAAQ,gBAAgB,GAAG;AAC7E,eAAO,YAAY,WAAW,OAAO;AAAA,MACvC;AACA,UAAI;AACF,eAAO,EAAE,KAAK,cAAc,YAAY,QAAQ,SAAS,CAAC,EAAE,MAAM,cAAc,KAAK;AAAA,MACvF,SAAS,OAAO;AACd,YAAI,cAAc,8CACb,cAAc,2CAA2C;AAC5D,iBAAO,YAAY,WAAW,OAAO;AAAA,QACvC;AACA,cAAM,IAAI;AAAA,UACR,uDAAuD,KAAK,UAAU,SAAS,CAAC,SAAS,eAAe;AAAA,UAExG,EAAE,MAAM;AAAA,QACV;AAAA,MACF;AAAA,IACF;AAAA,EACF,CAAC;AACD,YAAU,IAAI,GAAG;AACjB,SAAO;AACT;;;ACnFA,yBAAyB,YAAY,GAAG;AAMxC,IAAM,SAAS,MAAM,OAAO,aAAa;AAElC,IAAM,OAAO,OAAO;AACpB,IAAM,SAAS,OAAO;AACtB,IAAM,gCAAgC,OAAO;AAC7C,IAAM,SAAS,OAAO;AACtB,IAAM,QAAQ,OAAO;","names":["name"]}
1
+ {"version":3,"sources":["../src/dsh-host-resolution.ts","../src/bootstrap.ts"],"sourcesContent":["import { existsSync, readFileSync } from 'node:fs'\r\nimport { createRequire, registerHooks } from 'node:module'\r\nimport { dirname, isAbsolute, join, relative } from 'node:path'\r\nimport { fileURLToPath, pathToFileURL } from 'node:url'\r\n\r\nconst HOST_PACKAGES = [\r\n '@deepseek-ai/cordis',\r\n '@deepseek-ai/dsh-agent-default-model',\r\n '@deepseek-ai/dsh-client-ui-conversation',\r\n '@deepseek-ai/dsh-llm',\r\n '@deepseek-ai/dsh-native-command',\r\n '@deepseek-ai/dsh-session',\r\n '@deepseek-ai/dsh-session-format',\r\n '@deepseek-ai/dsh-session-format-catalog',\r\n '@deepseek-ai/dsh-session-format-v0-to-v1',\r\n '@deepseek-ai/dsh-settings',\r\n '@deepseek-ai/dsh-system-prompt',\r\n '@deepseek-ai/dsh-tools',\r\n '@deepseek-ai/schemastery',\r\n] as const\r\n\r\nconst installedHooks = Symbol.for('stratagate.dsh-host-resolution.v1')\r\n\r\nfunction isWithin(path: string, root: string): boolean {\r\n const child = relative(root, path)\r\n return child === '' || (!child.startsWith('..') && !isAbsolute(child))\r\n}\r\n\r\nfunction profileDirectory(start: string): string | undefined {\r\n let directory = start\r\n for (;;) {\r\n const manifestPath = join(directory, 'package.json')\r\n if (existsSync(manifestPath)) {\r\n try {\r\n const manifest = JSON.parse(readFileSync(manifestPath, 'utf8')) as { dsh?: { profile?: unknown } }\r\n if (manifest.dsh?.profile && typeof manifest.dsh.profile === 'object') return directory\r\n } catch {}\r\n }\r\n const parent = dirname(directory)\r\n if (parent === directory) return undefined\r\n directory = parent\r\n }\r\n}\r\n\r\nfunction hostPackage(specifier: string): boolean {\r\n return HOST_PACKAGES.some((name) => specifier === name || specifier.startsWith(`${name}/`))\r\n}\r\n\r\n/**\r\n * Force only StrataGate's DSH imports through the installation-owned fallback\r\n * created by DSH. The hook neither deletes nor rewrites the profile's package\r\n * tree, and imports belonging to the host or other plugins are untouched.\r\n */\r\nexport function installDshHostResolution(moduleUrl: string): boolean {\r\n const packageDirectory = dirname(dirname(fileURLToPath(moduleUrl)))\r\n const profile = profileDirectory(packageDirectory)\r\n if (!profile) return false\r\n\r\n const globalState = globalThis as typeof globalThis & { [installedHooks]?: Set<string> }\r\n const installed = globalState[installedHooks] ??= new Set<string>()\r\n const key = `${profile}\\u0000${packageDirectory}`\r\n if (installed.has(key)) return true\r\n\r\n const fallbackModules = join(dirname(profile), 'node_modules')\r\n const hostRequire = createRequire(join(fallbackModules, '.stratagate-host-resolution.cjs'))\r\n registerHooks({\r\n resolve(specifier, context, nextResolve) {\r\n const parent = context.parentURL?.startsWith('file:') ? fileURLToPath(context.parentURL) : undefined\r\n if (!hostPackage(specifier) || !parent || !isWithin(parent, packageDirectory)) {\r\n return nextResolve(specifier, context)\r\n }\r\n try {\r\n return { url: pathToFileURL(hostRequire.resolve(specifier)).href, shortCircuit: true }\r\n } catch (cause) {\r\n if (specifier === '@deepseek-ai/dsh-session-format-v0-to-v1'\r\n || specifier === '@deepseek-ai/dsh-session-format-catalog') {\r\n return nextResolve(specifier, context)\r\n }\r\n throw new Error(\r\n `StrataGate cannot resolve host-provided DSH package ${JSON.stringify(specifier)} from ${fallbackModules}. `\r\n + 'Start StrataGate through the DSH profile launcher so the host can prepare its module fallback.',\r\n { cause },\r\n )\r\n }\r\n },\r\n })\r\n installed.add(key)\r\n return true\r\n}\r\n","import { installDshHostResolution } from './dsh-host-resolution.js'\n\n// DSH prepares its installation-owned module fallback before it imports a\n// profile bundle. Install the narrowly-scoped resolver first, then load the\n// implementation so stale profile-local peers cannot win ESM resolution.\ninstallDshHostResolution(import.meta.url)\n\n// This file and src/index.ts are separate tsup entries. The runtime path is\n// intentionally external so the implementation is instantiated only after\n// the resolver above is active.\n// @ts-expect-error dist/plugin.js is emitted from src/index.ts during build.\nconst plugin = await import('./plugin.js') as typeof import('./index.js')\n\nexport const name = plugin.name\nexport const inject = plugin.inject\nexport const STRATAGATE_SETTINGS_NAMESPACE = plugin.STRATAGATE_SETTINGS_NAMESPACE\nexport const Config = plugin.Config\nexport const apply = plugin.apply\nexport type PluginConfig = import('./index.js').PluginConfig\n"],"mappings":";AAAA,SAAS,YAAY,oBAAoB;AACzC,SAAS,eAAe,qBAAqB;AAC7C,SAAS,SAAS,YAAY,MAAM,gBAAgB;AACpD,SAAS,eAAe,qBAAqB;AAE7C,IAAM,gBAAgB;AAAA,EACpB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,IAAM,iBAAiB,uBAAO,IAAI,mCAAmC;AAErE,SAAS,SAAS,MAAc,MAAuB;AACrD,QAAM,QAAQ,SAAS,MAAM,IAAI;AACjC,SAAO,UAAU,MAAO,CAAC,MAAM,WAAW,IAAI,KAAK,CAAC,WAAW,KAAK;AACtE;AAEA,SAAS,iBAAiB,OAAmC;AAC3D,MAAI,YAAY;AAChB,aAAS;AACP,UAAM,eAAe,KAAK,WAAW,cAAc;AACnD,QAAI,WAAW,YAAY,GAAG;AAC5B,UAAI;AACF,cAAM,WAAW,KAAK,MAAM,aAAa,cAAc,MAAM,CAAC;AAC9D,YAAI,SAAS,KAAK,WAAW,OAAO,SAAS,IAAI,YAAY,SAAU,QAAO;AAAA,MAChF,QAAQ;AAAA,MAAC;AAAA,IACX;AACA,UAAM,SAAS,QAAQ,SAAS;AAChC,QAAI,WAAW,UAAW,QAAO;AACjC,gBAAY;AAAA,EACd;AACF;AAEA,SAAS,YAAY,WAA4B;AAC/C,SAAO,cAAc,KAAK,CAACA,UAAS,cAAcA,SAAQ,UAAU,WAAW,GAAGA,KAAI,GAAG,CAAC;AAC5F;AAOO,SAAS,yBAAyB,WAA4B;AACnE,QAAM,mBAAmB,QAAQ,QAAQ,cAAc,SAAS,CAAC,CAAC;AAClE,QAAM,UAAU,iBAAiB,gBAAgB;AACjD,MAAI,CAAC,QAAS,QAAO;AAErB,QAAM,cAAc;AACpB,QAAM,YAAY,YAAY,cAAc,MAAM,oBAAI,IAAY;AAClE,QAAM,MAAM,GAAG,OAAO,KAAS,gBAAgB;AAC/C,MAAI,UAAU,IAAI,GAAG,EAAG,QAAO;AAE/B,QAAM,kBAAkB,KAAK,QAAQ,OAAO,GAAG,cAAc;AAC7D,QAAM,cAAc,cAAc,KAAK,iBAAiB,iCAAiC,CAAC;AAC1F,gBAAc;AAAA,IACZ,QAAQ,WAAW,SAAS,aAAa;AACvC,YAAM,SAAS,QAAQ,WAAW,WAAW,OAAO,IAAI,cAAc,QAAQ,SAAS,IAAI;AAC3F,UAAI,CAAC,YAAY,SAAS,KAAK,CAAC,UAAU,CAAC,SAAS,QAAQ,gBAAgB,GAAG;AAC7E,eAAO,YAAY,WAAW,OAAO;AAAA,MACvC;AACA,UAAI;AACF,eAAO,EAAE,KAAK,cAAc,YAAY,QAAQ,SAAS,CAAC,EAAE,MAAM,cAAc,KAAK;AAAA,MACvF,SAAS,OAAO;AACd,YAAI,cAAc,8CACb,cAAc,2CAA2C;AAC5D,iBAAO,YAAY,WAAW,OAAO;AAAA,QACvC;AACA,cAAM,IAAI;AAAA,UACR,uDAAuD,KAAK,UAAU,SAAS,CAAC,SAAS,eAAe;AAAA,UAExG,EAAE,MAAM;AAAA,QACV;AAAA,MACF;AAAA,IACF;AAAA,EACF,CAAC;AACD,YAAU,IAAI,GAAG;AACjB,SAAO;AACT;;;ACnFA,yBAAyB,YAAY,GAAG;AAMxC,IAAM,SAAS,MAAM,OAAO,aAAa;AAElC,IAAM,OAAO,OAAO;AACpB,IAAM,SAAS,OAAO;AACtB,IAAM,gCAAgC,OAAO;AAC7C,IAAM,SAAS,OAAO;AACtB,IAAM,QAAQ,OAAO;","names":["name"]}
package/dist/plugin.js CHANGED
@@ -9467,6 +9467,11 @@ var DshMetadataStore = class {
9467
9467
 
9468
9468
  // src/runtime.ts
9469
9469
  import { createHash as createHash3 } from "node:crypto";
9470
+
9471
+ // src/feedback-policy.ts
9472
+ var AGENT_FEEDBACK_ENABLED = false;
9473
+
9474
+ // src/runtime.ts
9470
9475
  import { existsSync } from "node:fs";
9471
9476
  import { dirname, resolve as resolve2 } from "node:path";
9472
9477
  import { DatabaseSync as DatabaseSync3 } from "node:sqlite";
@@ -9818,7 +9823,9 @@ function workspaceDisplayName(cwd) {
9818
9823
  return canonical2.split(/[\\/]/).at(-1) || "\u5F53\u524D\u5DE5\u4F5C\u533A";
9819
9824
  }
9820
9825
  function feedbackText(value, maximum) {
9821
- return typeof value === "string" ? value.trim().slice(0, maximum) : "";
9826
+ if (typeof value !== "string") return "";
9827
+ const text3 = value.trim().replace(/[\uD800-\uDFFF]/gu, "\uFFFD").slice(0, maximum);
9828
+ return text3.replace(/[\uD800-\uDBFF]$/, "");
9822
9829
  }
9823
9830
  var FEEDBACK_MARKDOWN_HEADINGS = {
9824
9831
  description: "\u95EE\u9898\u63CF\u8FF0",
@@ -10810,6 +10817,7 @@ var StrataGateRuntime = class {
10810
10817
  await Promise.all(settled.flatMap((result) => result.status === "fulfilled" ? [result.value.close()] : []));
10811
10818
  if (this.profileStorage) await this.profileStorage.close();
10812
10819
  this.sessionsById.clear();
10820
+ this.pendingFeedbackSuggestionSessions.clear();
10813
10821
  if (flushError !== void 0) throw flushError;
10814
10822
  }
10815
10823
  namespaceFor(session) {
@@ -10936,9 +10944,10 @@ var StrataGateRuntime = class {
10936
10944
  return { items, total: items.length };
10937
10945
  }
10938
10946
  notePluginError(session, _error) {
10939
- if (!this.closed) this.pendingFeedbackSuggestionSessions.add(String(session.id));
10947
+ if (AGENT_FEEDBACK_ENABLED && !this.closed) this.pendingFeedbackSuggestionSessions.add(String(session.id));
10940
10948
  }
10941
10949
  takeFeedbackSuggestion(session, now = Date.now()) {
10950
+ if (!AGENT_FEEDBACK_ENABLED) return "";
10942
10951
  const sessionId = String(session.id);
10943
10952
  if (!this.pendingFeedbackSuggestionSessions.delete(sessionId)) return "";
10944
10953
  const last = this.lastFeedbackPromptAt();
@@ -12322,7 +12331,7 @@ function registerMemoryTools(ctx, runtime) {
12322
12331
  return runtime.updatePersistentProfileFromTool(args.field, args.value);
12323
12332
  }
12324
12333
  }));
12325
- ctx.tools.register(defineTool({
12334
+ if (AGENT_FEEDBACK_ENABLED) ctx.tools.register(defineTool({
12326
12335
  name: "feedback_prepare",
12327
12336
  description: 'This tool is provided by the StrataGate plugin. Create or revise a local StrataGate feedback draft when the user directly requests it, or after a proactive suggestion permitted by the StrataGate feedback policy and the user explicitly agrees. A direct user request is already authorization. Use only facts known from the current conversation; leave unknown fields empty and never invent versions, logs, Block counts, or diagnostics. Never submit anything to GitHub. After success, briefly say the draft is local and not submitted, then render feedbackUrl as a Markdown link labeled "\u6253\u5F00\u53CD\u9988\u8349\u7A3F". Then ask exactly once: "\u8981\u4E0D\u8981\u987A\u4FBF\u8BA9\u6211\u5C1D\u8BD5\u4FEE\u590D\u8FD9\u4E2A\u95EE\u9898\uFF0C\u5E76\u63D0\u4EA4\u4E00\u4E2A PR\uFF1F" If the user does not respond or declines, do not ask again. Do not use a popup or other additional UI. Do not print draft fields or an Issue-content table, and do not direct the user through Settings manually.',
12328
12337
  parameters: {
@@ -14615,7 +14624,7 @@ async function apply(ctx, config) {
14615
14624
  }
14616
14625
  });
14617
14626
  ctx.systemPrompt.section({ name: "tool:stratagate-memory", order: 113, text: MEMORY_PROTOCOL });
14618
- ctx.systemPrompt.section({ name: "tool:stratagate-feedback", order: 114, text: FEEDBACK_PROTOCOL });
14627
+ if (AGENT_FEEDBACK_ENABLED) ctx.systemPrompt.section({ name: "tool:stratagate-feedback", order: 114, text: FEEDBACK_PROTOCOL });
14619
14628
  ctx.on("system-prompt/assemble", async (_assembly, context, next) => {
14620
14629
  const assembled = await next();
14621
14630
  const contexts = [...assembled.contexts];
@@ -14634,24 +14643,24 @@ async function apply(ctx, config) {
14634
14643
  autoMemory = { name: "stratagate:auto-memory", text: text3 };
14635
14644
  } catch (error) {
14636
14645
  ctx.logger.warn(`stratagate-memory auto-context failed: ${renderError(error)}`);
14637
- runtime.notePluginError(session, error);
14646
+ if (AGENT_FEEDBACK_ENABLED) runtime.notePluginError(session, error);
14638
14647
  }
14639
14648
  try {
14640
14649
  const directory = await runtime.buildMemoryDirectory(session);
14641
14650
  if (directory) contexts.push({ name: "stratagate:memory-directory", text: directory });
14642
14651
  } catch (error) {
14643
14652
  ctx.logger.warn(`stratagate-memory directory failed: ${renderError(error)}`);
14644
- runtime.notePluginError(session, error);
14653
+ if (AGENT_FEEDBACK_ENABLED) runtime.notePluginError(session, error);
14645
14654
  }
14646
14655
  if (autoMemory) contexts.push(autoMemory);
14647
- const feedbackSuggestion = runtime.takeFeedbackSuggestion(session);
14656
+ const feedbackSuggestion = AGENT_FEEDBACK_ENABLED ? runtime.takeFeedbackSuggestion(session) : "";
14648
14657
  if (feedbackSuggestion) contexts.push({ name: "stratagate:feedback-suggestion", text: feedbackSuggestion });
14649
14658
  return { ...assembled, contexts };
14650
14659
  });
14651
14660
  installRetrievalFinalization(ctx, runtime);
14652
14661
  registerMemoryTools(ctx, runtime);
14653
14662
  ctx.on("tools/result", (exec, result) => {
14654
- if (!result.isError || !exec.agent) return;
14663
+ if (!AGENT_FEEDBACK_ENABLED || !result.isError || !exec.agent) return;
14655
14664
  if (exec.name === "feedback_prepare" || exec.name.startsWith("memory_")) {
14656
14665
  runtime.notePluginError(exec.agent.session, result.error.message);
14657
14666
  }