@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.
- package/dist/package-version.d.ts +1 -1
- package/dist/package-version.js +1 -1
- package/dist/persistence/file-store.d.ts +4 -4
- package/dist/persistence/file-store.js +33 -6
- package/dist/persistence/sqlite-store.d.ts +4 -4
- package/dist/persistence/sqlite-store.js +31 -8
- package/dist/persistence/types.d.ts +16 -3
- package/dist/runtime/agent-runtime-adapter.d.ts +5 -0
- package/dist/runtime/agent-runtime-adapter.js +84 -18
- package/dist/runtime/harness.js +4 -33
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const AGENT_HARNESS_VERSION = "0.0.
|
|
1
|
+
export declare const AGENT_HARNESS_VERSION = "0.0.81";
|
package/dist/package-version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const AGENT_HARNESS_VERSION = "0.0.
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
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
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
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
|
-
|
|
705
|
-
|
|
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
|
|
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
|
}
|
package/dist/runtime/harness.js
CHANGED
|
@@ -261,26 +261,10 @@ export class AgentHarnessRuntime {
|
|
|
261
261
|
return tools.every((tool) => tool.retryable === true);
|
|
262
262
|
}
|
|
263
263
|
async listThreads(filter) {
|
|
264
|
-
|
|
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
|
-
|
|
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 =
|
|
328
|
-
|
|
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);
|