@botbotgo/agent-harness 0.0.46 → 0.0.48

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/README.md CHANGED
@@ -521,7 +521,7 @@ spec:
521
521
  systemPrompt: Coordinate the request.
522
522
  ```
523
523
 
524
- `kind: DeepAgent` and `kind: LangChainAgent` remain supported as compatibility forms, but `kind: Agent` is the recommended product-facing entry point.
524
+ Only `kind: Agent` is supported for agent objects. Select the concrete backend with `spec.execution.backend`.
525
525
 
526
526
  Common client-configurable agent fields:
527
527
 
package/dist/api.d.ts CHANGED
@@ -13,6 +13,7 @@ export declare function run(runtime: AgentHarnessRuntime, options: RunOptions):
13
13
  export declare function subscribe(runtime: AgentHarnessRuntime, listener: Parameters<AgentHarnessRuntime["subscribe"]>[0]): () => void;
14
14
  export declare function listThreads(runtime: AgentHarnessRuntime, filter?: Parameters<AgentHarnessRuntime["listThreads"]>[0]): Promise<ThreadSummary[]>;
15
15
  export declare function getThread(runtime: AgentHarnessRuntime, threadId: string): Promise<ThreadRecord | null>;
16
+ export declare function deleteThread(runtime: AgentHarnessRuntime, threadId: string): Promise<boolean>;
16
17
  export declare function listApprovals(runtime: AgentHarnessRuntime, filter?: Parameters<AgentHarnessRuntime["listApprovals"]>[0]): Promise<ApprovalRecord[]>;
17
18
  export declare function getApproval(runtime: AgentHarnessRuntime, approvalId: string): Promise<ApprovalRecord | null>;
18
19
  export declare function stop(runtime: AgentHarnessRuntime): Promise<void>;
package/dist/api.js CHANGED
@@ -21,6 +21,9 @@ export async function listThreads(runtime, filter) {
21
21
  export async function getThread(runtime, threadId) {
22
22
  return runtime.getThread(threadId);
23
23
  }
24
+ export async function deleteThread(runtime, threadId) {
25
+ return runtime.deleteThread(threadId);
26
+ }
24
27
  export async function listApprovals(runtime, filter) {
25
28
  return runtime.listApprovals(filter);
26
29
  }
package/dist/index.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- export { AgentHarnessRuntime, createAgentHarness, createToolMcpServer, getApproval, getThread, listApprovals, listThreads, run, serveToolsOverStdio, subscribe, stop, } from "./api.js";
1
+ export { AgentHarnessRuntime, createAgentHarness, createToolMcpServer, deleteThread, getApproval, getThread, listApprovals, listThreads, run, serveToolsOverStdio, subscribe, stop, } from "./api.js";
2
2
  export type { ToolMcpServerOptions } from "./mcp.js";
3
3
  export { tool } from "./tools.js";
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- export { AgentHarnessRuntime, createAgentHarness, createToolMcpServer, getApproval, getThread, listApprovals, listThreads, run, serveToolsOverStdio, subscribe, stop, } from "./api.js";
1
+ export { AgentHarnessRuntime, createAgentHarness, createToolMcpServer, deleteThread, getApproval, getThread, listApprovals, listThreads, run, serveToolsOverStdio, subscribe, stop, } from "./api.js";
2
2
  export { tool } from "./tools.js";
@@ -1 +1 @@
1
- export declare const AGENT_HARNESS_VERSION = "0.0.45";
1
+ export declare const AGENT_HARNESS_VERSION = "0.0.47";
@@ -1 +1 @@
1
- export const AGENT_HARNESS_VERSION = "0.0.45";
1
+ export const AGENT_HARNESS_VERSION = "0.0.47";
@@ -47,6 +47,10 @@ type PersistedRunRequest = {
47
47
  export declare class FilePersistence {
48
48
  private readonly runRoot;
49
49
  constructor(runRoot: string);
50
+ private threadIndexPath;
51
+ private runIndexPath;
52
+ private approvalIndexPath;
53
+ private delegationIndexPath;
50
54
  initialize(): Promise<void>;
51
55
  threadDir(threadId: string): string;
52
56
  runDir(threadId: string, runId: string): string;
@@ -78,6 +82,7 @@ export declare class FilePersistence {
78
82
  getRunApprovals(threadId: string, runId: string): Promise<InternalApprovalRecord[]>;
79
83
  getRunMeta(threadId: string, runId: string): Promise<RunMeta>;
80
84
  getRunLifecycle(threadId: string, runId: string): Promise<Lifecycle>;
85
+ deleteThread(threadId: string): Promise<boolean>;
81
86
  saveRunRequest(threadId: string, runId: string, request: PersistedRunRequest): Promise<void>;
82
87
  getRunRequest(threadId: string, runId: string): Promise<PersistedRunRequest | null>;
83
88
  clearRunRequest(threadId: string, runId: string): Promise<void>;
@@ -7,6 +7,18 @@ export class FilePersistence {
7
7
  constructor(runRoot) {
8
8
  this.runRoot = runRoot;
9
9
  }
10
+ threadIndexPath(threadId) {
11
+ return path.join(this.runRoot, "indexes", "threads", `${threadId}.json`);
12
+ }
13
+ runIndexPath(runId) {
14
+ return path.join(this.runRoot, "indexes", "runs", `${runId}.json`);
15
+ }
16
+ approvalIndexPath(approvalId) {
17
+ return path.join(this.runRoot, "indexes", "approvals", `${approvalId}.json`);
18
+ }
19
+ delegationIndexPath(delegationId) {
20
+ return path.join(this.runRoot, "indexes", "delegations", `${delegationId}.json`);
21
+ }
10
22
  async initialize() {
11
23
  await Promise.all([
12
24
  "indexes/threads",
@@ -266,6 +278,32 @@ export class FilePersistence {
266
278
  async getRunLifecycle(threadId, runId) {
267
279
  return readJson(path.join(this.runDir(threadId, runId), "lifecycle.json"));
268
280
  }
281
+ async deleteThread(threadId) {
282
+ const threadDir = this.threadDir(threadId);
283
+ const threadIndexPath = this.threadIndexPath(threadId);
284
+ if (!(await fileExists(threadDir)) && !(await fileExists(threadIndexPath))) {
285
+ return false;
286
+ }
287
+ const [runIndexes, approvals, delegations] = await Promise.all([
288
+ this.listRunIndexes(),
289
+ this.listApprovals(),
290
+ this.listDelegations(),
291
+ ]);
292
+ await Promise.all([
293
+ ...runIndexes
294
+ .filter((record) => record.threadId === threadId)
295
+ .map((record) => rm(this.runIndexPath(record.runId), { force: true })),
296
+ ...approvals
297
+ .filter((record) => record.threadId === threadId)
298
+ .map((record) => rm(this.approvalIndexPath(record.approvalId), { force: true })),
299
+ ...delegations
300
+ .filter((record) => record.threadId === threadId)
301
+ .map((record) => rm(this.delegationIndexPath(record.delegationId), { force: true })),
302
+ rm(threadIndexPath, { force: true }),
303
+ rm(threadDir, { recursive: true, force: true }),
304
+ ]);
305
+ return true;
306
+ }
269
307
  async saveRunRequest(threadId, runId, request) {
270
308
  await writeJson(path.join(this.runDir(threadId, runId), "request.json"), request);
271
309
  }
@@ -26,6 +26,7 @@ export declare class AgentHarnessRuntime {
26
26
  private readonly pendingRunSlots;
27
27
  private toPublicApprovalRecord;
28
28
  private normalizeInvocationEnvelope;
29
+ private isTerminalRunState;
29
30
  private listHostBindings;
30
31
  private defaultRunRoot;
31
32
  private heuristicRoute;
@@ -52,6 +53,8 @@ export declare class AgentHarnessRuntime {
52
53
  runId?: string;
53
54
  }): Promise<ApprovalRecord[]>;
54
55
  getApproval(approvalId: string): Promise<ApprovalRecord | null>;
56
+ private deleteThreadCheckpoints;
57
+ deleteThread(threadId: string): Promise<boolean>;
55
58
  createToolMcpServer(options: ToolMcpServerOptions): Promise<import("@modelcontextprotocol/sdk/server/mcp.js").McpServer>;
56
59
  serveToolsOverStdio(options: ToolMcpServerOptions): Promise<import("@modelcontextprotocol/sdk/server/mcp.js").McpServer>;
57
60
  routeAgent(input: MessageContent, options?: {
@@ -53,6 +53,9 @@ export class AgentHarnessRuntime {
53
53
  invocation,
54
54
  };
55
55
  }
56
+ isTerminalRunState(state) {
57
+ return state === "completed" || state === "failed";
58
+ }
56
59
  listHostBindings() {
57
60
  return inferRoutingBindings(this.workspace).hostBindings;
58
61
  }
@@ -283,6 +286,39 @@ export class AgentHarnessRuntime {
283
286
  const approval = await this.persistence.getApproval(approvalId);
284
287
  return approval ? this.toPublicApprovalRecord(approval) : null;
285
288
  }
289
+ async deleteThreadCheckpoints(threadId) {
290
+ const resolver = this.resolvedRuntimeAdapterOptions.checkpointerResolver;
291
+ if (!resolver) {
292
+ return;
293
+ }
294
+ const seen = new Set();
295
+ for (const binding of this.workspace.bindings.values()) {
296
+ const saver = resolver(binding);
297
+ if (!saver || seen.has(saver)) {
298
+ continue;
299
+ }
300
+ seen.add(saver);
301
+ const maybeDeleteThread = saver.deleteThread;
302
+ if (typeof maybeDeleteThread === "function") {
303
+ await maybeDeleteThread.call(saver, threadId);
304
+ }
305
+ }
306
+ }
307
+ async deleteThread(threadId) {
308
+ const thread = await this.getThread(threadId);
309
+ if (!thread) {
310
+ return false;
311
+ }
312
+ const activeRun = thread.runs.find((run) => !this.isTerminalRunState(run.state));
313
+ if (activeRun) {
314
+ throw new Error(`Cannot delete thread ${threadId} while run ${activeRun.runId} is ${activeRun.state}`);
315
+ }
316
+ const deleted = await this.persistence.deleteThread(threadId);
317
+ if (deleted) {
318
+ await this.deleteThreadCheckpoints(threadId);
319
+ }
320
+ return deleted;
321
+ }
286
322
  async createToolMcpServer(options) {
287
323
  const tools = this.resolveAgentTools(options.agentId).map(({ compiledTool, resolvedTool }) => ({
288
324
  compiledTool,
@@ -93,10 +93,6 @@ function normalizeKind(kind) {
93
93
  switch (kind) {
94
94
  case "Agent":
95
95
  return "agent";
96
- case "LangChainAgent":
97
- return "langchain-agent";
98
- case "DeepAgent":
99
- return "deepagent";
100
96
  case "FileStore":
101
97
  return "file-store";
102
98
  case "InMemoryStore":
@@ -138,6 +134,9 @@ function normalizeKind(kind) {
138
134
  }
139
135
  }
140
136
  export function normalizeYamlItem(item) {
137
+ if (item.kind === "DeepAgent" || item.kind === "LangChainAgent") {
138
+ throw new Error(`YAML object kind ${String(item.kind)} is no longer supported; use kind: Agent with spec.execution.backend instead`);
139
+ }
141
140
  const metadata = asObject(item.metadata);
142
141
  const spec = asObject(item.spec);
143
142
  const kind = typeof item.kind === "string" ? normalizeKind(item.kind) : undefined;
@@ -161,20 +160,6 @@ export function normalizeYamlItem(item) {
161
160
  ...(kind ? { kind } : {}),
162
161
  };
163
162
  }
164
- function normalizeResourceItem(item) {
165
- if ("metadata" in item || "spec" in item || "path" in item || typeof item.name !== "string") {
166
- return item;
167
- }
168
- const { name, description, kind, ...spec } = item;
169
- return {
170
- ...(typeof kind === "string" ? { kind } : {}),
171
- metadata: {
172
- name,
173
- ...(typeof description === "string" ? { description } : {}),
174
- },
175
- spec,
176
- };
177
- }
178
163
  function readRefArray(items) {
179
164
  return toArray(items)
180
165
  .map((item) => typeof item === "string"
@@ -323,32 +308,8 @@ async function objectItemsFromDocument(document, sourcePath) {
323
308
  if (catalogItems.length > 0) {
324
309
  return catalogItems;
325
310
  }
326
- const items = document.items;
327
- if (Array.isArray(items)) {
328
- const records = [];
329
- for (const item of items) {
330
- if (typeof item !== "object" || !item) {
331
- continue;
332
- }
333
- const typedItem = item;
334
- if (typeof typedItem.path === "string" && typedItem.path.trim()) {
335
- const referencedPath = path.isAbsolute(typedItem.path)
336
- ? typedItem.path
337
- : path.join(path.dirname(sourcePath), typedItem.path);
338
- if (existsSync(referencedPath) && statSync(referencedPath).isDirectory()) {
339
- const discoveredItems = await readYamlItems(referencedPath, undefined, { recursive: true });
340
- records.push(...discoveredItems.map(({ item }) => item));
341
- continue;
342
- }
343
- const parsedDocuments = parseAllDocuments(await readYamlOrJson(referencedPath));
344
- for (const parsedDocument of parsedDocuments) {
345
- records.push(...(await objectItemsFromDocument(parsedDocument.toJSON(), referencedPath)));
346
- }
347
- continue;
348
- }
349
- records.push(normalizeResourceItem(typedItem));
350
- }
351
- return records;
311
+ if ("items" in document) {
312
+ throw new Error(`YAML document ${sourcePath} uses unsupported legacy items wrapper; use kind/spec catalog documents or metadata/spec objects instead`);
352
313
  }
353
314
  return [document];
354
315
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@botbotgo/agent-harness",
3
- "version": "0.0.46",
3
+ "version": "0.0.48",
4
4
  "description": "Workspace runtime for multi-agent applications",
5
5
  "type": "module",
6
6
  "packageManager": "npm@10.9.2",