agentic-kit 0.3.0 → 1.2.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/README.md +76 -32
- package/esm/event-stream.js +77 -0
- package/esm/index.js +151 -41
- package/esm/messages.js +130 -0
- package/esm/model-registry.js +26 -0
- package/esm/package.json +1 -0
- package/esm/provider-registry.js +20 -0
- package/esm/transform-messages.js +139 -0
- package/esm/types.js +1 -0
- package/event-stream.d.ts +19 -0
- package/event-stream.js +83 -0
- package/index.d.ts +26 -30
- package/index.js +179 -42
- package/messages.d.ts +31 -0
- package/messages.js +144 -0
- package/model-registry.d.ts +7 -0
- package/model-registry.js +34 -0
- package/package.json +15 -8
- package/provider-registry.d.ts +6 -0
- package/provider-registry.js +27 -0
- package/transform-messages.d.ts +2 -0
- package/transform-messages.js +142 -0
- package/types.d.ts +231 -0
- package/types.js +2 -0
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
export function transformMessages(messages, model) {
|
|
2
|
+
const toolCallIdMap = new Map();
|
|
3
|
+
const transformed = messages.flatMap((message) => {
|
|
4
|
+
if (message.role !== 'assistant') {
|
|
5
|
+
if (message.role === 'toolResult') {
|
|
6
|
+
const normalizedId = toolCallIdMap.get(message.toolCallId);
|
|
7
|
+
if (normalizedId && normalizedId !== message.toolCallId) {
|
|
8
|
+
return [{ ...message, toolCallId: normalizedId }];
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
return [message];
|
|
12
|
+
}
|
|
13
|
+
if (message.stopReason === 'error' || message.stopReason === 'aborted') {
|
|
14
|
+
return [];
|
|
15
|
+
}
|
|
16
|
+
const sameModel = message.provider === model.provider &&
|
|
17
|
+
message.api === model.api &&
|
|
18
|
+
message.model === model.id;
|
|
19
|
+
const content = message.content.flatMap((block) => {
|
|
20
|
+
if (block.type === 'thinking') {
|
|
21
|
+
if (sameModel) {
|
|
22
|
+
return [block];
|
|
23
|
+
}
|
|
24
|
+
if (!block.thinking.trim()) {
|
|
25
|
+
return [];
|
|
26
|
+
}
|
|
27
|
+
const thinkingAsText = {
|
|
28
|
+
type: 'text',
|
|
29
|
+
text: `<thinking>${block.thinking}</thinking>`,
|
|
30
|
+
};
|
|
31
|
+
return [thinkingAsText];
|
|
32
|
+
}
|
|
33
|
+
if (block.type === 'toolCall') {
|
|
34
|
+
const normalizedId = normalizeToolCallId(block.id, model);
|
|
35
|
+
if (normalizedId !== block.id) {
|
|
36
|
+
toolCallIdMap.set(block.id, normalizedId);
|
|
37
|
+
}
|
|
38
|
+
const toolCall = normalizedId === block.id ? block : { ...block, id: normalizedId };
|
|
39
|
+
return [toolCall];
|
|
40
|
+
}
|
|
41
|
+
return [block];
|
|
42
|
+
});
|
|
43
|
+
return [{ ...message, content }];
|
|
44
|
+
});
|
|
45
|
+
return insertSyntheticToolResults(transformed);
|
|
46
|
+
}
|
|
47
|
+
function insertSyntheticToolResults(messages) {
|
|
48
|
+
const result = [];
|
|
49
|
+
let pendingToolCalls = [];
|
|
50
|
+
let seenToolResults = new Set();
|
|
51
|
+
for (const message of messages) {
|
|
52
|
+
if (message.role === 'assistant') {
|
|
53
|
+
flushPendingToolCalls(result, pendingToolCalls, seenToolResults);
|
|
54
|
+
pendingToolCalls = message.content.filter((block) => block.type === 'toolCall');
|
|
55
|
+
seenToolResults = new Set();
|
|
56
|
+
result.push(message);
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
if (message.role === 'toolResult') {
|
|
60
|
+
seenToolResults.add(message.toolCallId);
|
|
61
|
+
result.push(message);
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
flushPendingToolCalls(result, pendingToolCalls, seenToolResults);
|
|
65
|
+
pendingToolCalls = [];
|
|
66
|
+
seenToolResults = new Set();
|
|
67
|
+
result.push(message);
|
|
68
|
+
}
|
|
69
|
+
flushPendingToolCalls(result, pendingToolCalls, seenToolResults);
|
|
70
|
+
return result;
|
|
71
|
+
}
|
|
72
|
+
function flushPendingToolCalls(result, pendingToolCalls, seenToolResults) {
|
|
73
|
+
if (pendingToolCalls.length === 0) {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
for (const toolCall of pendingToolCalls) {
|
|
77
|
+
if (seenToolResults.has(toolCall.id)) {
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
const synthetic = {
|
|
81
|
+
role: 'toolResult',
|
|
82
|
+
toolCallId: toolCall.id,
|
|
83
|
+
toolName: toolCall.name,
|
|
84
|
+
content: [{ type: 'text', text: 'No result provided.' }],
|
|
85
|
+
isError: true,
|
|
86
|
+
timestamp: Date.now(),
|
|
87
|
+
};
|
|
88
|
+
result.push(synthetic);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
function normalizeToolCallId(id, model) {
|
|
92
|
+
const format = model.compat?.toolCallIdFormat ?? defaultToolCallIdFormat(model);
|
|
93
|
+
if (format === 'passthrough') {
|
|
94
|
+
return id;
|
|
95
|
+
}
|
|
96
|
+
if (format === 'mistral9') {
|
|
97
|
+
const alphanumeric = id.replace(/[^a-zA-Z0-9]/g, '');
|
|
98
|
+
if (alphanumeric.length >= 9) {
|
|
99
|
+
return alphanumeric.slice(0, 9);
|
|
100
|
+
}
|
|
101
|
+
return stableAlphanumericId(id, 9);
|
|
102
|
+
}
|
|
103
|
+
const safe = id.replace(/[^a-zA-Z0-9_-]/g, '_').slice(0, 64);
|
|
104
|
+
if (safe.length > 0) {
|
|
105
|
+
return safe;
|
|
106
|
+
}
|
|
107
|
+
return stableId(id, 24, /^[a-zA-Z0-9_-]+$/);
|
|
108
|
+
}
|
|
109
|
+
function defaultToolCallIdFormat(model) {
|
|
110
|
+
if (model.provider === 'anthropic' || model.api === 'anthropic-messages') {
|
|
111
|
+
return 'safe64';
|
|
112
|
+
}
|
|
113
|
+
return 'passthrough';
|
|
114
|
+
}
|
|
115
|
+
function stableId(input, length, pattern) {
|
|
116
|
+
let hash = 0;
|
|
117
|
+
for (let i = 0; i < input.length; i += 1) {
|
|
118
|
+
hash = (hash * 31 + input.charCodeAt(i)) >>> 0;
|
|
119
|
+
}
|
|
120
|
+
let value = `tc_${hash.toString(36)}`;
|
|
121
|
+
while (!pattern.test(value)) {
|
|
122
|
+
value = value.replace(/[^a-zA-Z0-9_-]/g, '_');
|
|
123
|
+
}
|
|
124
|
+
if (value.length >= length) {
|
|
125
|
+
return value.slice(0, length);
|
|
126
|
+
}
|
|
127
|
+
return value.padEnd(length, '0');
|
|
128
|
+
}
|
|
129
|
+
function stableAlphanumericId(input, length) {
|
|
130
|
+
let hash = 0;
|
|
131
|
+
for (let i = 0; i < input.length; i += 1) {
|
|
132
|
+
hash = (hash * 31 + input.charCodeAt(i)) >>> 0;
|
|
133
|
+
}
|
|
134
|
+
const value = `tc${hash.toString(36)}`.replace(/[^a-zA-Z0-9]/g, '');
|
|
135
|
+
if (value.length >= length) {
|
|
136
|
+
return value.slice(0, length);
|
|
137
|
+
}
|
|
138
|
+
return value.padEnd(length, '0');
|
|
139
|
+
}
|
package/esm/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { AssistantMessage, AssistantMessageEvent, AssistantMessageEventStream } from './types.js';
|
|
2
|
+
export declare class EventStream<TEvent, TResult = TEvent> implements AsyncIterable<TEvent> {
|
|
3
|
+
private readonly isTerminal;
|
|
4
|
+
private readonly extractResult;
|
|
5
|
+
private readonly queue;
|
|
6
|
+
private readonly waiting;
|
|
7
|
+
private done;
|
|
8
|
+
private readonly finalResultPromise;
|
|
9
|
+
private resolveFinalResult;
|
|
10
|
+
constructor(isTerminal: (event: TEvent) => boolean, extractResult: (event: TEvent) => TResult);
|
|
11
|
+
push(event: TEvent): void;
|
|
12
|
+
end(result?: TResult): void;
|
|
13
|
+
[Symbol.asyncIterator](): AsyncIterator<TEvent>;
|
|
14
|
+
result(): Promise<TResult>;
|
|
15
|
+
}
|
|
16
|
+
export declare class DefaultAssistantMessageEventStream extends EventStream<AssistantMessageEvent, AssistantMessage> implements AssistantMessageEventStream {
|
|
17
|
+
constructor();
|
|
18
|
+
}
|
|
19
|
+
export declare function createAssistantMessageEventStream(): DefaultAssistantMessageEventStream;
|
package/event-stream.js
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DefaultAssistantMessageEventStream = exports.EventStream = void 0;
|
|
4
|
+
exports.createAssistantMessageEventStream = createAssistantMessageEventStream;
|
|
5
|
+
class EventStream {
|
|
6
|
+
isTerminal;
|
|
7
|
+
extractResult;
|
|
8
|
+
queue = [];
|
|
9
|
+
waiting = [];
|
|
10
|
+
done = false;
|
|
11
|
+
finalResultPromise;
|
|
12
|
+
resolveFinalResult;
|
|
13
|
+
constructor(isTerminal, extractResult) {
|
|
14
|
+
this.isTerminal = isTerminal;
|
|
15
|
+
this.extractResult = extractResult;
|
|
16
|
+
this.finalResultPromise = new Promise((resolve) => {
|
|
17
|
+
this.resolveFinalResult = resolve;
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
push(event) {
|
|
21
|
+
if (this.done) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
if (this.isTerminal(event)) {
|
|
25
|
+
this.done = true;
|
|
26
|
+
this.resolveFinalResult(this.extractResult(event));
|
|
27
|
+
}
|
|
28
|
+
const waiter = this.waiting.shift();
|
|
29
|
+
if (waiter) {
|
|
30
|
+
waiter({ value: event, done: false });
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
this.queue.push(event);
|
|
34
|
+
}
|
|
35
|
+
end(result) {
|
|
36
|
+
this.done = true;
|
|
37
|
+
if (result !== undefined) {
|
|
38
|
+
this.resolveFinalResult(result);
|
|
39
|
+
}
|
|
40
|
+
while (this.waiting.length > 0) {
|
|
41
|
+
this.waiting.shift()({ value: undefined, done: true });
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
async *[Symbol.asyncIterator]() {
|
|
45
|
+
while (true) {
|
|
46
|
+
if (this.queue.length > 0) {
|
|
47
|
+
yield this.queue.shift();
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
if (this.done) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
const next = await new Promise((resolve) => {
|
|
54
|
+
this.waiting.push(resolve);
|
|
55
|
+
});
|
|
56
|
+
if (next.done) {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
yield next.value;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
result() {
|
|
63
|
+
return this.finalResultPromise;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
exports.EventStream = EventStream;
|
|
67
|
+
class DefaultAssistantMessageEventStream extends EventStream {
|
|
68
|
+
constructor() {
|
|
69
|
+
super((event) => event.type === 'done' || event.type === 'error', (event) => {
|
|
70
|
+
if (event.type === 'done') {
|
|
71
|
+
return event.message;
|
|
72
|
+
}
|
|
73
|
+
if (event.type === 'error') {
|
|
74
|
+
return event.error;
|
|
75
|
+
}
|
|
76
|
+
throw new Error('Unexpected terminal event');
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
exports.DefaultAssistantMessageEventStream = DefaultAssistantMessageEventStream;
|
|
81
|
+
function createAssistantMessageEventStream() {
|
|
82
|
+
return new DefaultAssistantMessageEventStream();
|
|
83
|
+
}
|
package/index.d.ts
CHANGED
|
@@ -1,41 +1,37 @@
|
|
|
1
|
-
import OllamaClient, { ChatMessage, GenerateInput } from '@agentic-kit/ollama';
|
|
2
1
|
import { AnthropicAdapter, type AnthropicOptions } from '@agentic-kit/anthropic';
|
|
2
|
+
import { OllamaAdapter, OllamaClient } from '@agentic-kit/ollama';
|
|
3
3
|
import { OpenAIAdapter, type OpenAIOptions } from '@agentic-kit/openai';
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
export
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
}
|
|
14
|
-
export
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
}
|
|
20
|
-
export declare
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
constructor(baseUrl?: string);
|
|
24
|
-
generate(input: GenerateInput): Promise<string>;
|
|
25
|
-
generateStreaming(input: GenerateInput, onChunk: (chunk: string) => void): Promise<void>;
|
|
26
|
-
listModels(): Promise<string[]>;
|
|
27
|
-
}
|
|
4
|
+
import { createAssistantMessageEventStream, EventStream } from './event-stream.js';
|
|
5
|
+
import { clearModels, getModel, getModels, getProviders as getModelProviders, registerModel, registerModels } from './model-registry.js';
|
|
6
|
+
import { clearProviders, getProvider as getRegisteredProvider, getProviders as getRegisteredProviders, registerProvider, unregisterProviders } from './provider-registry.js';
|
|
7
|
+
import type { AssistantMessage, AssistantMessageEventStream, Context, LegacyChatMessage, LegacyGenerateInput, LegacyStreamingOptions, ModelDescriptor, ProviderAdapter, StreamOptions } from './types.js';
|
|
8
|
+
export * from './event-stream.js';
|
|
9
|
+
export * from './messages.js';
|
|
10
|
+
export * from './transform-messages.js';
|
|
11
|
+
export * from './types.js';
|
|
12
|
+
export { createAssistantMessageEventStream, EventStream, OllamaClient };
|
|
13
|
+
export { AnthropicAdapter, OllamaAdapter, OpenAIAdapter };
|
|
14
|
+
export type { AnthropicOptions, OpenAIOptions };
|
|
15
|
+
export type ChatMessage = LegacyChatMessage;
|
|
16
|
+
export type GenerateInput = LegacyGenerateInput;
|
|
17
|
+
type NamedProviderAdapter = ProviderAdapter & {
|
|
18
|
+
name?: string;
|
|
19
|
+
};
|
|
20
|
+
export declare function stream(model: ModelDescriptor, context: Context, options?: StreamOptions): AssistantMessageEventStream;
|
|
21
|
+
export declare function complete(model: ModelDescriptor, context: Context, options?: StreamOptions): Promise<AssistantMessage>;
|
|
22
|
+
export declare function completeText(model: ModelDescriptor, context: Context, options?: StreamOptions): Promise<string>;
|
|
28
23
|
export declare class AgentKit {
|
|
29
|
-
private providers;
|
|
24
|
+
private readonly providers;
|
|
30
25
|
private current?;
|
|
31
|
-
addProvider(provider:
|
|
26
|
+
addProvider(provider: NamedProviderAdapter): this;
|
|
32
27
|
setProvider(name: string): this;
|
|
33
|
-
getCurrentProvider():
|
|
28
|
+
getCurrentProvider(): NamedProviderAdapter | undefined;
|
|
34
29
|
listProviders(): string[];
|
|
35
|
-
generate(input:
|
|
30
|
+
generate(input: LegacyGenerateInput, options?: LegacyStreamingOptions): Promise<string | void>;
|
|
36
31
|
listModels(): Promise<string[]>;
|
|
37
32
|
}
|
|
38
33
|
export declare function createOllamaKit(baseUrl?: string): AgentKit;
|
|
39
34
|
export declare function createAnthropicKit(options: AnthropicOptions | string): AgentKit;
|
|
40
|
-
export declare function createOpenAIKit(options
|
|
35
|
+
export declare function createOpenAIKit(options?: OpenAIOptions | string): AgentKit;
|
|
41
36
|
export declare function createMultiProviderKit(): AgentKit;
|
|
37
|
+
export { clearModels, clearProviders, getModel, getModelProviders, getModels, getRegisteredProvider as getProvider, getRegisteredProviders, registerModel, registerModels, registerProvider, unregisterProviders, };
|
package/index.js
CHANGED
|
@@ -1,88 +1,151 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var
|
|
3
|
-
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
4
15
|
};
|
|
5
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.
|
|
17
|
+
exports.unregisterProviders = exports.registerProvider = exports.registerModels = exports.registerModel = exports.getRegisteredProviders = exports.getProvider = exports.getModels = exports.getModelProviders = exports.getModel = exports.clearProviders = exports.clearModels = exports.AgentKit = exports.OpenAIAdapter = exports.OllamaAdapter = exports.AnthropicAdapter = exports.OllamaClient = exports.EventStream = exports.createAssistantMessageEventStream = void 0;
|
|
18
|
+
exports.stream = stream;
|
|
19
|
+
exports.complete = complete;
|
|
20
|
+
exports.completeText = completeText;
|
|
7
21
|
exports.createOllamaKit = createOllamaKit;
|
|
8
22
|
exports.createAnthropicKit = createAnthropicKit;
|
|
9
23
|
exports.createOpenAIKit = createOpenAIKit;
|
|
10
24
|
exports.createMultiProviderKit = createMultiProviderKit;
|
|
11
|
-
const ollama_1 = __importDefault(require("@agentic-kit/ollama"));
|
|
12
|
-
exports.OllamaClient = ollama_1.default;
|
|
13
25
|
const anthropic_1 = require("@agentic-kit/anthropic");
|
|
14
26
|
Object.defineProperty(exports, "AnthropicAdapter", { enumerable: true, get: function () { return anthropic_1.AnthropicAdapter; } });
|
|
27
|
+
const ollama_1 = require("@agentic-kit/ollama");
|
|
28
|
+
Object.defineProperty(exports, "OllamaAdapter", { enumerable: true, get: function () { return ollama_1.OllamaAdapter; } });
|
|
29
|
+
Object.defineProperty(exports, "OllamaClient", { enumerable: true, get: function () { return ollama_1.OllamaClient; } });
|
|
15
30
|
const openai_1 = require("@agentic-kit/openai");
|
|
16
31
|
Object.defineProperty(exports, "OpenAIAdapter", { enumerable: true, get: function () { return openai_1.OpenAIAdapter; } });
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
+
const event_stream_js_1 = require("./event-stream.js");
|
|
33
|
+
Object.defineProperty(exports, "createAssistantMessageEventStream", { enumerable: true, get: function () { return event_stream_js_1.createAssistantMessageEventStream; } });
|
|
34
|
+
Object.defineProperty(exports, "EventStream", { enumerable: true, get: function () { return event_stream_js_1.EventStream; } });
|
|
35
|
+
const messages_js_1 = require("./messages.js");
|
|
36
|
+
const model_registry_js_1 = require("./model-registry.js");
|
|
37
|
+
Object.defineProperty(exports, "clearModels", { enumerable: true, get: function () { return model_registry_js_1.clearModels; } });
|
|
38
|
+
Object.defineProperty(exports, "getModel", { enumerable: true, get: function () { return model_registry_js_1.getModel; } });
|
|
39
|
+
Object.defineProperty(exports, "getModels", { enumerable: true, get: function () { return model_registry_js_1.getModels; } });
|
|
40
|
+
Object.defineProperty(exports, "getModelProviders", { enumerable: true, get: function () { return model_registry_js_1.getProviders; } });
|
|
41
|
+
Object.defineProperty(exports, "registerModel", { enumerable: true, get: function () { return model_registry_js_1.registerModel; } });
|
|
42
|
+
Object.defineProperty(exports, "registerModels", { enumerable: true, get: function () { return model_registry_js_1.registerModels; } });
|
|
43
|
+
const provider_registry_js_1 = require("./provider-registry.js");
|
|
44
|
+
Object.defineProperty(exports, "clearProviders", { enumerable: true, get: function () { return provider_registry_js_1.clearProviders; } });
|
|
45
|
+
Object.defineProperty(exports, "getProvider", { enumerable: true, get: function () { return provider_registry_js_1.getProvider; } });
|
|
46
|
+
Object.defineProperty(exports, "getRegisteredProviders", { enumerable: true, get: function () { return provider_registry_js_1.getProviders; } });
|
|
47
|
+
Object.defineProperty(exports, "registerProvider", { enumerable: true, get: function () { return provider_registry_js_1.registerProvider; } });
|
|
48
|
+
Object.defineProperty(exports, "unregisterProviders", { enumerable: true, get: function () { return provider_registry_js_1.unregisterProviders; } });
|
|
49
|
+
const transform_messages_js_1 = require("./transform-messages.js");
|
|
50
|
+
__exportStar(require("./event-stream.js"), exports);
|
|
51
|
+
__exportStar(require("./messages.js"), exports);
|
|
52
|
+
__exportStar(require("./transform-messages.js"), exports);
|
|
53
|
+
__exportStar(require("./types.js"), exports);
|
|
54
|
+
(0, model_registry_js_1.registerModels)([...openai_1.OPENAI_COMPATIBLE_MODELS, ...anthropic_1.ANTHROPIC_MODELS, ...ollama_1.OLLAMA_MODELS]);
|
|
55
|
+
(0, provider_registry_js_1.registerProvider)(new openai_1.OpenAIAdapter());
|
|
56
|
+
(0, provider_registry_js_1.registerProvider)(new anthropic_1.AnthropicAdapter({ apiKey: '' }));
|
|
57
|
+
(0, provider_registry_js_1.registerProvider)(new ollama_1.OllamaAdapter());
|
|
58
|
+
function stream(model, context, options) {
|
|
59
|
+
const provider = (0, provider_registry_js_1.getProvider)(model.api);
|
|
60
|
+
if (!provider) {
|
|
61
|
+
throw new Error(`No provider registered for api '${model.api}'`);
|
|
32
62
|
}
|
|
63
|
+
return streamWithProvider(provider, model, context, options);
|
|
64
|
+
}
|
|
65
|
+
async function complete(model, context, options) {
|
|
66
|
+
const response = stream(model, context, options);
|
|
67
|
+
return response.result();
|
|
68
|
+
}
|
|
69
|
+
async function completeText(model, context, options) {
|
|
70
|
+
const message = await complete(model, context, options);
|
|
71
|
+
return (0, messages_js_1.getMessageText)(message);
|
|
33
72
|
}
|
|
34
|
-
exports.OllamaAdapter = OllamaAdapter;
|
|
35
|
-
// ─── AgentKit ─────────────────────────────────────────────────────────────────
|
|
36
73
|
class AgentKit {
|
|
37
74
|
providers = new Map();
|
|
38
75
|
current;
|
|
39
76
|
addProvider(provider) {
|
|
40
|
-
this.providers.set(provider
|
|
41
|
-
if (!this.current)
|
|
77
|
+
this.providers.set(getProviderName(provider), provider);
|
|
78
|
+
if (!this.current) {
|
|
42
79
|
this.current = provider;
|
|
80
|
+
}
|
|
43
81
|
return this;
|
|
44
82
|
}
|
|
45
83
|
setProvider(name) {
|
|
46
84
|
const provider = this.providers.get(name);
|
|
47
|
-
if (!provider)
|
|
85
|
+
if (!provider) {
|
|
48
86
|
throw new Error(`Provider '${name}' not found`);
|
|
87
|
+
}
|
|
49
88
|
this.current = provider;
|
|
50
89
|
return this;
|
|
51
90
|
}
|
|
52
|
-
getCurrentProvider() {
|
|
53
|
-
|
|
91
|
+
getCurrentProvider() {
|
|
92
|
+
return this.current;
|
|
93
|
+
}
|
|
94
|
+
listProviders() {
|
|
95
|
+
return Array.from(this.providers.keys());
|
|
96
|
+
}
|
|
54
97
|
async generate(input, options) {
|
|
55
|
-
if (!this.current)
|
|
98
|
+
if (!this.current) {
|
|
56
99
|
throw new Error('No provider set. Call addProvider() first.');
|
|
57
|
-
|
|
100
|
+
}
|
|
101
|
+
const provider = this.current;
|
|
102
|
+
const model = createLegacyModel(provider, input.model, input.maxTokens);
|
|
103
|
+
const context = legacyInputToContext(input);
|
|
104
|
+
const streamOptions = {
|
|
105
|
+
maxTokens: input.maxTokens,
|
|
106
|
+
temperature: input.temperature,
|
|
107
|
+
};
|
|
108
|
+
if (options?.onChunk || input.stream) {
|
|
109
|
+
options?.onStateChange?.('streaming');
|
|
58
110
|
try {
|
|
59
|
-
|
|
60
|
-
|
|
111
|
+
const response = streamWithProvider(provider, model, context, streamOptions);
|
|
112
|
+
for await (const event of response) {
|
|
113
|
+
if (event.type === 'text_delta') {
|
|
114
|
+
options?.onChunk?.(event.delta);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
assertLegacyGenerateSucceeded(await response.result());
|
|
118
|
+
options?.onComplete?.();
|
|
61
119
|
}
|
|
62
|
-
catch (
|
|
63
|
-
options
|
|
64
|
-
throw
|
|
120
|
+
catch (error) {
|
|
121
|
+
options?.onError?.(error);
|
|
122
|
+
throw error;
|
|
65
123
|
}
|
|
66
124
|
return;
|
|
67
125
|
}
|
|
68
126
|
try {
|
|
69
|
-
const
|
|
127
|
+
const message = assertLegacyGenerateSucceeded(await completeWithProvider(provider, model, context, streamOptions));
|
|
128
|
+
options?.onStateChange?.('complete');
|
|
129
|
+
const text = (0, messages_js_1.getMessageText)(message);
|
|
70
130
|
options?.onComplete?.();
|
|
71
|
-
return
|
|
131
|
+
return text;
|
|
72
132
|
}
|
|
73
|
-
catch (
|
|
74
|
-
options?.onError?.(
|
|
75
|
-
throw
|
|
133
|
+
catch (error) {
|
|
134
|
+
options?.onError?.(error);
|
|
135
|
+
throw error;
|
|
76
136
|
}
|
|
77
137
|
}
|
|
78
138
|
async listModels() {
|
|
79
|
-
|
|
139
|
+
if (!this.current?.listModels) {
|
|
140
|
+
return [];
|
|
141
|
+
}
|
|
142
|
+
const models = await this.current.listModels();
|
|
143
|
+
return models.map((model) => (typeof model === 'string' ? model : model.id));
|
|
80
144
|
}
|
|
81
145
|
}
|
|
82
146
|
exports.AgentKit = AgentKit;
|
|
83
|
-
// ─── Factory helpers ──────────────────────────────────────────────────────────
|
|
84
147
|
function createOllamaKit(baseUrl) {
|
|
85
|
-
return new AgentKit().addProvider(new OllamaAdapter(baseUrl));
|
|
148
|
+
return new AgentKit().addProvider(new ollama_1.OllamaAdapter(baseUrl));
|
|
86
149
|
}
|
|
87
150
|
function createAnthropicKit(options) {
|
|
88
151
|
return new AgentKit().addProvider(new anthropic_1.AnthropicAdapter(options));
|
|
@@ -93,3 +156,77 @@ function createOpenAIKit(options) {
|
|
|
93
156
|
function createMultiProviderKit() {
|
|
94
157
|
return new AgentKit();
|
|
95
158
|
}
|
|
159
|
+
function legacyInputToContext(input) {
|
|
160
|
+
const messages = input.messages
|
|
161
|
+
? input.messages
|
|
162
|
+
.filter((message) => message.role !== 'system')
|
|
163
|
+
.map((message) => message.role === 'assistant'
|
|
164
|
+
? {
|
|
165
|
+
role: 'assistant',
|
|
166
|
+
api: 'legacy',
|
|
167
|
+
provider: 'legacy',
|
|
168
|
+
model: input.model,
|
|
169
|
+
content: [{ type: 'text', text: message.content }],
|
|
170
|
+
usage: {
|
|
171
|
+
input: 0,
|
|
172
|
+
output: 0,
|
|
173
|
+
cacheRead: 0,
|
|
174
|
+
cacheWrite: 0,
|
|
175
|
+
totalTokens: 0,
|
|
176
|
+
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
|
|
177
|
+
},
|
|
178
|
+
stopReason: 'stop',
|
|
179
|
+
timestamp: Date.now(),
|
|
180
|
+
}
|
|
181
|
+
: {
|
|
182
|
+
role: 'user',
|
|
183
|
+
content: message.content,
|
|
184
|
+
timestamp: Date.now(),
|
|
185
|
+
})
|
|
186
|
+
: [{ role: 'user', content: input.prompt ?? '', timestamp: Date.now() }];
|
|
187
|
+
const systemPrompt = input.system ?? input.messages?.find((message) => message.role === 'system')?.content;
|
|
188
|
+
return {
|
|
189
|
+
systemPrompt,
|
|
190
|
+
messages,
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
function createLegacyModel(provider, modelId, maxTokens) {
|
|
194
|
+
if (provider.createModel) {
|
|
195
|
+
return provider.createModel(modelId, {
|
|
196
|
+
maxOutputTokens: maxTokens,
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
return {
|
|
200
|
+
id: modelId,
|
|
201
|
+
name: modelId,
|
|
202
|
+
api: provider.api,
|
|
203
|
+
provider: getProviderName(provider),
|
|
204
|
+
baseUrl: '',
|
|
205
|
+
input: ['text'],
|
|
206
|
+
reasoning: false,
|
|
207
|
+
tools: true,
|
|
208
|
+
maxOutputTokens: maxTokens,
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
function streamWithProvider(provider, model, context, options) {
|
|
212
|
+
const normalized = (0, messages_js_1.normalizeContext)(context);
|
|
213
|
+
const transformedContext = {
|
|
214
|
+
...normalized,
|
|
215
|
+
messages: (0, transform_messages_js_1.transformMessages)(normalized.messages, model),
|
|
216
|
+
};
|
|
217
|
+
return provider.stream(model, transformedContext, options);
|
|
218
|
+
}
|
|
219
|
+
async function completeWithProvider(provider, model, context, options) {
|
|
220
|
+
const response = streamWithProvider(provider, model, context, options);
|
|
221
|
+
return response.result();
|
|
222
|
+
}
|
|
223
|
+
function getProviderName(provider) {
|
|
224
|
+
return provider.name ?? provider.provider;
|
|
225
|
+
}
|
|
226
|
+
function assertLegacyGenerateSucceeded(message) {
|
|
227
|
+
if (message.stopReason === 'error' || message.stopReason === 'aborted') {
|
|
228
|
+
throw new Error(message.errorMessage ??
|
|
229
|
+
(message.stopReason === 'aborted' ? 'Generation aborted.' : 'Generation failed.'), { cause: message });
|
|
230
|
+
}
|
|
231
|
+
return message;
|
|
232
|
+
}
|
package/messages.d.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { AssistantMessage, Context, ImageContent, Message, ModelDescriptor, TextContent, ToolCallContent, ToolResultMessage, Usage, UserMessage } from './types.js';
|
|
2
|
+
export declare function createEmptyUsage(): Usage;
|
|
3
|
+
export declare function calculateUsageCost(model: ModelDescriptor, usage: Usage): Usage['cost'];
|
|
4
|
+
export declare function createAssistantMessage(model: ModelDescriptor): AssistantMessage;
|
|
5
|
+
export declare function createTextContent(text?: string): TextContent;
|
|
6
|
+
export declare function createImageContent(data: string, mimeType: string): ImageContent;
|
|
7
|
+
export declare function createToolCall(id: string, name: string): ToolCallContent;
|
|
8
|
+
export declare function createUserMessage(content: UserMessage['content']): UserMessage;
|
|
9
|
+
export declare function createToolResultMessage(toolCallId: string, toolName: string, content: ToolResultMessage['content'], isError?: boolean): ToolResultMessage;
|
|
10
|
+
export declare function getMessageText(message: AssistantMessage): string;
|
|
11
|
+
export interface InjectDeferralResultsOptions {
|
|
12
|
+
/** Text body for synthesized results. Defaults to a generic continue prompt. */
|
|
13
|
+
deferralText?: string;
|
|
14
|
+
/** Stamped onto each synthesized result's `details` field — typically `{ deferred: true }` so renderers can hide a "Done" badge. */
|
|
15
|
+
details?: unknown;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Synthesize toolResult messages for every toolCall that lacks both a decision
|
|
19
|
+
* and a paired toolResult. Returns input unchanged (referentially equal) when
|
|
20
|
+
* nothing needs synthesizing.
|
|
21
|
+
*
|
|
22
|
+
* Use case: user types a message instead of clicking approve/deny on a paused
|
|
23
|
+
* tool. The agent can't resume on text alone — every dangling toolCall needs
|
|
24
|
+
* a result before the next request. Compose with sendMessages to forward the
|
|
25
|
+
* conversation cleanly:
|
|
26
|
+
*
|
|
27
|
+
* await sendMessages([...injectDeferralResults(messages), createUserMessage(text)]);
|
|
28
|
+
*/
|
|
29
|
+
export declare function injectDeferralResults(messages: Message[], optionsOrText?: InjectDeferralResultsOptions | string): Message[];
|
|
30
|
+
export declare function cloneMessage<TMessage extends Message>(message: TMessage): TMessage;
|
|
31
|
+
export declare function normalizeContext(context: Context): Context;
|