@sulala/agent-os 0.1.23 → 0.1.24

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.
@@ -5,8 +5,8 @@
5
5
  <link rel="icon" type="image/png" href="/logo_dark.png" />
6
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
7
  <title>Sulala Agent Dashboard</title>
8
- <script type="module" crossorigin src="/assets/index-DBbAuioJ.js"></script>
9
- <link rel="stylesheet" crossorigin href="/assets/index-C2orVAIw.css">
8
+ <script type="module" crossorigin src="/assets/index-DdMu_Z6v.js"></script>
9
+ <link rel="stylesheet" crossorigin href="/assets/index-CVI9FAmG.css">
10
10
  </head>
11
11
  <body>
12
12
  <div id="root"></div>
@@ -0,0 +1,11 @@
1
+ {
2
+ "id": "crm_hubspot_agent",
3
+ "name": "HubSpot CRM Agent",
4
+ "description": "Updates HubSpot from pipeline output: creates and updates contacts and deals using the crm-hubspot skill. Use as the last node in a sales graph to sync follow-up and lead status to HubSpot. Configure HUBSPOT_ACCESS_TOKEN in Skills → crm-hubspot.",
5
+ "model": "gpt-4o-mini",
6
+ "skills": ["memory", "crm-hubspot"],
7
+ "personality": "Concise and factual. Parse the input, call the crm-hubspot scripts via exec with skill_id 'crm-hubspot', then return only a short summary of what was created or updated in HubSpot.",
8
+ "limits": {
9
+ "max_turns": 15
10
+ }
11
+ }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "id": "research_agent",
3
3
  "name": "Research Assistant",
4
- "description": "Search the web, fetch and summarize URLs, and follow RSS feeds. Use when the user asks to search for something, read a page, or get updates from a feed. Configure web-search API key in the skill if required.",
4
+ "description": "Search the web, fetch and summarize URLs, and follow RSS feeds. Use when the user asks to search for something, read a page, or get updates from a feed. In a graph/pipeline, only output your finding (e.g. the news summary); do not post to social media or delegate to other agents. Configure web-search API key in the skill if required.",
5
5
  "model": "gpt-4o-mini",
6
6
  "skills": ["memory", "web-search", "fetch", "rss"],
