@botbotgo/agent-harness 0.0.342 → 0.0.343

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.
@@ -16,6 +16,7 @@ export declare function streamChatMessage(input: {
16
16
  colorRequestTree?: boolean;
17
17
  showToolResults?: boolean;
18
18
  showRunningState?: boolean;
19
+ idleProgressMs?: number;
19
20
  }): Promise<{
20
21
  sessionId?: string;
21
22
  requestId?: string;
@@ -3,6 +3,7 @@ import { countRenderedLines, renderChatRequestRunning, renderChatTextChunk, summ
3
3
  import { buildTerminalRequestSnapshot, buildTodoContinuationSignature, flattenRequestExecutionSteps, renderRequestEventContinuation, renderRequestSnapshotTree, renderRequestTodoContinuation, } from "./request-tree.js";
4
4
  export async function streamChatMessage(input) {
5
5
  const requestStartedAt = Date.now();
6
+ const idleProgressMs = input.idleProgressMs ?? 30_000;
6
7
  let firstSnapshotAt;
7
8
  let firstDataAt;
8
9
  let latestSnapshot;
@@ -27,6 +28,8 @@ export async function streamChatMessage(input) {
27
28
  const requestTreeRenderThrottleMs = 75;
28
29
  let suppressRequestTreeRendering = false;
29
30
  let lastStableRequestTreeKey;
31
+ let idleProgressTimer;
32
+ let lastRuntimeProgressAt = requestStartedAt;
30
33
  let stdoutWriteChain = Promise.resolve();
31
34
  let stderrWriteChain = Promise.resolve();
32
35
  const enqueueChatWrite = (sink, _stream, chain, message) => chain.then(async () => {
@@ -173,6 +176,27 @@ export async function streamChatMessage(input) {
173
176
  }
174
177
  stderrWriteChain = enqueueChatWrite(input.stderr, input.stderrStream, stderrWriteChain, message);
175
178
  };
179
+ const clearIdleProgressTimer = () => {
180
+ if (idleProgressTimer) {
181
+ clearTimeout(idleProgressTimer);
182
+ idleProgressTimer = undefined;
183
+ }
184
+ };
185
+ const scheduleIdleProgress = () => {
186
+ clearIdleProgressTimer();
187
+ if (idleProgressMs <= 0 || wroteContent || wroteRenderableBlocks) {
188
+ return;
189
+ }
190
+ idleProgressTimer = setTimeout(() => {
191
+ const idleSeconds = Math.max(1, Math.round((Date.now() - lastRuntimeProgressAt) / 1000));
192
+ writeChatStderr(`[${formatPerfClock(Date.now())} +${formatElapsed(Date.now())}]${formatAgentProgressLabel(latestAgentId)} Still working; no runtime update for ${idleSeconds}s.\n`);
193
+ scheduleIdleProgress();
194
+ }, idleProgressMs);
195
+ };
196
+ const markRuntimeProgress = () => {
197
+ lastRuntimeProgressAt = Date.now();
198
+ scheduleIdleProgress();
199
+ };
176
200
  const suspendRequestTreeRendering = () => {
177
201
  if (!input.requestEvents || !input.liveRequestTree) {
178
202
  return;
@@ -258,6 +282,7 @@ export async function streamChatMessage(input) {
258
282
  ...(input.sessionId ? { sessionId: input.sessionId } : {}),
259
283
  input: input.message,
260
284
  eventListener(snapshot) {
285
+ markRuntimeProgress();
261
286
  latestSessionId = snapshot.sessionId || latestSessionId;
262
287
  latestRequestId = snapshot.requestId || latestRequestId;
263
288
  latestAgentId = snapshot.agentId || latestAgentId;
@@ -303,6 +328,7 @@ export async function streamChatMessage(input) {
303
328
  }
304
329
  },
305
330
  dataListener(delta) {
331
+ markRuntimeProgress();
306
332
  latestSessionId = delta.sessionId || latestSessionId;
307
333
  latestRequestId = delta.requestId || latestRequestId;
308
334
  firstDataAt ??= Date.now();
@@ -342,6 +368,7 @@ export async function streamChatMessage(input) {
342
368
  }
343
369
  },
344
370
  });
371
+ clearIdleProgressTimer();
345
372
  if (!result) {
346
373
  throw new Error("chat request completed without a terminal result");
347
374
  }
@@ -187,6 +187,7 @@ export type CompiledSubAgent = {
187
187
  builtinTools?: {
188
188
  filesystem?: boolean;
189
189
  todos?: boolean;
190
+ modelExposed?: boolean | string[];
190
191
  };
191
192
  };
192
193
  export type CompiledAsyncSubAgent = {
@@ -197,6 +198,11 @@ export type CompiledAsyncSubAgent = {
197
198
  headers?: Record<string, string>;
198
199
  };
199
200
  export type CompiledDeepAgentSubAgent = CompiledSubAgent | CompiledAsyncSubAgent;
201
+ export type CompiledBuiltinToolsConfig = {
202
+ filesystem?: boolean;
203
+ todos?: boolean;
204
+ modelExposed?: boolean | string[];
205
+ };
200
206
  export type LangChainAgentParams = {
201
207
  model: CompiledModel;
202
208
  tools: CompiledTool[];
@@ -209,6 +215,7 @@ export type LangChainAgentParams = {
209
215
  version?: "v1" | "v2";
210
216
  name?: string;
211
217
  description: string;
218
+ builtinTools?: CompiledBuiltinToolsConfig;
212
219
  };
213
220
  export type DeepAgentParams = {
214
221
  model: CompiledModel;
@@ -225,10 +232,7 @@ export type DeepAgentParams = {
225
232
  memory: string[];
226
233
  skills: string[];
227
234
  interactionMode?: "stream" | "invoke";
228
- builtinTools?: {
229
- filesystem?: boolean;
230
- todos?: boolean;
231
- };
235
+ builtinTools?: CompiledBuiltinToolsConfig;
232
236
  };
233
237
  export type LegacyLangChainAgentParams = LangChainAgentParams & {
234
238
  passthrough?: Record<string, unknown>;
@@ -1,2 +1,2 @@
1
- export declare const AGENT_HARNESS_VERSION = "0.0.342";
1
+ export declare const AGENT_HARNESS_VERSION = "0.0.343";
2
2
  export declare const AGENT_HARNESS_RELEASE_DATE = "2026-04-24";
@@ -1,2 +1,2 @@
1
- export const AGENT_HARNESS_VERSION = "0.0.342";
1
+ export const AGENT_HARNESS_VERSION = "0.0.343";
2
2
  export const AGENT_HARNESS_RELEASE_DATE = "2026-04-24";
@@ -246,6 +246,7 @@ export declare const BUILTIN_MIDDLEWARE_TOOL_DESCRIPTORS: readonly [{
246
246
  export declare function filterBuiltinMiddlewareToolDescriptors(options?: {
247
247
  filesystem?: boolean;
248
248
  todos?: boolean;
249
+ modelExposed?: boolean | string[];
249
250
  }): Array<{
250
251
  name: string;
251
252
  description: string;
@@ -29,6 +29,16 @@ export const BUILTIN_MIDDLEWARE_TOOL_DESCRIPTORS = [
29
29
  { name: "task", description: "Delegate a bounded task to a subagent." },
30
30
  ];
31
31
  export function filterBuiltinMiddlewareToolDescriptors(options) {
32
+ const modelExposedNames = new Set([
33
+ "fetch_url",
34
+ "http_request",
35
+ "send_message",
36
+ "request_approval",
37
+ "schedule_task",
38
+ ]);
39
+ const allowedModelExposedNames = Array.isArray(options?.modelExposed)
40
+ ? new Set(options.modelExposed)
41
+ : undefined;
32
42
  return BUILTIN_MIDDLEWARE_TOOL_DESCRIPTORS.filter((descriptor) => {
33
43
  if (options?.todos === false
34
44
  && (descriptor.name === "write_todos" || descriptor.name === "read_todos")) {
@@ -49,6 +59,14 @@ export function filterBuiltinMiddlewareToolDescriptors(options) {
49
59
  ].includes(descriptor.name)) {
50
60
  return false;
51
61
  }
62
+ if (modelExposedNames.has(descriptor.name)) {
63
+ if (options?.modelExposed === false) {
64
+ return false;
65
+ }
66
+ if (allowedModelExposedNames && !allowedModelExposedNames.has(descriptor.name)) {
67
+ return false;
68
+ }
69
+ }
52
70
  return true;
53
71
  }).map((descriptor) => ({ ...descriptor }));
54
72
  }
@@ -360,6 +360,7 @@ export class AgentRuntimeAdapter {
360
360
  }),
361
361
  }),
362
362
  explicitToolNames: primaryTools.map((tool) => tool.name),
363
+ modelExposed: getBindingBuiltinToolsConfig(binding)?.modelExposed,
363
364
  });
364
365
  const resolvedMiddleware = await this.resolveMiddleware(binding, interruptOn, { sessionId: options.sessionId ?? options.legacySessionId });
365
366
  const resolvedCheckpointer = resolveRunnableCheckpointer(this.options, binding);
@@ -405,6 +406,7 @@ export class AgentRuntimeAdapter {
405
406
  }),
406
407
  }),
407
408
  explicitToolNames: primaryTools.map((tool) => tool.name),
409
+ modelExposed: getBindingBuiltinToolsConfig(binding)?.modelExposed,
408
410
  });
409
411
  const resolvedMiddleware = await this.resolveMiddleware(binding);
410
412
  const resolvedSubagents = await this.resolveDeepAgentSubagents(getBindingDeepAgentSubagents(binding), binding, { sessionId: options.sessionId ?? options.legacySessionId });
@@ -6,6 +6,7 @@ export declare const DEFAULT_DEEPAGENT_RECURSION_LIMIT = 100;
6
6
  export declare function materializeModelExposedBuiltinMiddlewareTools(input: {
7
7
  builtinTools: Map<string, ExecutableTool>;
8
8
  explicitToolNames?: string[];
9
+ modelExposed?: boolean | string[];
9
10
  }): unknown[];
10
11
  export declare function resolveRunnableCheckpointer(options: RuntimeAdapterOptions, binding: CompiledAgentBinding): unknown;
11
12
  export declare function resolveRunnableInterruptOn(binding: CompiledAgentBinding): Record<string, {
@@ -18,12 +18,19 @@ const MODEL_EXPOSED_BUILTIN_MIDDLEWARE_TOOL_NAMES = new Set([
18
18
  "schedule_task",
19
19
  ]);
20
20
  export function materializeModelExposedBuiltinMiddlewareTools(input) {
21
+ if (input.modelExposed === false) {
22
+ return [];
23
+ }
21
24
  const explicitToolNames = new Set(input.explicitToolNames ?? []);
25
+ const allowedToolNames = Array.isArray(input.modelExposed)
26
+ ? new Set(input.modelExposed)
27
+ : undefined;
22
28
  const tools = [];
23
29
  for (const [toolName, tool] of input.builtinTools.entries()) {
24
30
  if (explicitToolNames.has(toolName)
25
31
  || BUILTIN_MIDDLEWARE_ALIAS_TOOL_NAMES.has(toolName)
26
- || !MODEL_EXPOSED_BUILTIN_MIDDLEWARE_TOOL_NAMES.has(toolName)) {
32
+ || !MODEL_EXPOSED_BUILTIN_MIDDLEWARE_TOOL_NAMES.has(toolName)
33
+ || (allowedToolNames && !allowedToolNames.has(toolName))) {
27
34
  continue;
28
35
  }
29
36
  tools.push(asStructuredExecutableTool(tool, toolName, tool.name));
@@ -11,6 +11,13 @@ function asObject(value) {
11
11
  function readStringArray(value) {
12
12
  return Array.isArray(value) ? value.filter((item) => typeof item === "string" && item.trim().length > 0) : [];
13
13
  }
14
+ const MODEL_EXPOSED_BUILTIN_TOOL_NAMES = new Set([
15
+ "fetch_url",
16
+ "http_request",
17
+ "send_message",
18
+ "request_approval",
19
+ "schedule_task",
20
+ ]);
14
21
  function getBindingSkillNames(binding) {
15
22
  if (!binding) {
16
23
  return [];
@@ -106,13 +113,20 @@ export function buildRequestRuntimeSnapshot(binding, options) {
106
113
  name: tool.name,
107
114
  description: tool.description,
108
115
  }));
116
+ const builtinToolsConfig = getBindingBuiltinToolsConfig(binding);
117
+ const builtinToolDescriptors = filterBuiltinMiddlewareToolDescriptors(builtinToolsConfig)
118
+ .filter((descriptor) => !declaredTools.some((tool) => tool.name === descriptor.name));
109
119
  const tools = isDeepAgentBinding(binding)
110
120
  ? [
111
121
  ...declaredTools,
112
- ...filterBuiltinMiddlewareToolDescriptors(getBindingBuiltinToolsConfig(binding))
113
- .filter((descriptor) => !declaredTools.some((tool) => tool.name === descriptor.name)),
122
+ ...builtinToolDescriptors,
114
123
  ]
115
- : declaredTools;
124
+ : builtinToolsConfig !== undefined
125
+ ? [
126
+ ...declaredTools,
127
+ ...builtinToolDescriptors.filter((descriptor) => MODEL_EXPOSED_BUILTIN_TOOL_NAMES.has(descriptor.name)),
128
+ ]
129
+ : declaredTools;
116
130
  return {
117
131
  agentId: binding.agent.id,
118
132
  ...(model ? {
@@ -1,4 +1,4 @@
1
- import type { CompiledAgentBinding, CompiledDeepAgentSubAgent, CompiledExecutionBinding, CompiledModel, CompiledSubAgent, CompiledTool, DeepAgentParams, LegacyDeepAgentParams, LegacyLangChainAgentParams, LangChainAgentParams } from "../../contracts/types.js";
1
+ import type { CompiledAgentBinding, CompiledBuiltinToolsConfig, CompiledDeepAgentSubAgent, CompiledExecutionBinding, CompiledModel, CompiledSubAgent, CompiledTool, DeepAgentParams, LegacyDeepAgentParams, LegacyLangChainAgentParams, LangChainAgentParams } from "../../contracts/types.js";
2
2
  export type BindingExecutionView = {
3
3
  adapterKind: string;
4
4
  langchainParams?: LegacyLangChainAgentParams;
@@ -32,10 +32,7 @@ export declare function getBindingGeneralPurposeAgent(binding: CompiledAgentBind
32
32
  export declare function getBindingTaskDescription(binding: CompiledAgentBinding): string | undefined;
33
33
  export declare function getBindingBackendConfig(binding: CompiledAgentBinding): Record<string, unknown> | undefined;
34
34
  export declare function getBindingInteractionMode(binding: CompiledAgentBinding): "stream" | "invoke" | undefined;
35
- export declare function getBindingBuiltinToolsConfig(binding: CompiledAgentBinding): {
36
- filesystem?: boolean;
37
- todos?: boolean;
38
- } | undefined;
35
+ export declare function getBindingBuiltinToolsConfig(binding: CompiledAgentBinding): CompiledBuiltinToolsConfig | undefined;
39
36
  export declare function getBindingFilesystemConfig(binding: CompiledAgentBinding): Record<string, unknown> | undefined;
40
37
  export declare function isLangChainBinding(binding: CompiledAgentBinding): boolean;
41
38
  export declare function isDeepAgentBinding(binding: CompiledAgentBinding): boolean;
@@ -463,6 +463,7 @@ export function compileBinding(workspaceRoot, agent, agents, referencedSubagentI
463
463
  : undefined,
464
464
  name: resolveAgentRuntimeName(agent),
465
465
  description: agent.description,
466
+ builtinTools: getAgentExecutionObject(agent, "builtinTools"),
466
467
  },
467
468
  };
468
469
  return attachLegacyExecutionAliases({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@botbotgo/agent-harness",
3
- "version": "0.0.342",
3
+ "version": "0.0.343",
4
4
  "description": "Workspace runtime for multi-agent applications",
5
5
  "license": "MIT",
6
6
  "type": "module",