@botbotgo/agent-harness 0.0.26 → 0.0.28
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/config/embedding-model.yaml +2 -3
- package/dist/config/models.yaml +8 -8
- package/dist/contracts/types.d.ts +10 -2
- package/dist/package-version.d.ts +1 -1
- package/dist/package-version.js +1 -1
- package/dist/resource/resource-impl.js +18 -2
- package/dist/runtime/agent-runtime-adapter.d.ts +4 -4
- package/dist/runtime/agent-runtime-adapter.js +7 -6
- package/dist/runtime/harness.d.ts +2 -2
- package/dist/runtime/harness.js +16 -14
- package/dist/runtime/thread-memory-sync.js +2 -1
- package/dist/utils/message-content.d.ts +5 -0
- package/dist/utils/message-content.js +30 -0
- package/dist/workspace/resource-compilers.js +17 -2
- package/package.json +5 -4
|
@@ -13,9 +13,8 @@ spec:
|
|
|
13
13
|
provider: ollama
|
|
14
14
|
# LangChain aligned feature: concrete embedding model identifier passed to the provider integration.
|
|
15
15
|
model: nomic-embed-text
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
baseUrl: https://ollama-rtx-4070.easynet.world/
|
|
16
|
+
# LangChain aligned feature: provider-specific initialization options for embeddings.
|
|
17
|
+
baseUrl: https://ollama-rtx-4070.easynet.world/
|
|
19
18
|
|
|
20
19
|
# ===================
|
|
21
20
|
# DeepAgents Features
|
package/dist/config/models.yaml
CHANGED
|
@@ -19,11 +19,11 @@ spec:
|
|
|
19
19
|
# LangChain aligned feature: concrete model identifier passed to the selected provider integration.
|
|
20
20
|
# Example values depend on `provider`, such as `gpt-oss:latest` for `ollama`.
|
|
21
21
|
model: gpt-oss:latest
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
22
|
+
# LangChain aligned feature: provider-specific initialization options.
|
|
23
|
+
# Write these fields directly on the model object.
|
|
24
|
+
# Common examples include `baseUrl`, `temperature`, and auth/client settings.
|
|
25
|
+
# `baseUrl` configures the Ollama-compatible endpoint used by the model client.
|
|
26
|
+
# For `openai-compatible`, `baseUrl` is normalized into the ChatOpenAI `configuration.baseURL` field.
|
|
27
|
+
baseUrl: https://ollama-rtx-4070.easynet.world/
|
|
28
|
+
# LangChain aligned feature: provider/model initialization option controlling sampling temperature.
|
|
29
|
+
temperature: 0.2
|
|
@@ -237,9 +237,17 @@ export type RunListeners = {
|
|
|
237
237
|
output: unknown;
|
|
238
238
|
}) => void | Promise<void>;
|
|
239
239
|
};
|
|
240
|
+
export type MessageContentPart = {
|
|
241
|
+
type: "text";
|
|
242
|
+
text: string;
|
|
243
|
+
} | {
|
|
244
|
+
type: "image_url";
|
|
245
|
+
image_url: string;
|
|
246
|
+
};
|
|
247
|
+
export type MessageContent = string | MessageContentPart[];
|
|
240
248
|
export type RunStartOptions = {
|
|
241
249
|
agentId?: string;
|
|
242
|
-
input:
|
|
250
|
+
input: MessageContent;
|
|
243
251
|
threadId?: string;
|
|
244
252
|
listeners?: RunListeners;
|
|
245
253
|
};
|
|
@@ -283,7 +291,7 @@ export type HarnessStreamItem = {
|
|
|
283
291
|
};
|
|
284
292
|
export type TranscriptMessage = {
|
|
285
293
|
role: "user" | "assistant";
|
|
286
|
-
content:
|
|
294
|
+
content: MessageContent;
|
|
287
295
|
runId: string;
|
|
288
296
|
createdAt: string;
|
|
289
297
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const AGENT_HARNESS_VERSION = "0.0.
|
|
1
|
+
export declare const AGENT_HARNESS_VERSION = "0.0.27";
|
package/dist/package-version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const AGENT_HARNESS_VERSION = "0.0.
|
|
1
|
+
export const AGENT_HARNESS_VERSION = "0.0.27";
|
|
@@ -133,12 +133,26 @@ function createInlineBackendResolver(workspace) {
|
|
|
133
133
|
inheritEnv: config?.inheritEnv !== false,
|
|
134
134
|
});
|
|
135
135
|
}
|
|
136
|
+
case "VfsSandbox": {
|
|
137
|
+
const rootDir = resolveBackendRootDir(config?.rootDir);
|
|
138
|
+
mkdirSync(rootDir, { recursive: true });
|
|
139
|
+
return new LocalShellBackend({
|
|
140
|
+
rootDir,
|
|
141
|
+
virtualMode: config?.virtualMode === false ? false : true,
|
|
142
|
+
timeout: typeof config?.timeout === "number" ? config.timeout : undefined,
|
|
143
|
+
maxOutputBytes: typeof config?.maxOutputBytes === "number" ? config.maxOutputBytes : undefined,
|
|
144
|
+
env: typeof config?.env === "object" && config.env
|
|
145
|
+
? Object.fromEntries(Object.entries(config.env).filter((entry) => typeof entry[1] === "string"))
|
|
146
|
+
: undefined,
|
|
147
|
+
inheritEnv: config?.inheritEnv !== false,
|
|
148
|
+
});
|
|
149
|
+
}
|
|
136
150
|
case "StateBackend":
|
|
137
151
|
return new StateBackend(runtimeLike);
|
|
138
152
|
case "StoreBackend":
|
|
139
153
|
return new StoreBackend(runtimeLike);
|
|
140
154
|
default:
|
|
141
|
-
throw new Error(`Unsupported DeepAgent backend kind "${kind}". Supported inline kinds: LocalShellBackend, StateBackend, StoreBackend, CompositeBackend.`);
|
|
155
|
+
throw new Error(`Unsupported DeepAgent backend kind "${kind}". Supported inline kinds: LocalShellBackend, VfsSandbox, StateBackend, StoreBackend, CompositeBackend.`);
|
|
142
156
|
}
|
|
143
157
|
};
|
|
144
158
|
return (runtimeLike) => {
|
|
@@ -146,6 +160,8 @@ function createInlineBackendResolver(workspace) {
|
|
|
146
160
|
switch (kind) {
|
|
147
161
|
case "LocalShellBackend":
|
|
148
162
|
return createBackend("LocalShellBackend", backendConfig, runtimeLike);
|
|
163
|
+
case "VfsSandbox":
|
|
164
|
+
return createBackend("VfsSandbox", backendConfig, runtimeLike);
|
|
149
165
|
case "StateBackend":
|
|
150
166
|
return new StateBackend(runtimeLike);
|
|
151
167
|
case "StoreBackend":
|
|
@@ -165,7 +181,7 @@ function createInlineBackendResolver(workspace) {
|
|
|
165
181
|
return new CompatibleCompositeBackend(createBackend(defaultBackendKind, stateConfig, runtimeLike), mappedRoutes);
|
|
166
182
|
}
|
|
167
183
|
default:
|
|
168
|
-
throw new Error(`Unsupported DeepAgent backend kind "${kind}". Supported inline kinds: LocalShellBackend, StateBackend, StoreBackend, CompositeBackend.`);
|
|
184
|
+
throw new Error(`Unsupported DeepAgent backend kind "${kind}". Supported inline kinds: LocalShellBackend, VfsSandbox, StateBackend, StoreBackend, CompositeBackend.`);
|
|
169
185
|
}
|
|
170
186
|
};
|
|
171
187
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { CompiledAgentBinding, RunResult, RuntimeAdapterOptions, TranscriptMessage } from "../contracts/types.js";
|
|
1
|
+
import type { CompiledAgentBinding, MessageContent, RunResult, RuntimeAdapterOptions, TranscriptMessage } from "../contracts/types.js";
|
|
2
2
|
import { type RuntimeStreamChunk } from "./parsing/stream-event-parsing.js";
|
|
3
3
|
type RunnableLike = {
|
|
4
4
|
invoke: (input: unknown, config?: Record<string, unknown>) => Promise<unknown>;
|
|
@@ -26,10 +26,10 @@ export declare class AgentRuntimeAdapter {
|
|
|
26
26
|
private buildRouteSystemPrompt;
|
|
27
27
|
private resolveSubagents;
|
|
28
28
|
create(binding: CompiledAgentBinding): Promise<RunnableLike>;
|
|
29
|
-
route(input:
|
|
29
|
+
route(input: MessageContent, primaryBinding: CompiledAgentBinding, secondaryBinding: CompiledAgentBinding, options?: {
|
|
30
30
|
systemPrompt?: string;
|
|
31
31
|
}): Promise<string>;
|
|
32
|
-
invoke(binding: CompiledAgentBinding, input:
|
|
33
|
-
stream(binding: CompiledAgentBinding, input:
|
|
32
|
+
invoke(binding: CompiledAgentBinding, input: MessageContent, threadId: string, runId: string, resumePayload?: unknown, history?: TranscriptMessage[]): Promise<RunResult>;
|
|
33
|
+
stream(binding: CompiledAgentBinding, input: MessageContent, threadId: string, history?: TranscriptMessage[]): AsyncGenerator<RuntimeStreamChunk | string>;
|
|
34
34
|
}
|
|
35
35
|
export { AgentRuntimeAdapter as RuntimeAdapter, AGENT_INTERRUPT_SENTINEL_PREFIX, AGENT_INTERRUPT_SENTINEL_PREFIX as INTERRUPT_SENTINEL_PREFIX, };
|
|
@@ -9,6 +9,7 @@ import { extractEmptyAssistantMessageFailure, extractReasoningText, extractToolF
|
|
|
9
9
|
import { extractAgentStep, extractInterruptPayload, extractReasoningStreamOutput, extractTerminalStreamOutput, extractToolResult, normalizeTerminalOutputKey, readStreamDelta, } from "./parsing/stream-event-parsing.js";
|
|
10
10
|
import { wrapToolForExecution } from "./tool-hitl.js";
|
|
11
11
|
import { resolveDeclaredMiddleware } from "./declared-middleware.js";
|
|
12
|
+
import { extractMessageText, normalizeMessageContent } from "../utils/message-content.js";
|
|
12
13
|
const AGENT_INTERRUPT_SENTINEL_PREFIX = "__agent_harness_interrupt__:";
|
|
13
14
|
const MODEL_SAFE_TOOL_NAME_PATTERN = /^[a-zA-Z0-9_-]+$/;
|
|
14
15
|
function asObject(value) {
|
|
@@ -172,7 +173,7 @@ export class AgentRuntimeAdapter {
|
|
|
172
173
|
},
|
|
173
174
|
{
|
|
174
175
|
role: "user",
|
|
175
|
-
content: `Original user request:\n${input}\n\nTool results:\n${toolContext}`,
|
|
176
|
+
content: `Original user request:\n${extractMessageText(input)}\n\nTool results:\n${toolContext}`,
|
|
176
177
|
},
|
|
177
178
|
]);
|
|
178
179
|
return sanitizeVisibleText(extractVisibleOutput(synthesized));
|
|
@@ -181,8 +182,8 @@ export class AgentRuntimeAdapter {
|
|
|
181
182
|
if (this.options.modelResolver) {
|
|
182
183
|
return wrapResolvedModel(await this.options.modelResolver(model.id));
|
|
183
184
|
}
|
|
184
|
-
if (model.provider === "ollama"
|
|
185
|
-
return wrapResolvedModel(new ChatOllama({ model: model.model,
|
|
185
|
+
if (model.provider === "ollama") {
|
|
186
|
+
return wrapResolvedModel(new ChatOllama({ model: model.model, ...model.init }));
|
|
186
187
|
}
|
|
187
188
|
if (model.provider === "openai-compatible") {
|
|
188
189
|
return wrapResolvedModel(new ChatOpenAI({ model: model.model, ...normalizeOpenAICompatibleInit(model.init) }));
|
|
@@ -203,8 +204,8 @@ export class AgentRuntimeAdapter {
|
|
|
203
204
|
}
|
|
204
205
|
buildAgentMessages(history, input) {
|
|
205
206
|
return [
|
|
206
|
-
...history.map((item) => ({ role: item.role, content: item.content })),
|
|
207
|
-
{ role: "user", content: input },
|
|
207
|
+
...history.map((item) => ({ role: item.role, content: normalizeMessageContent(item.content) })),
|
|
208
|
+
{ role: "user", content: normalizeMessageContent(input) },
|
|
208
209
|
];
|
|
209
210
|
}
|
|
210
211
|
buildRawModelMessages(systemPrompt, history, input) {
|
|
@@ -374,7 +375,7 @@ export class AgentRuntimeAdapter {
|
|
|
374
375
|
role: "system",
|
|
375
376
|
content: this.buildRouteSystemPrompt(primaryBinding, secondaryBinding, options.systemPrompt),
|
|
376
377
|
},
|
|
377
|
-
{ role: "user", content: input },
|
|
378
|
+
{ role: "user", content: extractMessageText(input) },
|
|
378
379
|
]);
|
|
379
380
|
const content = typeof result === "string"
|
|
380
381
|
? result
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ApprovalRecord, CompiledTool, HarnessEvent, HarnessStreamItem, RunStartOptions, RestartConversationOptions, RuntimeAdapterOptions, ResumeOptions, RunOptions, RunResult, ThreadSummary, ThreadRecord, WorkspaceBundle } from "../contracts/types.js";
|
|
1
|
+
import type { ApprovalRecord, CompiledTool, HarnessEvent, HarnessStreamItem, MessageContent, RunStartOptions, RestartConversationOptions, RuntimeAdapterOptions, ResumeOptions, RunOptions, RunResult, ThreadSummary, ThreadRecord, WorkspaceBundle } from "../contracts/types.js";
|
|
2
2
|
export declare class AgentHarness {
|
|
3
3
|
private readonly workspace;
|
|
4
4
|
private readonly runtimeAdapterOptions;
|
|
@@ -40,7 +40,7 @@ export declare class AgentHarness {
|
|
|
40
40
|
private getSession;
|
|
41
41
|
getThread(threadId: string): Promise<ThreadRecord | null>;
|
|
42
42
|
listPendingApprovals(): Promise<ApprovalRecord[]>;
|
|
43
|
-
routeAgent(input:
|
|
43
|
+
routeAgent(input: MessageContent, options?: {
|
|
44
44
|
threadId?: string;
|
|
45
45
|
}): Promise<string>;
|
|
46
46
|
private emit;
|
package/dist/runtime/harness.js
CHANGED
|
@@ -13,6 +13,7 @@ import { resolveCompiledVectorStore, resolveCompiledVectorStoreRef } from "./sup
|
|
|
13
13
|
import { ThreadMemorySync } from "./thread-memory-sync.js";
|
|
14
14
|
import { FileBackedStore } from "./store.js";
|
|
15
15
|
import { CheckpointMaintenanceLoop, discoverCheckpointMaintenanceTargets, readCheckpointMaintenanceConfig, } from "./checkpoint-maintenance.js";
|
|
16
|
+
import { extractMessageText, normalizeMessageContent } from "../utils/message-content.js";
|
|
16
17
|
export class AgentHarness {
|
|
17
18
|
workspace;
|
|
18
19
|
runtimeAdapterOptions;
|
|
@@ -39,27 +40,28 @@ export class AgentHarness {
|
|
|
39
40
|
}
|
|
40
41
|
heuristicRoute(input) {
|
|
41
42
|
const { primaryBinding, secondaryBinding } = inferRoutingBindings(this.workspace);
|
|
42
|
-
return heuristicRoute(input, primaryBinding, secondaryBinding);
|
|
43
|
+
return heuristicRoute(extractMessageText(input), primaryBinding, secondaryBinding);
|
|
43
44
|
}
|
|
44
45
|
async buildRoutingInput(input, threadId) {
|
|
46
|
+
const inputText = extractMessageText(input);
|
|
45
47
|
if (!threadId) {
|
|
46
|
-
return
|
|
48
|
+
return inputText;
|
|
47
49
|
}
|
|
48
50
|
const history = await this.persistence.listThreadMessages(threadId);
|
|
49
|
-
const priorHistory = history.filter((message) => message.content.trim());
|
|
51
|
+
const priorHistory = history.filter((message) => extractMessageText(message.content).trim());
|
|
50
52
|
if (priorHistory.length === 0) {
|
|
51
|
-
return
|
|
53
|
+
return inputText;
|
|
52
54
|
}
|
|
53
55
|
const recentTurns = priorHistory.slice(-6).map((message) => {
|
|
54
56
|
const role = message.role === "assistant" ? "assistant" : "user";
|
|
55
|
-
const compact = message.content.replace(/\s+/g, " ").trim();
|
|
57
|
+
const compact = extractMessageText(message.content).replace(/\s+/g, " ").trim();
|
|
56
58
|
return `${role}: ${compact.slice(0, 240)}`;
|
|
57
59
|
});
|
|
58
60
|
return [
|
|
59
61
|
"Recent conversation context:",
|
|
60
62
|
...recentTurns,
|
|
61
63
|
"",
|
|
62
|
-
`Current user request: ${
|
|
64
|
+
`Current user request: ${inputText}`,
|
|
63
65
|
].join("\n");
|
|
64
66
|
}
|
|
65
67
|
async resolveSelectedAgentId(input, requestedAgentId, threadId) {
|
|
@@ -234,25 +236,25 @@ export class AgentHarness {
|
|
|
234
236
|
}
|
|
235
237
|
async routeAgent(input, options = {}) {
|
|
236
238
|
const routingInput = await this.buildRoutingInput(input, options.threadId);
|
|
237
|
-
const normalized = input.trim().toLowerCase();
|
|
239
|
+
const normalized = extractMessageText(input).trim().toLowerCase();
|
|
238
240
|
const { primaryBinding, secondaryBinding, researchBinding } = inferRoutingBindings(this.workspace);
|
|
239
241
|
const deterministicIntent = resolveDeterministicRouteIntent(normalized);
|
|
240
242
|
if (requiresResearchRoute(normalized)) {
|
|
241
243
|
const explicitResearchBinding = this.workspace.bindings.get("research-lite") ?? this.workspace.bindings.get("research");
|
|
242
244
|
const hostResearchBinding = explicitResearchBinding?.harnessRuntime.hostFacing !== false ? explicitResearchBinding : researchBinding;
|
|
243
|
-
return hostResearchBinding?.agent.id ?? secondaryBinding?.agent.id ?? primaryBinding?.agent.id ?? heuristicRoute(input, primaryBinding, secondaryBinding);
|
|
245
|
+
return hostResearchBinding?.agent.id ?? secondaryBinding?.agent.id ?? primaryBinding?.agent.id ?? heuristicRoute(extractMessageText(input), primaryBinding, secondaryBinding);
|
|
244
246
|
}
|
|
245
247
|
if (secondaryBinding?.deepAgentParams) {
|
|
246
248
|
return secondaryBinding.agent.id;
|
|
247
249
|
}
|
|
248
250
|
if (deterministicIntent === "primary") {
|
|
249
|
-
return primaryBinding?.agent.id ?? heuristicRoute(input, primaryBinding, secondaryBinding);
|
|
251
|
+
return primaryBinding?.agent.id ?? heuristicRoute(extractMessageText(input), primaryBinding, secondaryBinding);
|
|
250
252
|
}
|
|
251
253
|
if (deterministicIntent === "secondary") {
|
|
252
|
-
return secondaryBinding?.agent.id ?? primaryBinding?.agent.id ?? heuristicRoute(input, primaryBinding, secondaryBinding);
|
|
254
|
+
return secondaryBinding?.agent.id ?? primaryBinding?.agent.id ?? heuristicRoute(extractMessageText(input), primaryBinding, secondaryBinding);
|
|
253
255
|
}
|
|
254
256
|
if (!primaryBinding || !secondaryBinding) {
|
|
255
|
-
return heuristicRoute(input, primaryBinding, secondaryBinding);
|
|
257
|
+
return heuristicRoute(extractMessageText(input), primaryBinding, secondaryBinding);
|
|
256
258
|
}
|
|
257
259
|
try {
|
|
258
260
|
return await this.runtimeAdapter.route(routingInput, primaryBinding, secondaryBinding, {
|
|
@@ -260,7 +262,7 @@ export class AgentHarness {
|
|
|
260
262
|
});
|
|
261
263
|
}
|
|
262
264
|
catch {
|
|
263
|
-
return heuristicRoute(input, primaryBinding, secondaryBinding);
|
|
265
|
+
return heuristicRoute(extractMessageText(input), primaryBinding, secondaryBinding);
|
|
264
266
|
}
|
|
265
267
|
}
|
|
266
268
|
async emit(threadId, runId, sequence, eventType, payload, source = "runtime") {
|
|
@@ -284,7 +286,7 @@ export class AgentHarness {
|
|
|
284
286
|
}
|
|
285
287
|
await this.persistence.appendThreadMessage(threadId, {
|
|
286
288
|
role: "user",
|
|
287
|
-
content: input,
|
|
289
|
+
content: normalizeMessageContent(input),
|
|
288
290
|
runId,
|
|
289
291
|
createdAt,
|
|
290
292
|
});
|
|
@@ -359,7 +361,7 @@ export class AgentHarness {
|
|
|
359
361
|
});
|
|
360
362
|
}
|
|
361
363
|
async persistApproval(threadId, runId, checkpointRef, input, interruptContent) {
|
|
362
|
-
const approval = createPendingApproval(threadId, runId, checkpointRef, input, interruptContent);
|
|
364
|
+
const approval = createPendingApproval(threadId, runId, checkpointRef, extractMessageText(input), interruptContent);
|
|
363
365
|
await this.persistence.createApproval(approval);
|
|
364
366
|
const artifact = await this.persistence.createArtifact(threadId, runId, {
|
|
365
367
|
artifactId: `artifact-approval-${runId}`,
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import { extractMessageText } from "../utils/message-content.js";
|
|
1
2
|
function excerpt(message) {
|
|
2
3
|
if (!message?.content) {
|
|
3
4
|
return "(none)";
|
|
4
5
|
}
|
|
5
|
-
const normalized = message.content.replace(/\s+/g, " ").trim();
|
|
6
|
+
const normalized = extractMessageText(message.content).replace(/\s+/g, " ").trim();
|
|
6
7
|
return normalized.length > 240 ? `${normalized.slice(0, 237)}...` : normalized;
|
|
7
8
|
}
|
|
8
9
|
function renderStatusMarkdown(thread, messages) {
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { MessageContent, MessageContentPart } from "../contracts/types.js";
|
|
2
|
+
export declare function isMessageContentPart(value: unknown): value is MessageContentPart;
|
|
3
|
+
export declare function isMessageContent(value: unknown): value is MessageContent;
|
|
4
|
+
export declare function extractMessageText(content: MessageContent): string;
|
|
5
|
+
export declare function normalizeMessageContent(content: MessageContent): MessageContent;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export function isMessageContentPart(value) {
|
|
2
|
+
if (typeof value !== "object" || !value) {
|
|
3
|
+
return false;
|
|
4
|
+
}
|
|
5
|
+
const typed = value;
|
|
6
|
+
return typed.type === "text" || typed.type === "image_url";
|
|
7
|
+
}
|
|
8
|
+
export function isMessageContent(value) {
|
|
9
|
+
return typeof value === "string" || (Array.isArray(value) && value.every(isMessageContentPart));
|
|
10
|
+
}
|
|
11
|
+
export function extractMessageText(content) {
|
|
12
|
+
if (typeof content === "string") {
|
|
13
|
+
return content;
|
|
14
|
+
}
|
|
15
|
+
return content
|
|
16
|
+
.filter((part) => part.type === "text")
|
|
17
|
+
.map((part) => part.text)
|
|
18
|
+
.join("");
|
|
19
|
+
}
|
|
20
|
+
export function normalizeMessageContent(content) {
|
|
21
|
+
if (typeof content === "string") {
|
|
22
|
+
return content;
|
|
23
|
+
}
|
|
24
|
+
return content.map((part) => {
|
|
25
|
+
if (part.type === "text") {
|
|
26
|
+
return { type: "text", text: part.text };
|
|
27
|
+
}
|
|
28
|
+
return { type: "image_url", image_url: part.image_url };
|
|
29
|
+
});
|
|
30
|
+
}
|
|
@@ -22,6 +22,19 @@ function mergeObjects(base, extra) {
|
|
|
22
22
|
...(extra ?? {}),
|
|
23
23
|
};
|
|
24
24
|
}
|
|
25
|
+
function extractTopLevelInitFields(value, reservedKeys) {
|
|
26
|
+
const reserved = new Set(reservedKeys);
|
|
27
|
+
const entries = Object.entries(value).filter(([key]) => !reserved.has(key));
|
|
28
|
+
if (entries.length === 0) {
|
|
29
|
+
return undefined;
|
|
30
|
+
}
|
|
31
|
+
return Object.fromEntries(entries);
|
|
32
|
+
}
|
|
33
|
+
function assertNoInitBlock(value, kind, id) {
|
|
34
|
+
if (value.init !== undefined) {
|
|
35
|
+
throw new Error(`${kind} ${id} must define provider options at the top level; nested init is not supported`);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
25
38
|
function parseHitlPolicy(value) {
|
|
26
39
|
const record = asObject(value);
|
|
27
40
|
if (!record) {
|
|
@@ -38,9 +51,10 @@ function parseHitlPolicy(value) {
|
|
|
38
51
|
}
|
|
39
52
|
export function parseModelObject(object) {
|
|
40
53
|
const value = object.value;
|
|
54
|
+
assertNoInitBlock(value, "Model", object.id);
|
|
41
55
|
const provider = String(value.provider ?? "").trim();
|
|
42
56
|
const model = String((value.model ?? value.name) ?? "").trim();
|
|
43
|
-
const init =
|
|
57
|
+
const init = extractTopLevelInitFields(value, ["provider", "model", "name", "init", "clientRef", "fallbacks", "metadata"]) ?? {};
|
|
44
58
|
const fallbacks = Array.isArray(value.fallbacks)
|
|
45
59
|
? value.fallbacks
|
|
46
60
|
.map((item) => (typeof item === "object" && item && "ref" in item ? String(item.ref) : undefined))
|
|
@@ -59,9 +73,10 @@ export function parseModelObject(object) {
|
|
|
59
73
|
}
|
|
60
74
|
export function parseEmbeddingModelObject(object) {
|
|
61
75
|
const value = object.value;
|
|
76
|
+
assertNoInitBlock(value, "EmbeddingModel", object.id);
|
|
62
77
|
const provider = String(value.provider ?? "").trim();
|
|
63
78
|
const model = String((value.model ?? value.name) ?? "").trim();
|
|
64
|
-
const init =
|
|
79
|
+
const init = extractTopLevelInitFields(value, ["provider", "model", "name", "init", "clientRef", "metadata"]) ?? {};
|
|
65
80
|
return {
|
|
66
81
|
id: object.id,
|
|
67
82
|
provider,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@botbotgo/agent-harness",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.28",
|
|
4
4
|
"description": "Agent Harness framework package",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"packageManager": "npm@10.9.2",
|
|
@@ -29,7 +29,6 @@
|
|
|
29
29
|
}
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@modelcontextprotocol/sdk": "^1.12.0",
|
|
33
32
|
"@langchain/anthropic": "^1.1.0",
|
|
34
33
|
"@langchain/community": "^1.1.24",
|
|
35
34
|
"@langchain/core": "^1.1.33",
|
|
@@ -39,7 +38,8 @@
|
|
|
39
38
|
"@langchain/ollama": "^1.2.6",
|
|
40
39
|
"@langchain/openai": "^1.1.0",
|
|
41
40
|
"@libsql/client": "^0.17.0",
|
|
42
|
-
"@llamaindex/ollama": "^0.1.
|
|
41
|
+
"@llamaindex/ollama": "^0.1.23",
|
|
42
|
+
"@modelcontextprotocol/sdk": "^1.12.0",
|
|
43
43
|
"deepagents": "1.8.4",
|
|
44
44
|
"langchain": "1.2.34",
|
|
45
45
|
"llamaindex": "^0.12.1",
|
|
@@ -50,7 +50,8 @@
|
|
|
50
50
|
"scripts": {
|
|
51
51
|
"build": "rm -rf dist tsconfig.tsbuildinfo && tsc -p tsconfig.json && cp -R config dist/",
|
|
52
52
|
"check": "tsc -p tsconfig.json --noEmit",
|
|
53
|
-
"test": "vitest run test/public-api.test.ts test/resource-optional-provider.test.ts test/resource-isolation.test.ts test/stock-research-app-load-harness.test.ts test/release-workflow.test.ts test/release-version.test.ts test/gitignore.test.ts test/package-lock.test.ts test/readme.test.ts test/runtime-adapter-regressions.test.ts test/tool-extension-gaps.test.ts test/checkpoint-maintenance.test.ts",
|
|
53
|
+
"test": "vitest run test/public-api.test.ts test/resource-optional-provider.test.ts test/resource-isolation.test.ts test/stock-research-app-load-harness.test.ts test/stock-research-app-run.test.ts test/release-workflow.test.ts test/release-version.test.ts test/gitignore.test.ts test/package-lock.test.ts test/readme.test.ts test/runtime-adapter-regressions.test.ts test/tool-extension-gaps.test.ts test/checkpoint-maintenance.test.ts test/llamaindex-dependency-compat.test.ts",
|
|
54
|
+
"test:real-providers": "vitest run test/real-provider-harness.test.ts",
|
|
54
55
|
"release:prepare": "npm version patch --no-git-tag-version && node ./scripts/sync-example-version.mjs",
|
|
55
56
|
"release:pack": "npm pack --dry-run",
|
|
56
57
|
"release:publish": "npm publish --access public --registry https://registry.npmjs.org/"
|