7
7
  "limits": {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "id": "social_media_agent",
3
3
  "name": "Social Media Assistant",
4
- "description": "Post to social networks (e.g. Bluesky), read your timeline, and reply to posts. Configure credentials in the skill (Agents → Edit → Skills, or Settings). Currently supports Bluesky.",
4
+ "description": "Post to social networks (e.g. Bluesky), read your timeline, and reply to posts. When used as the last node in a graph, post the text you receive to Bluesky. Configure credentials in the skill (Agents → Edit → Skills, or Settings). Currently supports Bluesky.",
5
5
  "model": "gpt-4o-mini",
6
6
  "skills": ["memory", "bluesky"],
7
7
  "limits": {
@@ -0,0 +1,10 @@
1
+ {
2
+ "id": "source_verify_agent",
3
+ "name": "Source Verify Agent",
4
+ "description": "Verify and summarize sources for news or claims. Use when the user or a pipeline asks to verify a source or fact-check. In a graph/pipeline, only output your verification result; do not post to social media or delegate to other agents.",
5
+ "model": "gpt-4o-mini",
6
+ "skills": ["memory", "web-search", "fetch"],
7
+ "limits": {
8
+ "max_turns": 15
9
+ }
10
+ }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "id": "writer_agent",
3
3
  "name": "Writer Assistant",
4
- "description": "Draft and send email (Gmail) and translate text. Use when the user wants to send an email or translate content. Gmail requires connection via Portal or skill config.",
4
+ "description": "Draft and send email (Gmail) and translate text. Use when the user wants to send an email or translate content. In a graph/pipeline, only rewrite or draft the content you are given; do not post to social media or delegate to other agents. Gmail requires connection via Portal or skill config.",
5
5
  "model": "gpt-4o-mini",
6
6
  "skills": ["memory", "gmail", "translate"],
7
7
  "limits": {
@@ -0,0 +1,32 @@
1
+ ---
2
+ name: content-writing
3
+ description: Guidelines for writing articles and summaries. Use when the agent is the Writer in a newsroom pipeline, or when the user asks for an article, summary, or post draft.
4
+ metadata:
5
+ clawdbot:
6
+ emoji: "✍️"
7
+ ---
8
+
9
+ # Content writing
10
+
11
+ Use this when you are the **Writer** agent: you receive topics, claims, or bullet points from other agents (e.g. News, Fact) and produce an article or summary.
12
+
13
+ ## Output types
14
+
15
+ - **Summary** — Short (2–4 sentences or bullets). Key facts only, neutral tone.
16
+ - **Article** — Headline + 2–5 short paragraphs. Clear structure: lead, key points, closing.
17
+ - **Social post** — One short paragraph or 1–3 sentences, ready for Bluesky or similar (e.g. under 300 characters if needed).
18
+
19
+ ## Guidelines
20
+
21
+ 1. **Tone:** Neutral and factual for news; avoid speculation unless labeled as such.
22
+ 2. **Structure:** Lead with the main point; then supporting details; end with implication or next step if relevant.
23
+ 3. **Attribution:** When facts come from a specific source, mention it (e.g. "According to …", "Source: …").
24
+ 4. **Length:** Match the requested format (summary vs article vs post). If not specified, default to a short article (3–5 paragraphs).
25
+ 5. **No fabrication:** Only state facts that were provided or that you can infer from the given context; do not invent quotes or statistics.
26
+
27
+ ## Workflow
28
+
29
+ 1. Take the input (topic, verified facts, headlines, or bullet points).
30
+ 2. Choose the right output type (summary / article / post).
31
+ 3. Draft the content following the guidelines above.
32
+ 4. Optionally output in Markdown; if the pipeline needs HTML, the next step can use markdown-to-html.
package/dist/cli.js CHANGED
@@ -23180,8 +23180,8 @@ function formatLLMErrorForUser(err) {
23180
23180
  }
23181
23181
  function runAgentInner(options) {
23182
23182
  return (async () => {
23183
- const { task, agent, conversationHistory = [] } = options;
23184
- const maxTurns = agent.limits?.max_turns ?? 10;
23183
+ const { task, agent, conversationHistory = [], maxTurnsOverride } = options;
23184
+ const maxTurns = maxTurnsOverride ?? agent.limits?.max_turns ?? 10;
23185
23185
  const maxTokens = agent.limits?.max_tokens;
23186
23186
  await ensureWorkspace(agent.id);
23187
23187
  await loadSkillsForAgent(agent);
@@ -23415,8 +23415,8 @@ async function runAgent(options) {
23415
23415
  return runAgentInner(options);
23416
23416
  }
23417
23417
  async function runAgentStream(options, onEvent) {
23418
- const { task, agent, conversationHistory = [] } = options;
23419
- const maxTurns = agent.limits?.max_turns ?? 10;
23418
+ const { task, agent, conversationHistory = [], maxTurnsOverride } = options;
23419
+ const maxTurns = maxTurnsOverride ?? agent.limits?.max_turns ?? 10;
23420
23420
  const maxTokens = agent.limits?.max_tokens;
23421
23421
  await ensureWorkspace(agent.id);
23422
23422
  await loadSkillsForAgent(agent);
@@ -25375,44 +25375,87 @@ var require_node_cron = __commonJS((exports) => {
25375
25375
  });
25376
25376
 
25377
25377
  // src/core/graphs.ts
25378
- import { readFile as readFile7, readdir as readdir4, writeFile as writeFile4, mkdir as mkdir5 } from "fs/promises";
25378
+ import { readFile as readFile7, readdir as readdir4, writeFile as writeFile4, mkdir as mkdir5, copyFile, unlink as unlink2 } from "fs/promises";
25379
25379
  import { join as join9 } from "path";
25380
+ import { existsSync as existsSync3 } from "fs";
25380
25381
  function getGraphsDir() {
25381
25382
  return process.env.AGENT_OS_GRAPHS_DIR || DEFAULT_GRAPHS_DIR;
25382
25383
  }
25384
+ function getSeedGraphsDir() {
25385
+ if (process.env.AGENT_OS_SEED_GRAPHS_DIR)
25386
+ return process.env.AGENT_OS_SEED_GRAPHS_DIR;
25387
+ const fromDist = join9(import.meta.dir, "..", "data", "graphs");
25388
+ const fromSrc = join9(import.meta.dir, "..", "..", "data", "graphs");
25389
+ if (existsSync3(fromDist))
25390
+ return fromDist;
25391
+ if (existsSync3(fromSrc))
25392
+ return fromSrc;
25393
+ return join9(process.cwd(), "data", "graphs");
25394
+ }
25383
25395
  async function listGraphs() {
25384
25396
  const dir = getGraphsDir();
25397
+ let entries;
25385
25398
  try {
25386
- const entries = await readdir4(dir);
25387
- const summaries = [];
25388
- for (const name of entries) {
25389
- if (name.endsWith(".json")) {
25390
- const id = name.replace(/\.graph\.json$/, "").replace(/\.json$/, "");
25391
- if (id)
25392
- summaries.push({ id });
25399
+ entries = await readdir4(dir);
25400
+ } catch (err) {
25401
+ if (err.code !== "ENOENT")
25402
+ throw err;
25403
+ entries = [];
25404
+ }
25405
+ if (entries.length === 0) {
25406
+ const seedDir = getSeedGraphsDir();
25407
+ try {
25408
+ const seedEntries = await readdir4(seedDir);
25409
+ await mkdir5(dir, { recursive: true });
25410
+ for (const name of seedEntries) {
25411
+ if (name.endsWith(".json")) {
25412
+ await copyFile(join9(seedDir, name), join9(dir, name));
25413
+ }
25393
25414
  }
25415
+ entries = await readdir4(dir);
25416
+ } catch {}
25417
+ }
25418
+ const summaries = [];
25419
+ for (const name of entries) {
25420
+ if (name.endsWith(".json")) {
25421
+ const id = name.replace(/\.graph\.json$/, "").replace(/\.json$/, "");
25422
+ if (id)
25423
+ summaries.push({ id });
25394
25424
  }
25395
- return summaries;
25396
- } catch (err) {
25397
- if (err.code === "ENOENT")
25398
- return [];
25399
- throw err;
25400
25425
  }
25426
+ return summaries;
25401
25427
  }
25402
25428
  async function loadGraph(id) {
25403
25429
  const dir = getGraphsDir();
25404
25430
  try {
25405
- const entries = await readdir4(dir);
25431
+ let entries;
25432
+ try {
25433
+ entries = await readdir4(dir);
25434
+ } catch (e) {
25435
+ if (e.code !== "ENOENT")
25436
+ throw e;
25437
+ entries = [];
25438
+ }
25406
25439
  const file = entries.find((name) => name === `${id}.json` || name === `${id}.graph.json`);
25407
- if (!file)
25440
+ if (file) {
25441
+ const raw = await readFile7(join9(dir, file), "utf-8");
25442
+ const parsed = JSON.parse(raw);
25443
+ validateGraph(parsed);
25444
+ return parsed;
25445
+ }
25446
+ const seedDir = getSeedGraphsDir();
25447
+ const seedFile = `${id}.json`;
25448
+ try {
25449
+ const raw = await readFile7(join9(seedDir, seedFile), "utf-8");
25450
+ const parsed = JSON.parse(raw);
25451
+ validateGraph(parsed);
25452
+ await mkdir5(dir, { recursive: true });
25453
+ await writeFile4(join9(dir, seedFile), raw, "utf-8");
25454
+ return parsed;
25455
+ } catch {
25408
25456
  return null;
25409
- const raw = await readFile7(join9(dir, file), "utf-8");
25410
- const parsed = JSON.parse(raw);
25411
- validateGraph(parsed);
25412
- return parsed;
25457
+ }
25413
25458
  } catch (err) {
25414
- if (err.code === "ENOENT")
25415
- return null;
25416
25459
  console.error("[graphs] Failed to load graph:", err);
25417
25460
  return null;
25418
25461
  }
@@ -25424,6 +25467,22 @@ async function saveGraph(graph) {
25424
25467
  const path = join9(dir, `${graph.id}.json`);
25425
25468
  await writeFile4(path, JSON.stringify(graph, null, 2), "utf-8");
25426
25469
  }
25470
+ async function deleteGraph(id) {
25471
+ if (!id || typeof id !== "string")
25472
+ throw new Error("Graph id required");
25473
+ const dir = getGraphsDir();
25474
+ let entries;
25475
+ try {
25476
+ entries = await readdir4(dir);
25477
+ } catch (err) {
25478
+ if (err.code !== "ENOENT")
25479
+ throw err;
25480
+ return;
25481
+ }
25482
+ const file = entries.find((name) => name === `${id}.json` || name === `${id}.graph.json`);
25483
+ if (file)
25484
+ await unlink2(join9(dir, file));
25485
+ }
25427
25486
  function validateGraph(graph) {
25428
25487
  if (!graph || typeof graph !== "object") {
25429
25488
  throw new Error("Graph must be an object");
@@ -25490,7 +25549,7 @@ function getPredecessors(graph) {
25490
25549
  return pred;
25491
25550
  }
25492
25551
  async function runGraph(options) {
25493
- const { graph, input } = options;
25552
+ const { graph, input, max_turns_per_node = DEFAULT_GRAPH_MAX_TURNS_PER_NODE } = options;
25494
25553
  const levels = topologicalLevels(graph);
25495
25554
  const predecessors = getPredecessors(graph);
25496
25555
  const outputs = new Map;
@@ -25515,7 +25574,11 @@ async function runGraph(options) {
25515
25574
  const taskInput = preds.length === 0 ? input : preds.map((p) => outputs.get(p) ?? "").filter(Boolean).join(`
25516
25575
 
25517
25576
  `) || input;
25518
- const result = await runAgent({ agent, task: taskInput });
25577
+ const result = await runAgent({
25578
+ agent,
25579
+ task: taskInput,
25580
+ maxTurnsOverride: max_turns_per_node
25581
+ });
25519
25582
  outputs.set(node.id, result.output || "");
25520
25583
  return {
25521
25584
  node_id: node.id,
@@ -25538,7 +25601,7 @@ async function runGraph(options) {
25538
25601
  };
25539
25602
  }
25540
25603
  async function runGraphStream(options, onEvent) {
25541
- const { graph, input } = options;
25604
+ const { graph, input, max_turns_per_node = DEFAULT_GRAPH_MAX_TURNS_PER_NODE } = options;
25542
25605
  const levels = topologicalLevels(graph);
25543
25606
  const predecessors = getPredecessors(graph);
25544
25607
  const outputs = new Map;
@@ -25564,7 +25627,11 @@ async function runGraphStream(options, onEvent) {
25564
25627
  const taskInput = preds.length === 0 ? input : preds.map((p) => outputs.get(p) ?? "").filter(Boolean).join(`
25565
25628
 
25566
25629
  `) || input;
25567
- const result = await runAgent({ agent, task: taskInput });
25630
+ const result = await runAgent({
25631
+ agent,
25632
+ task: taskInput,
25633
+ maxTurnsOverride: max_turns_per_node
25634
+ });
25568
25635
  outputs.set(node.id, result.output || "");
25569
25636
  const payload = {
25570
25637
  node_id: node.id,
@@ -25592,7 +25659,7 @@ async function runGraphStream(options, onEvent) {
25592
25659
  throw err;
25593
25660
  }
25594
25661
  }
25595
- var DEFAULT_GRAPHS_DIR;
25662
+ var DEFAULT_GRAPHS_DIR, DEFAULT_GRAPH_MAX_TURNS_PER_NODE = 5;
25596
25663
  var init_graphs = __esm(() => {
25597
25664
  init_agent_registry();
25598
25665
  init_runtime();
@@ -29609,7 +29676,7 @@ __export(exports_server, {
29609
29676
  startServer: () => startServer
29610
29677
  });
29611
29678
  import { join as join13, dirname as dirname2, resolve as resolve4 } from "path";
29612
- import { mkdirSync, existsSync as existsSync3 } from "fs";
29679
+ import { mkdirSync, existsSync as existsSync4 } from "fs";
29613
29680
  import { mkdir as mkdir7 } from "fs/promises";
29614
29681
  function isAuthExempt(pathname, method) {
29615
29682
  if (method === "OPTIONS")
@@ -29683,7 +29750,7 @@ function broadcastEvent(event) {
29683
29750
  }
29684
29751
  }
29685
29752
  function serveDashboard(pathname) {
29686
- if (!existsSync3(DASHBOARD_DIST) || !existsSync3(join13(DASHBOARD_DIST, "index.html"))) {
29753
+ if (!existsSync4(DASHBOARD_DIST) || !existsSync4(join13(DASHBOARD_DIST, "index.html"))) {
29687
29754
  return null;
29688
29755
  }
29689
29756
  const decoded = decodeURIComponent(pathname);
@@ -29692,7 +29759,7 @@ function serveDashboard(pathname) {
29692
29759
  }
29693
29760
  const subpath = decoded === "/" ? "index.html" : decoded.slice(1);
29694
29761
  const filePath = join13(DASHBOARD_DIST, subpath);
29695
- if (existsSync3(filePath)) {
29762
+ if (existsSync4(filePath)) {
29696
29763
  const file = Bun.file(filePath);
29697
29764
  const ext = subpath.split(".").pop() ?? "";
29698
29765
  const mime = {
@@ -29713,7 +29780,7 @@ function serveDashboard(pathname) {
29713
29780
  });
29714
29781
  }
29715
29782
  const indexPath = join13(DASHBOARD_DIST, "index.html");
29716
- if (existsSync3(indexPath)) {
29783
+ if (existsSync4(indexPath)) {
29717
29784
  return new Response(Bun.file(indexPath), {
29718
29785
  headers: { "Content-Type": "text/html" }
29719
29786
  });
@@ -29930,6 +29997,16 @@ function createRoutes() {
29930
29997
  const msg = e instanceof Error ? e.message : String(e);
29931
29998
  return jsonResponse({ error: msg }, 400);
29932
29999
  }
30000
+ },
30001
+ DELETE: async (req) => {
30002
+ const id = decodeURIComponent(req.params.id);
30003
+ try {
30004
+ await deleteGraph(id);
30005
+ return Response.json({ ok: true }, { headers: CORS_HEADERS });
30006
+ } catch (e) {
30007
+ const msg = e instanceof Error ? e.message : String(e);
30008
+ return jsonResponse({ error: msg }, 400);
30009
+ }
29933
30010
  }
29934
30011
  },
29935
30012
  "/api/memory/write": {
@@ -30150,7 +30227,7 @@ async function startServer() {
30150
30227
  await loadPlugins();
30151
30228
  await seedAgentsIfEmpty();
30152
30229
  const dashboardSecret = await getDashboardSecret();
30153
- const dashboardMissing = !existsSync3(DASHBOARD_DIST) || !existsSync3(join13(DASHBOARD_DIST, "index.html"));
30230
+ const dashboardMissing = !existsSync4(DASHBOARD_DIST) || !existsSync4(join13(DASHBOARD_DIST, "index.html"));
30154
30231
  if (dashboardMissing) {
30155
30232
  console.warn(`[sulala] Dashboard not found at ${DASHBOARD_DIST}. From package root run: cd dashboard && npm run build. If using a global install, reinstall: bun install -g @sulala/agent-os@latest`);
30156
30233
  }
@@ -30239,7 +30316,7 @@ var init_server = __esm(() => {
30239
30316
  const root = join13(import.meta.dir, "..");
30240
30317
  const a = resolve4(join13(root, "dashboard-dist"));
30241
30318
  const b = resolve4(join13(root, "dashboard", "dist"));
30242
- if (existsSync3(a) && existsSync3(join13(a, "index.html")))
30319
+ if (existsSync4(a) && existsSync4(join13(a, "index.html")))
30243
30320
  return a;
30244
30321
  return b;
30245
30322
  })();
@@ -30272,8 +30349,8 @@ init_loader();
30272
30349
  init_agent_registry();
30273
30350
  init_runtime();
30274
30351
  import { join as join14, dirname as dirname3 } from "path";
30275
- import { readFile as readFile10, writeFile as writeFile6, mkdir as mkdir8, unlink as unlink2 } from "fs/promises";
30276
- import { existsSync as existsSync4, readFileSync } from "fs";
30352
+ import { readFile as readFile10, writeFile as writeFile6, mkdir as mkdir8, unlink as unlink3 } from "fs/promises";
30353
+ import { existsSync as existsSync5, readFileSync } from "fs";
30277
30354
  var PID_FILE = join14(getAgentOsHome(), "sulala.pid");
30278
30355
  var DEFAULT_PORT = 3010;
30279
30356
  function openDashboard() {
@@ -30336,7 +30413,7 @@ async function cmdStart(args) {
30336
30413
  await mkdir8(getAgentOsHome(), { recursive: true });
30337
30414
  const projectRoot = join14(import.meta.dir, "..");
30338
30415
  const distEntry = join14(projectRoot, "dist", "index.js");
30339
- const serverEntry = existsSync4(distEntry) ? "dist/index.js" : "src/index.ts";
30416
+ const serverEntry = existsSync5(distEntry) ? "dist/index.js" : "src/index.ts";
30340
30417
  const child = Bun.spawn(["bun", "run", serverEntry], {
30341
30418
  cwd: projectRoot,
30342
30419
  stdout: "ignore",
@@ -30353,7 +30430,7 @@ async function cmdStart(args) {
30353
30430
  await startServer2();
30354
30431
  }
30355
30432
  async function cmdStop() {
30356
- if (!existsSync4(PID_FILE)) {
30433
+ if (!existsSync5(PID_FILE)) {
30357
30434
  console.error("No PID file found. Is the server running with 'sulala start --daemon'?");
30358
30435
  process.exit(1);
30359
30436
  }
@@ -30374,11 +30451,11 @@ async function cmdStop() {
30374
30451
  process.exit(1);
30375
30452
  }
30376
30453
  }
30377
- await unlink2(PID_FILE).catch(() => {});
30454
+ await unlink3(PID_FILE).catch(() => {});
30378
30455
  console.log("Sulala server stopped.");
30379
30456
  }
30380
30457
  async function startServerDaemonIfNeeded() {
30381
- if (existsSync4(PID_FILE)) {
30458
+ if (existsSync5(PID_FILE)) {
30382
30459
  try {
30383
30460
  const pidStr = await readFile10(PID_FILE, "utf-8");
30384
30461
  const pid = parseInt(pidStr.trim(), 10);
@@ -30391,7 +30468,7 @@ async function startServerDaemonIfNeeded() {
30391
30468
  await mkdir8(getAgentOsHome(), { recursive: true });
30392
30469
  const projectRoot = join14(import.meta.dir, "..");
30393
30470
  const distEntry = join14(projectRoot, "dist", "index.js");
30394
- const serverEntry = existsSync4(distEntry) ? "dist/index.js" : "src/index.ts";
30471
+ const serverEntry = existsSync5(distEntry) ? "dist/index.js" : "src/index.ts";
30395
30472
  const child = Bun.spawn(["bun", "run", serverEntry], {
30396
30473
  cwd: projectRoot,
30397
30474
  stdout: "ignore",
@@ -30408,7 +30485,7 @@ async function cmdOnboard() {
30408
30485
  await mkdir8(home, { recursive: true });
30409
30486
  await mkdir8(dirname3(getMemoryDbPath()), { recursive: true });
30410
30487
  const configPath = join14(home, "config.json");
30411
- if (!existsSync4(configPath)) {
30488
+ if (!existsSync5(configPath)) {
30412
30489
  const dashboardSecret = generateDashboardSecret();
30413
30490
  await writeFile6(configPath, JSON.stringify({
30414
30491
  provider: null,
@@ -30471,7 +30548,7 @@ async function cmdUpdate() {
30471
30548
  console.warn("Could not update package from npm (run 'bun install -g @sulala/agent-os@latest' manually):", err.trim() || out.trim());
30472
30549
  }
30473
30550
  const dbPath = getMemoryDbPath();
30474
- if (!existsSync4(dbPath)) {
30551
+ if (!existsSync5(dbPath)) {
30475
30552
  console.log("No database found. Run 'sulala onboard' to set up agents and skills.");
30476
30553
  return;
30477
30554
  }
@@ -30511,7 +30588,7 @@ async function cmdRun(args) {
30511
30588
  process.exit(1);
30512
30589
  }
30513
30590
  const dbPath = getMemoryDbPath();
30514
- if (existsSync4(dbPath)) {
30591
+ if (existsSync5(dbPath)) {
30515
30592
  setAgentStore(new MemoryStore(dbPath));
30516
30593
  }
30517
30594
  const agent = await getAgent(agentId);