agentic-kit 1.3.1 → 1.3.2

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/esm/index.js CHANGED
@@ -1,15 +1,12 @@
1
1
  import { ANTHROPIC_MODELS, AnthropicAdapter } from '@agentic-kit/anthropic';
2
2
  import { OLLAMA_MODELS, OllamaAdapter, OllamaClient } from '@agentic-kit/ollama';
3
3
  import { OPENAI_COMPATIBLE_MODELS, OpenAIAdapter, } from '@agentic-kit/openai';
4
- import { createAssistantMessageEventStream, EventStream } from './event-stream.js';
5
- import { createEmptyUsage, getMessageText, normalizeContext } from './messages.js';
4
+ import { createAssistantMessageEventStream, createEmptyUsage, EventStream, getMessageText, normalizeContext, } from '@agentic-kit/protocol';
6
5
  import { clearModels, getModel, getModels, getProviders as getModelProviders, registerModel, registerModels, } from './model-registry.js';
7
6
  import { clearProviders, getProvider as getRegisteredProvider, getProviders as getRegisteredProviders, registerProvider, unregisterProviders, } from './provider-registry.js';
8
7
  import { transformMessages } from './transform-messages.js';
9
- export * from './event-stream.js';
10
- export * from './messages.js';
11
8
  export * from './transform-messages.js';
12
- export * from './types.js';
9
+ export * from '@agentic-kit/protocol';
13
10
  export { createAssistantMessageEventStream, EventStream, OllamaClient };
14
11
  export { AnthropicAdapter, OllamaAdapter, OpenAIAdapter };
15
12
  registerModels([...OPENAI_COMPATIBLE_MODELS, ...ANTHROPIC_MODELS, ...OLLAMA_MODELS]);
package/index.d.ts CHANGED
@@ -1,14 +1,12 @@
1
1
  import { AnthropicAdapter, type AnthropicOptions } from '@agentic-kit/anthropic';
2
2
  import { OllamaAdapter, OllamaClient } from '@agentic-kit/ollama';
3
3
  import { OpenAIAdapter, type OpenAIOptions } from '@agentic-kit/openai';
4
- import { createAssistantMessageEventStream, EventStream } from './event-stream.js';
4
+ import type { AssistantMessage, AssistantMessageEventStream, Context, LegacyChatMessage, LegacyGenerateInput, LegacyStreamingOptions, ModelDescriptor, ProviderAdapter, StreamOptions } from '@agentic-kit/protocol';
5
+ import { createAssistantMessageEventStream, EventStream } from '@agentic-kit/protocol';
5
6
  import { clearModels, getModel, getModels, getProviders as getModelProviders, registerModel, registerModels } from './model-registry.js';
6
7
  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
8
  export * from './transform-messages.js';
11
- export * from './types.js';
9
+ export * from '@agentic-kit/protocol';
12
10
  export { createAssistantMessageEventStream, EventStream, OllamaClient };
13
11
  export { AnthropicAdapter, OllamaAdapter, OpenAIAdapter };
14
12
  export type { AnthropicOptions, OpenAIOptions };
