@agentconnect.md/daemon 1.0.0-rc.240 → 1.0.0-rc.241

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.
@@ -3,16 +3,16 @@ import { n as require_ms, t as require_src$3 } from "./src-DDtlVutj.js";
3
3
  import { n as init_esm_shims, t as __dirname } from "./esm-shims-DxGcm4Hw.js";
4
4
  import { t as DAEMON_VERSION } from "./version-DGaRXjBK.js";
5
5
  import { C as _coercedNumber, T as NEVER, a as array, d as literal, f as looseObject, i as any, m as object, o as boolean, p as number$1, t as ZodNumber, v as string, x as url$4 } from "./schemas-CQkO9hC5.js";
6
- import { a as agentChildEnv, i as selectAgent, n as findAgentFiles, o as loadConfig, r as loadAgents, s as persistDaemonId } from "./load-agents-C3pJSVeT.js";
6
+ import { a as agentChildEnv, i as selectAgent, n as findAgentFiles, o as loadConfig, r as loadAgents, s as persistDaemonId } from "./load-agents-Dt8ZYMsH.js";
7
7
  import { l as resolveRoot, o as mcpSocketPath, u as statePath } from "./paths-DEcUO8lC.js";
8
- import { C as resolveRuntimes, S as cachedRuntimeVersions, _ as encode, a as initGitInjection, b as RESERVED_MCP_SERVER_NAME, c as simpleGit, d as RELAY_DAEMON_SUBPROTOCOL, f as RELAY_DAEMON_WS_PATH, g as decodeEnvelope, h as buildEnvelope, i as prepareWorkspace, m as decodeRelayDaemonFrame, n as installedRuntimes, o as probeGitVersion, p as buildRelayDaemonFrame, r as prefetchWorkspace, s as sessionGitEnv, t as AcpHost, u as normalizeGitUrl, v as MAX_FRAME_BYTES, x as cachedRuntimeNames, y as MEMORY_INDEX } from "./acp-host-M9PGQrVJ.js";
8
+ import { A as toolsForIntegrations, C as decodeRelayDaemonFrame, D as MAX_FRAME_BYTES, E as encode, M as cachedRuntimeVersions, N as resolveRuntimes, O as RESERVED_MCP_SERVER_NAME, S as buildRelayDaemonFrame, T as decodeEnvelope, _ as writeMemoryFile, a as initGitInjection, b as RELAY_DAEMON_SUBPROTOCOL, c as simpleGit, d as memoryProviderFor, f as MemoryConflictError, g as resolveInMemoryDir, h as listMemory, i as prepareWorkspace, j as cachedRuntimeNames, k as MEMORY_TOOL_NAMES, l as createMemoryProvider, m as MemoryTooLargeError, n as installedRuntimes, o as probeGitVersion, p as MemoryPathError, r as prefetchWorkspace, s as sessionGitEnv, t as AcpHost, u as memoryKindOf, w as buildEnvelope, x as RELAY_DAEMON_WS_PATH, y as normalizeGitUrl } from "./acp-host-jS9ZQLGG.js";
9
9
  import { i as GitCredentialCache, n as gitcredSocketPath, r as writeGitcredShim, t as GitCredServer } from "./gitcred-server-Dcsq6QJe.js";
10
10
  import { B as ToolListChangedNotificationSchema, D as ListPromptsResultSchema, E as ListChangedOptionsBaseSchema, F as PromptListChangedNotificationSchema, G as isZ4Schema, H as isJSONRPCRequest, I as ReadResourceResultSchema, J as encodeFrame, K as safeParse, L as ResourceListChangedNotificationSchema, M as ListToolsResultSchema, O as ListResourceTemplatesResultSchema, P as McpError, R as SUPPORTED_PROTOCOL_VERSIONS, S as InitializeResultSchema, T as LATEST_PROTOCOL_VERSION, U as isJSONRPCResultResponse, V as isInitializedNotification, W as getObjectShape, _ as ElicitResultSchema, a as AjvJsonSchemaValidator, b as GetPromptResultSchema, c as mergeCapabilities, d as CompleteResultSchema, f as CreateMessageRequestSchema, g as ElicitRequestSchema, h as CreateTaskResultSchema, i as assertToolsCallTaskCapability, k as ListResourcesResultSchema, m as CreateMessageResultWithToolsSchema, n as serializeMessage, o as require_fast_deep_equal, p as CreateMessageResultSchema, q as decodeFrames, r as assertClientRequestTaskCapability, s as Protocol, t as ReadBuffer, u as CallToolResultSchema, v as EmptyResultSchema, w as JSONRPCMessageSchema, y as ErrorCode } from "./stdio-DnS8WcXi.js";
