@botbotgo/agent-harness 0.0.81 → 0.0.82

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.
@@ -1 +1 @@
1
- export declare const AGENT_HARNESS_VERSION = "0.0.80";
1
+ export declare const AGENT_HARNESS_VERSION = "0.0.81";
@@ -1 +1 @@
1
- export const AGENT_HARNESS_VERSION = "0.0.80";
1
+ export const AGENT_HARNESS_VERSION = "0.0.81";
@@ -1,5 +1,5 @@
1
1
  import type { ArtifactListing, ArtifactRecord, DelegationRecord, HarnessEvent, InternalApprovalRecord, RunSummary, RunState, ThreadSummary, ThreadRunRecord, TranscriptMessage } from "../contracts/types.js";
2
- import type { PersistedRunRequest, PersistedRunControlRecord, PersistedRunQueueRecord, PersistenceLifecycle as Lifecycle, RuntimePersistence, RecoveryIntent, PersistenceRunMeta as RunMeta, PersistenceThreadMeta as ThreadMeta } from "./types.js";
2
+ import type { ApprovalFilter, PersistedRunRequest, PersistedRunControlRecord, PersistedRunQueueRecord, PersistenceLifecycle as Lifecycle, RuntimePersistence, RecoveryIntent, PersistenceRunMeta as RunMeta, RunSummaryFilter, ThreadSummaryFilter, PersistenceThreadMeta as ThreadMeta } from "./types.js";
3
3
  type RunIndexRecord = {
4
4
  runId: string;
5
5
  threadId: string;
@@ -36,16 +36,16 @@ export declare class FilePersistence implements RuntimePersistence {
36
36
  }): Promise<void>;
37
37
  setRunState(threadId: string, runId: string, state: RunState, checkpointRef?: string | null): Promise<void>;
38
38
  appendEvent(event: HarnessEvent): Promise<void>;
39
- listSessions(): Promise<ThreadSummary[]>;
39
+ listSessions(filter?: ThreadSummaryFilter): Promise<ThreadSummary[]>;
40
40
  listRunIndexes(): Promise<RunIndexRecord[]>;
41
41
  private readRunSummary;
42
- listRuns(): Promise<RunSummary[]>;
42
+ listRuns(filter?: RunSummaryFilter): Promise<RunSummary[]>;
43
43
  getRun(runId: string): Promise<RunSummary | null>;
44
44
  getSession(threadId: string): Promise<ThreadSummary | null>;
45
45
  getThreadMeta(threadId: string): Promise<ThreadMeta | null>;
46
46
  listThreadRuns(threadId: string): Promise<ThreadRunRecord[]>;
47
47
  listRunEvents(threadId: string, runId: string): Promise<HarnessEvent[]>;
48
- listApprovals(): Promise<InternalApprovalRecord[]>;
48
+ listApprovals(filter?: ApprovalFilter): Promise<InternalApprovalRecord[]>;
49
49
  getApproval(approvalId: string): Promise<InternalApprovalRecord | null>;
50
50
  getRunApprovals(threadId: string, runId: string): Promise<InternalApprovalRecord[]>;
51
51
  getRunMeta(threadId: string, runId: string): Promise<RunMeta>;
@@ -182,7 +182,7 @@ export class FilePersistence {
182
182
  const sequenceId = String(event.sequence).padStart(6, "0");
183
183
  await writeJson(path.join(this.runDir(event.threadId, event.runId), "events", `${sequenceId}.json`), event);
184
184
  }
185
- async listSessions() {
185
+ async listSessions(filter = {}) {
186
186
  const threadIndexDir = path.join(this.runRoot, "indexes", "threads");
187
187
  if (!(await fileExists(threadIndexDir))) {
188
188
  return [];
@@ -200,7 +200,9 @@ export class FilePersistence {
200
200
  status: index.status,
201
201
  };
202
202
  }));
203
- return records.sort((a, b) => b.updatedAt.localeCompare(a.updatedAt));
203
+ return records
204
+ .filter((record) => !filter.agentId || record.agentId === filter.agentId)
205
+ .sort((a, b) => b.updatedAt.localeCompare(a.updatedAt));
204
206
  }
205
207
  async listRunIndexes() {
206
208
  const runIndexDir = path.join(this.runRoot, "indexes", "runs");
@@ -229,10 +231,23 @@ export class FilePersistence {
229
231
  resumable: lifecycle.resumable,
230
232
  };
231
233
  }
