agentic-kit 1.0.3 → 1.3.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.
@@ -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;
@@ -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
- export type { ChatMessage, GenerateInput };
5
- export { OllamaClient };
6
- export { AnthropicAdapter, type AnthropicOptions };
7
- export { OpenAIAdapter, type OpenAIOptions };
8
- export interface StreamingOptions {
9
- onChunk?: (chunk: string) => void;
10
- onStateChange?: (state: string) => void;
11
- onError?: (error: Error) => void;
12
- onComplete?: () => void;
13
- }
14
- export interface AgentProvider {
15
- readonly name: string;
16
- generate(input: GenerateInput): Promise<string>;
17
- generateStreaming(input: GenerateInput, onChunk: (chunk: string) => void): Promise<void>;
18
- listModels?(): Promise<string[]>;
19
- }
20
- export declare class OllamaAdapter implements AgentProvider {
21
- readonly name = "ollama";
22
- private client;
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: AgentProvider): this;
26
+ addProvider(provider: NamedProviderAdapter): this;
32
27
  setProvider(name: string): this;
33
- getCurrentProvider(): AgentProvider | undefined;
28
+ getCurrentProvider(): NamedProviderAdapter | undefined;
34
29
  listProviders(): string[];
35
- generate(input: GenerateInput, options?: StreamingOptions): Promise<string | void>;
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: OpenAIOptions | string): AgentKit;
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 __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
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.AgentKit = exports.OllamaAdapter = exports.OpenAIAdapter = exports.AnthropicAdapter = exports.OllamaClient = void 0;
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
- // ─── Ollama Adapter ───────────────────────────────────────────────────────────
18
- class OllamaAdapter {
19
- name = 'ollama';
20
- client;
21
- constructor(baseUrl) {
22
- this.client = new ollama_1.default(baseUrl);
23
- }
24
- async generate(input) {
25
- return this.client.generate(input);
26
- }
27
- async generateStreaming(input, onChunk) {
28
- return this.client.generate(input, onChunk);
29
- }
30
- async listModels() {
31
- return this.client.listModels();
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.name, 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() { return this.current; }
53
- listProviders() { return Array.from(this.providers.keys()); }
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
- if (options?.onChunk) {
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
- await this.current.generateStreaming(input, options.onChunk);
60
- options.onComplete?.();
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 (err) {
63
- options.onError?.(err);
64
- throw err;
120
+ catch (error) {
121
+ options?.onError?.(error);
122
+ throw error;
65
123
  }
66
124
  return;
67
125
  }
68
126
  try {
69
- const result = await this.current.generate(input);
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 result;
131
+ return text;
72
132
  }
73
- catch (err) {
74
- options?.onError?.(err);
75
- throw err;
133
+ catch (error) {
134
+ options?.onError?.(error);
135
+ throw error;
76
136
  }
77
137
  }
78
138
  async listModels() {
79
- return this.current?.listModels?.() ?? [];
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,70 @@ 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: (0, messages_js_1.createEmptyUsage)(),
171
+ stopReason: 'stop',
172
+ timestamp: Date.now(),
173
+ }
174
+ : {
175
+ role: 'user',
176
+ content: message.content,
177
+ timestamp: Date.now(),
178
+ })
179
+ : [{ role: 'user', content: input.prompt ?? '', timestamp: Date.now() }];
180
+ const systemPrompt = input.system ?? input.messages?.find((message) => message.role === 'system')?.content;
181
+ return {
182
+ systemPrompt,
183
+ messages,
184
+ };
185
+ }
186
+ function createLegacyModel(provider, modelId, maxTokens) {
187
+ if (provider.createModel) {
188
+ return provider.createModel(modelId, {
189
+ maxOutputTokens: maxTokens,
190
+ });
191
+ }
192
+ return {
193
+ id: modelId,
194
+ name: modelId,
195
+ api: provider.api,
196
+ provider: getProviderName(provider),
197
+ baseUrl: '',
198
+ input: ['text'],
199
+ reasoning: false,
200
+ tools: true,
201
+ maxOutputTokens: maxTokens,
202
+ };
203
+ }
204
+ function streamWithProvider(provider, model, context, options) {
205
+ const normalized = (0, messages_js_1.normalizeContext)(context);
206
+ const transformedContext = {
207
+ ...normalized,
208
+ messages: (0, transform_messages_js_1.transformMessages)(normalized.messages, model),
209
+ };
210
+ return provider.stream(model, transformedContext, options);
211
+ }
212
+ async function completeWithProvider(provider, model, context, options) {
213
+ const response = streamWithProvider(provider, model, context, options);
214
+ return response.result();
215
+ }
216
+ function getProviderName(provider) {
217
+ return provider.name ?? provider.provider;
218
+ }
219
+ function assertLegacyGenerateSucceeded(message) {
220
+ if (message.stopReason === 'error' || message.stopReason === 'aborted') {
221
+ throw new Error(message.errorMessage ??
222
+ (message.stopReason === 'aborted' ? 'Generation aborted.' : 'Generation failed.'), { cause: message });
223
+ }
224
+ return message;
225
+ }
package/messages.d.ts ADDED
@@ -0,0 +1,33 @@
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): void;
4
+ export declare function snapshotUsage(usage: Usage): Usage;
5
+ export declare function addUsage(target: Usage, delta: Usage): Usage;
6
+ export declare function createAssistantMessage(model: ModelDescriptor): AssistantMessage;
7
+ export declare function createTextContent(text?: string): TextContent;
8
+ export declare function createImageContent(data: string, mimeType: string): ImageContent;
9
+ export declare function createToolCall(id: string, name: string): ToolCallContent;
10
+ export declare function createUserMessage(content: UserMessage['content']): UserMessage;
11
+ export declare function createToolResultMessage(toolCallId: string, toolName: string, content: ToolResultMessage['content'], isError?: boolean): ToolResultMessage;
12
+ export declare function getMessageText(message: AssistantMessage): string;
13
+ export interface InjectDeferralResultsOptions {
14
+ /** Text body for synthesized results. Defaults to a generic continue prompt. */
15
+ deferralText?: string;
16
+ /** Stamped onto each synthesized result's `details` field — typically `{ deferred: true }` so renderers can hide a "Done" badge. */
17
+ details?: unknown;
18
+ }
19
+ /**
20
+ * Synthesize toolResult messages for every toolCall that lacks both a decision
21
+ * and a paired toolResult. Returns input unchanged (referentially equal) when
22
+ * nothing needs synthesizing.
23
+ *
24
+ * Use case: user types a message instead of clicking approve/deny on a paused
25
+ * tool. The agent can't resume on text alone — every dangling toolCall needs
26
+ * a result before the next request. Compose with sendMessages to forward the
27
+ * conversation cleanly:
28
+ *
29
+ * await sendMessages([...injectDeferralResults(messages), createUserMessage(text)]);
30
+ */
31
+ export declare function injectDeferralResults(messages: Message[], optionsOrText?: InjectDeferralResultsOptions | string): Message[];
32
+ export declare function cloneMessage<TMessage extends Message>(message: TMessage): TMessage;
33
+ export declare function normalizeContext(context: Context): Context;