@botbotgo/agent-harness 0.0.85 → 0.0.87
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.
|
|
1
|
+
export declare const AGENT_HARNESS_VERSION = "0.0.86";
|
package/dist/package-version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const AGENT_HARNESS_VERSION = "0.0.
|
|
1
|
+
export const AGENT_HARNESS_VERSION = "0.0.86";
|
|
@@ -15,6 +15,7 @@ export declare class SqlitePersistence implements RuntimePersistence {
|
|
|
15
15
|
private threadDir;
|
|
16
16
|
private runDir;
|
|
17
17
|
private execute;
|
|
18
|
+
private executeTransaction;
|
|
18
19
|
private selectOne;
|
|
19
20
|
private selectAll;
|
|
20
21
|
private mapThreadSummary;
|
|
@@ -29,6 +30,18 @@ export declare class SqlitePersistence implements RuntimePersistence {
|
|
|
29
30
|
status: RunState;
|
|
30
31
|
createdAt: string;
|
|
31
32
|
}): Promise<void>;
|
|
33
|
+
bootstrapRun(input: {
|
|
34
|
+
threadId: string;
|
|
35
|
+
agentId: string;
|
|
36
|
+
runId: string;
|
|
37
|
+
status: RunState;
|
|
38
|
+
createdAt: string;
|
|
39
|
+
executionMode: string;
|
|
40
|
+
adapterKind?: string;
|
|
41
|
+
userMessage: TranscriptMessage;
|
|
42
|
+
runRequest: PersistedRunRequest;
|
|
43
|
+
createThread: boolean;
|
|
44
|
+
}): Promise<void>;
|
|
32
45
|
createRun(input: {
|
|
33
46
|
threadId: string;
|
|
34
47
|
runId: string;
|
|
@@ -263,6 +263,31 @@ export class SqlitePersistence {
|
|
|
263
263
|
}
|
|
264
264
|
await client.execute(sql);
|
|
265
265
|
}
|
|
266
|
+
async executeTransaction(steps) {
|
|
267
|
+
await this.ensureInitialized();
|
|
268
|
+
const client = await this.getClient();
|
|
269
|
+
await client.execute("BEGIN IMMEDIATE");
|
|
270
|
+
try {
|
|
271
|
+
for (const step of steps) {
|
|
272
|
+
if (step.args) {
|
|
273
|
+
await client.execute(step.sql, step.args);
|
|
274
|
+
}
|
|
275
|
+
else {
|
|
276
|
+
await client.execute(step.sql);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
await client.execute("COMMIT");
|
|
280
|
+
}
|
|
281
|
+
catch (error) {
|
|
282
|
+
try {
|
|
283
|
+
await client.execute("ROLLBACK");
|
|
284
|
+
}
|
|
285
|
+
catch {
|
|
286
|
+
// Ignore rollback failures and preserve the original error.
|
|
287
|
+
}
|
|
288
|
+
throw error;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
266
291
|
async selectOne(sql, args) {
|
|
267
292
|
await this.ensureInitialized();
|
|
268
293
|
const client = await this.getClient();
|
|
@@ -347,6 +372,61 @@ export class SqlitePersistence {
|
|
|
347
372
|
(thread_id, workspace_id, entry_agent_id, status, latest_run_id, created_at, updated_at)
|
|
348
373
|
VALUES (?, ?, ?, ?, ?, ?, ?)`, [input.threadId, "default", input.agentId, input.status, input.runId, input.createdAt, input.createdAt]);
|
|
349
374
|
}
|
|
375
|
+
async bootstrapRun(input) {
|
|
376
|
+
await mkdir(this.threadDir(input.threadId), { recursive: true });
|
|
377
|
+
await mkdir(path.join(this.runDir(input.threadId, input.runId), "events"), { recursive: true });
|
|
378
|
+
const steps = [];
|
|
379
|
+
if (input.createThread) {
|
|
380
|
+
steps.push({
|
|
381
|
+
sql: `INSERT OR REPLACE INTO threads
|
|
382
|
+
(thread_id, workspace_id, entry_agent_id, status, latest_run_id, created_at, updated_at)
|
|
383
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)`,
|
|
384
|
+
args: [input.threadId, "default", input.agentId, input.status, input.runId, input.createdAt, input.createdAt],
|
|
385
|
+
});
|
|
386
|
+
}
|
|
387
|
+
steps.push({
|
|
388
|
+
sql: `INSERT OR REPLACE INTO runs
|
|
389
|
+
(run_id, thread_id, agent_id, execution_mode, adapter_kind, created_at, updated_at, state, previous_state, state_entered_at, last_transition_at, resumable, checkpoint_ref)
|
|
390
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
391
|
+
args: [
|
|
392
|
+
input.runId,
|
|
393
|
+
input.threadId,
|
|
394
|
+
input.agentId,
|
|
395
|
+
input.executionMode,
|
|
396
|
+
input.adapterKind ?? input.executionMode ?? null,
|
|
397
|
+
input.createdAt,
|
|
398
|
+
input.createdAt,
|
|
399
|
+
"running",
|
|
400
|
+
null,
|
|
401
|
+
input.createdAt,
|
|
402
|
+
input.createdAt,
|
|
403
|
+
0,
|
|
404
|
+
null,
|
|
405
|
+
],
|
|
406
|
+
}, {
|
|
407
|
+
sql: `INSERT OR REPLACE INTO run_control
|
|
408
|
+
(run_id, cancel_requested, cancel_reason, cancel_requested_at, heartbeat_at, worker_id, worker_started_at)
|
|
409
|
+
VALUES (?, 0, NULL, NULL, NULL, NULL, NULL)`,
|
|
410
|
+
args: [input.runId],
|
|
411
|
+
}, {
|
|
412
|
+
sql: `INSERT INTO thread_messages
|
|
413
|
+
(thread_id, role, content_json, run_id, created_at)
|
|
414
|
+
VALUES (?, ?, ?, ?, ?)`,
|
|
415
|
+
args: [
|
|
416
|
+
input.threadId,
|
|
417
|
+
input.userMessage.role,
|
|
418
|
+
JSON.stringify(input.userMessage.content),
|
|
419
|
+
input.userMessage.runId,
|
|
420
|
+
input.userMessage.createdAt,
|
|
421
|
+
],
|
|
422
|
+
}, {
|
|
423
|
+
sql: `INSERT OR REPLACE INTO run_requests
|
|
424
|
+
(run_id, thread_id, request_json, saved_at)
|
|
425
|
+
VALUES (?, ?, ?, ?)`,
|
|
426
|
+
args: [input.runId, input.threadId, JSON.stringify(input.runRequest), input.runRequest.savedAt],
|
|
427
|
+
});
|
|
428
|
+
await this.executeTransaction(steps);
|
|
429
|
+
}
|
|
350
430
|
async createRun(input) {
|
|
351
431
|
await mkdir(path.join(this.runDir(input.threadId, input.runId), "events"), { recursive: true });
|
|
352
432
|
await this.execute(`INSERT OR REPLACE INTO runs
|
|
@@ -75,6 +75,18 @@ export type ApprovalFilter = {
|
|
|
75
75
|
};
|
|
76
76
|
export interface RuntimePersistence {
|
|
77
77
|
initialize(): Promise<void>;
|
|
78
|
+
bootstrapRun?(input: {
|
|
79
|
+
threadId: string;
|
|
80
|
+
agentId: string;
|
|
81
|
+
runId: string;
|
|
82
|
+
status: RunState;
|
|
83
|
+
createdAt: string;
|
|
84
|
+
executionMode: string;
|
|
85
|
+
adapterKind?: string;
|
|
86
|
+
userMessage: TranscriptMessage;
|
|
87
|
+
runRequest: PersistedRunRequest;
|
|
88
|
+
createThread: boolean;
|
|
89
|
+
}): Promise<void>;
|
|
78
90
|
createThread(input: {
|
|
79
91
|
threadId: string;
|
|
80
92
|
agentId: string;
|
package/dist/runtime/harness.js
CHANGED
|
@@ -437,36 +437,54 @@ export class AgentHarnessRuntime {
|
|
|
437
437
|
this.backgroundTasks.delete(task);
|
|
438
438
|
});
|
|
439
439
|
}
|
|
440
|
-
async ensureThreadStarted(selectedAgentId, binding, input, existingThreadId) {
|
|
440
|
+
async ensureThreadStarted(selectedAgentId, binding, input, runRequest, existingThreadId) {
|
|
441
441
|
const threadId = existingThreadId ?? createPersistentId();
|
|
442
442
|
const runId = createPersistentId();
|
|
443
443
|
const createdAt = new Date().toISOString();
|
|
444
444
|
const isNewThread = !existingThreadId;
|
|
445
|
-
|
|
446
|
-
|
|
445
|
+
const userMessage = {
|
|
446
|
+
role: "user",
|
|
447
|
+
content: normalizeMessageContent(input),
|
|
448
|
+
runId,
|
|
449
|
+
createdAt,
|
|
450
|
+
};
|
|
451
|
+
if (typeof this.persistence.bootstrapRun === "function") {
|
|
452
|
+
await this.persistence.bootstrapRun({
|
|
447
453
|
threadId,
|
|
448
|
-
agentId:
|
|
454
|
+
agentId: binding.agent.id,
|
|
449
455
|
runId,
|
|
450
456
|
status: "running",
|
|
451
457
|
createdAt,
|
|
452
|
-
});
|
|
453
|
-
}
|
|
454
|
-
await Promise.all([
|
|
455
|
-
this.persistence.appendThreadMessage(threadId, {
|
|
456
|
-
role: "user",
|
|
457
|
-
content: normalizeMessageContent(input),
|
|
458
|
-
runId,
|
|
459
|
-
createdAt,
|
|
460
|
-
}),
|
|
461
|
-
this.persistence.createRun({
|
|
462
|
-
threadId,
|
|
463
|
-
runId,
|
|
464
|
-
agentId: binding.agent.id,
|
|
465
458
|
executionMode: getBindingAdapterKind(binding),
|
|
466
459
|
adapterKind: getBindingAdapterKind(binding),
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
460
|
+
userMessage,
|
|
461
|
+
runRequest,
|
|
462
|
+
createThread: isNewThread,
|
|
463
|
+
});
|
|
464
|
+
}
|
|
465
|
+
else {
|
|
466
|
+
if (isNewThread) {
|
|
467
|
+
await this.persistence.createThread({
|
|
468
|
+
threadId,
|
|
469
|
+
agentId: selectedAgentId,
|
|
470
|
+
runId,
|
|
471
|
+
status: "running",
|
|
472
|
+
createdAt,
|
|
473
|
+
});
|
|
474
|
+
}
|
|
475
|
+
await Promise.all([
|
|
476
|
+
this.persistence.appendThreadMessage(threadId, userMessage),
|
|
477
|
+
this.persistence.createRun({
|
|
478
|
+
threadId,
|
|
479
|
+
runId,
|
|
480
|
+
agentId: binding.agent.id,
|
|
481
|
+
executionMode: getBindingAdapterKind(binding),
|
|
482
|
+
adapterKind: getBindingAdapterKind(binding),
|
|
483
|
+
createdAt,
|
|
484
|
+
}),
|
|
485
|
+
this.persistence.saveRunRequest(threadId, runId, runRequest),
|
|
486
|
+
]);
|
|
487
|
+
}
|
|
470
488
|
return { threadId, runId, createdAt, isNewThread };
|
|
471
489
|
}
|
|
472
490
|
async loadPriorHistory(threadId, runId) {
|
|
@@ -1046,9 +1064,9 @@ export class AgentHarnessRuntime {
|
|
|
1046
1064
|
if (!policyDecision.allowed) {
|
|
1047
1065
|
throw new Error(`Policy evaluation blocked agent ${selectedAgentId}: ${policyDecision.reasons.join(", ")}`);
|
|
1048
1066
|
}
|
|
1049
|
-
const { threadId, runId, isNewThread } = await this.ensureThreadStarted(selectedAgentId, binding, options.input, options.threadId);
|
|
1050
1067
|
const priority = this.normalizeRunPriority(options.priority);
|
|
1051
|
-
const
|
|
1068
|
+
const runRequest = this.buildPersistedRunRequest(options.input, invocation, priority);
|
|
1069
|
+
const { threadId, runId, isNewThread } = await this.ensureThreadStarted(selectedAgentId, binding, options.input, runRequest, options.threadId);
|
|
1052
1070
|
const runCreatedEventPromise = this.emitRunCreated(threadId, runId, {
|
|
1053
1071
|
agentId: binding.agent.id,
|
|
1054
1072
|
requestedAgentId: options.agentId ?? AUTO_AGENT_ID,
|
|
@@ -1056,7 +1074,6 @@ export class AgentHarnessRuntime {
|
|
|
1056
1074
|
executionMode: getBindingAdapterKind(binding),
|
|
1057
1075
|
});
|
|
1058
1076
|
const releaseRunSlotPromise = this.acquireRunSlot(threadId, runId, "running", priority);
|
|
1059
|
-
await runRequestPromise;
|
|
1060
1077
|
await runCreatedEventPromise;
|
|
1061
1078
|
const releaseRunSlot = await releaseRunSlotPromise;
|
|
1062
1079
|
try {
|
|
@@ -1093,10 +1110,10 @@ export class AgentHarnessRuntime {
|
|
|
1093
1110
|
}
|
|
1094
1111
|
let emitted = false;
|
|
1095
1112
|
let streamActivityObserved = false;
|
|
1096
|
-
const { threadId, runId, isNewThread } = await this.ensureThreadStarted(selectedAgentId, binding, options.input, options.threadId);
|
|
1097
1113
|
const priority = this.normalizeRunPriority(options.priority);
|
|
1114
|
+
const runRequest = this.buildPersistedRunRequest(options.input, invocation, priority);
|
|
1115
|
+
const { threadId, runId, isNewThread } = await this.ensureThreadStarted(selectedAgentId, binding, options.input, runRequest, options.threadId);
|
|
1098
1116
|
const priorHistoryPromise = Promise.resolve(isNewThread ? [] : undefined).then((historyHint) => historyHint ?? this.loadPriorHistory(threadId, runId));
|
|
1099
|
-
const runRequestPromise = this.persistence.saveRunRequest(threadId, runId, this.buildPersistedRunRequest(options.input, invocation, priority));
|
|
1100
1117
|
const runCreatedEventPromise = this.emitRunCreated(threadId, runId, {
|
|
1101
1118
|
agentId: selectedAgentId,
|
|
1102
1119
|
requestedAgentId: options.agentId ?? AUTO_AGENT_ID,
|
|
@@ -1112,7 +1129,6 @@ export class AgentHarnessRuntime {
|
|
|
1112
1129
|
const [priorHistory, acquiredReleaseRunSlot] = await Promise.all([
|
|
1113
1130
|
priorHistoryPromise,
|
|
1114
1131
|
releaseRunSlotPromise,
|
|
1115
|
-
runRequestPromise,
|
|
1116
1132
|
]).then(([loadedPriorHistory, resolvedReleaseRunSlot]) => [loadedPriorHistory, resolvedReleaseRunSlot]);
|
|
1117
1133
|
releaseRunSlot = acquiredReleaseRunSlot;
|
|
1118
1134
|
let assistantOutput = "";
|