11
11
  import { URL as URL$1 } from "url";
12
12
  import * as tls from "tls";
13
13
  import * as net$5 from "net";
14
14
  import * as path$16 from "node:path";
15
- import { dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
15
+ import { dirname, join, relative, resolve, sep } from "node:path";
16
16
  import * as http$8 from "http";
17
17
  import { Agent } from "https";
18
18
  import { chmodSync, existsSync, mkdirSync, mkdtempSync, promises, readFileSync, rmSync, stat, unwatchFile, watch, watchFile, writeFileSync } from "node:fs";
@@ -4121,150 +4121,6 @@ function compareEntries(a, b) {
4121
4121
  return a.name < b.name ? -1 : a.name > b.name ? 1 : 0;
4122
4122
  }
4123
4123
  //#endregion
4124
- //#region src/agents/memory.ts
4125
- /**
4126
- * Agent memory — a DIRECTORY at the agent's ROOT (`<agent-root>/memory/`), OUTSIDE
4127
- * the workspace so it survives a workspace reset / re-clone and is never committed
4128
- * into a github-workspace repo.
4129
- *
4130
- * Index-plus-topics shape (the structure Claude Code's auto-memory uses): a lean
4131
- * `MEMORY.md` index — injected into the prompt every session, so it must stay small
4132
- * — plus any number of `<topic>.md` files the agent reads on demand. The agent
4133
- * maintains it via the `readMemory` / `writeMemory` / `listMemory` MCP tools; the
4134
- * daemon serves the same directory to the CP for the console.
4135
- *
4136
- * SECURITY: topic paths are agent/console-supplied, so every path is contained to
4137
- * the memory dir — absolute paths and `..` escapes are rejected, and the resolved
4138
- * path is re-checked so a symlink can't smuggle a target out. Flat by design (one
4139
- * level): a topic is a file directly under `memory/`, no nested dirs.
4140
- */
4141
- const MEMORY_DIRNAME = "memory";
4142
- /** Max bytes of the index injected into the prompt each session — keeps a large
4143
- * memory from swelling the context (mirrors Claude Code's 25 KB entrypoint cap). */
4144
- const MAX_INDEX_INJECT_BYTES = 25e3;
4145
- /** Hard cap on a single memory file. Injected/read every session, so an unbounded
4146
- * file would swell the prompt and the wire; writes over this are rejected. */
4147
- const MAX_MEMORY_FILE_BYTES = 256e3;
4148
- /** Raised when a memory path escapes the memory dir. Surfaces as `BAD_PAYLOAD`. */
4149
- var MemoryPathError = class extends Error {
4150
- constructor(message) {
4151
- super(message);
4152
- this.name = "MemoryPathError";
4153
- }
4154
- };
4155
- /** Raised when a write exceeds {@link MAX_MEMORY_FILE_BYTES}. `BAD_PAYLOAD`. */
4156
- var MemoryTooLargeError = class extends Error {
4157
- constructor(message) {
4158
- super(message);
4159
- this.name = "MemoryTooLargeError";
4160
- }
4161
- };
4162
- /** Raised when an `ifMatchMtime` precondition fails (the file changed under the
4163
- * writer — e.g. a console edit racing a newer agent write). Surfaces as CONFLICT. */
4164
- var MemoryConflictError = class extends Error {
4165
- constructor(message) {
4166
- super(message);
4167
- this.name = "MemoryConflictError";
4168
- }
4169
- };
4170
- /** The memory directory for an agent, given its root dir (where agent.json lives). */
4171
- function memoryDir(agentDir) {
4172
- return join(agentDir, MEMORY_DIRNAME);
4173
- }
4174
- /** Resolve a memory-dir-relative path to an absolute one, contained to the dir.
4175
- * Rejects absolute paths, `..` escapes, and any nested directory (flat only). */
4176
- function resolveInMemoryDir(agentDir, relPath) {
4177
- if (isAbsolute(relPath)) throw new MemoryPathError("absolute paths are not allowed");
4178
- const dir = memoryDir(agentDir);
4179
- const abs = resolve(dir, relPath);
4180
- if (abs !== dir && !abs.startsWith(dir + sep)) throw new MemoryPathError("path escapes the memory dir");
4181
- const rel = abs.slice(dir.length + 1);
4182
- if (rel.includes(sep)) throw new MemoryPathError("memory is a flat directory (no subdirectories)");
4183
- if (rel.length === 0) throw new MemoryPathError("a file name is required");
4184
- return abs;
4185
- }
4186
- /** Seed `<agent-root>/memory/MEMORY.md` with a header if the dir/index is absent
4187
- * (idempotent). Called at session start so a brand-new agent always has an index. */
4188
- function ensureMemory(agentDir, agentName) {
4189
- const dir = memoryDir(agentDir);
4190
- mkdirSync(dir, { recursive: true });
4191
- const index = join(dir, MEMORY_INDEX);
4192
- if (!existsSync(index)) writeFileSync(index, `# ${agentName} memory\n\nYour long-term memory index. Keep it short — link out to topic files (e.g. \`[deploys](deploys.md)\`) for detail and read them on demand with the readMemory tool.\n`);
4193
- }
4194
- /** Read the memory index (`MEMORY.md`) for prompt injection, trimmed to the inject
4195
- * cap so a large index can't blow up the prompt; '' when absent. */
4196
- async function readIndex(agentDir) {
4197
- const text = await readMemoryFile(agentDir, MEMORY_INDEX);
4198
- if (Buffer.byteLength(text) <= 25e3) return text;
4199
- return Buffer.from(text, "utf8").subarray(0, MAX_INDEX_INJECT_BYTES).toString("utf8") + "\n\n[…memory index truncated — trim MEMORY.md]";
4200
- }
4201
- /** Read a memory file's text; '' when it does not exist (never throws on ENOENT). */
4202
- async function readMemoryFile(agentDir, relPath) {
4203
- const abs = resolveInMemoryDir(agentDir, relPath);
4204
- try {
4205
- return await promises.readFile(abs, "utf8");
4206
- } catch (err) {
4207
- if (err.code === "ENOENT") return "";
4208
- throw err;
4209
- }
4210
- }
4211
- /** Overwrite a memory file with `content` (creating the dir if needed). Atomic
4212
- * (tmp + rename) so a concurrent read never sees a partial file.
4213
- *
4214
- * - Rejects content over {@link MAX_MEMORY_FILE_BYTES} ({@link MemoryTooLargeError}).
4215
- * - `ifMatchMtime` (optimistic concurrency): when given, the current file's mtime
4216
- * must equal it, else {@link MemoryConflictError} — so a console edit can't
4217
- * clobber a newer write. A brand-new file (no mtime) matches `ifMatchMtime`
4218
- * only when the caller passes none (or the empty string). */
4219
- async function writeMemoryFile(agentDir, relPath, content, ifMatchMtime) {
4220
- if (Buffer.byteLength(content) > 256e3) throw new MemoryTooLargeError(`memory file exceeds the ${MAX_MEMORY_FILE_BYTES}-byte limit`);
4221
- const abs = resolveInMemoryDir(agentDir, relPath);
4222
- if (ifMatchMtime) {
4223
- let current = null;
4224
- try {
4225
- current = (await promises.stat(abs)).mtime.toISOString();
4226
- } catch (err) {
4227
- if (err.code !== "ENOENT") throw err;
4228
- }
4229
- if (current !== ifMatchMtime) throw new MemoryConflictError("the memory file changed since it was read; reload and retry");
4230
- }
4231
- await promises.mkdir(memoryDir(agentDir), { recursive: true });
4232
- const tmp = `${abs}.tmp`;
4233
- await promises.writeFile(tmp, content, "utf8");
4234
- await promises.rename(tmp, abs);
4235
- const st = await promises.stat(abs);
4236
- return {
4237
- size: st.size,
4238
- mtime: st.mtime.toISOString()
4239
- };
4240
- }
4241
- /** List the files in the memory dir (flat; index + topics), sorted with the index
4242
- * first. Empty when the dir does not exist. `.tmp` write artifacts are skipped. */
4243
- async function listMemory(agentDir) {
4244
- const dir = memoryDir(agentDir);
4245
- let dirents;
4246
- try {
4247
- dirents = await promises.readdir(dir, { withFileTypes: true });
4248
- } catch (err) {
4249
- if (err.code === "ENOENT") return [];
4250
- throw err;
4251
- }
4252
- const files = [];
4253
- for (const d of dirents) {
4254
- if (!d.isFile() || d.name.endsWith(".tmp")) continue;
4255
- try {
4256
- const st = await promises.stat(join(dir, d.name));
4257
- files.push({
4258
- name: d.name,
4259
- size: st.size,
4260
- mtime: st.mtime.toISOString()
4261
- });
4262
- } catch {}
4263
- }
4264
- files.sort((a, b) => a.name === "MEMORY.md" ? -1 : b.name === "MEMORY.md" ? 1 : a.name.localeCompare(b.name));
4265
- return files;
4266
- }
4267
- //#endregion
4268
4124
  //#region src/cp/memory-reader.ts
4269
4125
  /**
4270
4126
  * `MemoryReader` — the seam answering the CP's `memory/list`, `memory/read` and
@@ -6413,6 +6269,7 @@ function hostSpawnSig(a) {
6413
6269
  executionMode: a.executionMode,
6414
6270
  fastMode: a.fastMode,
6415
6271
  permissionMode: a.permissionMode,
6272
+ memory: a.memory?.provider,
6416
6273
  env: a.runtimeOverrides?.env
6417
6274
  });
6418
6275
  }
@@ -10826,203 +10683,6 @@ function resolveAgentMcpServers(opts) {
10826
10683
  return out;
10827
10684
  }
10828
10685
  //#endregion
10829
- //#region src/mcp/tools.ts
10830
- const obj = (properties, required = []) => ({
10831
- type: "object",
10832
- properties,
10833
- required,
10834
- additionalProperties: false
10835
- });
10836
- /**
10837
- * Tools injected when an agent has a Slack integration. `sendSlackMessage` is
10838
- * the active-messaging tool from the design (token held by the daemon, invisible
10839
- * to the model); the rest are channel/user read helpers.
10840
- */
10841
- const SLACK_TOOLS = [
10842
- {
10843
- name: "sendSlackMessage",
10844
- description: "Send a message to a Slack channel. Omit `channel` to post in the channel this conversation is happening in. Omit `thread` to reply in the current thread; pass an empty string to post to the channel root instead.",
10845
- inputSchema: obj({
10846
- text: {
10847
- type: "string",
10848
- description: "Message body, in standard Markdown (CommonMark/GFM). Use `**bold**`, `~~strikethrough~~`, `# headings`, tables, etc. — Slack renders standard Markdown natively (do NOT use single-char Slack mrkdwn like `*bold*` or `~strike~`)."
10849
- },
10850
- channel: {
10851
- type: "string",
10852
- description: "Target channel ID (e.g. C0123ABC). Defaults to the current channel."
10853
- },
10854
- thread: {
10855
- type: "string",
10856
- description: "Thread timestamp to reply under. Defaults to the current thread; \"\" posts to the channel root."
10857
- }
10858
- }, ["text"])
10859
- },
10860
- {
10861
- name: "getCurrentChannel",
10862
- description: "Return the Slack channel (and thread) this conversation is bound to, including the channel name when available.",
10863
- inputSchema: obj({})
10864
- },
10865
- {
10866
- name: "listChannelMembers",
10867
- description: "List the users and bots in a channel (id, name, is_bot). Omit `channel` to list members of the current channel.",
10868
- inputSchema: obj({ channel: {
10869
- type: "string",
10870
- description: "Channel ID. Defaults to the current channel."
10871
- } })
10872
- },
10873
- {
10874
- name: "listChannels",
10875
- description: "List the public/private channels the bot is a member of and can post to.",
10876
- inputSchema: obj({})
10877
- },
10878
- {
10879
- name: "getUserProfile",
10880
- description: "Look up a Slack user or bot by id, returning their display name, real name, and bot flag.",
10881
- inputSchema: obj({ user: {
10882
- type: "string",
10883
- description: "User ID (e.g. U0123ABC)."
10884
- } }, ["user"])
10885
- },
10886
- {
10887
- name: "readSlackFile",
10888
- description: "Fetch the contents of a file shared in Slack, using the bot credentials. You do NOT have direct network access to Slack's private file URLs (they require the bot token) — use this tool instead of curl/fetch. Pass the file's `url` (the `url_private` / `uri` from a shared attachment or resource link). Images are returned as viewable image content; text files as text. Supply `mimeType` when known for correct handling.",
10889
- inputSchema: obj({
10890
- url: {
10891
- type: "string",
10892
- description: "The file's url_private (or url_private_download) / resource-link uri."
10893
- },
10894
- mimeType: {
10895
- type: "string",
10896
- description: "Optional MIME type hint, e.g. image/png or text/plain."
10897
- }
10898
- }, ["url"])
10899
- }
10900
- ];
10901
- /**
10902
- * Tools injected when an agent has a Telegram integration. Mirrors the Slack set
10903
- * but for the Telegram data model: `channel` is a chat id (e.g. -1001234567890),
10904
- * `thread` is a forum-topic `message_thread_id`, and there is no `listChannels`
10905
- * (a bot cannot enumerate the chats it belongs to).
10906
- */
10907
- const TELEGRAM_TOOLS = [
10908
- {
10909
- name: "sendTelegramMessage",
10910
- description: "Send a message to a Telegram chat. Omit `channel` to post in the chat this conversation is happening in. Omit `thread` to reply in the current forum topic; pass an empty string to post outside any topic.",
10911
- inputSchema: obj({
10912
- text: {
10913
- type: "string",
10914
- description: "Message body, in standard Markdown (CommonMark/GFM). Use `**bold**`, `*italic*`, `` `code` ``, `[links](url)`, lists, etc. — the daemon converts it to Telegram formatting and escapes special characters for you, so write plain Markdown (do NOT pre-escape with backslashes)."
10915
- },
10916
- channel: {
10917
- type: "string",
10918
- description: "Target chat id (e.g. -1001234567890, or a positive id for a private chat). Defaults to the current chat."
10919
- },
10920
- thread: {
10921
- type: "string",
10922
- description: "Forum-topic message_thread_id to reply under. Defaults to the current topic; \"\" posts outside any topic."
10923
- }
10924
- }, ["text"])
10925
- },
10926
- {
10927
- name: "getCurrentChannel",
10928
- description: "Return the Telegram chat (and forum topic) this conversation is bound to, including the chat title when available.",
10929
- inputSchema: obj({})
10930
- },
10931
- {
10932
- name: "listChannelMembers",
10933
- description: "List the users and bots in a chat (id, name, is_bot). Omit `channel` to list members of the current chat. Note: Telegram only exposes administrators for large groups.",
10934
- inputSchema: obj({ channel: {
10935
- type: "string",
10936
- description: "Chat id. Defaults to the current chat."
10937
- } })
10938
- },
10939
- {
10940
- name: "getUserProfile",
10941
- description: "Look up a Telegram user or bot by id, returning their display name, username, and bot flag.",
10942
- inputSchema: obj({ user: {
10943
- type: "string",
10944
- description: "Numeric user id (e.g. 12345678)."
10945
- } }, ["user"])
10946
- },
10947
- {
10948
- name: "readTelegramFile",
10949
- description: "Fetch the contents of a file shared in Telegram, using the bot credentials. You do NOT have direct network access to Telegram's file storage — use this tool instead of curl/fetch. Pass the file's `url` (the `file_id` from a shared attachment or the `uri` of a resource link). Images are returned as viewable image content; text files as text. Supply `mimeType` when known for correct handling.",
10950
- inputSchema: obj({
10951
- url: {
10952
- type: "string",
10953
- description: "The shared file's Telegram file_id (or resource-link uri)."
10954
- },
10955
- mimeType: {
10956
- type: "string",
10957
- description: "Optional MIME type hint, e.g. image/png or text/plain."
10958
- }
10959
- }, ["url"])
10960
- }
10961
- ];
10962
- /**
10963
- * The agent's long-term memory tools — available to EVERY agent regardless of
10964
- * integrations. Memory is a directory (`<agent-root>/memory/`) with a `MEMORY.md`
10965
- * index (injected into the prompt each session) plus `<topic>.md` files the agent
10966
- * reads on demand. Keep the index short; move detail into topic files.
10967
- */
10968
- const MEMORY_TOOLS = [
10969
- {
10970
- name: "listMemory",
10971
- description: "List your memory files — the MEMORY.md index plus any topic files you have written. Use this to discover what you have stored before reading or updating it.",
10972
- inputSchema: obj({})
10973
- },
10974
- {
10975
- name: "readMemory",
10976
- description: "Read one of your memory files. Omit `path` (or pass \"MEMORY.md\") to read the index; pass a topic file name (e.g. \"deploys.md\") to read that topic. The index is already shown to you at the start of each session — use this to pull the detail behind an index entry when it is relevant.",
10977
- inputSchema: obj({ path: {
10978
- type: "string",
10979
- description: "Memory file name (e.g. \"deploys.md\"). Defaults to the MEMORY.md index."
10980
- } })
10981
- },
10982
- {
10983
- name: "writeMemory",
10984
- description: "Save one of your memory files (whole-file overwrite). Omit `path` to write the MEMORY.md index; pass a topic file name (e.g. \"deploys.md\") for a topic. Keep the INDEX short — a scannable list that links to topic files (e.g. \"- [deploys](deploys.md) — how we ship\"); put the actual detail in the topic files. Use for durable facts across sessions: conventions, decisions, who to ask, things you had to re-learn. A flat directory — no subfolders in the path.",
10985
- inputSchema: obj({
10986
- path: {
10987
- type: "string",
10988
- description: "Memory file name (e.g. \"deploys.md\"). Defaults to the MEMORY.md index. No subdirectories."
10989
- },
10990
- content: {
10991
- type: "string",
10992
- description: "The full new file contents, in Markdown. Replaces the file."
10993
- }
10994
- }, ["content"])
10995
- }
10996
- ];
10997
- /** Names of every tool this module can inject — handy for routing/validation. */
10998
- const ALL_TOOL_NAMES = [...new Set([
10999
- ...SLACK_TOOLS,
11000
- ...TELEGRAM_TOOLS,
11001
- ...MEMORY_TOOLS
11002
- ].map((t) => t.name))];
11003
- /**
11004
- * The default MCP tool set for an agent. The memory tools are always present
11005
- * (every agent has memory); the platform tools are gated by the agent's
11006
- * integrations. Deduped by name so an agent bridging both platforms doesn't get
11007
- * the shared read helpers (getCurrentChannel/listChannelMembers/getUserProfile)
11008
- * twice — the first platform's variant wins, and both behave identically.
11009
- */
11010
- function toolsForIntegrations(integrations) {
11011
- const tools = [];
11012
- const seen = /* @__PURE__ */ new Set();
11013
- const add = (set) => {
11014
- for (const t of set) {
11015
- if (seen.has(t.name)) continue;
11016
- seen.add(t.name);
11017
- tools.push(t);
11018
- }
11019
- };
11020
- add(MEMORY_TOOLS);
11021
- if (integrations.some((i) => i.platform === "slack")) add(SLACK_TOOLS);
11022
- if (integrations.some((i) => i.platform === "telegram")) add(TELEGRAM_TOOLS);
11023
- return tools;
11024
- }
11025
- //#endregion
11026
10686
  //#region src/router/routing-table.ts
11027
10687
  const KIND_ORDER = [
11028
10688
  "mention",
@@ -197403,65 +197063,6 @@ function createSessionReader(store, workspaceUrlFor) {
197403
197063
  };
197404
197064
  }
197405
197065
  //#endregion
197406
- //#region src/agents/memory-provider.ts
197407
- /**
197408
- * `managed` memory: our `<agent-root>/memory/` directory. A thin, behavior-neutral
197409
- * facade over `agents/memory.ts` — every method delegates to the existing primitive
197410
- * and lets its error classes (`MemoryPathError` / `MemoryTooLargeError` /
197411
- * `MemoryConflictError`) propagate raw, so the MCP + CP error mappings are unchanged.
197412
- */
197413
- var ManagedMemoryProvider = class {
197414
- agentDirByAgent;
197415
- kind = "managed";
197416
- /** `agentDirByAgent` resolves an agent id → its root dir (which holds `memory/`),
197417
- * or undefined for an unknown agent — the same resolver the pre-provider call
197418
- * sites used. */
197419
- constructor(agentDirByAgent) {
197420
- this.agentDirByAgent = agentDirByAgent;
197421
- }
197422
- dirFor(agentId) {
197423
- const dir = this.agentDirByAgent(agentId);
197424
- if (!dir) throw new Error(`unknown agent ${agentId}`);
197425
- return dir;
197426
- }
197427
- runtimeEnv(_runtime) {
197428
- return {};
197429
- }
197430
- ensure(scope, agentName) {
197431
- ensureMemory(this.dirFor(scope.agentId), agentName);
197432
- }
197433
- async injectAtSessionStart(scope) {
197434
- return readIndex(this.dirFor(scope.agentId));
197435
- }
197436
- async recordTurn(_scope, _turn) {}
197437
- tools() {
197438
- return MEMORY_TOOLS;
197439
- }
197440
- async list(scope) {
197441
- return listMemory(this.dirFor(scope.agentId));
197442
- }
197443
- async read(scope, path) {
197444
- return {
197445
- path,
197446
- content: await readMemoryFile(this.dirFor(scope.agentId), path)
197447
- };
197448
- }
197449
- async write(scope, path, content, ifMatch) {
197450
- const { size, mtime } = await writeMemoryFile(this.dirFor(scope.agentId), path, content, ifMatch);
197451
- return {
197452
- ok: true,
197453
- path,
197454
- size,
197455
- mtime
197456
- };
197457
- }
197458
- };
197459
- /** Build the daemon's memory provider. Managed today; the config-driven selection
197460
- * between native/managed/external is a later phase. */
197461
- function createManagedMemoryProvider(agentDirByAgent) {
197462
- return new ManagedMemoryProvider(agentDirByAgent);
197463
- }
197464
- //#endregion
197465
197066
  //#region src/cp/workspace-git.ts
197466
197067
  /**
197467
197068
  * `WorkspaceGit` — the seam answering the CP's `workspace/gitstatus` and
@@ -197651,6 +197252,7 @@ function applySpecFields(raw, spec, opts) {
197651
197252
  else raw.permissionMode = spec.permissionMode;
197652
197253
  if (spec.pause !== void 0) raw.pause = spec.pause;
197653
197254
  if (spec.mcpServers !== void 0) raw.mcpServers = spec.mcpServers;
197255
+ if (spec.memory !== void 0) raw.memory = spec.memory;
197654
197256
  if (spec.outputMode !== void 0) {
197655
197257
  const out = typeof raw.output === "object" && raw.output !== null ? raw.output : {};
197656
197258
  out.mode = spec.outputMode;
@@ -213774,7 +213376,13 @@ var Daemon = class Daemon {
213774
213376
  opts;
213775
213377
  store;
213776
213378
  mcp;
213777
- memory = createManagedMemoryProvider((id) => this.agents.get(id)?.dir);
213379
+ memory = createMemoryProvider((id) => this.agents.get(id)?.dir, (id) => {
213380
+ const a = this.agents.get(id);
213381
+ return a ? this.runtimes[a.runtime] : void 0;
213382
+ }, (id) => {
213383
+ const a = this.agents.get(id);
213384
+ return a ? memoryKindOf(a) : "managed";
213385
+ });
213778
213386
  gitCreds;
213779
213387
  gitCredServer;
213780
213388
  agents = /* @__PURE__ */ new Map();
@@ -213936,7 +213544,8 @@ var Daemon = class Daemon {
213936
213544
  memory: this.memory,
213937
213545
  mcpServersFor: ({ agent, channel, thread }) => {
213938
213546
  const servers = [];
213939
- const tools = toolsForIntegrations(agent.integrations);
213547
+ let tools = toolsForIntegrations(agent.integrations);
213548
+ if (memoryKindOf(agent) === "native") tools = tools.filter((t) => !MEMORY_TOOL_NAMES.has(t.name));
213940
213549
  const integrationId = agent.integrations[0]?.id;
213941
213550
  if (tools.length > 0) {
213942
213551
  const token = this.mcp.register({
@@ -214385,6 +213994,7 @@ var Daemon = class Daemon {
214385
213994
  env: {
214386
213995
  ...agentChildEnv(agent),
214387
213996
  ...cpRuntimeEnv(agent),
213997
+ ...memoryProviderFor(agent, runtime).runtimeEnv(),
214388
213998
  ...agent.workspace.mode === "git-repo" && agent.workspace.gitCredential === "github-app" ? sessionGitEnv(agent.id) : {}
214389
213999
  },
214390
214000
  configPrefs: {
@@ -216501,4 +216111,4 @@ async function runForeground(opts, deps = {}) {
216501
216111
  //#endregion
216502
216112
  export { ClientTransport as i, CP_SUBPROTOCOL as n, CP_WS_PATH as r, runForeground as t };
216503
216113
 
216504
- //# sourceMappingURL=run-foreground-Cdxkfe7g.js.map
216114
+ //# sourceMappingURL=run-foreground-Caze66K4.js.map