@botbotgo/agent-harness 0.0.27 → 0.0.29
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/runtime/agent-runtime-adapter.d.ts +4 -4
- package/dist/runtime/agent-runtime-adapter.js +39 -11
- 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 +2 -1
|
@@ -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.28";
|
package/dist/package-version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const AGENT_HARNESS_VERSION = "0.0.
|
|
1
|
+
export const AGENT_HARNESS_VERSION = "0.0.28";
|
|
@@ -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,22 +9,50 @@ 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) {
|
|
15
16
|
return typeof value === "object" && value ? value : undefined;
|
|
16
17
|
}
|
|
18
|
+
function isPlaceholderApiKey(value) {
|
|
19
|
+
return typeof value === "string" && value.trim().toLowerCase() === "dummy";
|
|
20
|
+
}
|
|
21
|
+
function buildAuthOmittingFetch(baseFetch = fetch) {
|
|
22
|
+
return async (input, init) => {
|
|
23
|
+
const sanitizedHeaders = new Headers(input instanceof Request ? input.headers : undefined);
|
|
24
|
+
const initHeaders = new Headers(init?.headers);
|
|
25
|
+
initHeaders.forEach((value, key) => {
|
|
26
|
+
sanitizedHeaders.set(key, value);
|
|
27
|
+
});
|
|
28
|
+
sanitizedHeaders.delete("authorization");
|
|
29
|
+
if (input instanceof Request) {
|
|
30
|
+
return baseFetch(new Request(input, {
|
|
31
|
+
...init,
|
|
32
|
+
headers: sanitizedHeaders,
|
|
33
|
+
}));
|
|
34
|
+
}
|
|
35
|
+
return baseFetch(input, {
|
|
36
|
+
...init,
|
|
37
|
+
headers: sanitizedHeaders,
|
|
38
|
+
});
|
|
39
|
+
};
|
|
40
|
+
}
|
|
17
41
|
function normalizeOpenAICompatibleInit(init) {
|
|
18
42
|
const normalized = { ...init };
|
|
19
43
|
const configuration = asObject(init.configuration) ?? {};
|
|
20
44
|
const baseUrl = typeof init.baseUrl === "string" && init.baseUrl.trim() ? init.baseUrl.trim() : undefined;
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
45
|
+
const omitAuthHeader = init.omitAuthHeader === true || isPlaceholderApiKey(init.apiKey);
|
|
46
|
+
const nextConfiguration = { ...configuration };
|
|
47
|
+
if (baseUrl && typeof nextConfiguration.baseURL !== "string") {
|
|
48
|
+
nextConfiguration.baseURL = baseUrl;
|
|
49
|
+
}
|
|
50
|
+
if (omitAuthHeader) {
|
|
51
|
+
nextConfiguration.fetch = buildAuthOmittingFetch(typeof configuration.fetch === "function" ? configuration.fetch : fetch);
|
|
26
52
|
}
|
|
53
|
+
normalized.configuration = nextConfiguration;
|
|
27
54
|
delete normalized.baseUrl;
|
|
55
|
+
delete normalized.omitAuthHeader;
|
|
28
56
|
return normalized;
|
|
29
57
|
}
|
|
30
58
|
function sanitizeToolNameForModel(name) {
|
|
@@ -172,7 +200,7 @@ export class AgentRuntimeAdapter {
|
|
|
172
200
|
},
|
|
173
201
|
{
|
|
174
202
|
role: "user",
|
|
175
|
-
content: `Original user request:\n${input}\n\nTool results:\n${toolContext}`,
|
|
203
|
+
content: `Original user request:\n${extractMessageText(input)}\n\nTool results:\n${toolContext}`,
|
|
176
204
|
},
|
|
177
205
|
]);
|
|
178
206
|
return sanitizeVisibleText(extractVisibleOutput(synthesized));
|
|
@@ -181,8 +209,8 @@ export class AgentRuntimeAdapter {
|
|
|
181
209
|
if (this.options.modelResolver) {
|
|
182
210
|
return wrapResolvedModel(await this.options.modelResolver(model.id));
|
|
183
211
|
}
|
|
184
|
-
if (model.provider === "ollama"
|
|
185
|
-
return wrapResolvedModel(new ChatOllama({ model: model.model,
|
|
212
|
+
if (model.provider === "ollama") {
|
|
213
|
+
return wrapResolvedModel(new ChatOllama({ model: model.model, ...model.init }));
|
|
186
214
|
}
|
|
187
215
|
if (model.provider === "openai-compatible") {
|
|
188
216
|
return wrapResolvedModel(new ChatOpenAI({ model: model.model, ...normalizeOpenAICompatibleInit(model.init) }));
|
|
@@ -203,8 +231,8 @@ export class AgentRuntimeAdapter {
|
|
|
203
231
|
}
|
|
204
232
|
buildAgentMessages(history, input) {
|
|
205
233
|
return [
|
|
206
|
-
...history.map((item) => ({ role: item.role, content: item.content })),
|
|
207
|
-
{ role: "user", content: input },
|
|
234
|
+
...history.map((item) => ({ role: item.role, content: normalizeMessageContent(item.content) })),
|
|
235
|
+
{ role: "user", content: normalizeMessageContent(input) },
|
|
208
236
|
];
|
|
209
237
|
}
|
|
210
238
|
buildRawModelMessages(systemPrompt, history, input) {
|
|
@@ -374,7 +402,7 @@ export class AgentRuntimeAdapter {
|
|
|
374
402
|
role: "system",
|
|
375
403
|
content: this.buildRouteSystemPrompt(primaryBinding, secondaryBinding, options.systemPrompt),
|
|
376
404
|
},
|
|
377
|
-
{ role: "user", content: input },
|
|
405
|
+
{ role: "user", content: extractMessageText(input) },
|
|
378
406
|
]);
|
|
379
407
|
const content = typeof result === "string"
|
|
380
408
|
? 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.29",
|
|
4
4
|
"description": "Agent Harness framework package",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"packageManager": "npm@10.9.2",
|
|
@@ -51,6 +51,7 @@
|
|
|
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
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/"
|