@moikapy/origen 0.4.1 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,18 +2,28 @@
2
2
 
3
3
  > Multi-Provider Agent Engine — an agent harness, not a chatbot.
4
4
 
5
- Named after **Origen of Alexandria** (c. 185–254 AD) — the early church's greatest scholar. This package is the **generic** agent harness that wraps any LLM provider with tool calling, streaming, and Soul.md personas.
5
+ Named after **Origen of Alexandria** (c. 185–254 AD) — the early church's greatest scholar. This package is a **generic** agent harness that wraps any LLM provider with tool calling, streaming, Soul.md personas, and Cloudflare D1 integration.
6
6
 
7
7
  **Domain-specific tools live in separate packages.** For Bible study, see `@moikapy/scholar-tools`.
8
8
 
9
- ## Providers
9
+ ## Features
10
+
11
+ - **Multi-provider**: OpenRouter, Ollama, Anthropic, Google, OpenAI, DeepSeek, Groq, xAI via `@mariozechner/pi-ai`
12
+ - **Streaming first**: `streamOrigen()` yields typed events (reasoning, tool calls, text deltas, citations)
13
+ - **Parallel tool execution**: Tools run concurrently by default; sequential mode available
14
+ - **Soul.md personas**: Declarative persona definitions with profiles, moods, and voice tuning
15
+ - **D1 integration**: Tools receive a `D1Provider` for Cloudflare D1 database access
16
+ - **Provider-aware auth**: `getApiKey(provider)` resolves keys per-provider (OAuth PKCE, local Ollama, etc.)
17
+ - **Abort support**: Pass `signal: AbortSignal` to cancel streaming mid-flight
18
+ - **Citation extraction**: Pluggable `extractCitations` for domain-specific parsing
19
+ - **Thinking models**: Automatic extended reasoning for DeepSeek R1, Claude Sonnet 4, Gemini 2.5 Flash
10
20
 
11
- Origen supports multiple LLM providers via `@mariozechner/pi-ai`:
21
+ ## Providers
12
22
 
13
23
  | Provider | Models | Auth |
14
24
  |---|---|---|
15
25
  | **OpenRouter** | 275+ models, free tier available | OAuth PKCE / API key |
16
- | **Ollama** | Llama 3, Gemma 3, Mistral, Qwen 3, DeepSeek R1 | Local (no key needed) |
26
+ | **Ollama** | Llama 3, Gemma 3, Mistral, Qwen 3, DeepSeek R1, + any custom model | Local (no key needed) |
17
27
  | **Anthropic** | Claude Sonnet 4, etc. | API key |
18
28
  | **Google** | Gemini 2.5 Flash, etc. | API key |
19
29
  | **OpenAI** | GPT-4o, etc. | API key |