232
- async listRuns() {
234
+ async listRuns(filter = {}) {
233
235
  const indexes = await this.listRunIndexes();
234
236
  const runs = await Promise.all(indexes.map((record) => this.readRunSummary(record.threadId, record.runId)));
235
- return runs.sort((left, right) => right.updatedAt.localeCompare(left.updatedAt));
237
+ return runs
238
+ .filter((run) => {
239
+ if (filter.agentId && run.agentId !== filter.agentId) {
240
+ return false;
241
+ }
242
+ if (filter.threadId && run.threadId !== filter.threadId) {
243
+ return false;
244
+ }
245
+ if (filter.state && run.state !== filter.state) {
246
+ return false;
247
+ }
248
+ return true;
249
+ })
250
+ .sort((left, right) => right.updatedAt.localeCompare(left.updatedAt));
236
251
  }
237
252
  async getRun(runId) {
238
253
  const indexPath = this.runIndexPath(runId);
@@ -284,13 +299,25 @@ export class FilePersistence {
284
299
  const entries = (await readdir(eventsDir)).sort();
285
300
  return Promise.all(entries.map((entry) => readJson(path.join(eventsDir, entry))));
286
301
  }
287
- async listApprovals() {
302
+ async listApprovals(filter = {}) {
288
303
  const approvalsDir = path.join(this.runRoot, "indexes", "approvals");
289
304
  if (!(await fileExists(approvalsDir))) {
290
305
  return [];
291
306
  }
292
307
  const entries = (await readdir(approvalsDir)).sort();
293
- return Promise.all(entries.map((entry) => readJson(path.join(approvalsDir, entry))));
308
+ const approvals = await Promise.all(entries.map((entry) => readJson(path.join(approvalsDir, entry))));
309
+ return approvals.filter((approval) => {
310
+ if (filter.status && approval.status !== filter.status) {
311
+ return false;
312
+ }
313
+ if (filter.threadId && approval.threadId !== filter.threadId) {
314
+ return false;
315
+ }
316
+ if (filter.runId && approval.runId !== filter.runId) {
317
+ return false;
318
+ }
319
+ return true;
320
+ });
294
321
  }
295
322
  async getApproval(approvalId) {
296
323
  const approvalPath = path.join(this.runRoot, "indexes", "approvals", `${approvalId}.json`);
@@ -1,5 +1,5 @@
1
1
  import type { ArtifactListing, ArtifactRecord, HarnessEvent, InternalApprovalRecord, RunState, RunSummary, ThreadRunRecord, ThreadSummary, TranscriptMessage } from "../contracts/types.js";
2
- import type { PersistedRunRequest, PersistedRunControlRecord, PersistedRunQueueRecord, PersistenceLifecycle, PersistenceRunMeta, PersistenceThreadMeta, RecoveryIntent, RuntimePersistence } from "./types.js";
2
+ import type { PersistedRunRequest, PersistedRunControlRecord, PersistedRunQueueRecord, PersistenceLifecycle, PersistenceRunMeta, PersistenceThreadMeta, RecoveryIntent, RuntimePersistence, ApprovalFilter, RunSummaryFilter, ThreadSummaryFilter } from "./types.js";
3
3
  export declare function listProtectedCheckpointThreadIds(dbPath: string): Promise<Set<string>>;
4
4
  export declare class SqlitePersistence implements RuntimePersistence {
5
5
  private readonly runRoot;
@@ -39,14 +39,14 @@ export declare class SqlitePersistence implements RuntimePersistence {
39
39
  }): Promise<void>;
40
40
  setRunState(threadId: string, runId: string, state: RunState, checkpointRef?: string | null): Promise<void>;
41
41
  appendEvent(event: HarnessEvent): Promise<void>;
42
- listSessions(): Promise<ThreadSummary[]>;
43
- listRuns(): Promise<RunSummary[]>;
42
+ listSessions(filter?: ThreadSummaryFilter): Promise<ThreadSummary[]>;
43
+ listRuns(filter?: RunSummaryFilter): Promise<RunSummary[]>;
44
44
  getRun(runId: string): Promise<RunSummary | null>;
45
45
  getSession(threadId: string): Promise<ThreadSummary | null>;
46
46
  getThreadMeta(threadId: string): Promise<PersistenceThreadMeta | null>;
47
47
  listThreadRuns(threadId: string): Promise<ThreadRunRecord[]>;
48
48
  listRunEvents(threadId: string, runId: string): Promise<HarnessEvent[]>;
49
- listApprovals(): Promise<InternalApprovalRecord[]>;
49
+ listApprovals(filter?: ApprovalFilter): Promise<InternalApprovalRecord[]>;
50
50
  getApproval(approvalId: string): Promise<InternalApprovalRecord | null>;
51
51
  getRunApprovals(threadId: string, runId: string): Promise<InternalApprovalRecord[]>;
52
52
  getRunMeta(threadId: string, runId: string): Promise<PersistenceRunMeta>;
@@ -25,6 +25,16 @@ function toSqliteUrl(filePath) {
25
25
  function nowIso() {
26
26
  return new Date(Date.now()).toISOString();
27
27
  }
28
+ function buildWhereClause(filters) {
29
+ const active = filters.filter(([, value]) => value !== undefined);
30
+ if (active.length === 0) {
31
+ return { clause: "", args: [] };
32
+ }
33
+ return {
34
+ clause: ` WHERE ${active.map(([sql]) => sql).join(" AND ")}`,
35
+ args: active.map(([, value]) => value),
36
+ };
37
+ }
28
38
  async function selectProtectedThreadIds(dbPath) {
29
39
  if (!(await fileExists(dbPath))) {
30
40
  return [];
@@ -377,16 +387,24 @@ export class SqlitePersistence {
377
387
  (thread_id, run_id, sequence, event_json, created_at)
378
388
  VALUES (?, ?, ?, ?, ?)`, [event.threadId, event.runId, event.sequence, JSON.stringify(event), event.timestamp]);
379
389
  }
380
- async listSessions() {
390
+ async listSessions(filter = {}) {
391
+ const { clause, args } = buildWhereClause([
392
+ ["entry_agent_id = ?", filter.agentId],
393
+ ]);
381
394
  const rows = await this.selectAll(`SELECT thread_id, entry_agent_id, latest_run_id, created_at, updated_at, status
382
- FROM threads
383
- ORDER BY updated_at DESC`);
395
+ FROM threads${clause}
396
+ ORDER BY updated_at DESC`, args);
384
397
  return rows.map((row) => this.mapThreadSummary(row));
385
398
  }
386
- async listRuns() {
399
+ async listRuns(filter = {}) {
400
+ const { clause, args } = buildWhereClause([
401
+ ["agent_id = ?", filter.agentId],
402
+ ["thread_id = ?", filter.threadId],
403
+ ["state = ?", filter.state],
404
+ ]);
387
405
  const rows = await this.selectAll(`SELECT run_id, thread_id, agent_id, execution_mode, adapter_kind, created_at, updated_at, state, checkpoint_ref, resumable
388
- FROM runs
389
- ORDER BY updated_at DESC`);
406
+ FROM runs${clause}
407
+ ORDER BY updated_at DESC`, args);
390
408
  return rows.map((row) => this.mapRunSummary(row));
391
409
  }
392
410
  async getRun(runId) {
@@ -430,8 +448,13 @@ export class SqlitePersistence {
430
448
  ORDER BY sequence ASC`, [threadId, runId]);
431
449
  return rows.map((row) => parseJson(row.event_json));
432
450
  }
433
- async listApprovals() {
434
- const rows = await this.selectAll("SELECT * FROM approvals ORDER BY requested_at ASC, approval_id ASC");
451
+ async listApprovals(filter = {}) {
452
+ const { clause, args } = buildWhereClause([
453
+ ["status = ?", filter.status],
454
+ ["thread_id = ?", filter.threadId],
455
+ ["run_id = ?", filter.runId],
456
+ ]);
457
+ const rows = await this.selectAll(`SELECT * FROM approvals${clause} ORDER BY requested_at ASC, approval_id ASC`, args);
435
458
  return rows.map((row) => this.mapApproval(row));
436
459
  }
437
460
  async getApproval(approvalId) {
@@ -59,6 +59,19 @@ export type PersistedRunControlRecord = {
59
59
  workerId: string | null;
60
60
  workerStartedAt: string | null;
61
61
  };
62
+ export type ThreadSummaryFilter = {
63
+ agentId?: string;
64
+ };
65
+ export type RunSummaryFilter = {
66
+ agentId?: string;
67
+ threadId?: string;
68
+ state?: RunSummary["state"];
69
+ };
70
+ export type ApprovalFilter = {
71
+ status?: InternalApprovalRecord["status"];
72
+ threadId?: string;
73
+ runId?: string;
74
+ };
62
75
  export interface RuntimePersistence {
63
76
  initialize(): Promise<void>;
64
77
  createThread(input: {
@@ -78,13 +91,13 @@ export interface RuntimePersistence {
78
91
  }): Promise<void>;
79
92
  setRunState(threadId: string, runId: string, state: RunState, checkpointRef?: string | null): Promise<void>;
80
93
  appendEvent(event: HarnessEvent): Promise<void>;
81
- listSessions(): Promise<ThreadSummary[]>;
82
- listRuns(): Promise<RunSummary[]>;
94
+ listSessions(filter?: ThreadSummaryFilter): Promise<ThreadSummary[]>;
95
+ listRuns(filter?: RunSummaryFilter): Promise<RunSummary[]>;
83
96
  getRun(runId: string): Promise<RunSummary | null>;
84
97
  getSession(threadId: string): Promise<ThreadSummary | null>;
85
98
  getThreadMeta(threadId: string): Promise<PersistenceThreadMeta | null>;
86
99
  listThreadRuns(threadId: string): Promise<ThreadRunRecord[]>;
87
- listApprovals(): Promise<InternalApprovalRecord[]>;
100
+ listApprovals(filter?: ApprovalFilter): Promise<InternalApprovalRecord[]>;
88
101
  getApproval(approvalId: string): Promise<InternalApprovalRecord | null>;
89
102
  getRunApprovals(threadId: string, runId: string): Promise<InternalApprovalRecord[]>;
90
103
  getRunMeta(threadId: string, runId: string): Promise<PersistenceRunMeta>;
@@ -21,7 +21,10 @@ export declare function materializeDeepAgentSkillSourcePaths(options: {
21
21
  }): Promise<string[] | undefined>;
22
22
  export declare class AgentRuntimeAdapter {
23
23
  private readonly options;
24
+ private readonly modelCache;
25
+ private readonly runnableCache;
24
26
  constructor(options?: RuntimeAdapterOptions);
27
+ private getModelCacheKey;
25
28
  private resolveBindingTimeout;
26
29
  private resolveStreamIdleTimeout;
27
30
  private resolveProviderRetryPolicy;
@@ -48,11 +51,13 @@ export declare class AgentRuntimeAdapter {
48
51
  private resolveBuiltinMiddlewareBackend;
49
52
  private invokeBuiltinTaskTool;
50
53
  private resolveBuiltinMiddlewareTools;
54
+ private canReplayToolCallsLocally;
51
55
  private resolveLangChainAutomaticMiddleware;
52
56
  private resolveMiddleware;
53
57
  private resolveCheckpointer;
54
58
  private buildRouteSystemPrompt;
55
59
  private resolveSubagents;
60
+ private createRunnable;
56
61
  create(binding: CompiledAgentBinding): Promise<RunnableLike>;
57
62
  route(input: MessageContent, primaryBinding: CompiledAgentBinding, secondaryBinding: CompiledAgentBinding, options?: {
58
63
  systemPrompt?: string;
@@ -471,9 +471,19 @@ function asStructuredExecutableTool(resolvedTool, modelFacingName, description)
471
471
  }
472
472
  export class AgentRuntimeAdapter {
473
473
  options;
474
+ modelCache = new Map();
475
+ runnableCache = new WeakMap();
474
476
  constructor(options = {}) {
475
477
  this.options = options;
476
478
  }
479
+ getModelCacheKey(model) {
480
+ return JSON.stringify({
481
+ id: model.id,
482
+ runtimeValue: model.runtimeValue,
483
+ init: model.init,
484
+ clientRef: model.clientRef,
485
+ });
486
+ }
477
487
  resolveBindingTimeout(binding) {
478
488
  return resolveTimeoutMs(getBindingModelInit(binding)?.timeout);
479
489
  }
@@ -686,25 +696,40 @@ export class AgentRuntimeAdapter {
686
696
  return sanitizeVisibleText(extractVisibleOutput(synthesized));
687
697
  }
688
698
  async resolveModel(model) {
689
- if (this.options.modelResolver) {
690
- return wrapResolvedModel(await this.options.modelResolver(model.id));
691
- }
692
- if (model.provider === "ollama") {
693
- return wrapResolvedModel(new ChatOllama({ model: model.model, ...model.init }));
694
- }
695
- if (model.provider === "openai-compatible") {
696
- return wrapResolvedModel(new ChatOpenAI({ model: model.model, ...normalizeOpenAICompatibleInit(model.init) }));
699
+ const cacheKey = this.getModelCacheKey(model);
700
+ const cached = this.modelCache.get(cacheKey);
701
+ if (cached) {
702
+ return cached;
697
703
  }
698
- if (model.provider === "openai") {
699
- return wrapResolvedModel(new ChatOpenAI({ model: model.model, ...model.init }));
700
- }
701
- if (model.provider === "anthropic") {
702
- return wrapResolvedModel(new ChatAnthropic({ model: model.model, ...model.init }));
704
+ const pending = (async () => {
705
+ if (this.options.modelResolver) {
706
+ return wrapResolvedModel(await this.options.modelResolver(model.id));
707
+ }
708
+ if (model.provider === "ollama") {
709
+ return wrapResolvedModel(new ChatOllama({ model: model.model, ...model.init }));
710
+ }
711
+ if (model.provider === "openai-compatible") {
712
+ return wrapResolvedModel(new ChatOpenAI({ model: model.model, ...normalizeOpenAICompatibleInit(model.init) }));
713
+ }
714
+ if (model.provider === "openai") {
715
+ return wrapResolvedModel(new ChatOpenAI({ model: model.model, ...model.init }));
716
+ }
717
+ if (model.provider === "anthropic") {
718
+ return wrapResolvedModel(new ChatAnthropic({ model: model.model, ...model.init }));
719
+ }
720
+ if (model.provider === "google" || model.provider === "google-genai" || model.provider === "gemini") {
721
+ return wrapResolvedModel(new ChatGoogle({ model: model.model, ...model.init }));
722
+ }
723
+ return wrapResolvedModel(await initChatModel(model.model, { modelProvider: model.provider, ...model.init }));
724
+ })();
725
+ this.modelCache.set(cacheKey, pending);
726
+ try {
727
+ return await pending;
703
728
  }
704
- if (model.provider === "google" || model.provider === "google-genai" || model.provider === "gemini") {
705
- return wrapResolvedModel(new ChatGoogle({ model: model.model, ...model.init }));
729
+ catch (error) {
730
+ this.modelCache.delete(cacheKey);
731
+ throw error;
706
732
  }
707
- return wrapResolvedModel(await initChatModel(model.model, { modelProvider: model.provider, ...model.init }));
708
733
  }
709
734
  buildToolNameMapping(tools) {
710
735
  return buildToolNameMapping(tools);
@@ -1065,6 +1090,27 @@ export class AgentRuntimeAdapter {
1065
1090
  }
1066
1091
  return tools;
1067
1092
  }
1093
+ canReplayToolCallsLocally(binding, toolCalls, primaryTools, toolNameMapping, executableTools, builtinExecutableTools) {
1094
+ if (toolCalls.length === 0) {
1095
+ return false;
1096
+ }
1097
+ if (isLangChainBinding(binding)) {
1098
+ return true;
1099
+ }
1100
+ return toolCalls.every((toolCall) => {
1101
+ const resolvedToolName = resolveModelFacingToolName(toolCall.name, toolNameMapping, primaryTools);
1102
+ const executable = executableTools.get(toolCall.name) ?? executableTools.get(resolvedToolName);
1103
+ if (executable) {
1104
+ return false;
1105
+ }
1106
+ const builtinExecutable = builtinExecutableTools.get(toolCall.name) ??
1107
+ builtinExecutableTools.get(resolvedToolName) ??
1108
+ createModelFacingToolNameLookupCandidates(toolCall.name)
1109
+ .map((candidate) => builtinExecutableTools.get(candidate))
1110
+ .find((candidate) => candidate !== undefined);
1111
+ return builtinExecutable !== undefined;
1112
+ });
1113
+ }
1068
1114
  async resolveLangChainAutomaticMiddleware(binding) {
1069
1115
  const params = getBindingLangChainParams(binding);
1070
1116
  if (!params) {
@@ -1170,7 +1216,7 @@ export class AgentRuntimeAdapter {
1170
1216
  })),
1171
1217
  })));
1172
1218
  }
1173
- async create(binding) {
1219
+ async createRunnable(binding) {
1174
1220
  if (isLangChainBinding(binding)) {
1175
1221
  const params = getBindingLangChainParams(binding);
1176
1222
  const interruptOn = this.resolveInterruptOn(binding);
@@ -1226,6 +1272,21 @@ export class AgentRuntimeAdapter {
1226
1272
  };
1227
1273
  return createDeepAgent(deepAgentConfig);
1228
1274
  }
1275
+ async create(binding) {
1276
+ const cached = this.runnableCache.get(binding);
1277
+ if (cached) {
1278
+ return cached;
1279
+ }
1280
+ const pending = this.createRunnable(binding);
1281
+ this.runnableCache.set(binding, pending);
1282
+ try {
1283
+ return await pending;
1284
+ }
1285
+ catch (error) {
1286
+ this.runnableCache.delete(binding);
1287
+ throw error;
1288
+ }
1289
+ }
1229
1290
  async route(input, primaryBinding, secondaryBinding, options = {}) {
1230
1291
  const routeModelConfig = getBindingPrimaryModel(primaryBinding) ??
1231
1292
  getBindingPrimaryModel(secondaryBinding);
@@ -1323,12 +1384,17 @@ export class AgentRuntimeAdapter {
1323
1384
  let activeRequest = request;
1324
1385
  let currentMessages = Array.isArray(activeRequest.messages) ? [...activeRequest.messages] : [];
1325
1386
  const maxToolIterations = 8;
1387
+ let pendingResult;
1326
1388
  for (let iteration = 0; iteration < maxToolIterations; iteration += 1) {
1327
- result = await callRuntimeWithToolParseRecovery(activeRequest);
1389
+ result = pendingResult ?? await callRuntimeWithToolParseRecovery(activeRequest);
1390
+ pendingResult = undefined;
1328
1391
  const toolCalls = extractToolCallsFromResult(result);
1329
1392
  if (toolCalls.length === 0) {
1330
1393
  break;
1331
1394
  }
1395
+ if (!this.canReplayToolCallsLocally(binding, toolCalls, primaryTools, toolNameMapping, executableTools, builtinExecutableTools)) {
1396
+ break;
1397
+ }
1332
1398
  if (iteration + 1 === maxToolIterations) {
1333
1399
  throw new Error(`Tool-calling loop exceeded the maximum of ${maxToolIterations} iterations`);
1334
1400
  }
@@ -261,26 +261,10 @@ export class AgentHarnessRuntime {
261
261
  return tools.every((tool) => tool.retryable === true);
262
262
  }
263
263
  async listThreads(filter) {
264
- const threadSummaries = await this.persistence.listSessions();
265
- if (!filter?.agentId) {
266
- return threadSummaries;
267
- }
268
- return threadSummaries.filter((thread) => thread.agentId === filter.agentId);
264
+ return this.persistence.listSessions(filter);
269
265
  }
270
266
  async listRuns(filter) {
271
- const runs = await this.persistence.listRuns();
272
- return runs.filter((run) => {
273
- if (filter?.agentId && run.agentId !== filter.agentId) {
274
- return false;
275
- }
276
- if (filter?.threadId && run.threadId !== filter.threadId) {
277
- return false;
278
- }
279
- if (filter?.state && run.state !== filter.state) {
280
- return false;
281
- }
282
- return true;
283
- });
267
+ return this.persistence.listRuns(filter);
284
268
  }
285
269
  async getRun(runId) {
286
270
  return this.persistence.getRun(runId);
@@ -324,21 +308,8 @@ export class AgentHarnessRuntime {
324
308
  };
325
309
  }
326
310
  async listApprovals(filter) {
327
- const approvals = filter?.threadId && filter?.runId
328
- ? await this.persistence.getRunApprovals(filter.threadId, filter.runId)
329
- : await this.persistence.listApprovals();
330
- return approvals.filter((approval) => {
331
- if (filter?.status && approval.status !== filter.status) {
332
- return false;
333
- }
334
- if (filter?.threadId && approval.threadId !== filter.threadId) {
335
- return false;
336
- }
337
- if (filter?.runId && approval.runId !== filter.runId) {
338
- return false;
339
- }
340
- return true;
341
- }).map((approval) => this.toPublicApprovalRecord(approval));
311
+ const approvals = await this.persistence.listApprovals(filter);
312
+ return approvals.map((approval) => this.toPublicApprovalRecord(approval));
342
313
  }
343
314
  async getApproval(approvalId) {
344
315
  const approval = await this.persistence.getApproval(approvalId);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@botbotgo/agent-harness",
3
- "version": "0.0.81",
3
+ "version": "0.0.82",
4
4
  "description": "Workspace runtime for multi-agent applications",
5
5
  "type": "module",
6
6
  "packageManager": "npm@10.9.2",