@botbotgo/agent-harness 0.0.156 → 0.0.157
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/README.md +9 -0
- package/README.zh.md +9 -0
- package/dist/acp.d.ts +86 -0
- package/dist/acp.js +208 -0
- package/dist/api.d.ts +14 -2
- package/dist/api.js +10 -0
- package/dist/contracts/runtime.d.ts +48 -0
- package/dist/index.d.ts +3 -2
- package/dist/index.js +1 -1
- package/dist/package-version.d.ts +1 -1
- package/dist/package-version.js +1 -1
- package/dist/persistence/file-store.d.ts +1 -0
- package/dist/persistence/file-store.js +10 -1
- package/dist/persistence/types.d.ts +2 -0
- package/dist/runtime/agent-runtime-adapter.d.ts +5 -1
- package/dist/runtime/agent-runtime-adapter.js +61 -24
- package/dist/runtime/harness/run/governance.d.ts +2 -0
- package/dist/runtime/harness/run/governance.js +76 -0
- package/dist/runtime/harness/run/inspection.js +4 -0
- package/dist/runtime/harness/system/policy-engine.d.ts +2 -1
- package/dist/runtime/harness/system/policy-engine.js +5 -1
- package/dist/runtime/harness.d.ts +5 -1
- package/dist/runtime/harness.js +82 -0
- package/dist/workspace/agent-binding-compiler.js +7 -1
- package/package.json +6 -1
package/README.md
CHANGED
|
@@ -796,10 +796,15 @@ spec:
|
|
|
796
796
|
rootDir: .
|
|
797
797
|
virtualMode: true
|
|
798
798
|
maxFileSizeMb: 10
|
|
799
|
+
sessionStorage:
|
|
800
|
+
enabled: true
|
|
801
|
+
rootDir: "{runRoot}/threads/{threadId}/filesystem"
|
|
799
802
|
middleware: []
|
|
800
803
|
systemPrompt: Answer simple requests directly.
|
|
801
804
|
```
|
|
802
805
|
|
|
806
|
+
When `config.filesystem.sessionStorage.enabled: true` is set for a LangChain binding, the runtime keeps one filesystem root per persisted session/thread and reuses the same runnable cache entry for repeated work on that session instead of collapsing every run onto one shared workspace directory.
|
|
807
|
+
|
|
803
808
|
Example orchestra host:
|
|
804
809
|
|
|
805
810
|
```yaml
|
|
@@ -860,6 +865,10 @@ Primary exports:
|
|
|
860
865
|
- `deleteSession`
|
|
861
866
|
- `listApprovals`
|
|
862
867
|
- `getApproval`
|
|
868
|
+
- `listArtifacts`
|
|
869
|
+
- `getArtifact`
|
|
870
|
+
- `exportEvaluationBundle`
|
|
871
|
+
- `createAcpServer`
|
|
863
872
|
- `createToolMcpServer`
|
|
864
873
|
- `serveToolsOverStdio`
|
|
865
874
|
- `stop`
|
package/README.zh.md
CHANGED
|
@@ -763,10 +763,15 @@ spec:
|
|
|
763
763
|
rootDir: .
|
|
764
764
|
virtualMode: true
|
|
765
765
|
maxFileSizeMb: 10
|
|
766
|
+
sessionStorage:
|
|
767
|
+
enabled: true
|
|
768
|
+
rootDir: "{runRoot}/threads/{threadId}/filesystem"
|
|
766
769
|
middleware: []
|
|
767
770
|
systemPrompt: Answer simple requests directly.
|
|
768
771
|
```
|
|
769
772
|
|
|
773
|
+
当 LangChain 绑定启用 `config.filesystem.sessionStorage.enabled: true` 时,runtime 会为每个持久化 session/thread 维护独立的 filesystem 根目录,并按 session 复用 runnable cache,而不是把所有运行都压到同一个共享工作目录里。
|
|
774
|
+
|
|
770
775
|
orchestra 主机示例:
|
|
771
776
|
|
|
772
777
|
```yaml
|
|
@@ -827,6 +832,10 @@ spec:
|
|
|
827
832
|
- `deleteSession`
|
|
828
833
|
- `listApprovals`
|
|
829
834
|
- `getApproval`
|
|
835
|
+
- `listArtifacts`
|
|
836
|
+
- `getArtifact`
|
|
837
|
+
- `exportEvaluationBundle`
|
|
838
|
+
- `createAcpServer`
|
|
830
839
|
- `createToolMcpServer`
|
|
831
840
|
- `serveToolsOverStdio`
|
|
832
841
|
- `stop`
|
package/dist/acp.d.ts
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import type { ArtifactRecord, HarnessEvent, RequestRecord, RunOptions, SessionRecord } from "./contracts/types.js";
|
|
2
|
+
import type { AgentHarnessRuntime } from "./runtime/harness.js";
|
|
3
|
+
import { getApproval } from "./api.js";
|
|
4
|
+
type JsonRpcId = string | number | null;
|
|
5
|
+
export type AcpJsonRpcRequest = {
|
|
6
|
+
jsonrpc?: "2.0";
|
|
7
|
+
id?: JsonRpcId;
|
|
8
|
+
method: string;
|
|
9
|
+
params?: unknown;
|
|
10
|
+
};
|
|
11
|
+
export type AcpJsonRpcError = {
|
|
12
|
+
jsonrpc: "2.0";
|
|
13
|
+
id: JsonRpcId;
|
|
14
|
+
error: {
|
|
15
|
+
code: number;
|
|
16
|
+
message: string;
|
|
17
|
+
data?: unknown;
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
export type AcpJsonRpcSuccess = {
|
|
21
|
+
jsonrpc: "2.0";
|
|
22
|
+
id: JsonRpcId;
|
|
23
|
+
result: unknown;
|
|
24
|
+
};
|
|
25
|
+
export type AcpJsonRpcResponse = AcpJsonRpcError | AcpJsonRpcSuccess;
|
|
26
|
+
export type AcpSessionRecord = SessionRecord;
|
|
27
|
+
export type AcpRequestRecord = RequestRecord;
|
|
28
|
+
export type AcpApproval = Awaited<ReturnType<typeof getApproval>> extends infer T ? Exclude<T, null> : never;
|
|
29
|
+
export type AcpArtifact = ArtifactRecord & {
|
|
30
|
+
content?: unknown;
|
|
31
|
+
};
|
|
32
|
+
export type AcpRunRequestParams = Omit<Extract<RunOptions, {
|
|
33
|
+
input: unknown;
|
|
34
|
+
}>, "threadId"> & {
|
|
35
|
+
sessionId?: string;
|
|
36
|
+
};
|
|
37
|
+
export type AcpServerCapabilities = {
|
|
38
|
+
sessions: {
|
|
39
|
+
list: true;
|
|
40
|
+
get: true;
|
|
41
|
+
};
|
|
42
|
+
requests: {
|
|
43
|
+
submit: true;
|
|
44
|
+
list: true;
|
|
45
|
+
get: true;
|
|
46
|
+
};
|
|
47
|
+
approvals: {
|
|
48
|
+
list: true;
|
|
49
|
+
get: true;
|
|
50
|
+
resolve: true;
|
|
51
|
+
};
|
|
52
|
+
artifacts: {
|
|
53
|
+
list: true;
|
|
54
|
+
read: true;
|
|
55
|
+
};
|
|
56
|
+
events: {
|
|
57
|
+
subscribe: true;
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
export type AcpEventNotification = {
|
|
61
|
+
jsonrpc: "2.0";
|
|
62
|
+
method: "events.runtime";
|
|
63
|
+
params: {
|
|
64
|
+
event: {
|
|
65
|
+
eventId: string;
|
|
66
|
+
eventType: string;
|
|
67
|
+
timestamp: string;
|
|
68
|
+
sessionId: string;
|
|
69
|
+
requestId: string;
|
|
70
|
+
sequence: number;
|
|
71
|
+
source: HarnessEvent["source"];
|
|
72
|
+
payload: Record<string, unknown>;
|
|
73
|
+
};
|
|
74
|
+
};
|
|
75
|
+
};
|
|
76
|
+
export declare class AgentHarnessAcpServer {
|
|
77
|
+
private readonly runtime;
|
|
78
|
+
constructor(runtime: AgentHarnessRuntime);
|
|
79
|
+
capabilities(): AcpServerCapabilities;
|
|
80
|
+
subscribe(listener: (notification: AcpEventNotification) => void): () => void;
|
|
81
|
+
handle(request: AcpJsonRpcRequest): Promise<AcpJsonRpcResponse | undefined>;
|
|
82
|
+
private methodExists;
|
|
83
|
+
private dispatch;
|
|
84
|
+
}
|
|
85
|
+
export declare function createAcpServer(runtime: AgentHarnessRuntime): AgentHarnessAcpServer;
|
|
86
|
+
export {};
|
package/dist/acp.js
ADDED
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
import { getApproval, getArtifact, getRequest, getSession, listApprovals, listArtifacts, listRequests, listSessions, resolveApproval, run, } from "./api.js";
|
|
2
|
+
const CAPABILITIES = {
|
|
3
|
+
sessions: { list: true, get: true },
|
|
4
|
+
requests: { submit: true, list: true, get: true },
|
|
5
|
+
approvals: { list: true, get: true, resolve: true },
|
|
6
|
+
artifacts: { list: true, read: true },
|
|
7
|
+
events: { subscribe: true },
|
|
8
|
+
};
|
|
9
|
+
function asObject(value, method) {
|
|
10
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
11
|
+
throw new Error(`${method} requires an object params payload.`);
|
|
12
|
+
}
|
|
13
|
+
return value;
|
|
14
|
+
}
|
|
15
|
+
function readOptionalString(value) {
|
|
16
|
+
return typeof value === "string" && value.trim().length > 0 ? value.trim() : undefined;
|
|
17
|
+
}
|
|
18
|
+
function readRequiredString(value, field, method) {
|
|
19
|
+
const normalized = readOptionalString(value);
|
|
20
|
+
if (!normalized) {
|
|
21
|
+
throw new Error(`${method} requires ${field}.`);
|
|
22
|
+
}
|
|
23
|
+
return normalized;
|
|
24
|
+
}
|
|
25
|
+
function toNotification(event) {
|
|
26
|
+
return {
|
|
27
|
+
jsonrpc: "2.0",
|
|
28
|
+
method: "events.runtime",
|
|
29
|
+
params: {
|
|
30
|
+
event: {
|
|
31
|
+
eventId: event.eventId,
|
|
32
|
+
eventType: event.eventType,
|
|
33
|
+
timestamp: event.timestamp,
|
|
34
|
+
sessionId: event.threadId,
|
|
35
|
+
requestId: event.runId,
|
|
36
|
+
sequence: event.sequence,
|
|
37
|
+
source: event.source,
|
|
38
|
+
payload: event.payload,
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
async function readArtifactContent(runtime, params) {
|
|
44
|
+
const method = "artifacts.read";
|
|
45
|
+
const sessionId = readRequiredString(params.sessionId, "sessionId", method);
|
|
46
|
+
const requestId = readRequiredString(params.requestId, "requestId", method);
|
|
47
|
+
const artifactPath = readRequiredString(params.artifactPath, "artifactPath", method);
|
|
48
|
+
const listing = await listArtifacts(runtime, { sessionId, requestId });
|
|
49
|
+
const artifact = listing.items.find((item) => item.path === artifactPath);
|
|
50
|
+
if (!artifact) {
|
|
51
|
+
throw new Error(`Artifact not found for ${requestId}: ${artifactPath}`);
|
|
52
|
+
}
|
|
53
|
+
return {
|
|
54
|
+
...artifact,
|
|
55
|
+
content: await getArtifact(runtime, { sessionId, requestId, artifactPath }),
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
export class AgentHarnessAcpServer {
|
|
59
|
+
runtime;
|
|
60
|
+
constructor(runtime) {
|
|
61
|
+
this.runtime = runtime;
|
|
62
|
+
}
|
|
63
|
+
capabilities() {
|
|
64
|
+
return CAPABILITIES;
|
|
65
|
+
}
|
|
66
|
+
subscribe(listener) {
|
|
67
|
+
return this.runtime.subscribe((event) => {
|
|
68
|
+
listener(toNotification(event));
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
async handle(request) {
|
|
72
|
+
const id = request.id ?? null;
|
|
73
|
+
if (!request || typeof request !== "object" || typeof request.method !== "string" || request.method.trim().length === 0) {
|
|
74
|
+
return {
|
|
75
|
+
jsonrpc: "2.0",
|
|
76
|
+
id,
|
|
77
|
+
error: {
|
|
78
|
+
code: -32600,
|
|
79
|
+
message: "Invalid JSON-RPC request.",
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
if (request.jsonrpc !== undefined && request.jsonrpc !== "2.0") {
|
|
84
|
+
return {
|
|
85
|
+
jsonrpc: "2.0",
|
|
86
|
+
id,
|
|
87
|
+
error: {
|
|
88
|
+
code: -32600,
|
|
89
|
+
message: "Only JSON-RPC 2.0 requests are supported.",
|
|
90
|
+
},
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
try {
|
|
94
|
+
const result = await this.dispatch(request.method, request.params);
|
|
95
|
+
if (request.id === undefined) {
|
|
96
|
+
return undefined;
|
|
97
|
+
}
|
|
98
|
+
return {
|
|
99
|
+
jsonrpc: "2.0",
|
|
100
|
+
id,
|
|
101
|
+
result,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
catch (error) {
|
|
105
|
+
if (request.id === undefined) {
|
|
106
|
+
return undefined;
|
|
107
|
+
}
|
|
108
|
+
return {
|
|
109
|
+
jsonrpc: "2.0",
|
|
110
|
+
id,
|
|
111
|
+
error: {
|
|
112
|
+
code: this.methodExists(request.method) ? -32602 : -32601,
|
|
113
|
+
message: error instanceof Error ? error.message : "ACP request failed.",
|
|
114
|
+
},
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
methodExists(method) {
|
|
119
|
+
return new Set([
|
|
120
|
+
"capabilities.get",
|
|
121
|
+
"sessions.list",
|
|
122
|
+
"sessions.get",
|
|
123
|
+
"requests.submit",
|
|
124
|
+
"requests.list",
|
|
125
|
+
"requests.get",
|
|
126
|
+
"approvals.list",
|
|
127
|
+
"approvals.get",
|
|
128
|
+
"approvals.resolve",
|
|
129
|
+
"artifacts.list",
|
|
130
|
+
"artifacts.read",
|
|
131
|
+
]).has(method);
|
|
132
|
+
}
|
|
133
|
+
async dispatch(method, params) {
|
|
134
|
+
switch (method) {
|
|
135
|
+
case "capabilities.get":
|
|
136
|
+
return this.capabilities();
|
|
137
|
+
case "sessions.list": {
|
|
138
|
+
const payload = params === undefined ? {} : asObject(params, method);
|
|
139
|
+
return listSessions(this.runtime, {
|
|
140
|
+
agentId: readOptionalString(payload.agentId),
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
case "sessions.get": {
|
|
144
|
+
const payload = asObject(params, method);
|
|
145
|
+
return getSession(this.runtime, readRequiredString(payload.sessionId, "sessionId", method));
|
|
146
|
+
}
|
|
147
|
+
case "requests.submit": {
|
|
148
|
+
const payload = asObject(params, method);
|
|
149
|
+
return run(this.runtime, {
|
|
150
|
+
agentId: readOptionalString(payload.agentId),
|
|
151
|
+
input: payload.input,
|
|
152
|
+
invocation: payload.invocation,
|
|
153
|
+
listeners: payload.listeners,
|
|
154
|
+
priority: typeof payload.priority === "number" ? payload.priority : undefined,
|
|
155
|
+
sessionId: readOptionalString(payload.sessionId),
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
case "requests.list": {
|
|
159
|
+
const payload = params === undefined ? {} : asObject(params, method);
|
|
160
|
+
return listRequests(this.runtime, {
|
|
161
|
+
agentId: readOptionalString(payload.agentId),
|
|
162
|
+
sessionId: readOptionalString(payload.sessionId),
|
|
163
|
+
state: payload.state,
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
case "requests.get": {
|
|
167
|
+
const payload = asObject(params, method);
|
|
168
|
+
return getRequest(this.runtime, readRequiredString(payload.requestId, "requestId", method));
|
|
169
|
+
}
|
|
170
|
+
case "approvals.list": {
|
|
171
|
+
const payload = params === undefined ? {} : asObject(params, method);
|
|
172
|
+
return listApprovals(this.runtime, {
|
|
173
|
+
status: payload.status,
|
|
174
|
+
sessionId: readOptionalString(payload.sessionId),
|
|
175
|
+
requestId: readOptionalString(payload.requestId),
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
case "approvals.get": {
|
|
179
|
+
const payload = asObject(params, method);
|
|
180
|
+
return getApproval(this.runtime, readRequiredString(payload.approvalId, "approvalId", method));
|
|
181
|
+
}
|
|
182
|
+
case "approvals.resolve": {
|
|
183
|
+
const payload = asObject(params, method);
|
|
184
|
+
return resolveApproval(this.runtime, {
|
|
185
|
+
approvalId: readRequiredString(payload.approvalId, "approvalId", method),
|
|
186
|
+
decision: payload.decision,
|
|
187
|
+
editedInput: payload.editedInput,
|
|
188
|
+
requestId: readOptionalString(payload.requestId),
|
|
189
|
+
sessionId: readOptionalString(payload.sessionId),
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
case "artifacts.list": {
|
|
193
|
+
const payload = asObject(params, method);
|
|
194
|
+
return listArtifacts(this.runtime, {
|
|
195
|
+
sessionId: readRequiredString(payload.sessionId, "sessionId", method),
|
|
196
|
+
requestId: readRequiredString(payload.requestId, "requestId", method),
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
case "artifacts.read":
|
|
200
|
+
return readArtifactContent(this.runtime, asObject(params, method));
|
|
201
|
+
default:
|
|
202
|
+
throw new Error(`Unknown ACP method: ${method}`);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
export function createAcpServer(runtime) {
|
|
207
|
+
return new AgentHarnessAcpServer(runtime);
|
|
208
|
+
}
|
package/dist/api.d.ts
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
|
-
import type { CancelOptions, InvocationEnvelope, ListMemoriesInput, ListMemoriesResult, MemoryRecord, MemorizeInput, MemorizeResult, MessageContent, RecallInput, RecallResult, RemoveMemoryInput, RequestRecord, RequestSummary, ResumeOptions, RunDecisionOptions, RunResult, RunStartOptions, RuntimeHealthSnapshot, RuntimeAdapterOptions, SessionRecord, SessionSummary, UpdateMemoryInput, WorkspaceLoadOptions } from "./contracts/types.js";
|
|
1
|
+
import type { ArtifactListing, CancelOptions, InvocationEnvelope, ListMemoriesInput, ListMemoriesResult, MemoryRecord, MemorizeInput, MemorizeResult, MessageContent, RecallInput, RecallResult, RemoveMemoryInput, RequestRecord, RequestSummary, ResumeOptions, RunDecisionOptions, RunResult, RunStartOptions, RuntimeHealthSnapshot, RuntimeAdapterOptions, RuntimeEvaluationExport, RuntimeEvaluationExportInput, SessionRecord, SessionSummary, UpdateMemoryInput, WorkspaceLoadOptions } from "./contracts/types.js";
|
|
2
2
|
import { AgentHarnessRuntime } from "./runtime/harness.js";
|
|
3
3
|
import type { InventoryAgentRecord, InventorySkillRecord } from "./runtime/harness/system/inventory.js";
|
|
4
4
|
import type { RequirementAssessmentOptions } from "./runtime/harness/system/skill-requirements.js";
|
|
5
5
|
import type { ToolMcpServerOptions } from "./mcp.js";
|
|
6
|
+
export { AgentHarnessAcpServer, createAcpServer } from "./acp.js";
|
|
7
|
+
export type { AcpApproval, AcpArtifact, AcpEventNotification, AcpJsonRpcError, AcpJsonRpcRequest, AcpJsonRpcResponse, AcpJsonRpcSuccess, AcpRequestRecord, AcpRunRequestParams, AcpServerCapabilities, AcpSessionRecord, } from "./acp.js";
|
|
6
8
|
export { AgentHarnessRuntime } from "./runtime/harness.js";
|
|
7
9
|
export { createUpstreamTimelineReducer } from "./upstream-events.js";
|
|
8
|
-
export type { ListMemoriesInput, ListMemoriesResult, MemoryDecision, MemoryKind, MemoryRecord, MemoryScope, MemorizeInput, MemorizeResult, RecallInput, RecallResult, RemoveMemoryInput, UpdateMemoryInput, } from "./contracts/types.js";
|
|
10
|
+
export type { ListMemoriesInput, ListMemoriesResult, MemoryDecision, MemoryKind, MemoryRecord, MemoryScope, MemorizeInput, MemorizeResult, RecallInput, RecallResult, RemoveMemoryInput, RuntimeEvaluationExport, RuntimeEvaluationExportInput, UpdateMemoryInput, } from "./contracts/types.js";
|
|
9
11
|
type PublicApprovalRecord = {
|
|
10
12
|
approvalId: string;
|
|
11
13
|
pendingActionId: string;
|
|
@@ -72,7 +74,17 @@ export declare function getRequest(runtime: AgentHarnessRuntime, requestId: stri
|
|
|
72
74
|
export declare function deleteSession(runtime: AgentHarnessRuntime, sessionId: string): Promise<boolean>;
|
|
73
75
|
export declare function listApprovals(runtime: AgentHarnessRuntime, filter?: PublicApprovalFilter): Promise<PublicApprovalRecord[]>;
|
|
74
76
|
export declare function getApproval(runtime: AgentHarnessRuntime, approvalId: string): Promise<PublicApprovalRecord | null>;
|
|
77
|
+
export declare function listArtifacts(runtime: AgentHarnessRuntime, input: {
|
|
78
|
+
sessionId: string;
|
|
79
|
+
requestId: string;
|
|
80
|
+
}): Promise<ArtifactListing>;
|
|
81
|
+
export declare function getArtifact(runtime: AgentHarnessRuntime, input: {
|
|
82
|
+
sessionId: string;
|
|
83
|
+
requestId: string;
|
|
84
|
+
artifactPath: string;
|
|
85
|
+
}): Promise<unknown>;
|
|
75
86
|
export declare function getHealth(runtime: AgentHarnessRuntime): Promise<RuntimeHealthSnapshot>;
|
|
87
|
+
export declare function exportEvaluationBundle(runtime: AgentHarnessRuntime, input: RuntimeEvaluationExportInput): Promise<RuntimeEvaluationExport>;
|
|
76
88
|
export declare function listAgentSkills(runtime: AgentHarnessRuntime, agentId: string, options?: RequirementAssessmentOptions): InventorySkillRecord[];
|
|
77
89
|
export declare function getAgent(runtime: AgentHarnessRuntime, agentId: string, options?: RequirementAssessmentOptions): InventoryAgentRecord | null;
|
|
78
90
|
export declare function describeInventory(runtime: AgentHarnessRuntime, options?: RequirementAssessmentOptions): {
|
package/dist/api.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { AgentHarnessRuntime } from "./runtime/harness.js";
|
|
2
2
|
import { normalizeMessageContent } from "./utils/message-content.js";
|
|
3
3
|
import { loadWorkspace } from "./workspace/compile.js";
|
|
4
|
+
export { AgentHarnessAcpServer, createAcpServer } from "./acp.js";
|
|
4
5
|
export { AgentHarnessRuntime } from "./runtime/harness.js";
|
|
5
6
|
export { createUpstreamTimelineReducer } from "./upstream-events.js";
|
|
6
7
|
function toSessionSummary(summary) {
|
|
@@ -178,9 +179,18 @@ export async function getApproval(runtime, approvalId) {
|
|
|
178
179
|
const record = await runtime.getApproval(approvalId);
|
|
179
180
|
return record ? toApprovalRecord(record) : null;
|
|
180
181
|
}
|
|
182
|
+
export async function listArtifacts(runtime, input) {
|
|
183
|
+
return runtime.listArtifacts(input.sessionId, input.requestId);
|
|
184
|
+
}
|
|
185
|
+
export async function getArtifact(runtime, input) {
|
|
186
|
+
return runtime.readArtifact(input.sessionId, input.requestId, input.artifactPath);
|
|
187
|
+
}
|
|
181
188
|
export async function getHealth(runtime) {
|
|
182
189
|
return runtime.getHealth();
|
|
183
190
|
}
|
|
191
|
+
export async function exportEvaluationBundle(runtime, input) {
|
|
192
|
+
return runtime.exportEvaluationBundle(input);
|
|
193
|
+
}
|
|
184
194
|
export function listAgentSkills(runtime, agentId, options) {
|
|
185
195
|
return runtime.listAgentSkills(agentId, options);
|
|
186
196
|
}
|
|
@@ -96,6 +96,24 @@ export type RuntimeSnapshotTracing = {
|
|
|
96
96
|
tags?: string[];
|
|
97
97
|
metadata?: Record<string, unknown>;
|
|
98
98
|
};
|
|
99
|
+
export type RuntimeGovernanceRiskLevel = "low" | "medium" | "high";
|
|
100
|
+
export type RuntimeGovernanceToolPolicy = {
|
|
101
|
+
toolName: string;
|
|
102
|
+
toolId: string;
|
|
103
|
+
toolType: string;
|
|
104
|
+
category: "local" | "backend" | "mcp" | "provider-native";
|
|
105
|
+
risk: RuntimeGovernanceRiskLevel;
|
|
106
|
+
requiresApproval: boolean;
|
|
107
|
+
approvalPolicy: "explicit-hitl" | "runtime-default" | "none";
|
|
108
|
+
hasInputSchema: boolean;
|
|
109
|
+
inputRiskHints: string[];
|
|
110
|
+
};
|
|
111
|
+
export type RuntimeGovernanceBundle = {
|
|
112
|
+
bundleId: string;
|
|
113
|
+
title: string;
|
|
114
|
+
summary: string;
|
|
115
|
+
toolPolicies: RuntimeGovernanceToolPolicy[];
|
|
116
|
+
};
|
|
99
117
|
export type RuntimeSnapshot = {
|
|
100
118
|
agentId: string;
|
|
101
119
|
model?: RuntimeSnapshotModel;
|
|
@@ -103,6 +121,9 @@ export type RuntimeSnapshot = {
|
|
|
103
121
|
skills: RuntimeSnapshotSkill[];
|
|
104
122
|
memory: string[];
|
|
105
123
|
tracing?: RuntimeSnapshotTracing;
|
|
124
|
+
governance?: {
|
|
125
|
+
bundles: RuntimeGovernanceBundle[];
|
|
126
|
+
};
|
|
106
127
|
};
|
|
107
128
|
export type MemoryCandidate = {
|
|
108
129
|
content: string;
|
|
@@ -539,6 +560,7 @@ export type SkillPackagingConvention = {
|
|
|
539
560
|
export type PolicyDecision = {
|
|
540
561
|
allowed: boolean;
|
|
541
562
|
reasons: string[];
|
|
563
|
+
bundles?: RuntimeGovernanceBundle[];
|
|
542
564
|
};
|
|
543
565
|
export type PolicyEvaluator = {
|
|
544
566
|
kind: string;
|
|
@@ -548,6 +570,32 @@ export type EventSubscriber = {
|
|
|
548
570
|
kind: string;
|
|
549
571
|
onEvent: HarnessEventListener;
|
|
550
572
|
};
|
|
573
|
+
export type RuntimeEvaluationExportInput = {
|
|
574
|
+
sessionId: string;
|
|
575
|
+
requestId: string;
|
|
576
|
+
includeArtifacts?: boolean;
|
|
577
|
+
includeArtifactContents?: boolean;
|
|
578
|
+
expectedOutput?: string;
|
|
579
|
+
rubric?: string[];
|
|
580
|
+
tags?: string[];
|
|
581
|
+
metadata?: Record<string, unknown>;
|
|
582
|
+
};
|
|
583
|
+
export type RuntimeEvaluationArtifact = ArtifactRecord & {
|
|
584
|
+
content?: unknown;
|
|
585
|
+
};
|
|
586
|
+
export type RuntimeEvaluationExport = {
|
|
587
|
+
session: SessionRecord | null;
|
|
588
|
+
request: RequestRecord | null;
|
|
589
|
+
approvals: ApprovalRecord[];
|
|
590
|
+
transcript: TranscriptMessage[];
|
|
591
|
+
events: HarnessEvent[];
|
|
592
|
+
artifacts: RuntimeEvaluationArtifact[];
|
|
593
|
+
runtimeHealth: RuntimeHealthSnapshot;
|
|
594
|
+
expectedOutput?: string;
|
|
595
|
+
rubric: string[];
|
|
596
|
+
tags: string[];
|
|
597
|
+
metadata?: Record<string, unknown>;
|
|
598
|
+
};
|
|
551
599
|
export type RuntimeInventoryContext = {
|
|
552
600
|
workspace: WorkspaceBundle;
|
|
553
601
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
export { AgentHarnessRuntime, cancelRun, createAgentHarness, createUpstreamTimelineReducer, createToolMcpServer, deleteSession, describeInventory, getAgent, getApproval, getRequest, getHealth, listMemories, getSession, listAgentSkills, listApprovals, listRequests, listSessions, memorize, normalizeUserChatInput, recall, removeMemory, resolveApproval, run, serveToolsOverStdio, subscribe, stop, updateMemory, } from "./api.js";
|
|
2
|
-
export type {
|
|
1
|
+
export { AgentHarnessAcpServer, AgentHarnessRuntime, cancelRun, createAgentHarness, createAcpServer, createUpstreamTimelineReducer, createToolMcpServer, deleteSession, describeInventory, exportEvaluationBundle, getArtifact, getAgent, getApproval, getRequest, getHealth, listMemories, getSession, listAgentSkills, listArtifacts, listApprovals, listRequests, listSessions, memorize, normalizeUserChatInput, recall, removeMemory, resolveApproval, run, serveToolsOverStdio, subscribe, stop, updateMemory, } from "./api.js";
|
|
2
|
+
export type { AcpApproval, AcpArtifact, AcpEventNotification, AcpJsonRpcError, AcpJsonRpcRequest, AcpJsonRpcResponse, AcpJsonRpcSuccess, AcpRequestRecord, AcpRunRequestParams, AcpServerCapabilities, AcpSessionRecord, } from "./acp.js";
|
|
3
|
+
export type { ListMemoriesInput, ListMemoriesResult, MemoryDecision, MemoryKind, MemoryRecord, MemoryScope, MemorizeInput, MemorizeResult, NormalizeUserChatInputOptions, RecallInput, RecallResult, RemoveMemoryInput, RuntimeEvaluationExport, RuntimeEvaluationExportInput, UpdateMemoryInput, UserChatInput, UserChatMessage, } from "./api.js";
|
|
3
4
|
export type { ToolMcpServerOptions } from "./mcp.js";
|
|
4
5
|
export { tool } from "./tools.js";
|
|
5
6
|
export type { UpstreamTimelineProjection, UpstreamTimelineReducer } from "./upstream-events.js";
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { AgentHarnessRuntime, cancelRun, createAgentHarness, createUpstreamTimelineReducer, createToolMcpServer, deleteSession, describeInventory, getAgent, getApproval, getRequest, getHealth, listMemories, getSession, listAgentSkills, listApprovals, listRequests, listSessions, memorize, normalizeUserChatInput, recall, removeMemory, resolveApproval, run, serveToolsOverStdio, subscribe, stop, updateMemory, } from "./api.js";
|
|
1
|
+
export { AgentHarnessAcpServer, AgentHarnessRuntime, cancelRun, createAgentHarness, createAcpServer, createUpstreamTimelineReducer, createToolMcpServer, deleteSession, describeInventory, exportEvaluationBundle, getArtifact, getAgent, getApproval, getRequest, getHealth, listMemories, getSession, listAgentSkills, listArtifacts, listApprovals, listRequests, listSessions, memorize, normalizeUserChatInput, recall, removeMemory, resolveApproval, run, serveToolsOverStdio, subscribe, stop, updateMemory, } from "./api.js";
|
|
2
2
|
export { tool } from "./tools.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const AGENT_HARNESS_VERSION = "0.0.
|
|
1
|
+
export declare const AGENT_HARNESS_VERSION = "0.0.156";
|
package/dist/package-version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const AGENT_HARNESS_VERSION = "0.0.
|
|
1
|
+
export const AGENT_HARNESS_VERSION = "0.0.156";
|
|
@@ -69,6 +69,7 @@ export declare class FilePersistence implements RuntimePersistence {
|
|
|
69
69
|
resolveApproval(threadId: string, runId: string, approvalId: string, status: InternalApprovalRecord["status"]): Promise<InternalApprovalRecord>;
|
|
70
70
|
createArtifact(threadId: string, runId: string, artifact: ArtifactRecord, content: unknown): Promise<ArtifactRecord>;
|
|
71
71
|
listArtifacts(threadId: string, runId: string): Promise<ArtifactListing>;
|
|
72
|
+
readArtifact(threadId: string, runId: string, artifactPath: string): Promise<unknown>;
|
|
72
73
|
appendThreadMessage(threadId: string, message: TranscriptMessage): Promise<void>;
|
|
73
74
|
listThreadMessages(threadId: string, limit?: number): Promise<TranscriptMessage[]>;
|
|
74
75
|
saveRecoveryIntent(threadId: string, runId: string, intent: RecoveryIntent): Promise<void>;
|
|
@@ -328,7 +328,9 @@ export class FilePersistence {
|
|
|
328
328
|
if (!(await fileExists(eventsDir))) {
|
|
329
329
|
return [];
|
|
330
330
|
}
|
|
331
|
-
const entries = (await readdir(eventsDir))
|
|
331
|
+
const entries = (await readdir(eventsDir))
|
|
332
|
+
.filter((entry) => entry.endsWith(".json"))
|
|
333
|
+
.sort((left, right) => left.localeCompare(right));
|
|
332
334
|
return Promise.all(entries.map((entry) => readJson(path.join(eventsDir, entry))));
|
|
333
335
|
}
|
|
334
336
|
async listApprovals(filter = {}) {
|
|
@@ -460,6 +462,13 @@ export class FilePersistence {
|
|
|
460
462
|
async listArtifacts(threadId, runId) {
|
|
461
463
|
return readJson(path.join(this.runDir(threadId, runId), "artifacts.json"));
|
|
462
464
|
}
|
|
465
|
+
async readArtifact(threadId, runId, artifactPath) {
|
|
466
|
+
const filePath = path.join(this.runDir(threadId, runId), artifactPath);
|
|
467
|
+
if (!(await fileExists(filePath))) {
|
|
468
|
+
return null;
|
|
469
|
+
}
|
|
470
|
+
return readJson(filePath);
|
|
471
|
+
}
|
|
463
472
|
async appendThreadMessage(threadId, message) {
|
|
464
473
|
const messagesPath = path.join(this.threadDir(threadId), "messages.json");
|
|
465
474
|
const current = (await fileExists(messagesPath))
|
|
@@ -120,6 +120,7 @@ export interface RuntimePersistence {
|
|
|
120
120
|
}): Promise<void>;
|
|
121
121
|
setRunState(threadId: string, runId: string, state: RunState, checkpointRef?: string | null): Promise<void>;
|
|
122
122
|
appendEvent(event: HarnessEvent): Promise<void>;
|
|
123
|
+
listRunEvents(threadId: string, runId: string): Promise<HarnessEvent[]>;
|
|
123
124
|
listSessions(filter?: ThreadSummaryFilter): Promise<ThreadSummary[]>;
|
|
124
125
|
listRuns(filter?: RunSummaryFilter): Promise<RunSummary[]>;
|
|
125
126
|
getRun(runId: string): Promise<RunSummary | null>;
|
|
@@ -147,6 +148,7 @@ export interface RuntimePersistence {
|
|
|
147
148
|
resolveApproval(threadId: string, runId: string, approvalId: string, status: InternalApprovalRecord["status"]): Promise<InternalApprovalRecord>;
|
|
148
149
|
createArtifact(threadId: string, runId: string, artifact: ArtifactRecord, content: unknown): Promise<ArtifactRecord>;
|
|
149
150
|
listArtifacts(threadId: string, runId: string): Promise<ArtifactListing>;
|
|
151
|
+
readArtifact(threadId: string, runId: string, artifactPath: string): Promise<unknown>;
|
|
150
152
|
appendThreadMessage(threadId: string, message: TranscriptMessage): Promise<void>;
|
|
151
153
|
listThreadMessages(threadId: string, limit?: number): Promise<TranscriptMessage[]>;
|
|
152
154
|
saveRecoveryIntent(threadId: string, runId: string, intent: RecoveryIntent): Promise<void>;
|
|
@@ -63,6 +63,7 @@ export declare class AgentRuntimeAdapter {
|
|
|
63
63
|
private resolveTools;
|
|
64
64
|
private getToolNameMapping;
|
|
65
65
|
private resolveFilesystemBackend;
|
|
66
|
+
private resolveFilesystemRootDir;
|
|
66
67
|
private resolveBuiltinMiddlewareBackend;
|
|
67
68
|
private createDeclaredMiddlewareResolverOptions;
|
|
68
69
|
private createAssemblyResolvers;
|
|
@@ -75,7 +76,10 @@ export declare class AgentRuntimeAdapter {
|
|
|
75
76
|
private createLangChainRunnable;
|
|
76
77
|
private createRunnable;
|
|
77
78
|
private createDeepAgentRunnable;
|
|
78
|
-
|
|
79
|
+
private buildRunnableCacheKey;
|
|
80
|
+
create(binding: CompiledAgentBinding, options?: {
|
|
81
|
+
threadId?: string;
|
|
82
|
+
}): Promise<RunnableLike>;
|
|
79
83
|
invoke(binding: CompiledAgentBinding, input: MessageContent, threadId: string, runId: string, resumePayload?: unknown, history?: TranscriptMessage[], options?: {
|
|
80
84
|
context?: Record<string, unknown>;
|
|
81
85
|
state?: Record<string, unknown>;
|
|
@@ -159,7 +159,7 @@ function shouldAttachMinimalDeepAgentBackend(binding) {
|
|
|
159
159
|
export class AgentRuntimeAdapter {
|
|
160
160
|
options;
|
|
161
161
|
modelCache = new Map();
|
|
162
|
-
runnableCache = new
|
|
162
|
+
runnableCache = new Map();
|
|
163
163
|
toolNameMappingCache = new WeakMap();
|
|
164
164
|
constructor(options = {}) {
|
|
165
165
|
this.options = options;
|
|
@@ -213,7 +213,12 @@ export class AgentRuntimeAdapter {
|
|
|
213
213
|
}
|
|
214
214
|
}
|
|
215
215
|
invalidateBindingRuntimeCaches(binding) {
|
|
216
|
-
|
|
216
|
+
const prefix = `${binding.agent.sourcePath}::`;
|
|
217
|
+
for (const key of Array.from(this.runnableCache.keys())) {
|
|
218
|
+
if (key.startsWith(prefix)) {
|
|
219
|
+
this.runnableCache.delete(key);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
217
222
|
this.modelCache.clear();
|
|
218
223
|
}
|
|
219
224
|
resolveTools(tools, binding) {
|
|
@@ -232,15 +237,19 @@ export class AgentRuntimeAdapter {
|
|
|
232
237
|
this.toolNameMappingCache.set(binding, resolved);
|
|
233
238
|
return resolved;
|
|
234
239
|
}
|
|
235
|
-
resolveFilesystemBackend(binding) {
|
|
240
|
+
resolveFilesystemBackend(binding, options = {}) {
|
|
236
241
|
const filesystemConfig = getBindingFilesystemConfig(binding);
|
|
242
|
+
const sessionStorage = typeof filesystemConfig?.sessionStorage === "object" && filesystemConfig.sessionStorage
|
|
243
|
+
? filesystemConfig.sessionStorage
|
|
244
|
+
: undefined;
|
|
237
245
|
const configuredRootDir = typeof filesystemConfig?.rootDir === "string" && filesystemConfig.rootDir.trim().length > 0
|
|
238
246
|
? filesystemConfig.rootDir
|
|
239
247
|
: undefined;
|
|
240
248
|
const workspaceRoot = binding.harnessRuntime.workspaceRoot;
|
|
241
|
-
const
|
|
249
|
+
const baseRootDir = configuredRootDir
|
|
242
250
|
? (path.isAbsolute(configuredRootDir) ? configuredRootDir : path.resolve(workspaceRoot ?? process.cwd(), configuredRootDir))
|
|
243
251
|
: workspaceRoot ?? process.cwd();
|
|
252
|
+
const rootDir = this.resolveFilesystemRootDir(baseRootDir, binding, sessionStorage, options.threadId);
|
|
244
253
|
return new FilesystemBackend({
|
|
245
254
|
rootDir,
|
|
246
255
|
virtualMode: filesystemConfig?.virtualMode === true,
|
|
@@ -249,6 +258,25 @@ export class AgentRuntimeAdapter {
|
|
|
249
258
|
: 10,
|
|
250
259
|
});
|
|
251
260
|
}
|
|
261
|
+
resolveFilesystemRootDir(baseRootDir, binding, sessionStorage, threadId) {
|
|
262
|
+
const enabled = sessionStorage?.enabled === true;
|
|
263
|
+
if (!enabled || !threadId) {
|
|
264
|
+
return baseRootDir;
|
|
265
|
+
}
|
|
266
|
+
const workspaceRoot = binding.harnessRuntime.workspaceRoot ?? process.cwd();
|
|
267
|
+
const runRoot = binding.harnessRuntime.runRoot;
|
|
268
|
+
const configuredRootDir = typeof sessionStorage.rootDir === "string" && sessionStorage.rootDir.trim().length > 0
|
|
269
|
+
? sessionStorage.rootDir.trim()
|
|
270
|
+
: "{runRoot}/threads/{threadId}/filesystem";
|
|
271
|
+
const rendered = configuredRootDir
|
|
272
|
+
.replaceAll("{threadId}", threadId)
|
|
273
|
+
.replaceAll("{sessionId}", threadId)
|
|
274
|
+
.replaceAll("{agentId}", binding.agent.id)
|
|
275
|
+
.replaceAll("{runRoot}", runRoot)
|
|
276
|
+
.replaceAll("{workspaceRoot}", workspaceRoot)
|
|
277
|
+
.replaceAll("{baseRootDir}", baseRootDir);
|
|
278
|
+
return path.isAbsolute(rendered) ? rendered : path.resolve(workspaceRoot, rendered);
|
|
279
|
+
}
|
|
252
280
|
resolveBuiltinMiddlewareBackend(binding, options = {}) {
|
|
253
281
|
return resolveBuiltinMiddlewareBackendHelper({
|
|
254
282
|
binding,
|
|
@@ -257,7 +285,7 @@ export class AgentRuntimeAdapter {
|
|
|
257
285
|
options,
|
|
258
286
|
});
|
|
259
287
|
}
|
|
260
|
-
createDeclaredMiddlewareResolverOptions(binding) {
|
|
288
|
+
createDeclaredMiddlewareResolverOptions(binding, options = {}) {
|
|
261
289
|
return {
|
|
262
290
|
resolveModel: (model) => this.resolveModel(model),
|
|
263
291
|
resolveBackend: (resolvedBinding) => {
|
|
@@ -266,7 +294,7 @@ export class AgentRuntimeAdapter {
|
|
|
266
294
|
},
|
|
267
295
|
resolveFilesystemBackend: (resolvedBinding) => {
|
|
268
296
|
const targetBinding = resolvedBinding ?? binding;
|
|
269
|
-
return targetBinding ? this.resolveFilesystemBackend(targetBinding) : undefined;
|
|
297
|
+
return targetBinding ? this.resolveFilesystemBackend(targetBinding, { threadId: options.threadId }) : undefined;
|
|
270
298
|
},
|
|
271
299
|
resolveCustom: this.options.declaredMiddlewareResolver,
|
|
272
300
|
binding,
|
|
@@ -276,8 +304,8 @@ export class AgentRuntimeAdapter {
|
|
|
276
304
|
return {
|
|
277
305
|
resolveModel: (model) => this.resolveModel(model),
|
|
278
306
|
resolveTools: (tools, currentBinding) => this.resolveTools(tools, currentBinding),
|
|
279
|
-
resolveFilesystemBackend: (currentBinding) => this.resolveFilesystemBackend(currentBinding),
|
|
280
|
-
createDeclaredMiddlewareResolverOptions: (currentBinding) => this.createDeclaredMiddlewareResolverOptions(currentBinding),
|
|
307
|
+
resolveFilesystemBackend: (currentBinding) => this.resolveFilesystemBackend(currentBinding, { threadId: options.threadId }),
|
|
308
|
+
createDeclaredMiddlewareResolverOptions: (currentBinding) => this.createDeclaredMiddlewareResolverOptions(currentBinding, options),
|
|
281
309
|
resolveBuiltinMiddlewareBackend: (currentBinding, currentOptions = {}) => this.resolveBuiltinMiddlewareBackend(currentBinding, currentOptions),
|
|
282
310
|
resolveSubagents: (subagents, currentBinding) => this.resolveSubagents(subagents, currentBinding),
|
|
283
311
|
invokeBuiltinTaskTool: (currentBinding, toolInput, currentOptions = {}) => this.invokeBuiltinTaskTool(currentBinding, toolInput, currentOptions),
|
|
@@ -313,8 +341,8 @@ export class AgentRuntimeAdapter {
|
|
|
313
341
|
createDeclaredMiddlewareResolverOptions: assembly.createDeclaredMiddlewareResolverOptions,
|
|
314
342
|
});
|
|
315
343
|
}
|
|
316
|
-
async resolveLangChainRuntimeExtensionMiddleware(binding) {
|
|
317
|
-
const assembly = this.createAssemblyResolvers(binding);
|
|
344
|
+
async resolveLangChainRuntimeExtensionMiddleware(binding, options = {}) {
|
|
345
|
+
const assembly = this.createAssemblyResolvers(binding, options);
|
|
318
346
|
return resolveLangChainRuntimeExtensionMiddlewareHelper({
|
|
319
347
|
binding,
|
|
320
348
|
materializeAutomaticSummarizationMiddleware: (currentBinding) => this.materializeAutomaticSummarizationMiddleware(currentBinding),
|
|
@@ -324,14 +352,14 @@ export class AgentRuntimeAdapter {
|
|
|
324
352
|
resolveSubagents: assembly.resolveSubagents,
|
|
325
353
|
});
|
|
326
354
|
}
|
|
327
|
-
async resolveMiddleware(binding, interruptOn) {
|
|
328
|
-
const assembly = this.createAssemblyResolvers(binding);
|
|
355
|
+
async resolveMiddleware(binding, interruptOn, options = {}) {
|
|
356
|
+
const assembly = this.createAssemblyResolvers(binding, options);
|
|
329
357
|
return resolveMiddlewareHelper({
|
|
330
358
|
binding,
|
|
331
359
|
interruptOn,
|
|
332
360
|
runtimeAdapterOptions: this.options,
|
|
333
361
|
createDeclaredMiddlewareResolverOptions: assembly.createDeclaredMiddlewareResolverOptions,
|
|
334
|
-
resolveLangChainRuntimeExtensionMiddleware: (currentBinding) => this.resolveLangChainRuntimeExtensionMiddleware(currentBinding),
|
|
362
|
+
resolveLangChainRuntimeExtensionMiddleware: (currentBinding) => this.resolveLangChainRuntimeExtensionMiddleware(currentBinding, options),
|
|
335
363
|
});
|
|
336
364
|
}
|
|
337
365
|
async resolveSubagents(subagents, binding) {
|
|
@@ -354,7 +382,7 @@ export class AgentRuntimeAdapter {
|
|
|
354
382
|
const interruptOn = resolveRunnableInterruptOn(binding);
|
|
355
383
|
const resolvedModel = await this.resolveModel(primaryModel);
|
|
356
384
|
const resolvedTools = this.resolveTools(primaryTools, binding);
|
|
357
|
-
const resolvedMiddleware = await this.resolveMiddleware(binding, interruptOn);
|
|
385
|
+
const resolvedMiddleware = await this.resolveMiddleware(binding, interruptOn, { threadId: options.threadId });
|
|
358
386
|
const resolvedCheckpointer = resolveRunnableCheckpointer(this.options, binding);
|
|
359
387
|
const resolvedStore = this.options.storeResolver?.(binding);
|
|
360
388
|
const model = resolvedModel;
|
|
@@ -372,12 +400,12 @@ export class AgentRuntimeAdapter {
|
|
|
372
400
|
systemPromptOverride: options.systemPromptOverride,
|
|
373
401
|
}));
|
|
374
402
|
}
|
|
375
|
-
async createRunnable(binding) {
|
|
403
|
+
async createRunnable(binding, options = {}) {
|
|
376
404
|
if (getBindingAdapterKind(binding) === "langgraph") {
|
|
377
405
|
throw new Error(`Agent ${binding.agent.id} uses removed backend langgraph; use langchain-v1 or deepagent`);
|
|
378
406
|
}
|
|
379
407
|
if (isLangChainBinding(binding)) {
|
|
380
|
-
return this.createLangChainRunnable(binding);
|
|
408
|
+
return this.createLangChainRunnable(binding, { threadId: options.threadId });
|
|
381
409
|
}
|
|
382
410
|
return this.createDeepAgentRunnable(binding);
|
|
383
411
|
}
|
|
@@ -425,25 +453,34 @@ export class AgentRuntimeAdapter {
|
|
|
425
453
|
});
|
|
426
454
|
return createDeepAgent(deepAgentConfig);
|
|
427
455
|
}
|
|
428
|
-
|
|
429
|
-
const
|
|
456
|
+
buildRunnableCacheKey(binding, threadId) {
|
|
457
|
+
const filesystemConfig = getBindingFilesystemConfig(binding);
|
|
458
|
+
const sessionStorage = typeof filesystemConfig?.sessionStorage === "object" && filesystemConfig.sessionStorage
|
|
459
|
+
? filesystemConfig.sessionStorage
|
|
460
|
+
: undefined;
|
|
461
|
+
const sessionScoped = sessionStorage?.enabled === true;
|
|
462
|
+
return `${binding.agent.sourcePath}::${sessionScoped ? (threadId ?? "__default__") : "__binding__"}`;
|
|
463
|
+
}
|
|
464
|
+
async create(binding, options = {}) {
|
|
465
|
+
const cacheKey = this.buildRunnableCacheKey(binding, options.threadId);
|
|
466
|
+
const cached = this.runnableCache.get(cacheKey);
|
|
430
467
|
if (cached) {
|
|
431
468
|
return cached;
|
|
432
469
|
}
|
|
433
|
-
const pending = this.createRunnable(binding);
|
|
434
|
-
this.runnableCache.set(
|
|
470
|
+
const pending = this.createRunnable(binding, options);
|
|
471
|
+
this.runnableCache.set(cacheKey, pending);
|
|
435
472
|
try {
|
|
436
473
|
return await pending;
|
|
437
474
|
}
|
|
438
475
|
catch (error) {
|
|
439
|
-
this.runnableCache.delete(
|
|
476
|
+
this.runnableCache.delete(cacheKey);
|
|
440
477
|
throw error;
|
|
441
478
|
}
|
|
442
479
|
}
|
|
443
480
|
async invoke(binding, input, threadId, runId, resumePayload, history = [], options = {}) {
|
|
444
481
|
const callRuntime = async (activeBinding, activeRequest) => {
|
|
445
482
|
return this.invokeWithProviderRetry(activeBinding, async () => {
|
|
446
|
-
const runnable = await this.create(activeBinding);
|
|
483
|
+
const runnable = await this.create(activeBinding, { threadId });
|
|
447
484
|
return (await this.withTimeout(() => runnable.invoke(activeRequest, resolveLangChainInvocationConfig(activeBinding, {
|
|
448
485
|
threadId,
|
|
449
486
|
runId,
|
|
@@ -469,7 +506,7 @@ export class AgentRuntimeAdapter {
|
|
|
469
506
|
invokeOptions: options,
|
|
470
507
|
resolveTools: (tools, currentBinding) => this.resolveTools(tools, currentBinding),
|
|
471
508
|
getToolNameMapping: (currentBinding) => this.getToolNameMapping(currentBinding),
|
|
472
|
-
resolveBuiltinMiddlewareTools: (currentBinding, currentOptions) => this.resolveBuiltinMiddlewareTools(currentBinding, currentOptions),
|
|
509
|
+
resolveBuiltinMiddlewareTools: (currentBinding, currentOptions) => this.resolveBuiltinMiddlewareTools(currentBinding, { ...currentOptions, threadId }),
|
|
473
510
|
callRuntimeWithToolParseRecovery,
|
|
474
511
|
});
|
|
475
512
|
}
|
|
@@ -494,7 +531,7 @@ export class AgentRuntimeAdapter {
|
|
|
494
531
|
forceInvokeFallback,
|
|
495
532
|
canUseDirectModelStream,
|
|
496
533
|
langChainStreamModel,
|
|
497
|
-
createRunnable: () => this.create(binding),
|
|
534
|
+
createRunnable: () => this.create(binding, { threadId }),
|
|
498
535
|
withTimeout: (producer, timeoutMs, operation, stage) => this.withTimeout(producer, timeoutMs, operation, stage),
|
|
499
536
|
iterateWithTimeout: (iterable, timeoutMs, operation, deadlineAt, deadlineTimeoutMs) => this.iterateWithTimeout(iterable, timeoutMs, operation, deadlineAt, deadlineTimeoutMs),
|
|
500
537
|
invokeTimeoutMs: computeRemainingTimeoutMs(streamDeadlineAt, invokeTimeoutMs),
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { getBindingPrimaryTools } from "../../support/compiled-binding.js";
|
|
2
|
+
import { toolRequiresRuntimeApproval } from "../../adapter/tool/tool-hitl.js";
|
|
3
|
+
const WRITE_LIKE_PATTERN = /\b(write|edit|delete|create|update|append|insert|push|commit|publish|send|post|apply|merge|sync|upload|save)\b/i;
|
|
4
|
+
function inputHints(binding, tool) {
|
|
5
|
+
const hints = new Set();
|
|
6
|
+
const target = `${tool.name} ${tool.description}`.toLowerCase();
|
|
7
|
+
if (/(path|file|dir|directory|folder|workspace|repo|repository)/.test(target)) {
|
|
8
|
+
hints.add("filesystem-scope");
|
|
9
|
+
}
|
|
10
|
+
if (/(memory|knowledge|store|recall)/.test(target)) {
|
|
11
|
+
hints.add("memory-scope");
|
|
12
|
+
}
|
|
13
|
+
if (tool.config?.mcp) {
|
|
14
|
+
hints.add("remote-mcp");
|
|
15
|
+
}
|
|
16
|
+
if (binding.agent.executionMode === "deepagent") {
|
|
17
|
+
hints.add("delegated-runtime");
|
|
18
|
+
}
|
|
19
|
+
return Array.from(hints);
|
|
20
|
+
}
|
|
21
|
+
function classifyRisk(policy) {
|
|
22
|
+
if (policy.requiresApproval) {
|
|
23
|
+
return "high";
|
|
24
|
+
}
|
|
25
|
+
const target = `${policy.toolName} ${policy.description}`;
|
|
26
|
+
if (policy.toolType === "mcp" && WRITE_LIKE_PATTERN.test(target)) {
|
|
27
|
+
return "high";
|
|
28
|
+
}
|
|
29
|
+
if (policy.toolType === "backend" || policy.toolType === "mcp") {
|
|
30
|
+
return "medium";
|
|
31
|
+
}
|
|
32
|
+
return "low";
|
|
33
|
+
}
|
|
34
|
+
function toCategory(toolType) {
|
|
35
|
+
if (toolType === "mcp") {
|
|
36
|
+
return "mcp";
|
|
37
|
+
}
|
|
38
|
+
if (toolType === "backend") {
|
|
39
|
+
return "backend";
|
|
40
|
+
}
|
|
41
|
+
if (toolType === "provider") {
|
|
42
|
+
return "provider-native";
|
|
43
|
+
}
|
|
44
|
+
return "local";
|
|
45
|
+
}
|
|
46
|
+
export function buildRuntimeGovernanceBundles(binding) {
|
|
47
|
+
const toolPolicies = getBindingPrimaryTools(binding).map((tool) => {
|
|
48
|
+
const requiresApproval = toolRequiresRuntimeApproval(tool);
|
|
49
|
+
return {
|
|
50
|
+
toolName: tool.name,
|
|
51
|
+
toolId: tool.id,
|
|
52
|
+
toolType: tool.type,
|
|
53
|
+
category: toCategory(tool.type),
|
|
54
|
+
risk: classifyRisk({
|
|
55
|
+
toolType: tool.type,
|
|
56
|
+
requiresApproval,
|
|
57
|
+
toolName: tool.name,
|
|
58
|
+
description: tool.description,
|
|
59
|
+
config: tool.config,
|
|
60
|
+
}),
|
|
61
|
+
requiresApproval,
|
|
62
|
+
approvalPolicy: tool.hitl?.enabled === true ? "explicit-hitl" : requiresApproval ? "runtime-default" : "none",
|
|
63
|
+
hasInputSchema: typeof tool.inputSchemaRef === "string" && tool.inputSchemaRef.trim().length > 0,
|
|
64
|
+
inputRiskHints: inputHints(binding, tool),
|
|
65
|
+
};
|
|
66
|
+
});
|
|
67
|
+
if (toolPolicies.length === 0) {
|
|
68
|
+
return [];
|
|
69
|
+
}
|
|
70
|
+
return [{
|
|
71
|
+
bundleId: `governance/${binding.agent.id}`,
|
|
72
|
+
title: "Runtime tool governance",
|
|
73
|
+
summary: `${toolPolicies.filter((tool) => tool.requiresApproval).length} of ${toolPolicies.length} tool(s) require approval`,
|
|
74
|
+
toolPolicies,
|
|
75
|
+
}];
|
|
76
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { readSkillMetadata } from "../../support/skill-metadata.js";
|
|
2
2
|
import { getBindingMemorySources, getBindingPrimaryModel, getBindingPrimaryTools, getBindingSkills, getBindingSubagents, } from "../../support/compiled-binding.js";
|
|
3
|
+
import { buildRuntimeGovernanceBundles } from "./governance.js";
|
|
3
4
|
function asObject(value) {
|
|
4
5
|
return typeof value === "object" && value !== null ? value : null;
|
|
5
6
|
}
|
|
@@ -67,6 +68,9 @@ export function buildRunRuntimeSnapshot(binding, options) {
|
|
|
67
68
|
};
|
|
68
69
|
}),
|
|
69
70
|
memory: getBindingMemorySources(binding),
|
|
71
|
+
governance: {
|
|
72
|
+
bundles: buildRuntimeGovernanceBundles(binding),
|
|
73
|
+
},
|
|
70
74
|
...(tracing ? { tracing } : {}),
|
|
71
75
|
};
|
|
72
76
|
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import type { CompiledAgentBinding } from "../../../contracts/types.js";
|
|
1
|
+
import type { CompiledAgentBinding, RuntimeGovernanceBundle } from "../../../contracts/types.js";
|
|
2
2
|
export type PolicyEngineDecision = {
|
|
3
3
|
allowed: boolean;
|
|
4
4
|
reasons: string[];
|
|
5
|
+
bundles?: RuntimeGovernanceBundle[];
|
|
5
6
|
};
|
|
6
7
|
export declare class PolicyEngine {
|
|
7
8
|
/**
|
|
@@ -7,6 +7,7 @@ export class PolicyEngine {
|
|
|
7
7
|
*/
|
|
8
8
|
evaluate(binding) {
|
|
9
9
|
const reasons = [];
|
|
10
|
+
const bundles = [];
|
|
10
11
|
let allowed = true;
|
|
11
12
|
for (const evaluator of getPolicyEvaluators()) {
|
|
12
13
|
const decision = evaluator.evaluate(binding);
|
|
@@ -17,8 +18,11 @@ export class PolicyEngine {
|
|
|
17
18
|
allowed = false;
|
|
18
19
|
}
|
|
19
20
|
reasons.push(...decision.reasons);
|
|
21
|
+
if (Array.isArray(decision.bundles)) {
|
|
22
|
+
bundles.push(...decision.bundles);
|
|
23
|
+
}
|
|
20
24
|
}
|
|
21
|
-
return { allowed, reasons };
|
|
25
|
+
return bundles.length > 0 ? { allowed, reasons, bundles } : { allowed, reasons };
|
|
22
26
|
}
|
|
23
27
|
}
|
|
24
28
|
export { PolicyEngine as GovernanceEngine, };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ApprovalRecord, CancelOptions, HarnessEvent, HarnessStreamItem, RuntimeHealthSnapshot, ListMemoriesInput, ListMemoriesResult, MessageContent, RemoveMemoryInput, RunRecord, RunStartOptions, RestartConversationOptions, RuntimeAdapterOptions, ResumeOptions, RunOptions, RunResult, RunSummary, MemoryRecord, MemorizeInput, MemorizeResult, RecallInput, RecallResult, UpdateMemoryInput, ThreadSummary, ThreadRecord, WorkspaceBundle } from "../contracts/types.js";
|
|
1
|
+
import type { ApprovalRecord, ArtifactListing, CancelOptions, HarnessEvent, HarnessStreamItem, RuntimeHealthSnapshot, ListMemoriesInput, ListMemoriesResult, MessageContent, RemoveMemoryInput, RunRecord, RunStartOptions, RestartConversationOptions, RuntimeAdapterOptions, RuntimeEvaluationExport, RuntimeEvaluationExportInput, ResumeOptions, RunOptions, RunResult, RunSummary, MemoryRecord, MemorizeInput, MemorizeResult, RecallInput, RecallResult, UpdateMemoryInput, ThreadSummary, ThreadRecord, WorkspaceBundle } from "../contracts/types.js";
|
|
2
2
|
import { type ToolMcpServerOptions } from "../mcp.js";
|
|
3
3
|
import { type InventoryAgentRecord, type InventorySkillRecord } from "./harness/system/inventory.js";
|
|
4
4
|
import type { RequirementAssessmentOptions } from "./harness/system/skill-requirements.js";
|
|
@@ -82,6 +82,10 @@ export declare class AgentHarnessRuntime {
|
|
|
82
82
|
runId?: string;
|
|
83
83
|
}): Promise<ApprovalRecord[]>;
|
|
84
84
|
getApproval(approvalId: string): Promise<ApprovalRecord | null>;
|
|
85
|
+
listArtifacts(threadId: string, runId: string): Promise<ArtifactListing>;
|
|
86
|
+
readArtifact(threadId: string, runId: string, artifactPath: string): Promise<unknown>;
|
|
87
|
+
listRunEvents(threadId: string, runId: string): Promise<HarnessEvent[]>;
|
|
88
|
+
exportEvaluationBundle(input: RuntimeEvaluationExportInput): Promise<RuntimeEvaluationExport>;
|
|
85
89
|
listAgentSkills(agentId: string, options?: RequirementAssessmentOptions): InventorySkillRecord[];
|
|
86
90
|
getAgent(agentId: string, options?: RequirementAssessmentOptions): InventoryAgentRecord | null;
|
|
87
91
|
describeWorkspaceInventory(options?: RequirementAssessmentOptions): {
|
package/dist/runtime/harness.js
CHANGED
|
@@ -475,6 +475,51 @@ export class AgentHarnessRuntime {
|
|
|
475
475
|
persistence: this.persistence,
|
|
476
476
|
}, approvalId);
|
|
477
477
|
}
|
|
478
|
+
async listArtifacts(threadId, runId) {
|
|
479
|
+
return this.persistence.listArtifacts(threadId, runId);
|
|
480
|
+
}
|
|
481
|
+
async readArtifact(threadId, runId, artifactPath) {
|
|
482
|
+
return this.persistence.readArtifact(threadId, runId, artifactPath);
|
|
483
|
+
}
|
|
484
|
+
async listRunEvents(threadId, runId) {
|
|
485
|
+
return this.persistence.listRunEvents(threadId, runId);
|
|
486
|
+
}
|
|
487
|
+
async exportEvaluationBundle(input) {
|
|
488
|
+
const thread = await this.getThread(input.sessionId);
|
|
489
|
+
const run = await this.getRun(input.requestId);
|
|
490
|
+
const approvals = await this.listApprovals({ threadId: input.sessionId, runId: input.requestId });
|
|
491
|
+
const transcript = await this.persistence.listThreadMessages(input.sessionId, 500);
|
|
492
|
+
const events = await this.persistence.listRunEvents(input.sessionId, input.requestId);
|
|
493
|
+
const runtimeHealth = await this.getHealth();
|
|
494
|
+
const artifactsListing = input.includeArtifacts === false
|
|
495
|
+
? { items: [] }
|
|
496
|
+
: await this.persistence.listArtifacts(input.sessionId, input.requestId);
|
|
497
|
+
const artifacts = await Promise.all(artifactsListing.items.map(async (artifact) => ({
|
|
498
|
+
...artifact,
|
|
499
|
+
...(input.includeArtifactContents === true
|
|
500
|
+
? { content: await this.persistence.readArtifact(input.sessionId, input.requestId, artifact.path) }
|
|
501
|
+
: {}),
|
|
502
|
+
})));
|
|
503
|
+
return {
|
|
504
|
+
session: thread ? toSessionRecord(thread) : null,
|
|
505
|
+
request: run ? toRequestRecord(run) : null,
|
|
506
|
+
approvals,
|
|
507
|
+
transcript,
|
|
508
|
+
events,
|
|
509
|
+
artifacts,
|
|
510
|
+
runtimeHealth,
|
|
511
|
+
...(typeof input.expectedOutput === "string" && input.expectedOutput.trim().length > 0
|
|
512
|
+
? { expectedOutput: input.expectedOutput.trim() }
|
|
513
|
+
: {}),
|
|
514
|
+
rubric: Array.isArray(input.rubric)
|
|
515
|
+
? input.rubric.filter((item) => typeof item === "string" && item.trim().length > 0).map((item) => item.trim())
|
|
516
|
+
: [],
|
|
517
|
+
tags: Array.isArray(input.tags)
|
|
518
|
+
? input.tags.filter((item) => typeof item === "string" && item.trim().length > 0).map((item) => item.trim())
|
|
519
|
+
: [],
|
|
520
|
+
...(input.metadata ? { metadata: { ...input.metadata } } : {}),
|
|
521
|
+
};
|
|
522
|
+
}
|
|
478
523
|
listAgentSkills(agentId, options = {}) {
|
|
479
524
|
return listWorkspaceAgentSkills(this.workspace, agentId, {
|
|
480
525
|
assessRequirements: isInventoryEnabled(this.workspace),
|
|
@@ -1393,3 +1438,40 @@ export class AgentHarnessRuntime {
|
|
|
1393
1438
|
}, thread, nowMs);
|
|
1394
1439
|
}
|
|
1395
1440
|
}
|
|
1441
|
+
function toRequestSummary(summary) {
|
|
1442
|
+
return {
|
|
1443
|
+
requestId: summary.runId,
|
|
1444
|
+
sessionId: summary.threadId,
|
|
1445
|
+
agentId: summary.agentId,
|
|
1446
|
+
executionMode: summary.executionMode,
|
|
1447
|
+
adapterKind: summary.adapterKind,
|
|
1448
|
+
createdAt: summary.createdAt,
|
|
1449
|
+
updatedAt: summary.updatedAt,
|
|
1450
|
+
state: summary.state,
|
|
1451
|
+
checkpointRef: summary.checkpointRef,
|
|
1452
|
+
resumable: summary.resumable,
|
|
1453
|
+
startedAt: summary.startedAt,
|
|
1454
|
+
endedAt: summary.endedAt,
|
|
1455
|
+
lastActivityAt: summary.lastActivityAt,
|
|
1456
|
+
currentAgentId: summary.currentAgentId,
|
|
1457
|
+
delegationChain: summary.delegationChain,
|
|
1458
|
+
runtimeSnapshot: summary.runtimeSnapshot,
|
|
1459
|
+
};
|
|
1460
|
+
}
|
|
1461
|
+
function toSessionRecord(record) {
|
|
1462
|
+
return {
|
|
1463
|
+
sessionId: record.threadId,
|
|
1464
|
+
entryAgentId: record.entryAgentId,
|
|
1465
|
+
currentAgentId: record.currentAgentId,
|
|
1466
|
+
currentState: record.currentState,
|
|
1467
|
+
latestRequestId: record.latestRunId,
|
|
1468
|
+
createdAt: record.createdAt,
|
|
1469
|
+
updatedAt: record.updatedAt,
|
|
1470
|
+
messages: record.messages,
|
|
1471
|
+
requests: record.runs.map(toRequestSummary),
|
|
1472
|
+
pendingDecision: record.pendingDecision,
|
|
1473
|
+
};
|
|
1474
|
+
}
|
|
1475
|
+
function toRequestRecord(record) {
|
|
1476
|
+
return toRequestSummary(record);
|
|
1477
|
+
}
|
|
@@ -337,6 +337,12 @@ export function compileBinding(workspaceRoot, agent, agents, referencedSubagentI
|
|
|
337
337
|
const store = resolveStoreConfig(agent, refs);
|
|
338
338
|
const checkpointer = resolveCheckpointerConfig(agent, refs);
|
|
339
339
|
const runtimeMemory = resolveRuntimeMemoryConfig(agent, refs);
|
|
340
|
+
const runtimeFilesystemDefaults = agent.executionMode === "langchain-v1"
|
|
341
|
+
? asObject(runtimeDefaults?.filesystem)
|
|
342
|
+
: undefined;
|
|
343
|
+
const compiledFilesystemConfig = agent.executionMode === "langchain-v1"
|
|
344
|
+
? mergeConfigObjects(runtimeFilesystemDefaults, getAgentExecutionObject(agent, "filesystem", { executionMode: "langchain-v1" }))
|
|
345
|
+
: undefined;
|
|
340
346
|
const runRoot = typeof agent.runRoot === "string" && agent.runRoot.trim().length > 0
|
|
341
347
|
? path.resolve(workspaceRoot, agent.runRoot)
|
|
342
348
|
: typeof runtimeDefaults?.runRoot === "string" && runtimeDefaults.runRoot.trim().length > 0
|
|
@@ -362,7 +368,7 @@ export function compileBinding(workspaceRoot, agent, agents, referencedSubagentI
|
|
|
362
368
|
langchain: {
|
|
363
369
|
passthrough,
|
|
364
370
|
interruptOn: resolveInterruptOn(agent),
|
|
365
|
-
filesystem:
|
|
371
|
+
filesystem: compiledFilesystemConfig,
|
|
366
372
|
subagents: compileSubagents(agent, agents, workspaceRoot, models, tools, compiledAgentSkills, compiledAgentModel),
|
|
367
373
|
memory: compiledAgentMemory,
|
|
368
374
|
skills: compiledAgentSkills,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@botbotgo/agent-harness",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.157",
|
|
4
4
|
"description": "Workspace runtime for multi-agent applications",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"packageManager": "npm@10.9.2",
|
|
@@ -28,6 +28,11 @@
|
|
|
28
28
|
"import": "./dist/index.js",
|
|
29
29
|
"default": "./dist/index.js"
|
|
30
30
|
},
|
|
31
|
+
"./acp": {
|
|
32
|
+
"types": "./dist/acp.d.ts",
|
|
33
|
+
"import": "./dist/acp.js",
|
|
34
|
+
"default": "./dist/acp.js"
|
|
35
|
+
},
|
|
31
36
|
"./tools": {
|
|
32
37
|
"types": "./dist/tools.d.ts",
|
|
33
38
|
"import": "./dist/tools.js",
|