@botbotgo/agent-harness 0.0.35 → 0.0.37
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.36";
|
package/dist/package-version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const AGENT_HARNESS_VERSION = "0.0.
|
|
1
|
+
export const AGENT_HARNESS_VERSION = "0.0.36";
|
|
@@ -32,6 +32,16 @@ function asObject(value) {
|
|
|
32
32
|
function resolveTimeoutMs(value) {
|
|
33
33
|
return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : undefined;
|
|
34
34
|
}
|
|
35
|
+
function computeRemainingTimeoutMs(deadlineAt, fallbackTimeoutMs) {
|
|
36
|
+
if (!deadlineAt) {
|
|
37
|
+
return fallbackTimeoutMs;
|
|
38
|
+
}
|
|
39
|
+
const remaining = deadlineAt - Date.now();
|
|
40
|
+
if (remaining <= 0) {
|
|
41
|
+
return 0;
|
|
42
|
+
}
|
|
43
|
+
return fallbackTimeoutMs ? Math.min(fallbackTimeoutMs, remaining) : remaining;
|
|
44
|
+
}
|
|
35
45
|
function isPlaceholderApiKey(value) {
|
|
36
46
|
return typeof value === "string" && value.trim().toLowerCase() === "dummy";
|
|
37
47
|
}
|
|
@@ -209,11 +219,27 @@ export class AgentRuntimeAdapter {
|
|
|
209
219
|
});
|
|
210
220
|
});
|
|
211
221
|
}
|
|
212
|
-
async *iterateWithTimeout(iterable, timeoutMs, operation) {
|
|
222
|
+
async *iterateWithTimeout(iterable, timeoutMs, operation, deadlineAt, deadlineTimeoutMs) {
|
|
213
223
|
const iterator = iterable[Symbol.asyncIterator]();
|
|
214
224
|
try {
|
|
215
225
|
for (;;) {
|
|
216
|
-
const
|
|
226
|
+
const effectiveTimeoutMs = computeRemainingTimeoutMs(deadlineAt, timeoutMs);
|
|
227
|
+
if (effectiveTimeoutMs !== undefined && effectiveTimeoutMs <= 0) {
|
|
228
|
+
throw new RuntimeOperationTimeoutError(operation, deadlineTimeoutMs ?? timeoutMs ?? 0, "invoke");
|
|
229
|
+
}
|
|
230
|
+
let next;
|
|
231
|
+
try {
|
|
232
|
+
next = await this.withTimeout(() => iterator.next(), effectiveTimeoutMs, operation, "stream");
|
|
233
|
+
}
|
|
234
|
+
catch (error) {
|
|
235
|
+
if (error instanceof RuntimeOperationTimeoutError &&
|
|
236
|
+
deadlineAt &&
|
|
237
|
+
deadlineTimeoutMs &&
|
|
238
|
+
effectiveTimeoutMs !== timeoutMs) {
|
|
239
|
+
throw new RuntimeOperationTimeoutError(operation, deadlineTimeoutMs, "invoke");
|
|
240
|
+
}
|
|
241
|
+
throw error;
|
|
242
|
+
}
|
|
217
243
|
if (next.done) {
|
|
218
244
|
return;
|
|
219
245
|
}
|
|
@@ -591,6 +617,7 @@ export class AgentRuntimeAdapter {
|
|
|
591
617
|
try {
|
|
592
618
|
const invokeTimeoutMs = this.resolveBindingTimeout(binding);
|
|
593
619
|
const streamIdleTimeoutMs = this.resolveStreamIdleTimeout(binding);
|
|
620
|
+
const streamDeadlineAt = invokeTimeoutMs ? Date.now() + invokeTimeoutMs : undefined;
|
|
594
621
|
if (binding.langchainAgentParams) {
|
|
595
622
|
const langchainParams = binding.langchainAgentParams;
|
|
596
623
|
const resolvedModel = (await this.resolveModel(binding.langchainAgentParams.model));
|
|
@@ -605,8 +632,8 @@ export class AgentRuntimeAdapter {
|
|
|
605
632
|
// agent loop and only adds an extra model round-trip before the runnable path.
|
|
606
633
|
if (canUseDirectModelStream && typeof model.stream === "function") {
|
|
607
634
|
let emitted = false;
|
|
608
|
-
const stream = await this.withTimeout(() => model.stream(this.buildRawModelMessages(langchainParams.systemPrompt, history, input)), invokeTimeoutMs, "model stream start", "stream");
|
|
609
|
-
for await (const chunk of this.iterateWithTimeout(stream, streamIdleTimeoutMs, "model stream")) {
|
|
635
|
+
const stream = await this.withTimeout(() => model.stream(this.buildRawModelMessages(langchainParams.systemPrompt, history, input)), computeRemainingTimeoutMs(streamDeadlineAt, invokeTimeoutMs), "model stream start", "stream");
|
|
636
|
+
for await (const chunk of this.iterateWithTimeout(stream, streamIdleTimeoutMs, "model stream", streamDeadlineAt, invokeTimeoutMs)) {
|
|
610
637
|
const delta = readStreamDelta(chunk);
|
|
611
638
|
if (delta) {
|
|
612
639
|
emitted = true;
|
|
@@ -626,12 +653,12 @@ export class AgentRuntimeAdapter {
|
|
|
626
653
|
const runnable = await this.create(binding);
|
|
627
654
|
const request = { messages: this.buildAgentMessages(history, input) };
|
|
628
655
|
if (typeof runnable.streamEvents === "function") {
|
|
629
|
-
const events = await this.withTimeout(() => runnable.streamEvents(request, { configurable: { thread_id: threadId }, version: "v2" }), invokeTimeoutMs, "agent streamEvents start", "stream");
|
|
656
|
+
const events = await this.withTimeout(() => runnable.streamEvents(request, { configurable: { thread_id: threadId }, version: "v2" }), computeRemainingTimeoutMs(streamDeadlineAt, invokeTimeoutMs), "agent streamEvents start", "stream");
|
|
630
657
|
const allowVisibleStreamDeltas = Boolean(binding.langchainAgentParams);
|
|
631
658
|
let emittedOutput = "";
|
|
632
659
|
const seenTerminalOutputs = new Set();
|
|
633
660
|
let lastStep = "";
|
|
634
|
-
for await (const event of this.iterateWithTimeout(events, streamIdleTimeoutMs, "agent streamEvents")) {
|
|
661
|
+
for await (const event of this.iterateWithTimeout(events, streamIdleTimeoutMs, "agent streamEvents", streamDeadlineAt, invokeTimeoutMs)) {
|
|
635
662
|
const interruptPayload = extractInterruptPayload(event);
|
|
636
663
|
if (interruptPayload) {
|
|
637
664
|
yield { kind: "interrupt", content: interruptPayload };
|
|
@@ -691,9 +718,9 @@ export class AgentRuntimeAdapter {
|
|
|
691
718
|
}
|
|
692
719
|
}
|
|
693
720
|
if (binding.langchainAgentParams && typeof runnable.stream === "function") {
|
|
694
|
-
const stream = await this.withTimeout(() => runnable.stream(request, { configurable: { thread_id: threadId } }), invokeTimeoutMs, "agent stream start", "stream");
|
|
721
|
+
const stream = await this.withTimeout(() => runnable.stream(request, { configurable: { thread_id: threadId } }), computeRemainingTimeoutMs(streamDeadlineAt, invokeTimeoutMs), "agent stream start", "stream");
|
|
695
722
|
let emitted = false;
|
|
696
|
-
for await (const chunk of this.iterateWithTimeout(stream, streamIdleTimeoutMs, "agent stream")) {
|
|
723
|
+
for await (const chunk of this.iterateWithTimeout(stream, streamIdleTimeoutMs, "agent stream", streamDeadlineAt, invokeTimeoutMs)) {
|
|
697
724
|
const delta = readStreamDelta(chunk);
|
|
698
725
|
if (delta) {
|
|
699
726
|
emitted = true;
|
|
@@ -2,6 +2,7 @@ import { interrupt } from "@langchain/langgraph";
|
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
const DEDUPED_REMOTE_TOOL_NAMES = new Set(["builtin.fetch_url", "builtin.web_search"]);
|
|
4
4
|
const PATH_LIKE_INPUT_KEYS = new Set(["path", "root", "dir", "directory", "cwd"]);
|
|
5
|
+
const ROOT_SCOPING_INPUT_KEYS = new Set(["root", "dir", "directory", "cwd"]);
|
|
5
6
|
function toInputPreview(input) {
|
|
6
7
|
if (typeof input === "object" && input && !Array.isArray(input)) {
|
|
7
8
|
return input;
|
|
@@ -129,6 +130,10 @@ function guardWorkspaceBoundToolInput(input, compiledTool, binding) {
|
|
|
129
130
|
const absolute = path.resolve(workspaceRoot, candidate);
|
|
130
131
|
const relative = path.relative(workspaceRoot, absolute);
|
|
131
132
|
if (relative.startsWith("..") || path.isAbsolute(relative)) {
|
|
133
|
+
if (ROOT_SCOPING_INPUT_KEYS.has(key)) {
|
|
134
|
+
record[key] = workspaceRoot;
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
132
137
|
throw new Error(`Tool ${compiledTool.name} input ${key} resolves outside the workspace root`);
|
|
133
138
|
}
|
|
134
139
|
}
|