@@ -52,7 +62,6 @@ const config: AgentConfig = {
52
62
  tools: [myTool],
53
63
  getD1: async () => myD1Database,
54
64
  model: "openrouter/free",
55
- // Provider-aware key resolution
56
65
  getApiKey: async (provider) => {
57
66
  if (provider === "ollama") return "ollama";
58
67
  return getOpenRouterKey();
@@ -73,14 +82,44 @@ for await (const event of streamOrigen(messages, context, config)) {
73
82
 
74
83
  ## Ollama Support
75
84
 
85
+ ### Static Model List
86
+
87
+ Origen ships with hardcoded entries for popular Ollama models (Llama 3, Gemma 3, DeepSeek R1, etc.). These serve as fallbacks when Ollama isn't running.
88
+
89
+ ### Dynamic Discovery
90
+
91
+ When Ollama is running, Origen can pull the full list of available models — including cloud models (`:cloud` suffix) — via `fetchOllamaModels()`:
92
+
93
+ ```typescript
94
+ import { discoverOllamaModels, getModelsForUI } from "@moikapy/origen/models";
95
+
96
+ // Fetch from Ollama, merge into MODELS registry, return combined map
97
+ const allModels = await discoverOllamaModels("http://localhost:11434");
98
+ console.log(allModels["ollama/llama3.2"]); // { name: "llama3.2 (3.2B)", description: "Local — 3.2B (Q4_K_M) requires Ollama", free: true }
99
+
100
+ // Or do it in two steps for more control:
101
+ import { fetchOllamaModels, mergeOllamaModels } from "@moikapy/origen/models";
102
+
103
+ const discovered = await fetchOllamaModels("http://localhost:11434");
104
+ // Filter, transform, or inspect before merging
105
+ mergeOllamaModels(discovered);
106
+ ```
107
+
108
+ **Key behaviors:**
109
+ - Embedding models (e.g., `nomic-embed-text`) are automatically filtered out
110
+ - Cloud models (tagged `:cloud`) are tagged as "Cloud" in their description
111
+ - Reasoning model families (DeepSeek R1, Qwen3, etc.) are auto-detected
112
+ - Network errors return empty results — no crash, just static fallbacks
113
+ - 5-second timeout — won't block startup if Ollama is slow
114
+
115
+ ### Custom Models
116
+
117
+ Use `ollama/<model-name>` and Origen constructs a generic OpenAI-compatible config pointing at your Ollama server:
118
+
76
119
  ```typescript
77
120
  const config: AgentConfig = {
78
- model: "ollama/llama3",
121
+ model: "ollama/my-custom-finetune",
79
122
  ollamaBaseUrl: "http://localhost:11434/v1",
80
- getApiKey: async (provider) => {
81
- if (provider === "ollama") return "ollama"; // Ollama doesn't need a real key
82
- return undefined;
83
- },
84
123
  // ...
85
124
  };
86
125
  ```
@@ -100,21 +139,24 @@ console.log(concise.buildPrompt()); // Concise version
100
139
 
101
140
  ### Supported Soul.md Fields
102
141
 
103
- - **identity**: role, archetype, domain_focus, non_goals
104
- - **relationship**: stance, user_model_default, trust_baseline
105
- - **voice**: formality, warmth, verbosity, jargon, formatting, banned_phrases, preferred_phrases, emoji_policy
106
- - **interaction**: clarifying_questions, uncertainty, disagreement, confirmations
107
- - **cognition**: mode, depth, verification (fact_checking, cross_validation)
108
- - **safety**: refusal_style, privacy, speculation, no_fabrication, no_false_certainty
109
- - **actions**: when_to_use_tools, explain_actions, failover
110
- - **state**: dynamic moods with trigger-based transitions
111
- - **profiles**: named overlays (concise, scholarly, friendly, etc.)
112
-
113
- ## API
142
+ | Section | Fields |
143
+ |---|---|
144
+ | **identity** | role, archetype, domain_focus, non_goals |
145
+ | **relationship** | stance, user_model_default, trust_baseline |
146
+ | **voice** | formality, warmth, verbosity, jargon, formatting, banned_phrases, preferred_phrases, emoji_policy |
147
+ | **interaction** | clarifying_questions, uncertainty, disagreement, confirmations |
148
+ | **cognition** | mode, depth, verification (fact_checking, cross_validation) |
149
+ | **safety** | refusal_style, privacy, speculation, no_fabrication, no_false_certainty |
150
+ | **actions** | when_to_use_tools, explain_actions, failover |
151
+ | **state** | dynamic moods with trigger-based transitions |
152
+ | **profiles** | named overlays (concise, scholarly, friendly, etc.) |
153
+ | **composition** | extends, mixins, merge_policy |
154
+
155
+ ## API Reference
114
156
 
115
157
  ### `streamOrigen(messages, context, config, apiKey?)`
116
158
 
117
- Async generator yielding `StreamEvent`s. Handles the full agent loop with parallel tool execution.
159
+ Async generator yielding `StreamEvent`s. Handles the full agent loop with parallel tool execution. Events: `reasoning`, `tool_call`, `tool_result`, `text`, `done`, `error`.
118
160
 
119
161
  ### `callOrigen(messages, context, config, apiKey?)`
120
162
 
@@ -122,12 +164,20 @@ Non-streaming wrapper. Returns `{ message, citations, usage }`.
122
164
 
123
165
  ### `checkAuth(getApiKey)`
124
166
 
125
- Provider-aware auth check. Returns `{ authenticated, apiKey, provider, error? }`.
167
+ Provider-aware auth check. Tries OpenRouter → Ollama → Anthropic. Returns `{ authenticated, apiKey, provider, error? }`.
126
168
 
127
169
  ### `checkOpenRouterAuth(getApiKey)`
128
170
 
129
171
  OpenRouter-only auth check (backward compat).
130
172
 
173
+ ### `resolveModel(modelId, options?)`
174
+
175
+ Resolves a model ID string to a pi-ai `Model` object. Handles Ollama models, pi-ai registry lookups, and generic fallbacks.
176
+
177
+ ### `createEventStream(agent, extractCitations?)`
178
+
179
+ Eagerly subscribes to an Agent and returns `{ stream, unsubscribe }`. Subscribes synchronously before `prompt()` to avoid race conditions.
180
+
131
181
  ## Configuration
132
182
 
133
183
  ```typescript
@@ -150,16 +200,111 @@ interface AgentConfig {
150
200
  ## Models
151
201
 
152
202
  ```typescript
153
- import { MODELS, DEFAULT_MODEL, THINKING_MODELS, supportsThinking, isOllamaModel } from "@moikapy/origen/models";
203
+ import {
204
+ MODELS, DEFAULT_MODEL, THINKING_MODELS,
205
+ supportsThinking, isOllamaModel,
206
+ getModelsByProvider, getModelsForUI,
207
+ fetchOllamaModels, mergeOllamaModels, discoverOllamaModels,
208
+ } from "@moikapy/origen/models";
154
209
  ```
155
210
 
156
- ## What Changed (v0.3)
211
+ ### Built-in Model IDs
212
+
213
+ | ID | Name | Free? |
214
+ |---|---|---|
215
+ | `openrouter/free` | Free (Auto) | ✅ |
216
+ | `google/gemma-4-31b-it:free` | Gemma 4 31B | ✅ |
217
+ | `nvidia/nemotron-3-super-120b-a12b:free` | Nemotron 3 Super | ✅ |
218
+ | `deepseek/deepseek-r1:free` | DeepSeek R1 (Free) | ✅ |
219
+ | `qwen/qwen3-coder:free` | Qwen3 Coder | ✅ |
220
+ | `ollama/llama3` | Llama 3 (Ollama) | ✅ |
221
+ | `ollama/llama3.1` | Llama 3.1 8B (Ollama) | ✅ |
222
+ | `ollama/gemma3` | Gemma 3 (Ollama) | ✅ |
223
+ | `ollama/mistral` | Mistral 7B (Ollama) | ✅ |
224
+ | `ollama/qwen3` | Qwen 3 (Ollama) | ✅ |
225
+ | `ollama/deepseek-r1` | DeepSeek R1 (Ollama) | ✅ |
226
+ | `ollama/codellama` | Code Llama (Ollama) | ✅ |
227
+ | `ollama/phi3` | Phi-3 (Ollama) | ✅ |
228
+ | `openrouter/auto` | Auto (All) | ❌ |
229
+ | `anthropic/claude-sonnet-4` | Claude Sonnet 4 | ❌ |
230
+ | `google/gemini-2.5-flash-preview` | Gemini 2.5 Flash | ❌ |
231
+
232
+ ### Thinking Models
233
+
234
+ Extended reasoning support for: `anthropic/claude-sonnet-4`, `deepseek/deepseek-r1:free`, `google/gemini-2.5-flash-preview`, `ollama/deepseek-r1`.
235
+
236
+ ### Dynamic Ollama Discovery
237
+
238
+ Ollama models can be discovered at runtime from a running server:
239
+
240
+ | Function | Description |
241
+ |---|---|
242
+ | `fetchOllamaModels(baseUrl?)` | Query Ollama `/api/tags`, return `Record<string, ModelConfig>` |
243
+ | `mergeOllamaModels(models)` | Merge discovered models into the static `MODELS` registry |
244
+ | `discoverOllamaModels(baseUrl?)` | One-shot: fetch + merge + return combined map |
245
+
246
+ ## Exports Map
247
+
248
+ ```json
249
+ {
250
+ ".": "Main entry — streamOrigen, callOrigen, checkAuth, MODELS, Soul, etc.",
251
+ "./models": "MODELS registry, supportsThinking, isOllamaModel, getModelsByProvider",
252
+ "./soul": "Soul class, loadSoul, SoulConfig types",
253
+ "./adapter": "resolveModel, createEventStream, adaptTools, convertMessages"
254
+ }
255
+ ```
256
+
257
+ ## Architecture
258
+
259
+ ```
260
+ ┌─────────────────────────────────────────────────────┐
261
+ │ Your App │
262
+ │ streamOrigen(messages, context, config) │
263
+ └────────┬──────────────┬─────────────────────────────┘
264
+ │ │
265
+ ┌────▼────┐ ┌─────▼──────┐
266
+ │ agent.ts│ │ adapter.ts │
267
+ │ Agent │ │ Tool adapt │
268
+ │ loop │ │ Model res. │
269
+ │ Auth │ │ Event xlate│
270
+ └────┬────┘ └─────┬──────┘
271
+ │ │
272
+ ┌────▼──────────────▼────┐
273
+ │ pi-ai + pi-agent-core│
274
+ │ (LLM providers, │
275
+ │ streaming, tools) │
276
+ └───────────────────────┘
277
+ ```
157
278
 
279
+ - **agent.ts** — Agent loop, auth checks, event types. Orchestrates `Agent` from pi-agent-core.
280
+ - **adapter.ts** — Bridges Origen's simple types to pi-ai/pi-agent-core. Tool adaptation, model resolution, event translation, eager event stream.
281
+ - **models.ts** — Model registry with UI-safe configs, thinking model detection, provider filtering.
282
+ - **soul.ts** — Soul.md RFC-1 parser with YAML front matter, profile overlays, prompt generation.
283
+ - **types.ts** — Zero-dependency types (D1Like, Citation, UsageInfo, ReadingContext).
284
+
285
+ ## Changelog
286
+
287
+ ### v0.5 (current)
288
+ - **Dynamic Ollama discovery**: `fetchOllamaModels()`, `mergeOllamaModels()`, `discoverOllamaModels()` pull live models from Ollama's `/api/tags` endpoint
289
+ - **Improved Ollama model catalog**: Added Llama 3.1, Mistral Nemo, Code Llama, Phi-3; updated context windows
290
+ - **Ollama provider in resolveModel**: Now tries `ollama` in the pi-ai registry loop
291
+ - **Exported `defaultCitationExtractor`**: Now importable for custom citation pipelines
292
+ - **Reduced `as any` casts**: Replaced with documented type assertions where pi-ai generics are too narrow
293
+
294
+ ### v0.4
295
+ - **Zod validation**: Optional `inputSchema` on `OrigenTool` for runtime parameter validation
296
+ - **Qwen3 Coder**: Added `qwen/qwen3-coder:free` to model registry
297
+ - **getModelsForUI()**: UI-safe model configs without internal fields
298
+ - **getModelsByProvider()**: Filter models by provider prefix
299
+ - **UIModelConfig type**: Stripped model config safe for client-side use
300
+
301
+ ### v0.3
158
302
  - **Multi-provider**: OpenRouter, Ollama, Anthropic, Google, DeepSeek, Groq, xAI via pi-ai
159
303
  - **Parallel tool execution**: Tools run concurrently by default
160
304
  - **Abort support**: Pass `signal: AbortSignal` to cancel streaming
161
305
  - **Soul.md personas**: Declarative persona definitions with profiles and moods
162
306
  - **Provider-aware auth**: `getApiKey(provider)` resolves keys per-provider
307
+ - **Eager event stream**: `createEventStream()` subscribes before prompt to avoid race conditions
163
308
  - **No more hardcoded SSE parser**: Delegate to pi-ai + pi-agent-core
164
309
 
165
310
  ## License
@@ -0,0 +1,209 @@
1
+ import { Model, Api, Message, Context } from '@mariozechner/pi-ai';
2
+ import { AgentTool, AgentEvent } from '@mariozechner/pi-agent-core';
3
+ import { z } from 'zod';
4
+ import { ModelId } from './models.js';
5
+
6
+ /**
7
+ * Origen types — no runtime deps, safe for client + server.
8
+ */
9
+ /** D1-compatible database interface for tool execution */
10
+ interface D1Like {
11
+ prepare(sql: string): {
12
+ bind(...params: unknown[]): {
13
+ all(): Promise<{
14
+ results?: Record<string, unknown>[];
15
+ }>;
16
+ first(): Promise<Record<string, unknown> | null>;
17
+ run(): Promise<{
18
+ meta?: {
19
+ changes: number;
20
+ last_row_id: number;
21
+ };
22
+ }>;
23
+ };
24
+ };
25
+ }
26
+ /** Function that provides a D1 instance to tool executors */
27
+ type D1Provider = () => Promise<D1Like>;
28
+ /** Chat context passed from the UI (what the user is reading) */
29
+ interface ReadingContext {
30
+ translation: string;
31
+ bookCode: string;
32
+ chapter: number;
33
+ selectedVerses?: number[];
34
+ }
35
+ interface Citation {
36
+ book: string;
37
+ chapter: number;
38
+ verse: number;
39
+ }
40
+ interface UsageInfo {
41
+ promptTokens?: number;
42
+ completionTokens?: number;
43
+ totalCost?: number;
44
+ }
45
+ /** Model configuration entry */
46
+ interface ModelConfig {
47
+ name: string;
48
+ description: string;
49
+ free: boolean;
50
+ }
51
+
52
+ /**
53
+ * Origen — Agent Engine (v0.3)
54
+ *
55
+ * Multi-provider agent harness built on pi-ai + pi-agent-core.
56
+ * Supports OpenRouter, Ollama, Anthropic, Google, and any OpenAI-compatible API.
57
+ * Soul.md personas, streaming, parallel tool execution, abort support.
58
+ */
59
+
60
+ /**
61
+ * A tool that the host app registers with Origen.
62
+ * Simple interface: name, description, JSON schema, and an execute function
63
+ * that receives (args, getD1). The adapter wraps this into pi-agent-core's AgentTool.
64
+ */
65
+ interface OrigenTool {
66
+ name: string;
67
+ description: string;
68
+ /** OpenAI function-calling parameter schema (JSON) */
69
+ parameters: Record<string, unknown>;
70
+ /** Zod schema for runtime validation (optional) */
71
+ inputSchema?: z.ZodType;
72
+ execute: (args: Record<string, unknown>, getD1: D1Provider) => Promise<string>;
73
+ }
74
+ interface AgentConfig {
75
+ appName?: string;
76
+ systemPrompt?: string;
77
+ tools: OrigenTool[];
78
+ getD1: D1Provider;
79
+ model?: ModelId;
80
+ maxSteps?: number;
81
+ /** Custom citation extractor */
82
+ extractCitations?: (text: string) => Citation[];
83
+ /** Dynamic API key resolution per provider (e.g., for expiring OAuth tokens) */
84
+ getApiKey?: (provider: string) => Promise<string | undefined>;
85
+ /** Ollama base URL override (default: http://localhost:11434/v1) */
86
+ ollamaBaseUrl?: string;
87
+ /** Tool execution mode: "parallel" (default) or "sequential" */
88
+ toolExecution?: "sequential" | "parallel";
89
+ /** Abort signal for cancellation */
90
+ signal?: AbortSignal;
91
+ /** Reasoning/thinking level for models that support it */
92
+ thinkingLevel?: "off" | "minimal" | "low" | "medium" | "high";
93
+ }
94
+ interface AuthCheckResult {
95
+ authenticated: boolean;
96
+ apiKey: string | null;
97
+ provider?: string;
98
+ error?: string;
99
+ }
100
+ /**
101
+ * Provider-aware auth check. Tests key availability for each provider.
102
+ * If no provider argument, checks OpenRouter + Ollama availability.
103
+ */
104
+ declare function checkAuth(getApiKey: ((provider: string) => Promise<string | undefined>) | (() => Promise<string | null>)): Promise<AuthCheckResult>;
105
+ /** Convenience: check OpenRouter auth only (backward compat). */
106
+ declare function checkOpenRouterAuth(getApiKey: () => Promise<string | null>): Promise<AuthCheckResult>;
107
+ type StreamEvent = {
108
+ type: "reasoning";
109
+ content: string;
110
+ } | {
111
+ type: "tool_call";
112
+ name: string;
113
+ args: Record<string, unknown>;
114
+ } | {
115
+ type: "tool_result";
116
+ name: string;
117
+ result: string;
118
+ } | {
119
+ type: "text";
120
+ content: string;
121
+ } | {
122
+ type: "done";
123
+ message: string;
124
+ citations: Citation[];
125
+ usage?: UsageInfo;
126
+ } | {
127
+ type: "error";
128
+ message: string;
129
+ };
130
+ declare function streamOrigen(messages: Array<{
131
+ role: "user" | "assistant";
132
+ content: string;
133
+ }>, context: Record<string, unknown> | undefined, config: AgentConfig, apiKey?: string): AsyncGenerator<StreamEvent>;
134
+ interface AgentResponse {
135
+ message: string;
136
+ citations: Citation[];
137
+ usage?: UsageInfo;
138
+ }
139
+ declare function callOrigen(messages: Array<{
140
+ role: "user" | "assistant";
141
+ content: string;
142
+ }>, context: Record<string, unknown> | undefined, config: AgentConfig, apiKey?: string): Promise<AgentResponse>;
143
+
144
+ /**
145
+ * Adapter: bridges Origen's simple types to pi-agent-core/pi-ai types.
146
+ *
147
+ * - OrigenTool → AgentTool (injects D1Provider)
148
+ * - pi-ai Model resolution (OpenRouter, Ollama, Anthropic, Google)
149
+ * - StreamEvent translation (AgentEvent → Origen's StreamEvent)
150
+ */
151
+
152
+ /**
153
+ * Convert an OrigenTool into a pi-agent-core AgentTool.
154
+ * The D1Provider is captured in closure so the tool's execute gets it.
155
+ */
156
+ declare function adaptTool(tool: OrigenTool, getD1: D1Provider): AgentTool;
157
+ /** Adapt all OrigenTools for an Agent instance. */
158
+ declare function adaptTools(tools: OrigenTool[], getD1: D1Provider): AgentTool[];
159
+ interface ModelResolutionOptions {
160
+ /** Ollama base URL, e.g. "http://localhost:11434/v1" */
161
+ ollamaBaseUrl?: string;
162
+ }
163
+ /**
164
+ * Resolve a model ID string to a pi-ai Model object.
165
+ * Tries pi-ai's registry first, then falls back to built-in Ollama definitions.
166
+ */
167
+ declare function resolveModel(modelId: string, options?: ModelResolutionOptions): Model<Api>;
168
+ /** Convert Origen's simple messages to pi-ai Message format. */
169
+ declare function convertMessages(messages: Array<{
170
+ role: "user" | "assistant";
171
+ content: string;
172
+ }>): Message[];
173
+ /** Build a pi-ai Context from Origen's config. */
174
+ declare function buildContext(systemPrompt: string, messages: Message[], adaptedTools: AgentTool[]): Context;
175
+ /** Default citation extractor — [BOOK CHAPTER:VERSE] patterns (e.g., [GEN 1:1]).
176
+ * Bible-specific pattern. Consumers should provide their own extractCitations
177
+ * for non-biblical citation formats. Exported for reuse and testing.
178
+ */
179
+ declare function defaultCitationExtractor(text: string): Citation[];
180
+ /** Translate a pi-agent-core AgentEvent into an Origen StreamEvent. */
181
+ declare function translateEvent(event: AgentEvent, extractCitations?: (text: string) => Citation[]): StreamEvent | null;
182
+ /**
183
+ * Eagerly subscribe to an Agent and return an async iterable of Origen StreamEvents.
184
+ *
185
+ * CRITICAL: The subscription is created synchronously when this function is called,
186
+ * BEFORE agent.prompt() starts. This avoids the race condition where events
187
+ * emitted during prompt() are missed if subscription happens after.
188
+ *
189
+ * Usage:
190
+ * const { stream, unsubscribe } = createEventStream(agent, extractCitations);
191
+ * agent.prompt(messages); // events flow into stream via active subscription
192
+ * for await (const event of stream) { ... }
193
+ */
194
+ declare function createEventStream(agent: any, // Agent from pi-agent-core
195
+ extractCitations?: (text: string) => Citation[]): {
196
+ stream: AsyncGenerator<StreamEvent>;
197
+ unsubscribe: () => void;
198
+ };
199
+ /**
200
+ * Subscribe to an Agent and yield Origen StreamEvents.
201
+ * Handles the full lifecycle from agent_start to agent_end.
202
+ *
203
+ * @deprecated Use createEventStream() instead to avoid race conditions.
204
+ * This function subscribes lazily (on first iteration) which can miss events
205
+ * if the agent has already started emitting.
206
+ */
207
+ declare function agentToStreamEvents(agent: any, extractCitations?: (text: string) => Citation[]): AsyncGenerator<StreamEvent>;
208
+
209
+ export { type AgentConfig as A, type Citation as C, type D1Like as D, type ModelResolutionOptions as M, type OrigenTool as O, type ReadingContext as R, type StreamEvent as S, type UsageInfo as U, type AgentResponse as a, type AuthCheckResult as b, type D1Provider as c, type ModelConfig as d, callOrigen as e, checkAuth as f, checkOpenRouterAuth as g, createEventStream as h, defaultCitationExtractor as i, adaptTool as j, adaptTools as k, agentToStreamEvents as l, buildContext as m, convertMessages as n, resolveModel as r, streamOrigen as s, translateEvent as t };
package/dist/adapter.d.ts CHANGED
@@ -1,204 +1,5 @@
1
- import { ModelId } from './models.js';
2
- import { z } from 'zod';
3
- import { Model, Api, Message, Context } from '@mariozechner/pi-ai';
4
- import { AgentTool, AgentEvent } from '@mariozechner/pi-agent-core';
5
-
6
- /**
7
- * Origen types — no runtime deps, safe for client + server.
8
- */
9
- /** D1-compatible database interface for tool execution */
10
- interface D1Like {
11
- prepare(sql: string): {
12
- bind(...params: unknown[]): {
13
- all(): Promise<{
14
- results?: Record<string, unknown>[];
15
- }>;
16
- first(): Promise<Record<string, unknown> | null>;
17
- run(): Promise<{
18
- meta?: {
19
- changes: number;
20
- last_row_id: number;
21
- };
22
- }>;
23
- };
24
- };
25
- }
26
- /** Function that provides a D1 instance to tool executors */
27
- type D1Provider = () => Promise<D1Like>;
28
- /** Chat context passed from the UI (what the user is reading) */
29
- interface ReadingContext {
30
- translation: string;
31
- bookCode: string;
32
- chapter: number;
33
- selectedVerses?: number[];
34
- }
35
- interface Citation {
36
- book: string;
37
- chapter: number;
38
- verse: number;
39
- }
40
- interface UsageInfo {
41
- promptTokens?: number;
42
- completionTokens?: number;
43
- totalCost?: number;
44
- }
45
- /** Model configuration entry */
46
- interface ModelConfig {
47
- name: string;
48
- description: string;
49
- free: boolean;
50
- }
51
-
52
- /**
53
- * Origen — Agent Engine (v0.3)
54
- *
55
- * Multi-provider agent harness built on pi-ai + pi-agent-core.
56
- * Supports OpenRouter, Ollama, Anthropic, Google, and any OpenAI-compatible API.
57
- * Soul.md personas, streaming, parallel tool execution, abort support.
58
- */
59
-
60
- /**
61
- * A tool that the host app registers with Origen.
62
- * Simple interface: name, description, JSON schema, and an execute function
63
- * that receives (args, getD1). The adapter wraps this into pi-agent-core's AgentTool.
64
- */
65
- interface OrigenTool {
66
- name: string;
67
- description: string;
68
- /** OpenAI function-calling parameter schema (JSON) */
69
- parameters: Record<string, unknown>;
70
- /** Zod schema for runtime validation (optional) */
71
- inputSchema?: z.ZodType;
72
- execute: (args: Record<string, unknown>, getD1: D1Provider) => Promise<string>;
73
- }
74
- interface AgentConfig {
75
- appName?: string;
76
- systemPrompt?: string;
77
- tools: OrigenTool[];
78
- getD1: D1Provider;
79
- model?: ModelId;
80
- maxSteps?: number;
81
- /** Custom citation extractor */
82
- extractCitations?: (text: string) => Citation[];
83
- /** Dynamic API key resolution per provider (e.g., for expiring OAuth tokens) */
84
- getApiKey?: (provider: string) => Promise<string | undefined>;
85
- /** Ollama base URL override (default: http://localhost:11434/v1) */
86
- ollamaBaseUrl?: string;
87
- /** Tool execution mode: "parallel" (default) or "sequential" */
88
- toolExecution?: "sequential" | "parallel";
89
- /** Abort signal for cancellation */
90
- signal?: AbortSignal;
91
- /** Reasoning/thinking level for models that support it */
92
- thinkingLevel?: "off" | "minimal" | "low" | "medium" | "high";
93
- }
94
- interface AuthCheckResult {
95
- authenticated: boolean;
96
- apiKey: string | null;
97
- provider?: string;
98
- error?: string;
99
- }
100
- /**
101
- * Provider-aware auth check. Tests key availability for each provider.
102
- * If no provider argument, checks OpenRouter + Ollama availability.
103
- */
104
- declare function checkAuth(getApiKey: ((provider: string) => Promise<string | undefined>) | (() => Promise<string | null>)): Promise<AuthCheckResult>;
105
- /** Convenience: check OpenRouter auth only (backward compat). */
106
- declare function checkOpenRouterAuth(getApiKey: () => Promise<string | null>): Promise<AuthCheckResult>;
107
- type StreamEvent = {
108
- type: "reasoning";
109
- content: string;
110
- } | {
111
- type: "tool_call";
112
- name: string;
113
- args: Record<string, unknown>;
114
- } | {
115
- type: "tool_result";
116
- name: string;
117
- result: string;
118
- } | {
119
- type: "text";
120
- content: string;
121
- } | {
122
- type: "done";
123
- message: string;
124
- citations: Citation[];
125
- usage?: UsageInfo;
126
- } | {
127
- type: "error";
128
- message: string;
129
- };
130
- declare function streamOrigen(messages: Array<{
131
- role: "user" | "assistant";
132
- content: string;
133
- }>, context: Record<string, unknown> | undefined, config: AgentConfig, apiKey?: string): AsyncGenerator<StreamEvent>;
134
- interface AgentResponse {
135
- message: string;
136
- citations: Citation[];
137
- usage?: UsageInfo;
138
- }
139
- declare function callOrigen(messages: Array<{
140
- role: "user" | "assistant";
141
- content: string;
142
- }>, context: Record<string, unknown> | undefined, config: AgentConfig, apiKey?: string): Promise<AgentResponse>;
143
-
144
- /**
145
- * Adapter: bridges Origen's simple types to pi-agent-core/pi-ai types.
146
- *
147
- * - OrigenTool → AgentTool (injects D1Provider)
148
- * - pi-ai Model resolution (OpenRouter, Ollama, Anthropic, Google)
149
- * - StreamEvent translation (AgentEvent → Origen's StreamEvent)
150
- */
151
-
152
- /**
153
- * Convert an OrigenTool into a pi-agent-core AgentTool.
154
- * The D1Provider is captured in closure so the tool's execute gets it.
155
- */
156
- declare function adaptTool(tool: OrigenTool, getD1: D1Provider): AgentTool;
157
- /** Adapt all OrigenTools for an Agent instance. */
158
- declare function adaptTools(tools: OrigenTool[], getD1: D1Provider): AgentTool[];
159
- interface ModelResolutionOptions {
160
- /** Ollama base URL, e.g. "http://localhost:11434/v1" */
161
- ollamaBaseUrl?: string;
162
- }
163
- /**
164
- * Resolve a model ID string to a pi-ai Model object.
165
- * Tries pi-ai's registry first, then falls back to built-in Ollama definitions.
166
- */
167
- declare function resolveModel(modelId: string, options?: ModelResolutionOptions): Model<Api>;
168
- /** Convert Origen's simple messages to pi-ai Message format. */
169
- declare function convertMessages(messages: Array<{
170
- role: "user" | "assistant";
171
- content: string;
172
- }>): Message[];
173
- /** Build a pi-ai Context from Origen's config. */
174
- declare function buildContext(systemPrompt: string, messages: Message[], adaptedTools: AgentTool[]): Context;
175
- /** Translate a pi-agent-core AgentEvent into an Origen StreamEvent. */
176
- declare function translateEvent(event: AgentEvent, extractCitations?: (text: string) => Citation[]): StreamEvent | null;
177
- /**
178
- * Eagerly subscribe to an Agent and return an async iterable of Origen StreamEvents.
179
- *
180
- * CRITICAL: The subscription is created synchronously when this function is called,
181
- * BEFORE agent.prompt() starts. This avoids the race condition where events
182
- * emitted during prompt() are missed if subscription happens after.
183
- *
184
- * Usage:
185
- * const { stream, unsubscribe } = createEventStream(agent, extractCitations);
186
- * agent.prompt(messages); // events flow into stream via active subscription
187
- * for await (const event of stream) { ... }
188
- */
189
- declare function createEventStream(agent: any, // Agent from pi-agent-core
190
- extractCitations?: (text: string) => Citation[]): {
191
- stream: AsyncGenerator<StreamEvent>;
192
- unsubscribe: () => void;
193
- };
194
- /**
195
- * Subscribe to an Agent and yield Origen StreamEvents.
196
- * Handles the full lifecycle from agent_start to agent_end.
197
- *
198
- * @deprecated Use createEventStream() instead to avoid race conditions.
199
- * This function subscribes lazily (on first iteration) which can miss events
200
- * if the agent has already started emitting.
201
- */
202
- declare function agentToStreamEvents(agent: any, extractCitations?: (text: string) => Citation[]): AsyncGenerator<StreamEvent>;
203
-
204
- export { type AgentConfig as A, type Citation as C, type D1Like as D, type ModelConfig as M, type ModelResolutionOptions, type OrigenTool as O, type ReadingContext as R, type StreamEvent as S, type UsageInfo as U, type AgentResponse as a, adaptTool, adaptTools, agentToStreamEvents, type AuthCheckResult as b, buildContext, type D1Provider as c, convertMessages, createEventStream, callOrigen as d, checkAuth as e, checkOpenRouterAuth as f, resolveModel, streamOrigen as s, translateEvent };
1
+ import '@mariozechner/pi-ai';
2
+ import '@mariozechner/pi-agent-core';
3
+ export { M as ModelResolutionOptions, j as adaptTool, k as adaptTools, l as agentToStreamEvents, m as buildContext, n as convertMessages, h as createEventStream, i as defaultCitationExtractor, r as resolveModel, t as translateEvent } from './adapter-DXIT3O2f.js';
4
+ import 'zod';
5
+ import './models.js';