@open-multi-agent/core 1.4.0
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/LICENSE +21 -0
- package/README.md +373 -0
- package/dist/agent/agent.d.ts +153 -0
- package/dist/agent/agent.d.ts.map +1 -0
- package/dist/agent/agent.js +559 -0
- package/dist/agent/agent.js.map +1 -0
- package/dist/agent/loop-detector.d.ts +39 -0
- package/dist/agent/loop-detector.d.ts.map +1 -0
- package/dist/agent/loop-detector.js +122 -0
- package/dist/agent/loop-detector.js.map +1 -0
- package/dist/agent/pool.d.ts +158 -0
- package/dist/agent/pool.d.ts.map +1 -0
- package/dist/agent/pool.js +320 -0
- package/dist/agent/pool.js.map +1 -0
- package/dist/agent/runner.d.ts +242 -0
- package/dist/agent/runner.d.ts.map +1 -0
- package/dist/agent/runner.js +943 -0
- package/dist/agent/runner.js.map +1 -0
- package/dist/agent/structured-output.d.ts +33 -0
- package/dist/agent/structured-output.d.ts.map +1 -0
- package/dist/agent/structured-output.js +116 -0
- package/dist/agent/structured-output.js.map +1 -0
- package/dist/cli/oma.d.ts +30 -0
- package/dist/cli/oma.d.ts.map +1 -0
- package/dist/cli/oma.js +433 -0
- package/dist/cli/oma.js.map +1 -0
- package/dist/dashboard/layout-tasks.d.ts +23 -0
- package/dist/dashboard/layout-tasks.d.ts.map +1 -0
- package/dist/dashboard/layout-tasks.js +79 -0
- package/dist/dashboard/layout-tasks.js.map +1 -0
- package/dist/dashboard/render-team-run-dashboard.d.ts +11 -0
- package/dist/dashboard/render-team-run-dashboard.d.ts.map +1 -0
- package/dist/dashboard/render-team-run-dashboard.js +456 -0
- package/dist/dashboard/render-team-run-dashboard.js.map +1 -0
- package/dist/errors.d.ts +14 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +20 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +79 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +92 -0
- package/dist/index.js.map +1 -0
- package/dist/llm/adapter.d.ts +54 -0
- package/dist/llm/adapter.d.ts.map +1 -0
- package/dist/llm/adapter.js +101 -0
- package/dist/llm/adapter.js.map +1 -0
- package/dist/llm/anthropic.d.ts +57 -0
- package/dist/llm/anthropic.d.ts.map +1 -0
- package/dist/llm/anthropic.js +432 -0
- package/dist/llm/anthropic.js.map +1 -0
- package/dist/llm/azure-openai.d.ts +74 -0
- package/dist/llm/azure-openai.d.ts.map +1 -0
- package/dist/llm/azure-openai.js +267 -0
- package/dist/llm/azure-openai.js.map +1 -0
- package/dist/llm/bedrock.d.ts +41 -0
- package/dist/llm/bedrock.d.ts.map +1 -0
- package/dist/llm/bedrock.js +345 -0
- package/dist/llm/bedrock.js.map +1 -0
- package/dist/llm/copilot.d.ts +92 -0
- package/dist/llm/copilot.d.ts.map +1 -0
- package/dist/llm/copilot.js +433 -0
- package/dist/llm/copilot.js.map +1 -0
- package/dist/llm/deepseek.d.ts +21 -0
- package/dist/llm/deepseek.d.ts.map +1 -0
- package/dist/llm/deepseek.js +24 -0
- package/dist/llm/deepseek.js.map +1 -0
- package/dist/llm/gemini.d.ts +65 -0
- package/dist/llm/gemini.d.ts.map +1 -0
- package/dist/llm/gemini.js +427 -0
- package/dist/llm/gemini.js.map +1 -0
- package/dist/llm/grok.d.ts +21 -0
- package/dist/llm/grok.d.ts.map +1 -0
- package/dist/llm/grok.js +24 -0
- package/dist/llm/grok.js.map +1 -0
- package/dist/llm/minimax.d.ts +21 -0
- package/dist/llm/minimax.d.ts.map +1 -0
- package/dist/llm/minimax.js +24 -0
- package/dist/llm/minimax.js.map +1 -0
- package/dist/llm/openai-common.d.ts +65 -0
- package/dist/llm/openai-common.d.ts.map +1 -0
- package/dist/llm/openai-common.js +286 -0
- package/dist/llm/openai-common.js.map +1 -0
- package/dist/llm/openai.d.ts +63 -0
- package/dist/llm/openai.d.ts.map +1 -0
- package/dist/llm/openai.js +256 -0
- package/dist/llm/openai.js.map +1 -0
- package/dist/llm/qiniu.d.ts +21 -0
- package/dist/llm/qiniu.d.ts.map +1 -0
- package/dist/llm/qiniu.js +24 -0
- package/dist/llm/qiniu.js.map +1 -0
- package/dist/mcp.d.ts +3 -0
- package/dist/mcp.d.ts.map +1 -0
- package/dist/mcp.js +2 -0
- package/dist/mcp.js.map +1 -0
- package/dist/memory/shared.d.ts +162 -0
- package/dist/memory/shared.d.ts.map +1 -0
- package/dist/memory/shared.js +294 -0
- package/dist/memory/shared.js.map +1 -0
- package/dist/memory/store.d.ts +72 -0
- package/dist/memory/store.d.ts.map +1 -0
- package/dist/memory/store.js +121 -0
- package/dist/memory/store.js.map +1 -0
- package/dist/orchestrator/orchestrator.d.ts +245 -0
- package/dist/orchestrator/orchestrator.d.ts.map +1 -0
- package/dist/orchestrator/orchestrator.js +1400 -0
- package/dist/orchestrator/orchestrator.js.map +1 -0
- package/dist/orchestrator/scheduler.d.ts +112 -0
- package/dist/orchestrator/scheduler.d.ts.map +1 -0
- package/dist/orchestrator/scheduler.js +256 -0
- package/dist/orchestrator/scheduler.js.map +1 -0
- package/dist/task/queue.d.ts +191 -0
- package/dist/task/queue.d.ts.map +1 -0
- package/dist/task/queue.js +408 -0
- package/dist/task/queue.js.map +1 -0
- package/dist/task/task.d.ts +90 -0
- package/dist/task/task.d.ts.map +1 -0
- package/dist/task/task.js +206 -0
- package/dist/task/task.js.map +1 -0
- package/dist/team/messaging.d.ts +106 -0
- package/dist/team/messaging.d.ts.map +1 -0
- package/dist/team/messaging.js +183 -0
- package/dist/team/messaging.js.map +1 -0
- package/dist/team/team.d.ts +141 -0
- package/dist/team/team.d.ts.map +1 -0
- package/dist/team/team.js +293 -0
- package/dist/team/team.js.map +1 -0
- package/dist/tool/built-in/bash.d.ts +12 -0
- package/dist/tool/built-in/bash.d.ts.map +1 -0
- package/dist/tool/built-in/bash.js +133 -0
- package/dist/tool/built-in/bash.js.map +1 -0
- package/dist/tool/built-in/delegate.d.ts +29 -0
- package/dist/tool/built-in/delegate.d.ts.map +1 -0
- package/dist/tool/built-in/delegate.js +92 -0
- package/dist/tool/built-in/delegate.js.map +1 -0
- package/dist/tool/built-in/file-edit.d.ts +14 -0
- package/dist/tool/built-in/file-edit.d.ts.map +1 -0
- package/dist/tool/built-in/file-edit.js +130 -0
- package/dist/tool/built-in/file-edit.js.map +1 -0
- package/dist/tool/built-in/file-read.d.ts +12 -0
- package/dist/tool/built-in/file-read.d.ts.map +1 -0
- package/dist/tool/built-in/file-read.js +82 -0
- package/dist/tool/built-in/file-read.js.map +1 -0
- package/dist/tool/built-in/file-write.d.ts +11 -0
- package/dist/tool/built-in/file-write.d.ts.map +1 -0
- package/dist/tool/built-in/file-write.js +70 -0
- package/dist/tool/built-in/file-write.js.map +1 -0
- package/dist/tool/built-in/fs-walk.d.ts +23 -0
- package/dist/tool/built-in/fs-walk.d.ts.map +1 -0
- package/dist/tool/built-in/fs-walk.js +78 -0
- package/dist/tool/built-in/fs-walk.js.map +1 -0
- package/dist/tool/built-in/glob.d.ts +12 -0
- package/dist/tool/built-in/glob.d.ts.map +1 -0
- package/dist/tool/built-in/glob.js +82 -0
- package/dist/tool/built-in/glob.js.map +1 -0
- package/dist/tool/built-in/grep.d.ts +15 -0
- package/dist/tool/built-in/grep.d.ts.map +1 -0
- package/dist/tool/built-in/grep.js +218 -0
- package/dist/tool/built-in/grep.js.map +1 -0
- package/dist/tool/built-in/index.d.ts +48 -0
- package/dist/tool/built-in/index.d.ts.map +1 -0
- package/dist/tool/built-in/index.js +56 -0
- package/dist/tool/built-in/index.js.map +1 -0
- package/dist/tool/executor.d.ts +100 -0
- package/dist/tool/executor.d.ts.map +1 -0
- package/dist/tool/executor.js +184 -0
- package/dist/tool/executor.js.map +1 -0
- package/dist/tool/framework.d.ts +167 -0
- package/dist/tool/framework.d.ts.map +1 -0
- package/dist/tool/framework.js +402 -0
- package/dist/tool/framework.js.map +1 -0
- package/dist/tool/mcp.d.ts +31 -0
- package/dist/tool/mcp.d.ts.map +1 -0
- package/dist/tool/mcp.js +175 -0
- package/dist/tool/mcp.js.map +1 -0
- package/dist/tool/text-tool-extractor.d.ts +32 -0
- package/dist/tool/text-tool-extractor.d.ts.map +1 -0
- package/dist/tool/text-tool-extractor.js +195 -0
- package/dist/tool/text-tool-extractor.js.map +1 -0
- package/dist/types.d.ts +916 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +8 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/keywords.d.ts +18 -0
- package/dist/utils/keywords.d.ts.map +1 -0
- package/dist/utils/keywords.js +32 -0
- package/dist/utils/keywords.js.map +1 -0
- package/dist/utils/semaphore.d.ts +49 -0
- package/dist/utils/semaphore.d.ts.map +1 -0
- package/dist/utils/semaphore.js +89 -0
- package/dist/utils/semaphore.js.map +1 -0
- package/dist/utils/tokens.d.ts +7 -0
- package/dist/utils/tokens.d.ts.map +1 -0
- package/dist/utils/tokens.js +30 -0
- package/dist/utils/tokens.js.map +1 -0
- package/dist/utils/trace.d.ts +12 -0
- package/dist/utils/trace.d.ts.map +1 -0
- package/dist/utils/trace.js +30 -0
- package/dist/utils/trace.js.map +1 -0
- package/docs/DECISIONS.md +49 -0
- package/docs/cli.md +265 -0
- package/docs/context-management.md +24 -0
- package/docs/featured-partner.md +28 -0
- package/docs/observability.md +56 -0
- package/docs/providers.md +78 -0
- package/docs/shared-memory.md +27 -0
- package/docs/tool-configuration.md +152 -0
- package/package.json +96 -0
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Shared OpenAI wire-format conversion helpers.
|
|
3
|
+
*
|
|
4
|
+
* Both the OpenAI and Copilot adapters use the OpenAI Chat Completions API
|
|
5
|
+
* format. This module contains the common conversion logic so it isn't
|
|
6
|
+
* duplicated across adapters.
|
|
7
|
+
*/
|
|
8
|
+
import type { ChatCompletion, ChatCompletionMessageParam, ChatCompletionTool } from 'openai/resources/chat/completions/index.js';
|
|
9
|
+
import type { LLMMessage, LLMResponse, LLMToolDef } from '../types.js';
|
|
10
|
+
/**
|
|
11
|
+
* Convert a framework {@link LLMToolDef} to an OpenAI {@link ChatCompletionTool}.
|
|
12
|
+
*/
|
|
13
|
+
export declare function toOpenAITool(tool: LLMToolDef): ChatCompletionTool;
|
|
14
|
+
export declare function getOpenAIReasoningText(source: unknown): string;
|
|
15
|
+
/**
|
|
16
|
+
* Convert framework {@link LLMMessage}s into OpenAI
|
|
17
|
+
* {@link ChatCompletionMessageParam} entries.
|
|
18
|
+
*
|
|
19
|
+
* `tool_result` blocks are expanded into top-level `tool`-role messages
|
|
20
|
+
* because OpenAI uses a dedicated role for tool results rather than embedding
|
|
21
|
+
* them inside user-content arrays.
|
|
22
|
+
*
|
|
23
|
+
* For mixed user messages (tool_result + text/image), the tool messages are
|
|
24
|
+
* emitted FIRST so they sit immediately after the assistant's `tool_calls`.
|
|
25
|
+
* The OpenAI Chat Completions API requires every assistant `tool_calls` block
|
|
26
|
+
* to be answered by tool-role messages before any subsequent user-role
|
|
27
|
+
* message; inserting a user message between them produces a 400 error
|
|
28
|
+
* ("messages with role 'tool' must be a response to a preceding message
|
|
29
|
+
* with 'tool_calls'"). This path is exercised in practice by the agent
|
|
30
|
+
* runner's loop-detection warning injection (see {@link AgentRunner}, which
|
|
31
|
+
* appends a text warning to a tool_result message when a loop is detected).
|
|
32
|
+
*/
|
|
33
|
+
export declare function toOpenAIMessages(messages: LLMMessage[]): ChatCompletionMessageParam[];
|
|
34
|
+
/**
|
|
35
|
+
* Convert an OpenAI {@link ChatCompletion} into a framework {@link LLMResponse}.
|
|
36
|
+
*
|
|
37
|
+
* Takes only the first choice (index 0), consistent with how the framework
|
|
38
|
+
* is designed for single-output agents.
|
|
39
|
+
*
|
|
40
|
+
* @param completion - The raw OpenAI completion.
|
|
41
|
+
* @param knownToolNames - Optional whitelist of tool names. When the model
|
|
42
|
+
* returns no `tool_calls` but the text contains JSON
|
|
43
|
+
* that looks like a tool call, the fallback extractor
|
|
44
|
+
* uses this list to validate matches. Pass the names
|
|
45
|
+
* of tools sent in the request for best results.
|
|
46
|
+
*/
|
|
47
|
+
export declare function fromOpenAICompletion(completion: ChatCompletion, knownToolNames?: string[]): LLMResponse;
|
|
48
|
+
/**
|
|
49
|
+
* Normalize an OpenAI `finish_reason` string to the framework's canonical
|
|
50
|
+
* stop-reason vocabulary.
|
|
51
|
+
*
|
|
52
|
+
* Mapping:
|
|
53
|
+
* - `'stop'` → `'end_turn'`
|
|
54
|
+
* - `'tool_calls'` → `'tool_use'`
|
|
55
|
+
* - `'length'` → `'max_tokens'`
|
|
56
|
+
* - `'content_filter'` → `'content_filter'`
|
|
57
|
+
* - anything else → passed through unchanged
|
|
58
|
+
*/
|
|
59
|
+
export declare function normalizeFinishReason(reason: string): string;
|
|
60
|
+
/**
|
|
61
|
+
* Prepend a system message when `systemPrompt` is provided, then append the
|
|
62
|
+
* converted conversation messages.
|
|
63
|
+
*/
|
|
64
|
+
export declare function buildOpenAIMessageList(messages: LLMMessage[], systemPrompt: string | undefined): ChatCompletionMessageParam[];
|
|
65
|
+
//# sourceMappingURL=openai-common.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openai-common.d.ts","sourceRoot":"","sources":["../../src/llm/openai-common.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EACV,cAAc,EAEd,0BAA0B,EAE1B,kBAAkB,EAGnB,MAAM,4CAA4C,CAAA;AAEnD,OAAO,KAAK,EAEV,UAAU,EACV,WAAW,EACX,UAAU,EAIX,MAAM,aAAa,CAAA;AAOpB;;GAEG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,UAAU,GAAG,kBAAkB,CASjE;AAuBD,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,CAG9D;AAUD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,UAAU,EAAE,GAAG,0BAA0B,EAAE,CAgCrF;AAsED;;;;;;;;;;;;GAYG;AACH,wBAAgB,oBAAoB,CAClC,UAAU,EAAE,cAAc,EAC1B,cAAc,CAAC,EAAE,MAAM,EAAE,GACxB,WAAW,CAgFb;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAQ5D;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,UAAU,EAAE,EACtB,YAAY,EAAE,MAAM,GAAG,SAAS,GAC/B,0BAA0B,EAAE,CAS9B"}
|
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Shared OpenAI wire-format conversion helpers.
|
|
3
|
+
*
|
|
4
|
+
* Both the OpenAI and Copilot adapters use the OpenAI Chat Completions API
|
|
5
|
+
* format. This module contains the common conversion logic so it isn't
|
|
6
|
+
* duplicated across adapters.
|
|
7
|
+
*/
|
|
8
|
+
import { extractToolCallsFromText } from '../tool/text-tool-extractor.js';
|
|
9
|
+
// ---------------------------------------------------------------------------
|
|
10
|
+
// Framework → OpenAI
|
|
11
|
+
// ---------------------------------------------------------------------------
|
|
12
|
+
/**
|
|
13
|
+
* Convert a framework {@link LLMToolDef} to an OpenAI {@link ChatCompletionTool}.
|
|
14
|
+
*/
|
|
15
|
+
export function toOpenAITool(tool) {
|
|
16
|
+
return {
|
|
17
|
+
type: 'function',
|
|
18
|
+
function: {
|
|
19
|
+
name: tool.name,
|
|
20
|
+
description: tool.description,
|
|
21
|
+
parameters: tool.inputSchema,
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
function extractReasoningText(value) {
|
|
26
|
+
if (typeof value === 'string')
|
|
27
|
+
return value;
|
|
28
|
+
if (Array.isArray(value)) {
|
|
29
|
+
return value
|
|
30
|
+
.map((part) => {
|
|
31
|
+
if (typeof part === 'string')
|
|
32
|
+
return part;
|
|
33
|
+
if (part === null || typeof part !== 'object')
|
|
34
|
+
return '';
|
|
35
|
+
const record = part;
|
|
36
|
+
if (typeof record['text'] === 'string')
|
|
37
|
+
return record['text'];
|
|
38
|
+
if (typeof record['content'] === 'string')
|
|
39
|
+
return record['content'];
|
|
40
|
+
if (typeof record['reasoning_content'] === 'string')
|
|
41
|
+
return record['reasoning_content'];
|
|
42
|
+
return '';
|
|
43
|
+
})
|
|
44
|
+
.join('');
|
|
45
|
+
}
|
|
46
|
+
return '';
|
|
47
|
+
}
|
|
48
|
+
export function getOpenAIReasoningText(source) {
|
|
49
|
+
if (source === null || typeof source !== 'object')
|
|
50
|
+
return '';
|
|
51
|
+
return extractReasoningText(source['reasoning_content']);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Determine whether a framework message contains any `tool_result` content
|
|
55
|
+
* blocks, which must be serialised as separate OpenAI `tool`-role messages.
|
|
56
|
+
*/
|
|
57
|
+
function hasToolResults(msg) {
|
|
58
|
+
return msg.content.some((b) => b.type === 'tool_result');
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Convert framework {@link LLMMessage}s into OpenAI
|
|
62
|
+
* {@link ChatCompletionMessageParam} entries.
|
|
63
|
+
*
|
|
64
|
+
* `tool_result` blocks are expanded into top-level `tool`-role messages
|
|
65
|
+
* because OpenAI uses a dedicated role for tool results rather than embedding
|
|
66
|
+
* them inside user-content arrays.
|
|
67
|
+
*
|
|
68
|
+
* For mixed user messages (tool_result + text/image), the tool messages are
|
|
69
|
+
* emitted FIRST so they sit immediately after the assistant's `tool_calls`.
|
|
70
|
+
* The OpenAI Chat Completions API requires every assistant `tool_calls` block
|
|
71
|
+
* to be answered by tool-role messages before any subsequent user-role
|
|
72
|
+
* message; inserting a user message between them produces a 400 error
|
|
73
|
+
* ("messages with role 'tool' must be a response to a preceding message
|
|
74
|
+
* with 'tool_calls'"). This path is exercised in practice by the agent
|
|
75
|
+
* runner's loop-detection warning injection (see {@link AgentRunner}, which
|
|
76
|
+
* appends a text warning to a tool_result message when a loop is detected).
|
|
77
|
+
*/
|
|
78
|
+
export function toOpenAIMessages(messages) {
|
|
79
|
+
const result = [];
|
|
80
|
+
for (const msg of messages) {
|
|
81
|
+
if (msg.role === 'assistant') {
|
|
82
|
+
result.push(toOpenAIAssistantMessage(msg));
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
// user role
|
|
86
|
+
if (!hasToolResults(msg)) {
|
|
87
|
+
result.push(toOpenAIUserMessage(msg));
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
// Emit tool messages first to satisfy OpenAI's strict ordering rule.
|
|
91
|
+
for (const block of msg.content) {
|
|
92
|
+
if (block.type === 'tool_result') {
|
|
93
|
+
const toolMsg = {
|
|
94
|
+
role: 'tool',
|
|
95
|
+
tool_call_id: block.tool_use_id,
|
|
96
|
+
content: block.content,
|
|
97
|
+
};
|
|
98
|
+
result.push(toolMsg);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
const nonToolBlocks = msg.content.filter((b) => b.type !== 'tool_result');
|
|
102
|
+
if (nonToolBlocks.length > 0) {
|
|
103
|
+
result.push(toOpenAIUserMessage({ role: 'user', content: nonToolBlocks }));
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return result;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Convert a `user`-role framework message into an OpenAI user message.
|
|
112
|
+
* Image blocks are converted to the OpenAI image_url content part format.
|
|
113
|
+
*/
|
|
114
|
+
function toOpenAIUserMessage(msg) {
|
|
115
|
+
if (msg.content.length === 1 && msg.content[0]?.type === 'text') {
|
|
116
|
+
return { role: 'user', content: msg.content[0].text };
|
|
117
|
+
}
|
|
118
|
+
const parts = [];
|
|
119
|
+
for (const block of msg.content) {
|
|
120
|
+
if (block.type === 'text') {
|
|
121
|
+
parts.push({ type: 'text', text: block.text });
|
|
122
|
+
}
|
|
123
|
+
else if (block.type === 'image') {
|
|
124
|
+
parts.push({
|
|
125
|
+
type: 'image_url',
|
|
126
|
+
image_url: {
|
|
127
|
+
url: `data:${block.source.media_type};base64,${block.source.data}`,
|
|
128
|
+
},
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
// tool_result blocks are handled by the caller (toOpenAIMessages); skip here.
|
|
132
|
+
}
|
|
133
|
+
return { role: 'user', content: parts };
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Convert an `assistant`-role framework message into an OpenAI assistant message.
|
|
137
|
+
* `tool_use` blocks become `tool_calls`; `text` blocks become message content.
|
|
138
|
+
*/
|
|
139
|
+
function toOpenAIAssistantMessage(msg) {
|
|
140
|
+
const toolCalls = [];
|
|
141
|
+
const textParts = [];
|
|
142
|
+
for (const block of msg.content) {
|
|
143
|
+
if (block.type === 'tool_use') {
|
|
144
|
+
toolCalls.push({
|
|
145
|
+
id: block.id,
|
|
146
|
+
type: 'function',
|
|
147
|
+
function: {
|
|
148
|
+
name: block.name,
|
|
149
|
+
arguments: JSON.stringify(block.input),
|
|
150
|
+
},
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
else if (block.type === 'text') {
|
|
154
|
+
textParts.push(block.text);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
const assistantMsg = {
|
|
158
|
+
role: 'assistant',
|
|
159
|
+
content: textParts.length > 0 ? textParts.join('') : null,
|
|
160
|
+
};
|
|
161
|
+
if (toolCalls.length > 0) {
|
|
162
|
+
assistantMsg.tool_calls = toolCalls;
|
|
163
|
+
}
|
|
164
|
+
return assistantMsg;
|
|
165
|
+
}
|
|
166
|
+
// ---------------------------------------------------------------------------
|
|
167
|
+
// OpenAI → Framework
|
|
168
|
+
// ---------------------------------------------------------------------------
|
|
169
|
+
/**
|
|
170
|
+
* Convert an OpenAI {@link ChatCompletion} into a framework {@link LLMResponse}.
|
|
171
|
+
*
|
|
172
|
+
* Takes only the first choice (index 0), consistent with how the framework
|
|
173
|
+
* is designed for single-output agents.
|
|
174
|
+
*
|
|
175
|
+
* @param completion - The raw OpenAI completion.
|
|
176
|
+
* @param knownToolNames - Optional whitelist of tool names. When the model
|
|
177
|
+
* returns no `tool_calls` but the text contains JSON
|
|
178
|
+
* that looks like a tool call, the fallback extractor
|
|
179
|
+
* uses this list to validate matches. Pass the names
|
|
180
|
+
* of tools sent in the request for best results.
|
|
181
|
+
*/
|
|
182
|
+
export function fromOpenAICompletion(completion, knownToolNames) {
|
|
183
|
+
const choice = completion.choices[0];
|
|
184
|
+
if (choice === undefined) {
|
|
185
|
+
throw new Error('OpenAI returned a completion with no choices');
|
|
186
|
+
}
|
|
187
|
+
const content = [];
|
|
188
|
+
const message = choice.message;
|
|
189
|
+
const reasoningText = getOpenAIReasoningText(message);
|
|
190
|
+
if (reasoningText.length > 0) {
|
|
191
|
+
const reasoningBlock = { type: 'reasoning', text: reasoningText };
|
|
192
|
+
content.push(reasoningBlock);
|
|
193
|
+
}
|
|
194
|
+
if (message.content !== null && message.content !== undefined) {
|
|
195
|
+
const textBlock = { type: 'text', text: message.content };
|
|
196
|
+
content.push(textBlock);
|
|
197
|
+
}
|
|
198
|
+
for (const toolCall of message.tool_calls ?? []) {
|
|
199
|
+
let parsedInput = {};
|
|
200
|
+
try {
|
|
201
|
+
const parsed = JSON.parse(toolCall.function.arguments);
|
|
202
|
+
if (parsed !== null && typeof parsed === 'object' && !Array.isArray(parsed)) {
|
|
203
|
+
parsedInput = parsed;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
catch {
|
|
207
|
+
// Malformed arguments from the model — surface as empty object.
|
|
208
|
+
}
|
|
209
|
+
const toolUseBlock = {
|
|
210
|
+
type: 'tool_use',
|
|
211
|
+
id: toolCall.id,
|
|
212
|
+
name: toolCall.function.name,
|
|
213
|
+
input: parsedInput,
|
|
214
|
+
};
|
|
215
|
+
content.push(toolUseBlock);
|
|
216
|
+
}
|
|
217
|
+
// ---------------------------------------------------------------------------
|
|
218
|
+
// Fallback: extract tool calls from text when native tool_calls is empty.
|
|
219
|
+
//
|
|
220
|
+
// Some local models (Ollama thinking models, misconfigured vLLM) return tool
|
|
221
|
+
// calls as plain text instead of using the tool_calls wire format. When we
|
|
222
|
+
// have text but no tool_calls, try to extract them from the text.
|
|
223
|
+
// ---------------------------------------------------------------------------
|
|
224
|
+
const hasNativeToolCalls = (message.tool_calls ?? []).length > 0;
|
|
225
|
+
if (!hasNativeToolCalls &&
|
|
226
|
+
knownToolNames !== undefined &&
|
|
227
|
+
knownToolNames.length > 0 &&
|
|
228
|
+
message.content !== null &&
|
|
229
|
+
message.content !== undefined &&
|
|
230
|
+
message.content.length > 0) {
|
|
231
|
+
const extracted = extractToolCallsFromText(message.content, knownToolNames);
|
|
232
|
+
if (extracted.length > 0) {
|
|
233
|
+
content.push(...extracted);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
const hasToolUseBlocks = content.some(b => b.type === 'tool_use');
|
|
237
|
+
const rawStopReason = choice.finish_reason ?? 'stop';
|
|
238
|
+
// If we extracted tool calls from text but the finish_reason was 'stop',
|
|
239
|
+
// correct it to 'tool_use' so the agent runner continues the loop.
|
|
240
|
+
const stopReason = hasToolUseBlocks && rawStopReason === 'stop'
|
|
241
|
+
? 'tool_use'
|
|
242
|
+
: normalizeFinishReason(rawStopReason);
|
|
243
|
+
return {
|
|
244
|
+
id: completion.id,
|
|
245
|
+
content,
|
|
246
|
+
model: completion.model,
|
|
247
|
+
stop_reason: stopReason,
|
|
248
|
+
usage: {
|
|
249
|
+
input_tokens: completion.usage?.prompt_tokens ?? 0,
|
|
250
|
+
output_tokens: completion.usage?.completion_tokens ?? 0,
|
|
251
|
+
},
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Normalize an OpenAI `finish_reason` string to the framework's canonical
|
|
256
|
+
* stop-reason vocabulary.
|
|
257
|
+
*
|
|
258
|
+
* Mapping:
|
|
259
|
+
* - `'stop'` → `'end_turn'`
|
|
260
|
+
* - `'tool_calls'` → `'tool_use'`
|
|
261
|
+
* - `'length'` → `'max_tokens'`
|
|
262
|
+
* - `'content_filter'` → `'content_filter'`
|
|
263
|
+
* - anything else → passed through unchanged
|
|
264
|
+
*/
|
|
265
|
+
export function normalizeFinishReason(reason) {
|
|
266
|
+
switch (reason) {
|
|
267
|
+
case 'stop': return 'end_turn';
|
|
268
|
+
case 'tool_calls': return 'tool_use';
|
|
269
|
+
case 'length': return 'max_tokens';
|
|
270
|
+
case 'content_filter': return 'content_filter';
|
|
271
|
+
default: return reason;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Prepend a system message when `systemPrompt` is provided, then append the
|
|
276
|
+
* converted conversation messages.
|
|
277
|
+
*/
|
|
278
|
+
export function buildOpenAIMessageList(messages, systemPrompt) {
|
|
279
|
+
const result = [];
|
|
280
|
+
if (systemPrompt !== undefined && systemPrompt.length > 0) {
|
|
281
|
+
result.push({ role: 'system', content: systemPrompt });
|
|
282
|
+
}
|
|
283
|
+
result.push(...toOpenAIMessages(messages));
|
|
284
|
+
return result;
|
|
285
|
+
}
|
|
286
|
+
//# sourceMappingURL=openai-common.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openai-common.js","sourceRoot":"","sources":["../../src/llm/openai-common.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview OpenAI adapter implementing {@link LLMAdapter}.
|
|
3
|
+
*
|
|
4
|
+
* Converts between the framework's internal {@link ContentBlock} types and the
|
|
5
|
+
* OpenAI Chat Completions wire format. Key mapping decisions:
|
|
6
|
+
*
|
|
7
|
+
* - Framework `tool_use` blocks in assistant messages → OpenAI `tool_calls`
|
|
8
|
+
* - Framework `tool_result` blocks in user messages → OpenAI `tool` role messages
|
|
9
|
+
* - Framework `image` blocks in user messages → OpenAI image content parts
|
|
10
|
+
* - System prompt in {@link LLMChatOptions} → prepended `system` message
|
|
11
|
+
*
|
|
12
|
+
* Because OpenAI and Anthropic use fundamentally different role-based structures
|
|
13
|
+
* for tool calling (Anthropic embeds tool results in user-role content arrays;
|
|
14
|
+
* OpenAI uses a dedicated `tool` role), the conversion necessarily splits
|
|
15
|
+
* `tool_result` blocks out into separate top-level messages.
|
|
16
|
+
*
|
|
17
|
+
* API key resolution order:
|
|
18
|
+
* 1. `apiKey` constructor argument
|
|
19
|
+
* 2. `OPENAI_API_KEY` environment variable
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```ts
|
|
23
|
+
* import { OpenAIAdapter } from './openai.js'
|
|
24
|
+
*
|
|
25
|
+
* const adapter = new OpenAIAdapter()
|
|
26
|
+
* const response = await adapter.chat(messages, {
|
|
27
|
+
* model: 'gpt-5.4',
|
|
28
|
+
* maxTokens: 1024,
|
|
29
|
+
* })
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
import type { ContentBlock, LLMAdapter, LLMChatOptions, LLMMessage, LLMResponse, LLMStreamOptions, LLMToolDef, StreamEvent } from '../types.js';
|
|
33
|
+
/**
|
|
34
|
+
* LLM adapter backed by the OpenAI Chat Completions API.
|
|
35
|
+
*
|
|
36
|
+
* Thread-safe — a single instance may be shared across concurrent agent runs.
|
|
37
|
+
*/
|
|
38
|
+
export declare class OpenAIAdapter implements LLMAdapter {
|
|
39
|
+
#private;
|
|
40
|
+
readonly name: string;
|
|
41
|
+
constructor(apiKey?: string, baseURL?: string);
|
|
42
|
+
/**
|
|
43
|
+
* Send a synchronous (non-streaming) chat request and return the complete
|
|
44
|
+
* {@link LLMResponse}.
|
|
45
|
+
*
|
|
46
|
+
* Throws an `OpenAI.APIError` on non-2xx responses. Callers should catch and
|
|
47
|
+
* handle these (e.g. rate limits, context length exceeded).
|
|
48
|
+
*/
|
|
49
|
+
chat(messages: LLMMessage[], options: LLMChatOptions): Promise<LLMResponse>;
|
|
50
|
+
/**
|
|
51
|
+
* Send a streaming chat request and yield {@link StreamEvent}s incrementally.
|
|
52
|
+
*
|
|
53
|
+
* Sequence guarantees match {@link AnthropicAdapter.stream}:
|
|
54
|
+
* - Zero or more `text` events
|
|
55
|
+
* - Zero or more `reasoning` events
|
|
56
|
+
* - Zero or more `tool_use` events (emitted once per tool call, after
|
|
57
|
+
* arguments have been fully assembled)
|
|
58
|
+
* - Exactly one terminal event: `done` or `error`
|
|
59
|
+
*/
|
|
60
|
+
stream(messages: LLMMessage[], options: LLMStreamOptions): AsyncIterable<StreamEvent>;
|
|
61
|
+
}
|
|
62
|
+
export type { ContentBlock, LLMAdapter, LLMChatOptions, LLMMessage, LLMResponse, LLMStreamOptions, LLMToolDef, StreamEvent, };
|
|
63
|
+
//# sourceMappingURL=openai.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openai.d.ts","sourceRoot":"","sources":["../../src/llm/openai.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AASH,OAAO,KAAK,EACV,YAAY,EACZ,UAAU,EACV,cAAc,EACd,UAAU,EACV,WAAW,EACX,gBAAgB,EAChB,UAAU,EACV,WAAW,EAGZ,MAAM,aAAa,CAAA;AAepB;;;;GAIG;AACH,qBAAa,aAAc,YAAW,UAAU;;IAC9C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAW;gBAIpB,MAAM,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM;IAW7C;;;;;;OAMG;IACG,IAAI,CAAC,QAAQ,EAAE,UAAU,EAAE,EAAE,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,WAAW,CAAC;IAuCjF;;;;;;;;;OASG;IACI,MAAM,CACX,QAAQ,EAAE,UAAU,EAAE,EACtB,OAAO,EAAE,gBAAgB,GACxB,aAAa,CAAC,WAAW,CAAC;CA6K9B;AAGD,YAAY,EACV,YAAY,EACZ,UAAU,EACV,cAAc,EACd,UAAU,EACV,WAAW,EACX,gBAAgB,EAChB,UAAU,EACV,WAAW,GACZ,CAAA"}
|