@poncho-ai/harness 0.24.0 → 0.25.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.
package/dist/index.js CHANGED
@@ -1402,7 +1402,8 @@ if (result.compacted) {
1402
1402
  When \`memory.enabled\` is true in \`poncho.config.js\`, the harness enables a simple memory model:
1403
1403
 
1404
1404
  - A single persistent main memory document is loaded at run start and interpolated into the system prompt under \`## Persistent Memory\`.
1405
- - \`memory_main_update\` can replace or append to that document. The tool description instructs the model to proactively evaluate each turn whether durable memory should be updated.
1405
+ - \`memory_main_write\` overwrites the entire memory document (for initial writes or full rewrites).
1406
+ - \`memory_main_edit\` performs targeted string-replacement edits on memory (find \`old_str\`, replace with \`new_str\`), mirroring \`edit_file\` semantics. The tool description instructs the model to proactively evaluate each turn whether durable memory should be updated.
1406
1407
  - \`conversation_recall\` can search recent prior conversations (keyword scoring) when historical context is relevant (\`as we discussed\`, \`last time\`, etc.).
1407
1408
 
1408
1409
  \`\`\`javascript
@@ -1420,9 +1421,10 @@ export default {
1420
1421
 
1421
1422
  Available memory tools:
1422
1423
 
1423
- - \`memory_main_get\`
1424
- - \`memory_main_update\`
1425
- - \`conversation_recall\`
1424
+ - \`memory_main_get\` \u2014 read the current memory document
1425
+ - \`memory_main_write\` \u2014 overwrite the entire memory document
1426
+ - \`memory_main_edit\` \u2014 edit memory via exact string replacement (\`old_str\` / \`new_str\`)
1427
+ - \`conversation_recall\` \u2014 search past conversations
1426
1428
  `,
1427
1429
  "configuration": `# Configuration & Security
1428
1430
 
@@ -2028,6 +2030,8 @@ var ponchoDocsTool = defineTool({
2028
2030
 
2029
2031
  // src/harness.ts
2030
2032
  import { randomUUID as randomUUID3 } from "crypto";
2033
+ import { readFile as readFile7 } from "fs/promises";
2034
+ import { resolve as resolve9 } from "path";
2031
2035
  import { getTextContent as getTextContent3 } from "@poncho-ai/sdk";
2032
2036
 
2033
2037
  // src/upload-store.ts
@@ -2384,14 +2388,9 @@ var InMemoryMemoryStore = class {
2384
2388
  return this.mainMemory;
2385
2389
  }
2386
2390
  async updateMainMemory(input) {
2387
- const now2 = Date.now();
2388
- const existing = await this.getMainMemory();
2389
- const nextContent = input.mode === "append" && existing.content ? `${existing.content}
2390
-
2391
- ${input.content}`.trim() : input.content;
2392
2391
  this.mainMemory = {
2393
- content: nextContent.trim(),
2394
- updatedAt: now2
2392
+ content: input.content.trim(),
2393
+ updatedAt: Date.now()
2395
2394
  };
2396
2395
  return this.mainMemory;
2397
2396
  }
@@ -2449,12 +2448,8 @@ var FileMainMemoryStore = class {
2449
2448
  }
2450
2449
  async updateMainMemory(input) {
2451
2450
  await this.ensureLoaded();
2452
- const existing = await this.getMainMemory();
2453
- const nextContent = input.mode === "append" && existing.content ? `${existing.content}
2454
-
2455
- ${input.content}`.trim() : input.content;
2456
2451
  this.mainMemory = {
2457
- content: nextContent.trim(),
2452
+ content: input.content.trim(),
2458
2453
  updatedAt: Date.now()
2459
2454
  };
2460
2455
  await this.persist();
@@ -2493,8 +2488,7 @@ var KeyValueMainMemoryStoreBase = class {
2493
2488
  }
2494
2489
  } catch {
2495
2490
  await this.memoryFallback.updateMainMemory({
2496
- content: payload.main.content,
2497
- mode: "replace"
2491
+ content: payload.main.content
2498
2492
  });
2499
2493
  }
2500
2494
  }
@@ -2505,11 +2499,8 @@ var KeyValueMainMemoryStoreBase = class {
2505
2499
  async updateMainMemory(input) {
2506
2500
  const key = this.key();
2507
2501
  const payload = await this.readPayload(key);
2508
- const nextContent = input.mode === "append" && payload.main.content ? `${payload.main.content}
2509
-
2510
- ${input.content}`.trim() : input.content;
2511
2502
  payload.main = {
2512
- content: nextContent.trim(),
2503
+ content: input.content.trim(),
2513
2504
  updatedAt: Date.now()
2514
2505
  };
2515
2506
  await this.writePayload(key, payload);
@@ -2775,19 +2766,14 @@ var createMemoryTools = (store, options) => {
2775
2766
  }
2776
2767
  }),
2777
2768
  defineTool2({
2778
- name: "memory_main_update",
2779
- description: "Update persistent main memory when new stable preferences, long-term goals, or durable facts appear. Proactively evaluate every turn whether memory should be updated, and avoid storing ephemeral details.",
2769
+ name: "memory_main_write",
2770
+ description: "Overwrite the entire persistent main memory document. Use for initial writes or full rewrites. Prefer memory_main_edit for targeted changes to existing memory.",
2780
2771
  inputSchema: {
2781
2772
  type: "object",
2782
2773
  properties: {
2783
- mode: {
2784
- type: "string",
2785
- enum: ["replace", "append"],
2786
- description: "replace overwrites memory; append adds content to the end"
2787
- },
2788
2774
  content: {
2789
2775
  type: "string",
2790
- description: "The memory content to write"
2776
+ description: "The full memory content to write"
2791
2777
  }
2792
2778
  },
2793
2779
  required: ["content"],
@@ -2798,8 +2784,50 @@ var createMemoryTools = (store, options) => {
2798
2784
  if (!content) {
2799
2785
  throw new Error("content is required");
2800
2786
  }
2801
- const mode = input.mode === "append" || input.mode === "replace" ? input.mode : "replace";
2802
- const memory = await store.updateMainMemory({ content, mode });
2787
+ const memory = await store.updateMainMemory({ content });
2788
+ return { ok: true, memory };
2789
+ }
2790
+ }),
2791
+ defineTool2({
2792
+ name: "memory_main_edit",
2793
+ description: "Edit persistent main memory by replacing an exact string match with new content. The old_str must match exactly one location in memory. Use an empty new_str to delete matched content. Proactively evaluate every turn whether memory should be updated.",
2794
+ inputSchema: {
2795
+ type: "object",
2796
+ properties: {
2797
+ old_str: {
2798
+ type: "string",
2799
+ description: "The exact text to find and replace (must be unique in memory). Include surrounding context if needed to ensure uniqueness."
2800
+ },
2801
+ new_str: {
2802
+ type: "string",
2803
+ description: "The replacement text (use empty string to delete the matched content)"
2804
+ }
2805
+ },
2806
+ required: ["old_str", "new_str"],
2807
+ additionalProperties: false
2808
+ },
2809
+ handler: async (input) => {
2810
+ const oldStr = typeof input.old_str === "string" ? input.old_str : "";
2811
+ const newStr = typeof input.new_str === "string" ? input.new_str : "";
2812
+ if (!oldStr) {
2813
+ throw new Error("old_str must not be empty.");
2814
+ }
2815
+ const current = await store.getMainMemory();
2816
+ const content = current.content;
2817
+ const first = content.indexOf(oldStr);
2818
+ if (first === -1) {
2819
+ throw new Error(
2820
+ "old_str not found in memory. Make sure it matches exactly, including whitespace and line breaks."
2821
+ );
2822
+ }
2823
+ const last = content.lastIndexOf(oldStr);
2824
+ if (first !== last) {
2825
+ throw new Error(
2826
+ "old_str appears multiple times in memory. Please provide more context to ensure a unique match."
2827
+ );
2828
+ }
2829
+ const newContent = content.slice(0, first) + newStr + content.slice(first + oldStr.length);
2830
+ const memory = await store.updateMainMemory({ content: newContent });
2803
2831
  return { ok: true, memory };
2804
2832
  }
2805
2833
  }),
@@ -4688,6 +4716,7 @@ var AgentHarness = class _AgentHarness {
4688
4716
  _browserSession;
4689
4717
  _browserMod;
4690
4718
  parsedAgent;
4719
+ agentFileFingerprint = "";
4691
4720
  mcpBridge;
4692
4721
  subagentManager;
4693
4722
  resolveToolAccess(toolName) {
@@ -4800,20 +4829,17 @@ var AgentHarness = class _AgentHarness {
4800
4829
  return this.parsedAgent?.frontmatter.approvalRequired?.scripts ?? [];
4801
4830
  }
4802
4831
  getRequestedMcpPatterns() {
4803
- const skillPatterns = /* @__PURE__ */ new Set();
4832
+ const patterns = new Set(this.getAgentMcpIntent());
4804
4833
  for (const skillName of this.activeSkillNames) {
4805
4834
  const skill = this.loadedSkills.find((entry) => entry.name === skillName);
4806
4835
  if (!skill) {
4807
4836
  continue;
4808
4837
  }
4809
4838
  for (const pattern of skill.allowedTools.mcp) {
4810
- skillPatterns.add(pattern);
4839
+ patterns.add(pattern);
4811
4840
  }
4812
4841
  }
4813
- if (skillPatterns.size > 0) {
4814
- return [...skillPatterns];
4815
- }
4816
- return this.getAgentMcpIntent();
4842
+ return [...patterns];
4817
4843
  }
4818
4844
  getRequestedScriptPatterns() {
4819
4845
  const patterns = new Set(this.getAgentScriptIntent());
@@ -4829,20 +4855,17 @@ var AgentHarness = class _AgentHarness {
4829
4855
  return [...patterns];
4830
4856
  }
4831
4857
  getRequestedMcpApprovalPatterns() {
4832
- const skillPatterns = /* @__PURE__ */ new Set();
4858
+ const patterns = new Set(this.getAgentMcpApprovalPatterns());
4833
4859
  for (const skillName of this.activeSkillNames) {
4834
4860
  const skill = this.loadedSkills.find((entry) => entry.name === skillName);
4835
4861
  if (!skill) {
4836
4862
  continue;
4837
4863
  }
4838
4864
  for (const pattern of skill.approvalRequired.mcp) {
4839
- skillPatterns.add(pattern);
4865
+ patterns.add(pattern);
4840
4866
  }
4841
4867
  }
4842
- if (skillPatterns.size > 0) {
4843
- return [...skillPatterns];
4844
- }
4845
- return this.getAgentMcpApprovalPatterns();
4868
+ return [...patterns];
4846
4869
  }
4847
4870
  getRequestedScriptApprovalPatterns() {
4848
4871
  const patterns = new Set(this.getAgentScriptApprovalPatterns());
@@ -4973,13 +4996,54 @@ var AgentHarness = class _AgentHarness {
4973
4996
  );
4974
4997
  }
4975
4998
  static SKILL_REFRESH_DEBOUNCE_MS = 3e3;
4976
- async refreshSkillsIfChanged() {
4999
+ /**
5000
+ * Re-read AGENT.md and update the parsed agent when the file has changed
5001
+ * on disk. Returns `true` when the agent was actually re-parsed.
5002
+ *
5003
+ * Preserves the agent identity (id) across reloads so conversation
5004
+ * continuity isn't broken.
5005
+ */
5006
+ async refreshAgentIfChanged() {
4977
5007
  if (this.environment !== "development") {
4978
- return;
5008
+ return false;
4979
5009
  }
4980
- const elapsed = Date.now() - this.lastSkillRefreshAt;
4981
- if (this.lastSkillRefreshAt > 0 && elapsed < _AgentHarness.SKILL_REFRESH_DEBOUNCE_MS) {
4982
- return;
5010
+ try {
5011
+ const agentFilePath = resolve9(this.workingDir, "AGENT.md");
5012
+ const rawContent = await readFile7(agentFilePath, "utf8");
5013
+ if (rawContent === this.agentFileFingerprint) {
5014
+ return false;
5015
+ }
5016
+ const parsed = parseAgentMarkdown(rawContent);
5017
+ if (!parsed.frontmatter.id && this.parsedAgent?.frontmatter.id) {
5018
+ parsed.frontmatter.id = this.parsedAgent.frontmatter.id;
5019
+ }
5020
+ this.parsedAgent = parsed;
5021
+ this.agentFileFingerprint = rawContent;
5022
+ return true;
5023
+ } catch (error) {
5024
+ console.warn(
5025
+ `[poncho][agent] Failed to refresh AGENT.md in development mode: ${error instanceof Error ? error.message : String(error)}`
5026
+ );
5027
+ return false;
5028
+ }
5029
+ }
5030
+ /**
5031
+ * Re-scan skill directories and update metadata, tools, and context window
5032
+ * when skills have changed on disk. Returns `true` when the skill set was
5033
+ * actually updated.
5034
+ *
5035
+ * @param force - bypass the time-based debounce (used for mid-run refreshes
5036
+ * after the agent may have written new skill files).
5037
+ */
5038
+ async refreshSkillsIfChanged(force = false) {
5039
+ if (this.environment !== "development") {
5040
+ return false;
5041
+ }
5042
+ if (!force) {
5043
+ const elapsed = Date.now() - this.lastSkillRefreshAt;
5044
+ if (this.lastSkillRefreshAt > 0 && elapsed < _AgentHarness.SKILL_REFRESH_DEBOUNCE_MS) {
5045
+ return false;
5046
+ }
4983
5047
  }
4984
5048
  this.lastSkillRefreshAt = Date.now();
4985
5049
  try {
@@ -4989,22 +5053,35 @@ var AgentHarness = class _AgentHarness {
4989
5053
  );
4990
5054
  const nextFingerprint = this.buildSkillFingerprint(latestSkills);
4991
5055
  if (nextFingerprint === this.skillFingerprint) {
4992
- return;
5056
+ return false;
4993
5057
  }
4994
5058
  this.loadedSkills = latestSkills;
4995
5059
  this.skillContextWindow = buildSkillContextWindow(latestSkills);
4996
5060
  this.skillFingerprint = nextFingerprint;
4997
5061
  this.registerSkillTools(latestSkills);
4998
- this.activeSkillNames.clear();
5062
+ const latestSkillNames = new Set(latestSkills.map((s) => s.name));
5063
+ for (const name of this.activeSkillNames) {
5064
+ if (!latestSkillNames.has(name)) {
5065
+ this.activeSkillNames.delete(name);
5066
+ }
5067
+ }
5068
+ if (this.mcpBridge) {
5069
+ await this.mcpBridge.discoverTools();
5070
+ }
4999
5071
  await this.refreshMcpTools("skills:changed");
5072
+ return true;
5000
5073
  } catch (error) {
5001
5074
  console.warn(
5002
5075
  `[poncho][skills] Failed to refresh skills in development mode: ${error instanceof Error ? error.message : String(error)}`
5003
5076
  );
5077
+ return false;
5004
5078
  }
5005
5079
  }
5006
5080
  async initialize() {
5007
- this.parsedAgent = await parseAgentFile(this.workingDir);
5081
+ const agentFilePath = resolve9(this.workingDir, "AGENT.md");
5082
+ const agentRawContent = await readFile7(agentFilePath, "utf8");
5083
+ this.parsedAgent = parseAgentMarkdown(agentRawContent);
5084
+ this.agentFileFingerprint = agentRawContent;
5008
5085
  const identity = await ensureAgentIdentity(this.workingDir);
5009
5086
  if (!this.parsedAgent.frontmatter.id) {
5010
5087
  this.parsedAgent.frontmatter.id = identity.id;
@@ -5082,9 +5159,9 @@ var AgentHarness = class _AgentHarness {
5082
5159
  await writeFile6(filePath, json, "utf8");
5083
5160
  },
5084
5161
  async load() {
5085
- const { readFile: readFile8 } = await import("fs/promises");
5162
+ const { readFile: readFile9 } = await import("fs/promises");
5086
5163
  try {
5087
- return await readFile8(filePath, "utf8");
5164
+ return await readFile9(filePath, "utf8");
5088
5165
  } catch {
5089
5166
  return void 0;
5090
5167
  }
@@ -5248,9 +5325,9 @@ var AgentHarness = class _AgentHarness {
5248
5325
  for await (const event of this.run(input)) {
5249
5326
  eventQueue.push(event);
5250
5327
  if (queueResolve) {
5251
- const resolve10 = queueResolve;
5328
+ const resolve11 = queueResolve;
5252
5329
  queueResolve = null;
5253
- resolve10();
5330
+ resolve11();
5254
5331
  }
5255
5332
  }
5256
5333
  } catch (error) {
@@ -5269,8 +5346,8 @@ var AgentHarness = class _AgentHarness {
5269
5346
  if (eventQueue.length > 0) {
5270
5347
  yield eventQueue.shift();
5271
5348
  } else if (!generatorDone) {
5272
- await new Promise((resolve10) => {
5273
- queueResolve = resolve10;
5349
+ await new Promise((resolve11) => {
5350
+ queueResolve = resolve11;
5274
5351
  });
5275
5352
  }
5276
5353
  }
@@ -5308,13 +5385,14 @@ var AgentHarness = class _AgentHarness {
5308
5385
  await this.initialize();
5309
5386
  }
5310
5387
  const memoryPromise = this.memoryStore ? this.memoryStore.getMainMemory() : void 0;
5388
+ await this.refreshAgentIfChanged();
5311
5389
  await this.refreshSkillsIfChanged();
5312
5390
  this._currentRunConversationId = input.conversationId;
5313
5391
  const ownerParam = input.parameters?.__ownerId;
5314
5392
  if (typeof ownerParam === "string") {
5315
5393
  this._currentRunOwnerId = ownerParam;
5316
5394
  }
5317
- const agent = this.parsedAgent;
5395
+ let agent = this.parsedAgent;
5318
5396
  const runId = `run_${randomUUID3()}`;
5319
5397
  const start = now();
5320
5398
  const maxSteps = agent.frontmatter.limits?.maxSteps ?? 50;
@@ -5325,11 +5403,11 @@ var AgentHarness = class _AgentHarness {
5325
5403
  const messages = [...input.messages ?? []];
5326
5404
  const inputMessageCount = messages.length;
5327
5405
  const events = [];
5328
- const systemPrompt = renderAgentPrompt(agent, {
5406
+ const renderCurrentAgentPrompt = () => renderAgentPrompt(this.parsedAgent, {
5329
5407
  parameters: input.parameters,
5330
5408
  runtime: {
5331
5409
  runId,
5332
- agentId: agent.frontmatter.id ?? agent.frontmatter.name,
5410
+ agentId: this.parsedAgent.frontmatter.id ?? this.parsedAgent.frontmatter.name,
5333
5411
  environment: this.environment,
5334
5412
  workingDir: this.workingDir
5335
5413
  }
@@ -5357,9 +5435,6 @@ Browser sessions (cookies, localStorage, login state) are automatically saved an
5357
5435
 
5358
5436
  ### Tabs and resources
5359
5437
  Each conversation gets its own browser tab sharing a single browser instance. Call \`browser_close\` when done to free the tab. If you don't close it, the tab stays open and the user can continue interacting with it.` : "";
5360
- const promptWithSkills = this.skillContextWindow ? `${systemPrompt}${developmentContext}
5361
-
5362
- ${this.skillContextWindow}${browserContext}` : `${systemPrompt}${developmentContext}${browserContext}`;
5363
5438
  const mainMemory = await memoryPromise;
5364
5439
  const boundedMainMemory = mainMemory && mainMemory.content.length > 4e3 ? `${mainMemory.content.slice(0, 4e3)}
5365
5440
  ...[truncated]` : mainMemory?.content;
@@ -5367,7 +5442,12 @@ ${this.skillContextWindow}${browserContext}` : `${systemPrompt}${developmentCont
5367
5442
  ## Persistent Memory
5368
5443
 
5369
5444
  ${boundedMainMemory.trim()}` : "";
5370
- const integrityPrompt = `${promptWithSkills}${memoryContext}
5445
+ const buildSystemPrompt = () => {
5446
+ const agentPrompt = renderCurrentAgentPrompt();
5447
+ const promptWithSkills = this.skillContextWindow ? `${agentPrompt}${developmentContext}
5448
+
5449
+ ${this.skillContextWindow}${browserContext}` : `${agentPrompt}${developmentContext}${browserContext}`;
5450
+ return `${promptWithSkills}${memoryContext}
5371
5451
 
5372
5452
  ## Execution Integrity
5373
5453
 
@@ -5375,6 +5455,10 @@ ${boundedMainMemory.trim()}` : "";
5375
5455
  - Do not fabricate "Tool Used" or "Tool Result" logs as plain text.
5376
5456
  - Never output faux execution transcripts, markdown tool logs, or "Tool Used/Result" sections.
5377
5457
  - If no suitable tool is available, explicitly say that and ask for guidance.`;
5458
+ };
5459
+ let integrityPrompt = buildSystemPrompt();
5460
+ let lastPromptFingerprint = `${this.agentFileFingerprint}
5461
+ ${this.skillFingerprint}`;
5378
5462
  const pushEvent = (event) => {
5379
5463
  events.push(event);
5380
5464
  return event;
@@ -5797,8 +5881,8 @@ ${textContent}` };
5797
5881
  let timer;
5798
5882
  nextPart = await Promise.race([
5799
5883
  fullStreamIterator.next(),
5800
- new Promise((resolve10) => {
5801
- timer = setTimeout(() => resolve10(null), timeout);
5884
+ new Promise((resolve11) => {
5885
+ timer = setTimeout(() => resolve11(null), timeout);
5802
5886
  })
5803
5887
  ]);
5804
5888
  clearTimeout(timer);
@@ -6106,6 +6190,19 @@ ${textContent}` };
6106
6190
  content: JSON.stringify(toolResultsForModel),
6107
6191
  metadata: toolMsgMeta
6108
6192
  });
6193
+ if (this.environment === "development") {
6194
+ const agentChanged = await this.refreshAgentIfChanged();
6195
+ const skillsChanged = await this.refreshSkillsIfChanged(true);
6196
+ if (agentChanged || skillsChanged) {
6197
+ agent = this.parsedAgent;
6198
+ const currentFingerprint = `${this.agentFileFingerprint}
6199
+ ${this.skillFingerprint}`;
6200
+ if (currentFingerprint !== lastPromptFingerprint) {
6201
+ integrityPrompt = buildSystemPrompt();
6202
+ lastPromptFingerprint = currentFingerprint;
6203
+ }
6204
+ }
6205
+ }
6109
6206
  yield pushEvent({
6110
6207
  type: "step:completed",
6111
6208
  step,
@@ -6294,8 +6391,8 @@ var LatitudeCapture = class {
6294
6391
 
6295
6392
  // src/state.ts
6296
6393
  import { randomUUID as randomUUID4 } from "crypto";
6297
- import { mkdir as mkdir4, readFile as readFile7, readdir as readdir4, rename as rename2, rm as rm3, writeFile as writeFile5 } from "fs/promises";
6298
- import { dirname as dirname4, resolve as resolve9 } from "path";
6394
+ import { mkdir as mkdir4, readFile as readFile8, readdir as readdir4, rename as rename2, rm as rm3, writeFile as writeFile5 } from "fs/promises";
6395
+ import { dirname as dirname4, resolve as resolve10 } from "path";
6299
6396
  var DEFAULT_OWNER = "local-owner";
6300
6397
  var LOCAL_STATE_FILE = "state.json";
6301
6398
  var CONVERSATIONS_DIRECTORY = "conversations";
@@ -6488,8 +6585,8 @@ var FileConversationStore = class {
6488
6585
  agentId: this.agentId
6489
6586
  });
6490
6587
  const agentDir = getAgentStoreDirectory(identity);
6491
- const conversationsDir = resolve9(agentDir, CONVERSATIONS_DIRECTORY);
6492
- const indexPath = resolve9(conversationsDir, LOCAL_CONVERSATION_INDEX_FILE);
6588
+ const conversationsDir = resolve10(agentDir, CONVERSATIONS_DIRECTORY);
6589
+ const indexPath = resolve10(conversationsDir, LOCAL_CONVERSATION_INDEX_FILE);
6493
6590
  this.paths = { conversationsDir, indexPath };
6494
6591
  return this.paths;
6495
6592
  }
@@ -6503,9 +6600,9 @@ var FileConversationStore = class {
6503
6600
  }
6504
6601
  async readConversationFile(fileName) {
6505
6602
  const { conversationsDir } = await this.resolvePaths();
6506
- const filePath = resolve9(conversationsDir, fileName);
6603
+ const filePath = resolve10(conversationsDir, fileName);
6507
6604
  try {
6508
- const raw = await readFile7(filePath, "utf8");
6605
+ const raw = await readFile8(filePath, "utf8");
6509
6606
  return JSON.parse(raw);
6510
6607
  } catch {
6511
6608
  return void 0;
@@ -6551,7 +6648,7 @@ var FileConversationStore = class {
6551
6648
  this.loaded = true;
6552
6649
  const { indexPath } = await this.resolvePaths();
6553
6650
  try {
6554
- const raw = await readFile7(indexPath, "utf8");
6651
+ const raw = await readFile8(indexPath, "utf8");
6555
6652
  const parsed = JSON.parse(raw);
6556
6653
  for (const conversation of parsed.conversations ?? []) {
6557
6654
  this.conversations.set(conversation.conversationId, conversation);
@@ -6574,7 +6671,7 @@ var FileConversationStore = class {
6574
6671
  const { conversationsDir } = await this.resolvePaths();
6575
6672
  const existing = this.conversations.get(conversation.conversationId);
6576
6673
  const fileName = existing?.fileName ?? this.resolveConversationFileName(conversation);
6577
- const filePath = resolve9(conversationsDir, fileName);
6674
+ const filePath = resolve10(conversationsDir, fileName);
6578
6675
  this.writing = this.writing.then(async () => {
6579
6676
  await writeJsonAtomic2(filePath, conversation);
6580
6677
  this.conversations.set(conversation.conversationId, {
@@ -6672,7 +6769,7 @@ var FileConversationStore = class {
6672
6769
  if (removed) {
6673
6770
  this.writing = this.writing.then(async () => {
6674
6771
  if (existing) {
6675
- await rm3(resolve9(conversationsDir, existing.fileName), { force: true });
6772
+ await rm3(resolve10(conversationsDir, existing.fileName), { force: true });
6676
6773
  }
6677
6774
  await this.writeIndex();
6678
6775
  });
@@ -6702,7 +6799,7 @@ var FileStateStore = class {
6702
6799
  workingDir: this.workingDir,
6703
6800
  agentId: this.agentId
6704
6801
  });
6705
- this.filePath = resolve9(getAgentStoreDirectory(identity), LOCAL_STATE_FILE);
6802
+ this.filePath = resolve10(getAgentStoreDirectory(identity), LOCAL_STATE_FILE);
6706
6803
  }
6707
6804
  isExpired(state) {
6708
6805
  return typeof this.ttlMs === "number" && Date.now() - state.updatedAt > this.ttlMs;
@@ -6714,7 +6811,7 @@ var FileStateStore = class {
6714
6811
  }
6715
6812
  this.loaded = true;
6716
6813
  try {
6717
- const raw = await readFile7(this.filePath, "utf8");
6814
+ const raw = await readFile8(this.filePath, "utf8");
6718
6815
  const parsed = JSON.parse(raw);
6719
6816
  for (const state of parsed.states ?? []) {
6720
6817
  this.states.set(state.runId, state);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@poncho-ai/harness",
3
- "version": "0.24.0",
3
+ "version": "0.25.0",
4
4
  "description": "Agent execution runtime - conversation loop, tool dispatch, streaming",
5
5
  "repository": {
6
6
  "type": "git",