agentic-kit 1.10.0 → 2.1.1

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 CHANGED
@@ -5,119 +5,40 @@
5
5
  </p>
6
6
 
7
7
  <p align="center" width="100%">
8
- <a href="https://github.com/constructive-io/agentic-kit/actions/workflows/run-tests.yaml">
9
- <img height="20" src="https://github.com/constructive-io/agentic-kit/actions/workflows/run-tests.yaml/badge.svg" />
8
+ <a href="https://github.com/constructive-io/constructive/actions/workflows/run-tests.yaml">
9
+ <img height="20" src="https://github.com/constructive-io/constructive/actions/workflows/run-tests.yaml/badge.svg" />
10
10
  </a>
11
- <a href="https://github.com/constructive-io/agentic-kit/blob/main/LICENSE"><img height="20" src="https://img.shields.io/badge/license-MIT-blue.svg"/></a>
12
- <a href="https://www.npmjs.com/package/agentic-kit"><img height="20" src="https://img.shields.io/github/package-json/v/constructive-io/agentic-kit?filename=packages%2Fagentic-kit%2Fpackage.json"/></a>
11
+ <a href="https://github.com/constructive-io/constructive/blob/main/LICENSE"><img height="20" src="https://img.shields.io/badge/license-MIT-blue.svg"/></a>
12
+ <a href="https://www.npmjs.com/package/agentic-kit"><img height="20" src="https://img.shields.io/github/package-json/v/constructive-io/constructive?filename=agentic%2Fagentic-kit%2Fpackage.json"/></a>
13
13
  </p>
14
14
 
15
- A low-level provider portability layer for LLM applications. `agentic-kit`
16
- provides:
15
+ Umbrella package for the agentic-kit family — build your own custom agents with a provider-agnostic chat layer, a stateful agent runtime, and the Constructive harness.
17
16
 
18
- - provider-independent `ModelDescriptor` and `Context` types
19
- - structured streaming events for text, reasoning, and tool calls
20
- - model and provider registries
21
- - cross-provider message normalization for replay and handoff
22
- - a one-release compatibility wrapper for the legacy `AgentKit.generate()` API
23
-
24
- ## Installation
25
-
26
- ```bash
27
- npm install agentic-kit
28
- ```
29
-
30
-
31
- ## Quick Start
32
-
33
- ### Structured API
17
+ ## Usage
34
18
 
35
19
  ```typescript
36
- import { complete, getModel } from 'agentic-kit';
37
-
38
- const model = getModel('openai', 'gpt-4o-mini');
39
- const message = await complete(model!, {
40
- messages: [{ role: 'user', content: 'Hello', timestamp: Date.now() }],
41
- });
42
-
43
- console.log(message.content);
44
- ```
20
+ // Chat layer (re-exported at the top level, same API as @agentic-kit/chat)
21
+ import { complete, stream, createOpenAIKit } from 'agentic-kit';
45
22
 
46
- ### Streaming
23
+ // Agent runtime
24
+ import { agent } from 'agentic-kit';
47
25
 
48
- ```typescript
49
- import { stream, getModel } from 'agentic-kit';
50
-
51
- const model = getModel('openai', 'gpt-4o-mini');
52
- const result = stream(model!, {
53
- messages: [{ role: 'user', content: 'Explain tool calling briefly.', timestamp: Date.now() }],
54
- });
55
-
56
- for await (const event of result) {
57
- if (event.type === 'text_delta') {
58
- process.stdout.write(event.delta);
59
- }
60
- }
26
+ // Harness (skills resolution, gating, blueprints)
27
+ import { harness } from 'agentic-kit';
61
28
  ```
62
29
 
63
- ## API Reference
64
-
65
- ### Core API
66
-
67
- - `stream(model: ModelDescriptor, context: Context, options?: StreamOptions)`
68
- - `complete(model: ModelDescriptor, context: Context, options?: StreamOptions)`
69
- - `completeText(model: ModelDescriptor, context: Context, options?: StreamOptions)`
70
-
71
- ### Registry
72
-
73
- - `registerModel(model)`, `registerModels(models)`, `clearModels()`
74
- - `registerProvider(provider, sourceId?)`, `unregisterProviders(sourceId)`, `clearProviders()`
75
- - `getModel(provider, modelId)`, `getModels(provider?)`, `getModelProviders()`
76
- - `getProvider(api)`, `getRegisteredProviders()`
77
-
78
- The package pre-registers `OpenAIAdapter`, `AnthropicAdapter`, and
79
- `OllamaAdapter` (with empty credentials) plus the built-in model catalogs
80
- from each adapter package. Re-register an adapter with your own API key to
81
- activate it.
82
-
83
- ### Message helpers
84
-
85
- - `createUserMessage(content)`, `createAssistantMessage(model)`,
86
- `createToolResultMessage(toolCallId, toolName, content, isError?)`
87
- - `createTextContent(text?)`, `createImageContent(data, mimeType)`,
88
- `createToolCall(id, name)`
89
- - `getMessageText(assistant)` — concatenate text blocks.
90
- - `cloneMessage(message)` — deep clone.
91
- - `normalizeContext(context)` — apply per-message normalization.
92
- - `injectDeferralResults(messages, options?)` — synthesize stand-in
93
- `toolResult` messages for every `toolCall` that lacks both a decision and
94
- a paired result. Useful when the user types a new message instead of
95
- responding to a paused tool — the next request needs a well-formed
96
- transcript.
97
- - `transformMessages(messages, model)` — cross-provider normalization for
98
- replay across different providers.
99
-
100
- ### Adapter re-exports
101
-
102
- - `OpenAIAdapter`, `AnthropicAdapter`, `OllamaAdapter`
103
- - Types: `OpenAIOptions`, `AnthropicOptions`
104
- - `OllamaClient` for direct Ollama HTTP access.
105
-
106
- ### Legacy Compatibility API
107
-
108
- `AgentKit` is still available for one transition release:
109
-
110
- ```ts
111
- interface GenerateInput {
112
- model: string;
113
- prompt?: string;
114
- messages?: Array<{ role: 'system' | 'user' | 'assistant'; content: string }>;
115
- stream?: boolean;
116
- }
117
- ```
30
+ ## Packages
118
31
 