package/index.js CHANGED
@@ -29,10 +29,9 @@ Object.defineProperty(exports, "OllamaAdapter", { enumerable: true, get: functio
29
29
  Object.defineProperty(exports, "OllamaClient", { enumerable: true, get: function () { return ollama_1.OllamaClient; } });
30
30
  const openai_1 = require("@agentic-kit/openai");
31
31
  Object.defineProperty(exports, "OpenAIAdapter", { enumerable: true, get: function () { return openai_1.OpenAIAdapter; } });
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");
32
+ const protocol_1 = require("@agentic-kit/protocol");
33
+ Object.defineProperty(exports, "createAssistantMessageEventStream", { enumerable: true, get: function () { return protocol_1.createAssistantMessageEventStream; } });
34
+ Object.defineProperty(exports, "EventStream", { enumerable: true, get: function () { return protocol_1.EventStream; } });
36
35
  const model_registry_js_1 = require("./model-registry.js");
37
36
  Object.defineProperty(exports, "clearModels", { enumerable: true, get: function () { return model_registry_js_1.clearModels; } });
38
37
  Object.defineProperty(exports, "getModel", { enumerable: true, get: function () { return model_registry_js_1.getModel; } });
@@ -47,10 +46,8 @@ Object.defineProperty(exports, "getRegisteredProviders", { enumerable: true, get
47
46
  Object.defineProperty(exports, "registerProvider", { enumerable: true, get: function () { return provider_registry_js_1.registerProvider; } });
48
47
  Object.defineProperty(exports, "unregisterProviders", { enumerable: true, get: function () { return provider_registry_js_1.unregisterProviders; } });
49
48
  const transform_messages_js_1 = require("./transform-messages.js");
50
- __exportStar(require("./event-stream.js"), exports);
51
- __exportStar(require("./messages.js"), exports);
52
49
  __exportStar(require("./transform-messages.js"), exports);
53
- __exportStar(require("./types.js"), exports);
50
+ __exportStar(require("@agentic-kit/protocol"), exports);
54
51
  (0, model_registry_js_1.registerModels)([...openai_1.OPENAI_COMPATIBLE_MODELS, ...anthropic_1.ANTHROPIC_MODELS, ...ollama_1.OLLAMA_MODELS]);
55
52
  (0, provider_registry_js_1.registerProvider)(new openai_1.OpenAIAdapter());
56
53
  (0, provider_registry_js_1.registerProvider)(new anthropic_1.AnthropicAdapter({ apiKey: '' }));
@@ -68,7 +65,7 @@ async function complete(model, context, options) {
68
65
  }
69
66
  async function completeText(model, context, options) {
70
67
  const message = await complete(model, context, options);
71
- return (0, messages_js_1.getMessageText)(message);
68
+ return (0, protocol_1.getMessageText)(message);
72
69
  }
73
70
  class AgentKit {
74
71
  providers = new Map();
@@ -126,7 +123,7 @@ class AgentKit {
126
123
  try {
127
124
  const message = assertLegacyGenerateSucceeded(await completeWithProvider(provider, model, context, streamOptions));
128
125
  options?.onStateChange?.('complete');
129
- const text = (0, messages_js_1.getMessageText)(message);
126
+ const text = (0, protocol_1.getMessageText)(message);
130
127
  options?.onComplete?.();
131
128
  return text;
132
129
  }
@@ -167,7 +164,7 @@ function legacyInputToContext(input) {
167
164
  provider: 'legacy',
168
165
  model: input.model,
169
166
  content: [{ type: 'text', text: message.content }],
170
- usage: (0, messages_js_1.createEmptyUsage)(),
167
+ usage: (0, protocol_1.createEmptyUsage)(),
171
168
  stopReason: 'stop',
172
169
  timestamp: Date.now(),
173
170
  }
@@ -202,7 +199,7 @@ function createLegacyModel(provider, modelId, maxTokens) {
202
199
  };
203
200
  }
204
201
  function streamWithProvider(provider, model, context, options) {
205
- const normalized = (0, messages_js_1.normalizeContext)(context);
202
+ const normalized = (0, protocol_1.normalizeContext)(context);
206
203
  const transformedContext = {
207
204
  ...normalized,
208
205
  messages: (0, transform_messages_js_1.transformMessages)(normalized.messages, model),
@@ -1,4 +1,4 @@
1
- import type { ModelDescriptor } from './types.js';
1
+ import type { ModelDescriptor } from '@agentic-kit/protocol';
2
2
  export declare function registerModel(model: ModelDescriptor): void;
3
3
  export declare function registerModels(models: ModelDescriptor[]): void;
4
4
  export declare function getModel(provider: string, modelId: string): ModelDescriptor | undefined;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentic-kit",
3
- "version": "1.3.1",
3
+ "version": "1.3.2",
4
4
  "author": "Dan Lynch <pyramation@gmail.com>",
5
5
  "description": "Provider-agnostic LLM adapter with streaming and multi-turn support",
6
6
  "main": "index.js",
@@ -37,10 +37,11 @@
37
37
  "test:watch": "jest --watch"
38
38
  },
39
39
  "dependencies": {
40
- "@agentic-kit/anthropic": "1.2.1",
41
- "@agentic-kit/ollama": "2.0.0",
42
- "@agentic-kit/openai": "1.2.1"
40
+ "@agentic-kit/anthropic": "1.2.2",
41
+ "@agentic-kit/ollama": "2.0.1",
42
+ "@agentic-kit/openai": "1.2.2",
43
+ "@agentic-kit/protocol": "1.1.0"
43
44
  },
44
45
  "keywords": [],
45
- "gitHead": "c2b13e65b26f14c9983e9b7cc4eafbe4919b13d4"
46
+ "gitHead": "fbf34d1146e8543664d904f75e5b3440f2b1d2a4"
46
47
  }
@@ -1,4 +1,4 @@
1
- import type { ProviderAdapter } from './types.js';
1
+ import type { ProviderAdapter } from '@agentic-kit/protocol';
2
2
  export declare function registerProvider(adapter: ProviderAdapter, sourceId?: string): void;
3
3
  export declare function getProvider(api: string): ProviderAdapter | undefined;
4
4
  export declare function getProviders(): ProviderAdapter[];
@@ -1,2 +1,2 @@
1
- import type { Message, ModelDescriptor } from './types.js';
1
+ import type { Message, ModelDescriptor } from '@agentic-kit/protocol';
2
2
  export declare function transformMessages(messages: Message[], model: ModelDescriptor): Message[];
@@ -1,77 +0,0 @@
1
- export class EventStream {
2
- isTerminal;
3
- extractResult;
4
- queue = [];
5
- waiting = [];
6
- done = false;
7
- finalResultPromise;
8
- resolveFinalResult;
9
- constructor(isTerminal, extractResult) {
10
- this.isTerminal = isTerminal;
11
- this.extractResult = extractResult;
12
- this.finalResultPromise = new Promise((resolve) => {
13
- this.resolveFinalResult = resolve;
14
- });
15
- }
16
- push(event) {
17
- if (this.done) {
18
- return;
19
- }
20
- if (this.isTerminal(event)) {
21
- this.done = true;
22
- this.resolveFinalResult(this.extractResult(event));
23
- }
24
- const waiter = this.waiting.shift();
25
- if (waiter) {
26
- waiter({ value: event, done: false });
27
- return;
28
- }
29
- this.queue.push(event);
30
- }
31
- end(result) {
32
- this.done = true;
33
- if (result !== undefined) {
34
- this.resolveFinalResult(result);
35
- }
36
- while (this.waiting.length > 0) {
37
- this.waiting.shift()({ value: undefined, done: true });
38
- }
39
- }
40
- async *[Symbol.asyncIterator]() {
41
- while (true) {
42
- if (this.queue.length > 0) {
43
- yield this.queue.shift();
44
- continue;
45
- }
46
- if (this.done) {
47
- return;
48
- }
49
- const next = await new Promise((resolve) => {
50
- this.waiting.push(resolve);
51
- });
52
- if (next.done) {
53
- return;
54
- }
55
- yield next.value;
56
- }
57
- }
58
- result() {
59
- return this.finalResultPromise;
60
- }
61
- }
62
- export class DefaultAssistantMessageEventStream extends EventStream {
63
- constructor() {
64
- super((event) => event.type === 'done' || event.type === 'error', (event) => {
65
- if (event.type === 'done') {
66
- return event.message;
67
- }
68
- if (event.type === 'error') {
69
- return event.error;
70
- }
71
- throw new Error('Unexpected terminal event');
72
- });
73
- }
74
- }
75
- export function createAssistantMessageEventStream() {
76
- return new DefaultAssistantMessageEventStream();
77
- }
package/esm/messages.js DELETED
@@ -1,147 +0,0 @@
1
- export function createEmptyUsage() {
2
- return {
3
- input: 0,
4
- output: 0,
5
- reasoning: 0,
6
- cacheRead: 0,
7
- cacheWrite: 0,
8
- totalTokens: 0,
9
- cost: {
10
- input: 0,
11
- output: 0,
12
- cacheRead: 0,
13
- cacheWrite: 0,
14
- total: 0,
15
- },
16
- };
17
- }
18
- export function calculateUsageCost(model, usage) {
19
- const schedule = model.cost;
20
- usage.cost.input = ((schedule?.input ?? 0) / 1_000_000) * usage.input;
21
- usage.cost.output = ((schedule?.output ?? 0) / 1_000_000) * usage.output;
22
- usage.cost.cacheRead = ((schedule?.cacheRead ?? 0) / 1_000_000) * usage.cacheRead;
23
- usage.cost.cacheWrite = ((schedule?.cacheWrite ?? 0) / 1_000_000) * usage.cacheWrite;
24
- usage.cost.total =
25
- usage.cost.input + usage.cost.output + usage.cost.cacheRead + usage.cost.cacheWrite;
26
- }
27
- export function snapshotUsage(usage) {
28
- return { ...usage, cost: { ...usage.cost } };
29
- }
30
- export function addUsage(target, delta) {
31
- target.input += delta.input;
32
- target.output += delta.output;
33
- target.reasoning += delta.reasoning;
34
- target.cacheRead += delta.cacheRead;
35
- target.cacheWrite += delta.cacheWrite;
36
- target.totalTokens += delta.totalTokens;
37
- target.cost.input += delta.cost.input;
38
- target.cost.output += delta.cost.output;
39
- target.cost.cacheRead += delta.cost.cacheRead;
40
- target.cost.cacheWrite += delta.cost.cacheWrite;
41
- target.cost.total += delta.cost.total;
42
- return target;
43
- }
44
- export function createAssistantMessage(model) {
45
- return {
46
- role: 'assistant',
47
- api: model.api,
48
- provider: model.provider,
49
- model: model.id,
50
- content: [],
51
- usage: createEmptyUsage(),
52
- stopReason: 'stop',
53
- timestamp: Date.now(),
54
- };
55
- }
56
- export function createTextContent(text = '') {
57
- return { type: 'text', text };
58
- }
59
- export function createImageContent(data, mimeType) {
60
- return { type: 'image', data, mimeType };
61
- }
62
- export function createToolCall(id, name) {
63
- return { type: 'toolCall', id, name, arguments: {}, rawArguments: '' };
64
- }
65
- export function createUserMessage(content) {
66
- return {
67
- role: 'user',
68
- content,
69
- timestamp: Date.now(),
70
- };
71
- }
72
- export function createToolResultMessage(toolCallId, toolName, content, isError = false) {
73
- return {
74
- role: 'toolResult',
75
- toolCallId,
76
- toolName,
77
- content,
78
- isError,
79
- timestamp: Date.now(),
80
- };
81
- }
82
- export function getMessageText(message) {
83
- return message.content
84
- .filter((block) => block.type === 'text')
85
- .map((block) => block.text)
86
- .join('');
87
- }
88
- const DEFAULT_DEFERRAL_TEXT = 'User did not respond. Continue.';
89
- /**
90
- * Synthesize toolResult messages for every toolCall that lacks both a decision
91
- * and a paired toolResult. Returns input unchanged (referentially equal) when
92
- * nothing needs synthesizing.
93
- *
94
- * Use case: user types a message instead of clicking approve/deny on a paused
95
- * tool. The agent can't resume on text alone — every dangling toolCall needs
96
- * a result before the next request. Compose with sendMessages to forward the
97
- * conversation cleanly:
98
- *
99
- * await sendMessages([...injectDeferralResults(messages), createUserMessage(text)]);
100
- */
101
- export function injectDeferralResults(messages, optionsOrText = {}) {
102
- const opts = typeof optionsOrText === 'string' ? { deferralText: optionsOrText } : optionsOrText;
103
- const deferralText = opts.deferralText ?? DEFAULT_DEFERRAL_TEXT;
104
- const completed = new Set();
105
- for (const m of messages) {
106
- if (m.role === 'toolResult')
107
- completed.add(m.toolCallId);
108
- }
109
- const synthetic = [];
110
- for (const m of messages) {
111
- if (m.role !== 'assistant')
112
- continue;
113
- for (const block of m.content) {
114
- if (block.type !== 'toolCall')
115
- continue;
116
- if (completed.has(block.id))
117
- continue;
118
- if ('decision' in block && block.decision !== undefined)
119
- continue;
120
- const result = createToolResultMessage(block.id, block.name, [
121
- { type: 'text', text: deferralText },
122
- ]);
123
- if (opts.details !== undefined)
124
- result.details = opts.details;
125
- synthetic.push(result);
126
- }
127
- }
128
- if (synthetic.length === 0)
129
- return messages;
130
- return [...messages, ...synthetic];
131
- }
132
- export function cloneMessage(message) {
133
- return JSON.parse(JSON.stringify(message));
134
- }
135
- export function normalizeContext(context) {
136
- return {
137
- systemPrompt: context.systemPrompt,
138
- tools: context.tools ?? [],
139
- messages: context.messages.map((message) => ensureTimestamp(cloneMessage(message))),
140
- };
141
- }
142
- function ensureTimestamp(message) {
143
- if (typeof message.timestamp !== 'number') {
144
- message.timestamp = Date.now();
145
- }
146
- return message;
147
- }
package/esm/types.js DELETED
@@ -1 +0,0 @@
1
- export {};
package/event-stream.d.ts DELETED
@@ -1,19 +0,0 @@
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 DELETED
@@ -1,83 +0,0 @@
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/messages.d.ts DELETED
@@ -1,33 +0,0 @@
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;
package/messages.js DELETED
@@ -1,163 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createEmptyUsage = createEmptyUsage;
4
- exports.calculateUsageCost = calculateUsageCost;
5
- exports.snapshotUsage = snapshotUsage;
6
- exports.addUsage = addUsage;
7
- exports.createAssistantMessage = createAssistantMessage;
8
- exports.createTextContent = createTextContent;
9
- exports.createImageContent = createImageContent;
10
- exports.createToolCall = createToolCall;
11
- exports.createUserMessage = createUserMessage;
12
- exports.createToolResultMessage = createToolResultMessage;
13
- exports.getMessageText = getMessageText;
14
- exports.injectDeferralResults = injectDeferralResults;
15
- exports.cloneMessage = cloneMessage;
16
- exports.normalizeContext = normalizeContext;
17
- function createEmptyUsage() {
18
- return {
19
- input: 0,
20
- output: 0,
21
- reasoning: 0,
22
- cacheRead: 0,
23
- cacheWrite: 0,
24
- totalTokens: 0,
25
- cost: {
26
- input: 0,
27
- output: 0,
28
- cacheRead: 0,
29
- cacheWrite: 0,
30
- total: 0,
31
- },
32
- };
33
- }
34
- function calculateUsageCost(model, usage) {
35
- const schedule = model.cost;
36
- usage.cost.input = ((schedule?.input ?? 0) / 1_000_000) * usage.input;
37
- usage.cost.output = ((schedule?.output ?? 0) / 1_000_000) * usage.output;
38
- usage.cost.cacheRead = ((schedule?.cacheRead ?? 0) / 1_000_000) * usage.cacheRead;
39
- usage.cost.cacheWrite = ((schedule?.cacheWrite ?? 0) / 1_000_000) * usage.cacheWrite;
40
- usage.cost.total =
41
- usage.cost.input + usage.cost.output + usage.cost.cacheRead + usage.cost.cacheWrite;
42
- }
43
- function snapshotUsage(usage) {
44
- return { ...usage, cost: { ...usage.cost } };
45
- }
46
- function addUsage(target, delta) {
47
- target.input += delta.input;
48
- target.output += delta.output;
49
- target.reasoning += delta.reasoning;
50
- target.cacheRead += delta.cacheRead;
51
- target.cacheWrite += delta.cacheWrite;
52
- target.totalTokens += delta.totalTokens;
53
- target.cost.input += delta.cost.input;
54
- target.cost.output += delta.cost.output;
55
- target.cost.cacheRead += delta.cost.cacheRead;
56
- target.cost.cacheWrite += delta.cost.cacheWrite;
57
- target.cost.total += delta.cost.total;
58
- return target;
59
- }
60
- function createAssistantMessage(model) {
61
- return {
62
- role: 'assistant',
63
- api: model.api,
64
- provider: model.provider,
65
- model: model.id,
66
- content: [],
67
- usage: createEmptyUsage(),
68
- stopReason: 'stop',
69
- timestamp: Date.now(),
70
- };
71
- }
72
- function createTextContent(text = '') {
73
- return { type: 'text', text };
74
- }
75
- function createImageContent(data, mimeType) {
76
- return { type: 'image', data, mimeType };
77
- }
78
- function createToolCall(id, name) {
79
- return { type: 'toolCall', id, name, arguments: {}, rawArguments: '' };
80
- }
81
- function createUserMessage(content) {
82
- return {
83
- role: 'user',
84
- content,
85
- timestamp: Date.now(),
86
- };
87
- }
88
- function createToolResultMessage(toolCallId, toolName, content, isError = false) {
89
- return {
90
- role: 'toolResult',
91
- toolCallId,
92
- toolName,
93
- content,
94
- isError,
95
- timestamp: Date.now(),
96
- };
97
- }
98
- function getMessageText(message) {
99
- return message.content
100
- .filter((block) => block.type === 'text')
101
- .map((block) => block.text)
102
- .join('');
103
- }
104
- const DEFAULT_DEFERRAL_TEXT = 'User did not respond. Continue.';
105
- /**
106
- * Synthesize toolResult messages for every toolCall that lacks both a decision
107
- * and a paired toolResult. Returns input unchanged (referentially equal) when
108
- * nothing needs synthesizing.
109
- *
110
- * Use case: user types a message instead of clicking approve/deny on a paused
111
- * tool. The agent can't resume on text alone — every dangling toolCall needs
112
- * a result before the next request. Compose with sendMessages to forward the
113
- * conversation cleanly:
114
- *
115
- * await sendMessages([...injectDeferralResults(messages), createUserMessage(text)]);
116
- */
117
- function injectDeferralResults(messages, optionsOrText = {}) {
118
- const opts = typeof optionsOrText === 'string' ? { deferralText: optionsOrText } : optionsOrText;
119
- const deferralText = opts.deferralText ?? DEFAULT_DEFERRAL_TEXT;
120
- const completed = new Set();
121
- for (const m of messages) {
122
- if (m.role === 'toolResult')
123
- completed.add(m.toolCallId);
124
- }
125
- const synthetic = [];
126
- for (const m of messages) {
127
- if (m.role !== 'assistant')
128
- continue;
129
- for (const block of m.content) {
130
- if (block.type !== 'toolCall')
131
- continue;
132
- if (completed.has(block.id))
133
- continue;
134
- if ('decision' in block && block.decision !== undefined)
135
- continue;
136
- const result = createToolResultMessage(block.id, block.name, [
137
- { type: 'text', text: deferralText },
138
- ]);
139
- if (opts.details !== undefined)
140
- result.details = opts.details;
141
- synthetic.push(result);
142
- }
143
- }
144
- if (synthetic.length === 0)
145
- return messages;
146
- return [...messages, ...synthetic];
147
- }
148
- function cloneMessage(message) {
149
- return JSON.parse(JSON.stringify(message));
150
- }
151
- function normalizeContext(context) {
152
- return {
153
- systemPrompt: context.systemPrompt,
154
- tools: context.tools ?? [],
155
- messages: context.messages.map((message) => ensureTimestamp(cloneMessage(message))),
156
- };
157
- }
158
- function ensureTimestamp(message) {
159
- if (typeof message.timestamp !== 'number') {
160
- message.timestamp = Date.now();
161
- }
162
- return message;
163
- }
package/types.d.ts DELETED
@@ -1,232 +0,0 @@
1
- export type JsonPrimitive = string | number | boolean | null;
2
- export type JsonValue = JsonPrimitive | JsonObject | JsonValue[];
3
- export interface JsonObject {
4
- [key: string]: JsonValue | undefined;
5
- }
6
- export interface JsonSchema {
7
- $id?: string;
8
- $ref?: string;
9
- additionalProperties?: boolean | JsonSchema;
10
- allOf?: JsonSchema[];
11
- anyOf?: JsonSchema[];
12
- const?: JsonValue;
13
- default?: JsonValue;
14
- description?: string;
15
- enum?: JsonValue[];
16
- format?: string;
17
- items?: JsonSchema | JsonSchema[];
18
- maxItems?: number;
19
- maxLength?: number;
20
- maximum?: number;
21
- minItems?: number;
22
- minLength?: number;
23
- minimum?: number;
24
- oneOf?: JsonSchema[];
25
- pattern?: string;
26
- properties?: Record<string, JsonSchema>;
27
- required?: string[];
28
- title?: string;
29
- type?: string | string[];
30
- }
31
- export type InputCapability = 'text' | 'image';
32
- export interface CostSchedule {
33
- input?: number;
34
- output?: number;
35
- cacheRead?: number;
36
- cacheWrite?: number;
37
- }
38
- export interface OpenAICompatibleCompat {
39
- maxTokensField?: 'max_completion_tokens' | 'max_tokens';
40
- reasoningFormat?: 'none' | 'openai';
41
- supportsReasoningEffort?: boolean;
42
- supportsStrictToolSchema?: boolean;
43
- supportsUsageInStreaming?: boolean;
44
- toolCallIdFormat?: 'passthrough' | 'safe64' | 'mistral9';
45
- requiresToolResultName?: boolean;
46
- }
47
- export interface ModelDescriptor {
48
- id: string;
49
- name: string;
50
- api: string;
51
- provider: string;
52
- baseUrl: string;
53
- input: InputCapability[];
54
- reasoning: boolean;
55
- tools?: boolean;
56
- contextWindow?: number;
57
- maxOutputTokens?: number;
58
- cost?: CostSchedule;
59
- headers?: Record<string, string>;
60
- compat?: OpenAICompatibleCompat;
61
- }
62
- export interface TextContent {
63
- type: 'text';
64
- text: string;
65
- }
66
- export interface ImageContent {
67
- type: 'image';
68
- data: string;
69
- mimeType: string;
70
- }
71
- export interface ThinkingContent {
72
- type: 'thinking';
73
- thinking: string;
74
- signature?: string;
75
- }
76
- export interface ToolCallContent {
77
- type: 'toolCall';
78
- id: string;
79
- name: string;
80
- arguments: Record<string, JsonValue | undefined>;
81
- rawArguments?: string;
82
- decision?: unknown;
83
- }
84
- export interface Usage {
85
- input: number;
86
- output: number;
87
- reasoning: number;
88
- cacheRead: number;
89
- cacheWrite: number;
90
- totalTokens: number;
91
- cost: {
92
- input: number;
93
- output: number;
94
- cacheRead: number;
95
- cacheWrite: number;
96
- total: number;
97
- };
98
- }
99
- export type StopReason = 'stop' | 'length' | 'toolUse' | 'error' | 'aborted';
100
- export interface UserMessage {
101
- role: 'user';
102
- content: string | Array<TextContent | ImageContent>;
103
- timestamp: number;
104
- }
105
- export interface AssistantMessage {
106
- role: 'assistant';
107
- content: Array<TextContent | ThinkingContent | ToolCallContent>;
108
- api: string;
109
- provider: string;
110
- model: string;
111
- usage: Usage;
112
- stopReason: StopReason;
113
- errorMessage?: string;
114
- timestamp: number;
115
- }
116
- export interface ToolResultMessage<TDetails = unknown> {
117
- role: 'toolResult';
118
- toolCallId: string;
119
- toolName: string;
120
- content: Array<TextContent | ImageContent>;
121
- isError: boolean;
122
- details?: TDetails;
123
- timestamp: number;
124
- }
125
- export type Message = UserMessage | AssistantMessage | ToolResultMessage;
126
- export interface ToolDefinition<TSchema extends JsonSchema = JsonSchema> {
127
- name: string;
128
- description: string;
129
- parameters: TSchema;
130
- }
131
- export interface Context {
132
- systemPrompt?: string;
133
- messages: Message[];
134
- tools?: ToolDefinition[];
135
- }
136
- export type CacheRetention = 'none' | 'short' | 'long';
137
- export interface StreamOptions {
138
- apiKey?: string;
139
- cacheRetention?: CacheRetention;
140
- headers?: Record<string, string>;
141
- maxRetryDelayMs?: number;
142
- maxTokens?: number;
143
- metadata?: Record<string, JsonValue | undefined>;
144
- onPayload?: (payload: unknown) => void;
145
- reasoning?: 'minimal' | 'low' | 'medium' | 'high' | 'xhigh';
146
- sessionId?: string;
147
- signal?: AbortSignal;
148
- temperature?: number;
149
- }
150
- export type AssistantMessageEvent = {
151
- type: 'start';
152
- partial: AssistantMessage;
153
- } | {
154
- type: 'text_start';
155
- contentIndex: number;
156
- partial: AssistantMessage;
157
- } | {
158
- type: 'text_delta';
159
- contentIndex: number;
160
- delta: string;
161
- partial: AssistantMessage;
162
- } | {
163
- type: 'text_end';
164
- contentIndex: number;
165
- content: string;
166
- partial: AssistantMessage;
167
- } | {
168
- type: 'thinking_start';
169
- contentIndex: number;
170
- partial: AssistantMessage;
171
- } | {
172
- type: 'thinking_delta';
173
- contentIndex: number;
174
- delta: string;
175
- partial: AssistantMessage;
176
- } | {
177
- type: 'thinking_end';
178
- contentIndex: number;
179
- content: string;
180
- partial: AssistantMessage;
181
- } | {
182
- type: 'toolcall_start';
183
- contentIndex: number;
184
- partial: AssistantMessage;
185
- } | {
186
- type: 'toolcall_delta';
187
- contentIndex: number;
188
- delta: string;
189
- partial: AssistantMessage;
190
- } | {
191
- type: 'toolcall_end';
192
- contentIndex: number;
193
- toolCall: ToolCallContent;
194
- partial: AssistantMessage;
195
- } | {
196
- type: 'done';
197
- reason: Extract<StopReason, 'stop' | 'length' | 'toolUse'>;
198
- message: AssistantMessage;
199
- } | {
200
- type: 'error';
201
- reason: Extract<StopReason, 'error' | 'aborted'>;
202
- error: AssistantMessage;
203
- };
204
- export interface ProviderAdapter<TOptions extends StreamOptions = StreamOptions> {
205
- api: string;
206
- provider: string;
207
- createModel?: (modelId: string, overrides?: Partial<ModelDescriptor>) => ModelDescriptor;
208
- listModels?: (options?: Pick<StreamOptions, 'apiKey' | 'headers'>) => Promise<Array<ModelDescriptor | string>>;
209
- stream: (model: ModelDescriptor, context: Context, options?: TOptions) => AssistantMessageEventStream;
210
- }
211
- export interface LegacyChatMessage {
212
- role: 'system' | 'user' | 'assistant';
213
- content: string;
214
- }
215
- export interface LegacyGenerateInput {
216
- model: string;
217
- prompt?: string;
218
- messages?: LegacyChatMessage[];
219
- system?: string;
220
- stream?: boolean;
221
- temperature?: number;
222
- maxTokens?: number;
223
- }
224
- export interface LegacyStreamingOptions {
225
- onChunk?: (chunk: string) => void;
226
- onComplete?: () => void;
227
- onError?: (error: Error) => void;
228
- onStateChange?: (state: string) => void;
229
- }
230
- export interface AssistantMessageEventStream extends AsyncIterable<AssistantMessageEvent> {
231
- result(): Promise<AssistantMessage>;
232
- }
package/types.js DELETED
@@ -1,2 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });