@botbotgo/agent-harness 0.0.147 → 0.0.148
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/runtime/adapter/tool/tool-hitl.d.ts +1 -0
- package/dist/runtime/adapter/tool/tool-hitl.js +79 -1
- package/dist/runtime/harness/bindings.js +2 -1
- package/dist/tool-modules.d.ts +2 -0
- package/dist/tools.d.ts +4 -0
- 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.147";
|
package/dist/package-version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const AGENT_HARNESS_VERSION = "0.0.
|
|
1
|
+
export const AGENT_HARNESS_VERSION = "0.0.147";
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { CompiledTool } from "../../../contracts/types.js";
|
|
2
2
|
import type { CompiledAgentBinding } from "../../../contracts/types.js";
|
|
3
3
|
type InterruptFn = <I = unknown, R = unknown>(value: I) => R;
|
|
4
|
+
export declare function toolRequiresRuntimeApproval(compiledTool: CompiledTool): boolean;
|
|
4
5
|
export declare function wrapToolForHumanInTheLoop<T>(resolvedTool: T, compiledTool: CompiledTool, interruptFn?: InterruptFn): T;
|
|
5
6
|
export declare function wrapToolForExecution<T>(resolvedTool: T, compiledTool: CompiledTool, binding?: CompiledAgentBinding, interruptFn?: InterruptFn): T;
|
|
6
7
|
export {};
|
|
@@ -3,6 +3,83 @@ 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
5
|
const ROOT_SCOPING_INPUT_KEYS = new Set(["root", "dir", "directory", "cwd"]);
|
|
6
|
+
const SENSITIVE_MEMORY_LEVELS = new Set(["high", "sensitive", "restricted", "secret", "confidential"]);
|
|
7
|
+
const NON_THREAD_MEMORY_SCOPES = new Set(["workspace", "agent", "user", "project"]);
|
|
8
|
+
const WRITE_LIKE_REMOTE_TOOL_PATTERN = /\b(write|edit|delete|create|update|append|insert|push|commit|publish|send|post|apply|merge|sync|upload|save)\b/i;
|
|
9
|
+
function asRecord(value) {
|
|
10
|
+
return typeof value === "object" && value !== null && !Array.isArray(value)
|
|
11
|
+
? value
|
|
12
|
+
: undefined;
|
|
13
|
+
}
|
|
14
|
+
function asString(value) {
|
|
15
|
+
return typeof value === "string" && value.trim().length > 0 ? value.trim() : undefined;
|
|
16
|
+
}
|
|
17
|
+
function readApprovalOverride(compiledTool) {
|
|
18
|
+
if (compiledTool.config?.requireApproval === true) {
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
21
|
+
const approval = asRecord(compiledTool.config?.approval);
|
|
22
|
+
if (approval?.required === true || approval?.enabled === true) {
|
|
23
|
+
return true;
|
|
24
|
+
}
|
|
25
|
+
const mcpConfig = asRecord(compiledTool.config?.mcp);
|
|
26
|
+
return mcpConfig?.requireApproval === true || mcpConfig?.approvalRequired === true;
|
|
27
|
+
}
|
|
28
|
+
function requiresApprovalForSensitiveMemoryWrite(compiledTool) {
|
|
29
|
+
const memoryConfig = asRecord(compiledTool.config?.memory);
|
|
30
|
+
if (memoryConfig?.enabled !== true) {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
if (memoryConfig.requireApproval === true || memoryConfig.approvalRequired === true) {
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
const scope = asString(memoryConfig.scope)?.toLowerCase() ?? "thread";
|
|
37
|
+
const sensitivity = asString(memoryConfig.sensitivity)?.toLowerCase();
|
|
38
|
+
if (sensitivity && SENSITIVE_MEMORY_LEVELS.has(sensitivity)) {
|
|
39
|
+
return true;
|
|
40
|
+
}
|
|
41
|
+
return NON_THREAD_MEMORY_SCOPES.has(scope) && sensitivity !== "public" && sensitivity !== "low";
|
|
42
|
+
}
|
|
43
|
+
function requiresApprovalForHighRiskMcpWrite(compiledTool) {
|
|
44
|
+
if (compiledTool.type !== "mcp") {
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
if (readApprovalOverride(compiledTool)) {
|
|
48
|
+
return true;
|
|
49
|
+
}
|
|
50
|
+
const mcpConfig = asRecord(compiledTool.config?.mcp);
|
|
51
|
+
const targetText = [
|
|
52
|
+
compiledTool.name,
|
|
53
|
+
compiledTool.description,
|
|
54
|
+
asString(mcpConfig?.tool),
|
|
55
|
+
asString(mcpConfig?.ref),
|
|
56
|
+
asString(mcpConfig?.operation),
|
|
57
|
+
]
|
|
58
|
+
.filter((value) => Boolean(value))
|
|
59
|
+
.join(" ");
|
|
60
|
+
return WRITE_LIKE_REMOTE_TOOL_PATTERN.test(targetText);
|
|
61
|
+
}
|
|
62
|
+
export function toolRequiresRuntimeApproval(compiledTool) {
|
|
63
|
+
if (compiledTool.hitl?.enabled === true) {
|
|
64
|
+
return true;
|
|
65
|
+
}
|
|
66
|
+
return readApprovalOverride(compiledTool) || requiresApprovalForSensitiveMemoryWrite(compiledTool) || requiresApprovalForHighRiskMcpWrite(compiledTool);
|
|
67
|
+
}
|
|
68
|
+
function toolApprovalReason(compiledTool) {
|
|
69
|
+
if (compiledTool.hitl?.enabled === true) {
|
|
70
|
+
return undefined;
|
|
71
|
+
}
|
|
72
|
+
if (requiresApprovalForSensitiveMemoryWrite(compiledTool)) {
|
|
73
|
+
return "sensitive-memory-write";
|
|
74
|
+
}
|
|
75
|
+
if (requiresApprovalForHighRiskMcpWrite(compiledTool)) {
|
|
76
|
+
return "high-risk-mcp-write";
|
|
77
|
+
}
|
|
78
|
+
if (readApprovalOverride(compiledTool)) {
|
|
79
|
+
return "runtime-policy";
|
|
80
|
+
}
|
|
81
|
+
return undefined;
|
|
82
|
+
}
|
|
6
83
|
function toInputPreview(input) {
|
|
7
84
|
if (typeof input === "object" && input && !Array.isArray(input)) {
|
|
8
85
|
return input;
|
|
@@ -25,7 +102,7 @@ function resolveApprovedInput(originalInput, resumeValue) {
|
|
|
25
102
|
return originalInput;
|
|
26
103
|
}
|
|
27
104
|
export function wrapToolForHumanInTheLoop(resolvedTool, compiledTool, interruptFn = interrupt) {
|
|
28
|
-
if (!compiledTool
|
|
105
|
+
if (!toolRequiresRuntimeApproval(compiledTool) || typeof resolvedTool !== "object" || resolvedTool === null) {
|
|
29
106
|
return resolvedTool;
|
|
30
107
|
}
|
|
31
108
|
const target = resolvedTool;
|
|
@@ -35,6 +112,7 @@ export function wrapToolForHumanInTheLoop(resolvedTool, compiledTool, interruptF
|
|
|
35
112
|
toolId: compiledTool.id,
|
|
36
113
|
allowedDecisions: compiledTool.hitl?.allow ?? ["approve", "edit", "reject"],
|
|
37
114
|
inputPreview: toInputPreview(input),
|
|
115
|
+
...(toolApprovalReason(compiledTool) ? { approvalReason: toolApprovalReason(compiledTool) } : {}),
|
|
38
116
|
});
|
|
39
117
|
const approvedInput = resolveApprovedInput(input, resumed);
|
|
40
118
|
if (approvedInput === Symbol.for("agent-harness.hitl.reject")) {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { resolveBindingTimeout, resolveProviderRetryPolicy, resolveStreamIdleTimeout } from "../adapter/resilience.js";
|
|
2
|
+
import { toolRequiresRuntimeApproval } from "../adapter/tool/tool-hitl.js";
|
|
2
3
|
import { getBindingPrimaryTools } from "../support/compiled-binding.js";
|
|
3
4
|
export function getWorkspaceBinding(workspace, agentId) {
|
|
4
5
|
return workspace.bindings.get(agentId);
|
|
@@ -29,7 +30,7 @@ export function projectBindingToolExecutionPolicy(binding) {
|
|
|
29
30
|
name: tool.name,
|
|
30
31
|
retryable: tool.retryable === true,
|
|
31
32
|
hasInputSchema: typeof tool.inputSchemaRef === "string" && tool.inputSchemaRef.trim().length > 0,
|
|
32
|
-
requiresApproval: tool
|
|
33
|
+
requiresApproval: toolRequiresRuntimeApproval(tool),
|
|
33
34
|
}));
|
|
34
35
|
const retryableToolCount = projectedTools.filter((tool) => tool.retryable).length;
|
|
35
36
|
return {
|
package/dist/tool-modules.d.ts
CHANGED
package/dist/tools.d.ts
CHANGED
|
@@ -10,6 +10,8 @@ export type ToolDefinitionObject = {
|
|
|
10
10
|
enabled: boolean;
|
|
11
11
|
kind?: string;
|
|
12
12
|
scope?: string;
|
|
13
|
+
sensitivity?: string;
|
|
14
|
+
requireApproval?: boolean;
|
|
13
15
|
maxCandidates?: number;
|
|
14
16
|
tags?: string[];
|
|
15
17
|
};
|
|
@@ -28,6 +30,8 @@ export declare function tool(definition: {
|
|
|
28
30
|
enabled: boolean;
|
|
29
31
|
kind?: string;
|
|
30
32
|
scope?: string;
|
|
33
|
+
sensitivity?: string;
|
|
34
|
+
requireApproval?: boolean;
|
|
31
35
|
maxCandidates?: number;
|
|
32
36
|
tags?: string[];
|
|
33
37
|
};
|