119
- Use `createOpenAIKit`, `createAnthropicKit`, `createOllamaKit`, or
120
- `createMultiProviderKit()` if you still need the old prompt-only entrypoint.
32
+ | Package | Description |
33
+ |---------|-------------|
34
+ | [`@agentic-kit/chat`](https://github.com/constructive-io/constructive/tree/main/agentic/chat) | Provider-agnostic LLM adapter with streaming and multi-turn support |
35
+ | [`@agentic-kit/protocol`](https://github.com/constructive-io/constructive/tree/main/agentic/protocol) | Shared types and event stream |
36
+ | [`@agentic-kit/openai`](https://github.com/constructive-io/constructive/tree/main/agentic/openai) | OpenAI-compatible provider adapter |
37
+ | [`@agentic-kit/anthropic`](https://github.com/constructive-io/constructive/tree/main/agentic/anthropic) | Anthropic provider adapter |
38
+ | [`@agentic-kit/ollama`](https://github.com/constructive-io/constructive/tree/main/agentic/ollama) | Ollama provider adapter |
39
+ | [`@agentic-kit/agent`](https://github.com/constructive-io/constructive/tree/main/agentic/agent) | Minimal stateful agent runtime |
40
+ | [`@agentic-kit/harness`](https://github.com/constructive-io/constructive/tree/main/agentic/harness) | Host-neutral coding-agent harness: skills layers, confirm gating, blueprints |
41
+ | [`@agentic-kit/react`](https://github.com/constructive-io/constructive/tree/main/agentic/react) | React bindings (`useChat`) — install separately (React peer dependency) |
121
42
 
122
43
  ---
123
44
 
@@ -153,6 +74,7 @@ Common issues and solutions for pgpm, PostgreSQL, and testing.
153
74
  ### 🧪 Testing
154
75
 
155
76
  * [pgsql-test](https://github.com/constructive-io/constructive/tree/main/postgres/pgsql-test): **📊 Isolated testing environments** with per-test transaction rollbacks—ideal for integration tests, complex migrations, and RLS simulation.
77
+ * [pglite-test](https://github.com/constructive-io/constructive/tree/main/postgres/pglite-test): **🪶 Drop-in pgsql-test replacement backed by PGlite** — in-process Postgres, no server required, instance-per-suite isolation.
156
78
  * [pgsql-seed](https://github.com/constructive-io/constructive/tree/main/postgres/pgsql-seed): **🌱 PostgreSQL seeding utilities** for CSV, JSON, SQL data loading, and pgpm deployment.
157
79
  * [supabase-test](https://github.com/constructive-io/constructive/tree/main/postgres/supabase-test): **🧪 Supabase-native test harness** preconfigured for the local Supabase stack—per-test rollbacks, JWT/role context helpers, and CI/GitHub Actions ready.
158
80
  * [graphile-test](https://github.com/constructive-io/constructive/tree/main/graphile/graphile-test): **🔐 Authentication mocking** for Graphile-focused test helpers and emulating row-level security contexts.
package/esm/index.js CHANGED
@@ -1,183 +1,3 @@
1
- import { ANTHROPIC_MODELS, AnthropicAdapter } from '@agentic-kit/anthropic';
2
- import { OLLAMA_MODELS, OllamaAdapter, OllamaClient } from '@agentic-kit/ollama';
3
- import { OPENAI_COMPATIBLE_MODELS, OpenAIAdapter, } from '@agentic-kit/openai';
4
- import { createAssistantMessageEventStream, createEmptyUsage, EventStream, getMessageText, normalizeContext, } from '@agentic-kit/protocol';
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 { transformMessages } from './transform-messages.js';
8
- export * from './transform-messages.js';
9
- export * from '@agentic-kit/protocol';
10
- export { createAssistantMessageEventStream, EventStream, OllamaClient };
11
- export { AnthropicAdapter, OllamaAdapter, OpenAIAdapter };
12
- registerModels([...OPENAI_COMPATIBLE_MODELS, ...ANTHROPIC_MODELS, ...OLLAMA_MODELS]);
13
- registerProvider(new OpenAIAdapter());
14
- registerProvider(new AnthropicAdapter({ apiKey: '' }));
15
- registerProvider(new OllamaAdapter());
16
- export function stream(model, context, options) {
17
- const provider = getRegisteredProvider(model.api);
18
- if (!provider) {
19
- throw new Error(`No provider registered for api '${model.api}'`);
20
- }
21
- return streamWithProvider(provider, model, context, options);
22
- }
23
- export async function complete(model, context, options) {
24
- const response = stream(model, context, options);
25
- return response.result();
26
- }
27
- export async function completeText(model, context, options) {
28
- const message = await complete(model, context, options);
29
- return getMessageText(message);
30
- }
31
- export class AgentKit {
32
- providers = new Map();
33
- current;
34
- addProvider(provider) {
35
- this.providers.set(getProviderName(provider), provider);
36
- if (!this.current) {
37
- this.current = provider;
38
- }
39
- return this;
40
- }
41
- setProvider(name) {
42
- const provider = this.providers.get(name);
43
- if (!provider) {
44
- throw new Error(`Provider '${name}' not found`);
45
- }
46
- this.current = provider;
47
- return this;
48
- }
49
- getCurrentProvider() {
50
- return this.current;
51
- }
52
- listProviders() {
53
- return Array.from(this.providers.keys());
54
- }
55
- async generate(input, options) {
56
- if (!this.current) {
57
- throw new Error('No provider set. Call addProvider() first.');
58
- }
59
- const provider = this.current;
60
- const model = createLegacyModel(provider, input.model, input.maxTokens);
61
- const context = legacyInputToContext(input);
62
- const streamOptions = {
63
- maxTokens: input.maxTokens,
64
- temperature: input.temperature,
65
- };
66
- if (options?.onChunk || input.stream) {
67
- options?.onStateChange?.('streaming');
68
- try {
69
- const response = streamWithProvider(provider, model, context, streamOptions);
70
- for await (const event of response) {
71
- if (event.type === 'text_delta') {
72
- options?.onChunk?.(event.delta);
73
- }
74
- }
75
- assertLegacyGenerateSucceeded(await response.result());
76
- options?.onComplete?.();
77
- }
78
- catch (error) {
79
- options?.onError?.(error);
80
- throw error;
81
- }
82
- return;
83
- }
84
- try {
85
- const message = assertLegacyGenerateSucceeded(await completeWithProvider(provider, model, context, streamOptions));
86
- options?.onStateChange?.('complete');
87
- const text = getMessageText(message);
88
- options?.onComplete?.();
89
- return text;
90
- }
91
- catch (error) {
92
- options?.onError?.(error);
93
- throw error;
94
- }
95
- }
96
- async listModels() {
97
- if (!this.current?.listModels) {
98
- return [];
99
- }
100
- const models = await this.current.listModels();
101
- return models.map((model) => (typeof model === 'string' ? model : model.id));
102
- }
103
- }
104
- export function createOllamaKit(baseUrl) {
105
- return new AgentKit().addProvider(new OllamaAdapter(baseUrl));
106
- }
107
- export function createAnthropicKit(options) {
108
- return new AgentKit().addProvider(new AnthropicAdapter(options));
109
- }
110
- export function createOpenAIKit(options) {
111
- return new AgentKit().addProvider(new OpenAIAdapter(options));
112
- }
113
- export function createMultiProviderKit() {
114
- return new AgentKit();
115
- }
116
- export { clearModels, clearProviders, getModel, getModelProviders, getModels, getRegisteredProvider as getProvider, getRegisteredProviders, registerModel, registerModels, registerProvider, unregisterProviders, };
117
- function legacyInputToContext(input) {
118
- const messages = input.messages
119
- ? input.messages
120
- .filter((message) => message.role !== 'system')
121
- .map((message) => message.role === 'assistant'
122
- ? {
123
- role: 'assistant',
124
- api: 'legacy',
125
- provider: 'legacy',
126
- model: input.model,
127
- content: [{ type: 'text', text: message.content }],
128
- usage: createEmptyUsage(),
129
- stopReason: 'stop',
130
- timestamp: Date.now(),
131
- }
132
- : {
133
- role: 'user',
134
- content: message.content,
135
- timestamp: Date.now(),
136
- })
137
- : [{ role: 'user', content: input.prompt ?? '', timestamp: Date.now() }];
138
- const systemPrompt = input.system ?? input.messages?.find((message) => message.role === 'system')?.content;
139
- return {
140
- systemPrompt,
141
- messages,
142
- };
143
- }
144
- function createLegacyModel(provider, modelId, maxTokens) {
145
- if (provider.createModel) {
146
- return provider.createModel(modelId, {
147
- maxOutputTokens: maxTokens,
148
- });
149
- }
150
- return {
151
- id: modelId,
152
- name: modelId,
153
- api: provider.api,
154
- provider: getProviderName(provider),
155
- baseUrl: '',
156
- input: ['text'],
157
- reasoning: false,
158
- tools: true,
159
- maxOutputTokens: maxTokens,
160
- };
161
- }
162
- function streamWithProvider(provider, model, context, options) {
163
- const normalized = normalizeContext(context);
164
- const transformedContext = {
165
- ...normalized,
166
- messages: transformMessages(normalized.messages, model),
167
- };
168
- return provider.stream(model, transformedContext, options);
169
- }
170
- async function completeWithProvider(provider, model, context, options) {
171
- const response = streamWithProvider(provider, model, context, options);
172
- return response.result();
173
- }
174
- function getProviderName(provider) {
175
- return provider.name ?? provider.provider;
176
- }
177
- function assertLegacyGenerateSucceeded(message) {
178
- if (message.stopReason === 'error' || message.stopReason === 'aborted') {
179
- throw new Error(message.errorMessage ??
180
- (message.stopReason === 'aborted' ? 'Generation aborted.' : 'Generation failed.'), { cause: message });
181
- }
182
- return message;
183
- }
1
+ export * from '@agentic-kit/chat';
2
+ export * as agent from '@agentic-kit/agent';
3
+ export * as harness from '@agentic-kit/harness';
package/index.d.ts CHANGED
@@ -1,34 +1,3 @@
1
- import { AnthropicAdapter, type AnthropicOptions } from '@agentic-kit/anthropic';
2
- import { OllamaAdapter, OllamaClient } from '@agentic-kit/ollama';
3
- import { OpenAIAdapter, type OpenAIOptions } from '@agentic-kit/openai';
4
- import { type AssistantMessage, type AssistantMessageEventStream, type Context, createAssistantMessageEventStream, EventStream, type LegacyChatMessage, type LegacyGenerateInput, type LegacyStreamingOptions, type ModelDescriptor, type ProviderAdapter, type StreamOptions } from '@agentic-kit/protocol';
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
- export * from './transform-messages.js';
8
- export * from '@agentic-kit/protocol';
9
- export { createAssistantMessageEventStream, EventStream, OllamaClient };
10
- export { AnthropicAdapter, OllamaAdapter, OpenAIAdapter };
11
- export type { AnthropicOptions, OpenAIOptions };
12
- export type ChatMessage = LegacyChatMessage;
13
- export type GenerateInput = LegacyGenerateInput;
14
- type NamedProviderAdapter = ProviderAdapter & {
15
- name?: string;
16
- };
17
- export declare function stream(model: ModelDescriptor, context: Context, options?: StreamOptions): AssistantMessageEventStream;
18
- export declare function complete(model: ModelDescriptor, context: Context, options?: StreamOptions): Promise<AssistantMessage>;
19
- export declare function completeText(model: ModelDescriptor, context: Context, options?: StreamOptions): Promise<string>;
20
- export declare class AgentKit {
21
- private readonly providers;
22
- private current?;
23
- addProvider(provider: NamedProviderAdapter): this;
24
- setProvider(name: string): this;
25
- getCurrentProvider(): NamedProviderAdapter | undefined;
26
- listProviders(): string[];
27
- generate(input: LegacyGenerateInput, options?: LegacyStreamingOptions): Promise<string | void>;
28
- listModels(): Promise<string[]>;
29
- }
30
- export declare function createOllamaKit(baseUrl?: string): AgentKit;
31
- export declare function createAnthropicKit(options: AnthropicOptions | string): AgentKit;
32
- export declare function createOpenAIKit(options?: OpenAIOptions | string): AgentKit;
33
- export declare function createMultiProviderKit(): AgentKit;
34
- export { clearModels, clearProviders, getModel, getModelProviders, getModels, getRegisteredProvider as getProvider, getRegisteredProviders, registerModel, registerModels, registerProvider, unregisterProviders, };
1
+ export * from '@agentic-kit/chat';
2
+ export * as agent from '@agentic-kit/agent';
3
+ export * as harness from '@agentic-kit/harness';
package/index.js CHANGED
@@ -10,213 +10,33 @@ var __createBinding = (this && this.__createBinding) || (Object.create ? (functi
10
10
  if (k2 === undefined) k2 = k;
11
11
  o[k2] = m[k];
12
12
  }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
13
18
  var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
19
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
20
  };
16
- Object.defineProperty(exports, "__esModule", { value: true });
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;
21
- exports.createOllamaKit = createOllamaKit;
22
- exports.createAnthropicKit = createAnthropicKit;
23
- exports.createOpenAIKit = createOpenAIKit;
24
- exports.createMultiProviderKit = createMultiProviderKit;
25
- const anthropic_1 = require("@agentic-kit/anthropic");
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; } });
30
- const openai_1 = require("@agentic-kit/openai");
31
- Object.defineProperty(exports, "OpenAIAdapter", { enumerable: true, get: function () { return openai_1.OpenAIAdapter; } });
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; } });
35
- const model_registry_js_1 = require("./model-registry.js");
36
- Object.defineProperty(exports, "clearModels", { enumerable: true, get: function () { return model_registry_js_1.clearModels; } });
37
- Object.defineProperty(exports, "getModel", { enumerable: true, get: function () { return model_registry_js_1.getModel; } });
38
- Object.defineProperty(exports, "getModels", { enumerable: true, get: function () { return model_registry_js_1.getModels; } });
39
- Object.defineProperty(exports, "getModelProviders", { enumerable: true, get: function () { return model_registry_js_1.getProviders; } });
40
- Object.defineProperty(exports, "registerModel", { enumerable: true, get: function () { return model_registry_js_1.registerModel; } });
41
- Object.defineProperty(exports, "registerModels", { enumerable: true, get: function () { return model_registry_js_1.registerModels; } });
42
- const provider_registry_js_1 = require("./provider-registry.js");
43
- Object.defineProperty(exports, "clearProviders", { enumerable: true, get: function () { return provider_registry_js_1.clearProviders; } });
44
- Object.defineProperty(exports, "getProvider", { enumerable: true, get: function () { return provider_registry_js_1.getProvider; } });
45
- Object.defineProperty(exports, "getRegisteredProviders", { enumerable: true, get: function () { return provider_registry_js_1.getProviders; } });
46
- Object.defineProperty(exports, "registerProvider", { enumerable: true, get: function () { return provider_registry_js_1.registerProvider; } });
47
- Object.defineProperty(exports, "unregisterProviders", { enumerable: true, get: function () { return provider_registry_js_1.unregisterProviders; } });
48
- const transform_messages_js_1 = require("./transform-messages.js");
49
- __exportStar(require("./transform-messages.js"), exports);
50
- __exportStar(require("@agentic-kit/protocol"), exports);
51
- (0, model_registry_js_1.registerModels)([...openai_1.OPENAI_COMPATIBLE_MODELS, ...anthropic_1.ANTHROPIC_MODELS, ...ollama_1.OLLAMA_MODELS]);
52
- (0, provider_registry_js_1.registerProvider)(new openai_1.OpenAIAdapter());
53
- (0, provider_registry_js_1.registerProvider)(new anthropic_1.AnthropicAdapter({ apiKey: '' }));
54
- (0, provider_registry_js_1.registerProvider)(new ollama_1.OllamaAdapter());
55
- function stream(model, context, options) {
56
- const provider = (0, provider_registry_js_1.getProvider)(model.api);
57
- if (!provider) {
58
- throw new Error(`No provider registered for api '${model.api}'`);
59
- }
60
- return streamWithProvider(provider, model, context, options);
61
- }
62
- async function complete(model, context, options) {
63
- const response = stream(model, context, options);
64
- return response.result();
65
- }
66
- async function completeText(model, context, options) {
67
- const message = await complete(model, context, options);
68
- return (0, protocol_1.getMessageText)(message);
69
- }
70
- class AgentKit {
71
- providers = new Map();
72
- current;
73
- addProvider(provider) {
74
- this.providers.set(getProviderName(provider), provider);
75
- if (!this.current) {
76
- this.current = provider;
77
- }
78
- return this;
79
- }
80
- setProvider(name) {
81
- const provider = this.providers.get(name);
82
- if (!provider) {
83
- throw new Error(`Provider '${name}' not found`);
84
- }
85
- this.current = provider;
86
- return this;
87
- }
88
- getCurrentProvider() {
89
- return this.current;
90
- }
91
- listProviders() {
92
- return Array.from(this.providers.keys());
93
- }
94
- async generate(input, options) {
95
- if (!this.current) {
96
- throw new Error('No provider set. Call addProvider() first.');
97
- }
98
- const provider = this.current;
99
- const model = createLegacyModel(provider, input.model, input.maxTokens);
100
- const context = legacyInputToContext(input);
101
- const streamOptions = {
102
- maxTokens: input.maxTokens,
103
- temperature: input.temperature,
21
+ var __importStar = (this && this.__importStar) || (function () {
22
+ var ownKeys = function(o) {
23
+ ownKeys = Object.getOwnPropertyNames || function (o) {
24
+ var ar = [];
25
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
26
+ return ar;
104
27
  };
105
- if (options?.onChunk || input.stream) {
106
- options?.onStateChange?.('streaming');
107
- try {
108
- const response = streamWithProvider(provider, model, context, streamOptions);
109
- for await (const event of response) {
110
- if (event.type === 'text_delta') {
111
- options?.onChunk?.(event.delta);
112
- }
113
- }
114
- assertLegacyGenerateSucceeded(await response.result());
115
- options?.onComplete?.();
116
- }
117
- catch (error) {
118
- options?.onError?.(error);
119
- throw error;
120
- }
121
- return;
122
- }
123
- try {
124
- const message = assertLegacyGenerateSucceeded(await completeWithProvider(provider, model, context, streamOptions));
125
- options?.onStateChange?.('complete');
126
- const text = (0, protocol_1.getMessageText)(message);
127
- options?.onComplete?.();
128
- return text;
129
- }
130
- catch (error) {
131
- options?.onError?.(error);
132
- throw error;
133
- }
134
- }
135
- async listModels() {
136
- if (!this.current?.listModels) {
137
- return [];
138
- }
139
- const models = await this.current.listModels();
140
- return models.map((model) => (typeof model === 'string' ? model : model.id));
141
- }
142
- }
143
- exports.AgentKit = AgentKit;
144
- function createOllamaKit(baseUrl) {
145
- return new AgentKit().addProvider(new ollama_1.OllamaAdapter(baseUrl));
146
- }
147
- function createAnthropicKit(options) {
148
- return new AgentKit().addProvider(new anthropic_1.AnthropicAdapter(options));
149
- }
150
- function createOpenAIKit(options) {
151
- return new AgentKit().addProvider(new openai_1.OpenAIAdapter(options));
152
- }
153
- function createMultiProviderKit() {
154
- return new AgentKit();
155
- }
156
- function legacyInputToContext(input) {
157
- const messages = input.messages
158
- ? input.messages
159
- .filter((message) => message.role !== 'system')
160
- .map((message) => message.role === 'assistant'
161
- ? {
162
- role: 'assistant',
163
- api: 'legacy',
164
- provider: 'legacy',
165
- model: input.model,
166
- content: [{ type: 'text', text: message.content }],
167
- usage: (0, protocol_1.createEmptyUsage)(),
168
- stopReason: 'stop',
169
- timestamp: Date.now(),
170
- }
171
- : {
172
- role: 'user',
173
- content: message.content,
174
- timestamp: Date.now(),
175
- })
176
- : [{ role: 'user', content: input.prompt ?? '', timestamp: Date.now() }];
177
- const systemPrompt = input.system ?? input.messages?.find((message) => message.role === 'system')?.content;
178
- return {
179
- systemPrompt,
180
- messages,
181
- };
182
- }
183
- function createLegacyModel(provider, modelId, maxTokens) {
184
- if (provider.createModel) {
185
- return provider.createModel(modelId, {
186
- maxOutputTokens: maxTokens,
187
- });
188
- }
189
- return {
190
- id: modelId,
191
- name: modelId,
192
- api: provider.api,
193
- provider: getProviderName(provider),
194
- baseUrl: '',
195
- input: ['text'],
196
- reasoning: false,
197
- tools: true,
198
- maxOutputTokens: maxTokens,
28
+ return ownKeys(o);
199
29
  };
200
- }
201
- function streamWithProvider(provider, model, context, options) {
202
- const normalized = (0, protocol_1.normalizeContext)(context);
203
- const transformedContext = {
204
- ...normalized,
205
- messages: (0, transform_messages_js_1.transformMessages)(normalized.messages, model),
30
+ return function (mod) {
31
+ if (mod && mod.__esModule) return mod;
32
+ var result = {};
33
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
34
+ __setModuleDefault(result, mod);
35
+ return result;
206
36
  };
207
- return provider.stream(model, transformedContext, options);
208
- }
209
- async function completeWithProvider(provider, model, context, options) {
210
- const response = streamWithProvider(provider, model, context, options);
211
- return response.result();
212
- }
213
- function getProviderName(provider) {
214
- return provider.name ?? provider.provider;
215
- }
216
- function assertLegacyGenerateSucceeded(message) {
217
- if (message.stopReason === 'error' || message.stopReason === 'aborted') {
218
- throw new Error(message.errorMessage ??
219
- (message.stopReason === 'aborted' ? 'Generation aborted.' : 'Generation failed.'), { cause: message });
220
- }
221
- return message;
222
- }
37
+ })();
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.harness = exports.agent = void 0;
40
+ __exportStar(require("@agentic-kit/chat"), exports);
41
+ exports.agent = __importStar(require("@agentic-kit/agent"));
42
+ exports.harness = __importStar(require("@agentic-kit/harness"));
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "agentic-kit",
3
- "version": "1.10.0",
3
+ "version": "2.1.1",
4
4
  "author": "Dan Lynch <pyramation@gmail.com>",
5
- "description": "Provider-agnostic LLM adapter with streaming and multi-turn support",
5
+ "description": "Umbrella package for the agentic-kit family: chat, agent runtime, and harness",
6
6
  "main": "index.js",
7
7
  "module": "esm/index.js",
8
8
  "types": "index.d.ts",
@@ -29,11 +29,10 @@
29
29
  "test:watch": "jest --watch"
30
30
  },
31
31
  "dependencies": {
32
- "@agentic-kit/anthropic": "1.9.0",
33
- "@agentic-kit/ollama": "2.7.0",
34
- "@agentic-kit/openai": "1.9.0",
35
- "@agentic-kit/protocol": "1.8.0"
32
+ "@agentic-kit/agent": "0.12.1",
33
+ "@agentic-kit/chat": "1.11.1",
34
+ "@agentic-kit/harness": "0.3.1"
36
35
  },
37
36
  "keywords": [],
38
- "gitHead": "73f55ad24d9a92e7ef1e268526b31bfb7bb12b28"
37
+ "gitHead": "6f85eefed51d88b3a857ff36d20da44b7ebb47c9"
39
38
  }
@@ -1,26 +0,0 @@
1
- const modelsByProvider = new Map();
2
- export function registerModel(model) {
3
- const providerModels = modelsByProvider.get(model.provider) ?? new Map();
4
- providerModels.set(model.id, model);
5
- modelsByProvider.set(model.provider, providerModels);
6
- }
7
- export function registerModels(models) {
8
- for (const model of models) {
9
- registerModel(model);
10
- }
11
- }
12
- export function getModel(provider, modelId) {
13
- return modelsByProvider.get(provider)?.get(modelId);
14
- }
15
- export function getModels(provider) {
16
- if (provider) {
17
- return Array.from(modelsByProvider.get(provider)?.values() ?? []);
18
- }
19
- return Array.from(modelsByProvider.values()).flatMap((entries) => Array.from(entries.values()));
20
- }
21
- export function getProviders() {
22
- return Array.from(modelsByProvider.keys());
23
- }
24
- export function clearModels() {
25
- modelsByProvider.clear();
26
- }
@@ -1,20 +0,0 @@
1
- const providersByApi = new Map();
2
- export function registerProvider(adapter, sourceId) {
3
- providersByApi.set(adapter.api, { adapter, sourceId });
4
- }
5
- export function getProvider(api) {
6
- return providersByApi.get(api)?.adapter;
7
- }
8
- export function getProviders() {
9
- return Array.from(providersByApi.values(), (entry) => entry.adapter);
10
- }
11
- export function unregisterProviders(sourceId) {
12
- for (const [api, entry] of providersByApi.entries()) {
13
- if (entry.sourceId === sourceId) {
14
- providersByApi.delete(api);
15
- }
16
- }
17
- }
18
- export function clearProviders() {
19
- providersByApi.clear();
20
- }
@@ -1,139 +0,0 @@
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
- }
@@ -1,7 +0,0 @@
1
- import type { ModelDescriptor } from '@agentic-kit/protocol';
2
- export declare function registerModel(model: ModelDescriptor): void;
3
- export declare function registerModels(models: ModelDescriptor[]): void;
4
- export declare function getModel(provider: string, modelId: string): ModelDescriptor | undefined;
5
- export declare function getModels(provider?: string): ModelDescriptor[];
6
- export declare function getProviders(): string[];
7
- export declare function clearModels(): void;
package/model-registry.js DELETED
@@ -1,34 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.registerModel = registerModel;
4
- exports.registerModels = registerModels;
5
- exports.getModel = getModel;
6
- exports.getModels = getModels;
7
- exports.getProviders = getProviders;
8
- exports.clearModels = clearModels;
9
- const modelsByProvider = new Map();
10
- function registerModel(model) {
11
- const providerModels = modelsByProvider.get(model.provider) ?? new Map();
12
- providerModels.set(model.id, model);
13
- modelsByProvider.set(model.provider, providerModels);
14
- }
15
- function registerModels(models) {
16
- for (const model of models) {
17
- registerModel(model);
18
- }
19
- }
20
- function getModel(provider, modelId) {
21
- return modelsByProvider.get(provider)?.get(modelId);
22
- }
23
- function getModels(provider) {
24
- if (provider) {
25
- return Array.from(modelsByProvider.get(provider)?.values() ?? []);
26
- }
27
- return Array.from(modelsByProvider.values()).flatMap((entries) => Array.from(entries.values()));
28
- }
29
- function getProviders() {
30
- return Array.from(modelsByProvider.keys());
31
- }
32
- function clearModels() {
33
- modelsByProvider.clear();
34
- }
@@ -1,6 +0,0 @@
1
- import type { ProviderAdapter } from '@agentic-kit/protocol';
2
- export declare function registerProvider(adapter: ProviderAdapter, sourceId?: string): void;
3
- export declare function getProvider(api: string): ProviderAdapter | undefined;
4
- export declare function getProviders(): ProviderAdapter[];
5
- export declare function unregisterProviders(sourceId: string): void;
6
- export declare function clearProviders(): void;
@@ -1,27 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.registerProvider = registerProvider;
4
- exports.getProvider = getProvider;
5
- exports.getProviders = getProviders;
6
- exports.unregisterProviders = unregisterProviders;
7
- exports.clearProviders = clearProviders;
8
- const providersByApi = new Map();
9
- function registerProvider(adapter, sourceId) {
10
- providersByApi.set(adapter.api, { adapter, sourceId });
11
- }
12
- function getProvider(api) {
13
- return providersByApi.get(api)?.adapter;
14
- }
15
- function getProviders() {
16
- return Array.from(providersByApi.values(), (entry) => entry.adapter);
17
- }
18
- function unregisterProviders(sourceId) {
19
- for (const [api, entry] of providersByApi.entries()) {
20
- if (entry.sourceId === sourceId) {
21
- providersByApi.delete(api);
22
- }
23
- }
24
- }
25
- function clearProviders() {
26
- providersByApi.clear();
27
- }
@@ -1,2 +0,0 @@
1
- import type { Message, ModelDescriptor } from '@agentic-kit/protocol';
2
- export declare function transformMessages(messages: Message[], model: ModelDescriptor): Message[];
@@ -1,142 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.transformMessages = transformMessages;
4
- function transformMessages(messages, model) {
5
- const toolCallIdMap = new Map();
6
- const transformed = messages.flatMap((message) => {
7
- if (message.role !== 'assistant') {
8
- if (message.role === 'toolResult') {
9
- const normalizedId = toolCallIdMap.get(message.toolCallId);
10
- if (normalizedId && normalizedId !== message.toolCallId) {
11
- return [{ ...message, toolCallId: normalizedId }];
12
- }
13
- }
14
- return [message];
15
- }
16
- if (message.stopReason === 'error' || message.stopReason === 'aborted') {
17
- return [];
18
- }
19
- const sameModel = message.provider === model.provider &&
20
- message.api === model.api &&
21
- message.model === model.id;
22
- const content = message.content.flatMap((block) => {
23
- if (block.type === 'thinking') {
24
- if (sameModel) {
25
- return [block];
26
- }
27
- if (!block.thinking.trim()) {
28
- return [];
29
- }
30
- const thinkingAsText = {
31
- type: 'text',
32
- text: `<thinking>${block.thinking}</thinking>`,
33
- };
34
- return [thinkingAsText];
35
- }
36
- if (block.type === 'toolCall') {
37
- const normalizedId = normalizeToolCallId(block.id, model);
38
- if (normalizedId !== block.id) {
39
- toolCallIdMap.set(block.id, normalizedId);
40
- }
41
- const toolCall = normalizedId === block.id ? block : { ...block, id: normalizedId };
42
- return [toolCall];
43
- }
44
- return [block];
45
- });
46
- return [{ ...message, content }];
47
- });
48
- return insertSyntheticToolResults(transformed);
49
- }
50
- function insertSyntheticToolResults(messages) {
51
- const result = [];
52
- let pendingToolCalls = [];
53
- let seenToolResults = new Set();
54
- for (const message of messages) {
55
- if (message.role === 'assistant') {
56
- flushPendingToolCalls(result, pendingToolCalls, seenToolResults);
57
- pendingToolCalls = message.content.filter((block) => block.type === 'toolCall');
58
- seenToolResults = new Set();
59
- result.push(message);
60
- continue;
61
- }
62
- if (message.role === 'toolResult') {
63
- seenToolResults.add(message.toolCallId);
64
- result.push(message);
65
- continue;
66
- }
67
- flushPendingToolCalls(result, pendingToolCalls, seenToolResults);
68
- pendingToolCalls = [];
69
- seenToolResults = new Set();
70
- result.push(message);
71
- }
72
- flushPendingToolCalls(result, pendingToolCalls, seenToolResults);
73
- return result;
74
- }
75
- function flushPendingToolCalls(result, pendingToolCalls, seenToolResults) {
76
- if (pendingToolCalls.length === 0) {
77
- return;
78
- }
79
- for (const toolCall of pendingToolCalls) {
80
- if (seenToolResults.has(toolCall.id)) {
81
- continue;
82
- }
83
- const synthetic = {
84
- role: 'toolResult',
85
- toolCallId: toolCall.id,
86
- toolName: toolCall.name,
87
- content: [{ type: 'text', text: 'No result provided.' }],
88
- isError: true,
89
- timestamp: Date.now(),
90
- };
91
- result.push(synthetic);
92
- }
93
- }
94
- function normalizeToolCallId(id, model) {
95
- const format = model.compat?.toolCallIdFormat ?? defaultToolCallIdFormat(model);
96
- if (format === 'passthrough') {
97
- return id;
98
- }
99
- if (format === 'mistral9') {
100
- const alphanumeric = id.replace(/[^a-zA-Z0-9]/g, '');
101
- if (alphanumeric.length >= 9) {
102
- return alphanumeric.slice(0, 9);
103
- }
104
- return stableAlphanumericId(id, 9);
105
- }
106
- const safe = id.replace(/[^a-zA-Z0-9_-]/g, '_').slice(0, 64);
107
- if (safe.length > 0) {
108
- return safe;
109
- }
110
- return stableId(id, 24, /^[a-zA-Z0-9_-]+$/);
111
- }
112
- function defaultToolCallIdFormat(model) {
113
- if (model.provider === 'anthropic' || model.api === 'anthropic-messages') {
114
- return 'safe64';
115
- }
116
- return 'passthrough';
117
- }
118
- function stableId(input, length, pattern) {
119
- let hash = 0;
120
- for (let i = 0; i < input.length; i += 1) {
121
- hash = (hash * 31 + input.charCodeAt(i)) >>> 0;
122
- }
123
- let value = `tc_${hash.toString(36)}`;
124
- while (!pattern.test(value)) {
125
- value = value.replace(/[^a-zA-Z0-9_-]/g, '_');
126
- }
127
- if (value.length >= length) {
128
- return value.slice(0, length);
129
- }
130
- return value.padEnd(length, '0');
131
- }
132
- function stableAlphanumericId(input, length) {
133
- let hash = 0;
134
- for (let i = 0; i < input.length; i += 1) {
135
- hash = (hash * 31 + input.charCodeAt(i)) >>> 0;
136
- }
137
- const value = `tc${hash.toString(36)}`.replace(/[^a-zA-Z0-9]/g, '');
138
- if (value.length >= length) {
139
- return value.slice(0, length);
140
- }
141
- return value.padEnd(length, '0');
142
- }