@elfenlabs/cog 0.1.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Elfenlabs
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,295 @@
1
+ # 🧠 Cog
2
+
3
+ A minimal agent SDK for TypeScript. Three primitives, zero opinions on your LLM provider.
4
+
5
+ ```
6
+ npm install @elfenlabs/cog
7
+ ```
8
+
9
+ ## Quick Start
10
+
11
+ ```typescript
12
+ import { createContext, createTool, createOpenAIProvider, runAgent } from '@elfenlabs/cog'
13
+
14
+ // Define a tool
15
+ const getWeather = createTool({
16
+ id: 'get_weather',
17
+ description: 'Get the current weather for a city',
18
+ schema: {
19
+ city: { type: 'string', description: 'The city name' },
20
+ },
21
+ execute: async (args) => {
22
+ const { city } = args as { city: string }
23
+ return { city, temp: 22, condition: 'sunny' }
24
+ },
25
+ })
26
+
27
+ // Create context and provider
28
+ const ctx = createContext()
29
+ ctx.push("What's the weather in Tokyo?")
30
+
31
+ const provider = createOpenAIProvider('https://api.openai.com', 'gpt-4o', {
32
+ apiKey: process.env.OPENAI_API_KEY,
33
+ })
34
+
35
+ // Run the agent
36
+ const result = await runAgent({
37
+ ctx,
38
+ provider,
39
+ instruction: 'You are a helpful assistant. Use tools when needed.',
40
+ tools: [getWeather],
41
+ })
42
+
43
+ console.log(result.response) // "The weather in Tokyo is 22°C and sunny."
44
+ console.log(result.steps) // 2
45
+ console.log(result.usage) // { promptTokens, completionTokens, totalTokens }
46
+ ```
47
+
48
+ ## Primitives
49
+
50
+ | Primitive | What it is |
51
+ |---|---|
52
+ | **Context** | Append-only message chain. You push messages in, the agent loop reads them out. |
53
+ | **Tool** | Schema + execute function. The agent calls tools automatically based on model output. |
54
+ | **Agent** | The loop. Calls the provider, executes tool calls, repeats until the model responds with text. |
55
+
56
+ ## Context
57
+
58
+ An ordered `Message[]` chain. Push strings (become `user` messages) or full `Message` objects.
59
+
60
+ ```typescript
61
+ import { createContext } from '@elfenlabs/cog'
62
+
63
+ const ctx = createContext()
64
+
65
+ // Strings become user messages
66
+ ctx.push('What is 2 + 2?')
67
+
68
+ // Full messages for other roles
69
+ ctx.push({ role: 'system', content: 'You are a math tutor.' })
70
+
71
+ // Read messages
72
+ ctx.messages // readonly Message[]
73
+
74
+ // Serialize / restore
75
+ const snapshot = ctx.serialize()
76
+ const restored = createContext({ from: snapshot })
77
+ ```
78
+
79
+ ### Message Shape
80
+
81
+ ```typescript
82
+ type Message = {
83
+ role: 'system' | 'user' | 'assistant' | 'tool'
84
+ content: string
85
+ reasoning?: string // chain-of-thought from reasoning models
86
+ toolCallId?: string // links tool results back to the call
87
+ toolCalls?: ToolCallRequest[] // tool calls requested by the model
88
+ }
89
+ ```
90
+
91
+ ## Tool
92
+
93
+ A tool is an `id`, a `description`, a `schema`, and an `execute` function.
94
+
95
+ ```typescript
96
+ import { createTool } from '@elfenlabs/cog'
97
+
98
+ const calculator = createTool({
99
+ id: 'calculator',
100
+ description: 'Evaluate a math expression',
101
+ schema: {
102
+ expression: { type: 'string', description: 'The expression to evaluate', required: true },
103
+ },
104
+ execute: async (args) => {
105
+ const { expression } = args as { expression: string }
106
+ return { result: eval(expression) }
107
+ },
108
+ })
109
+
110
+ // The .spec property gives you the wire format for provider APIs
111
+ calculator.spec // { name, description, parameters }
112
+ ```
113
+
114
+ ### Parameter Types
115
+
116
+ ```typescript
117
+ type ToolParameter = {
118
+ type: 'string' | 'number' | 'boolean'
119
+ description: string
120
+ required?: boolean // default: true
121
+ }
122
+ ```
123
+
124
+ ## Agent Loop
125
+
126
+ `runAgent` calls the provider in a loop, executing tool calls until the model responds with text only.
127
+
128
+ ```typescript
129
+ import { runAgent } from '@elfenlabs/cog'
130
+
131
+ const result = await runAgent({
132
+ ctx, // Context — the conversation so far
133
+ provider, // Provider — any LLM backend
134
+ instruction: '...', // system prompt (prepended to every call)
135
+ tools: [tool1, tool2], // available tools
136
+
137
+ // Limits
138
+ maxSteps: 50, // default: 50
139
+ signal: abortController.signal,
140
+
141
+ // Streaming callbacks
142
+ onThinkingStart: () => {},
143
+ onThinking: (chunk) => {}, // reasoning tokens (dim/hidden)
144
+ onThinkingEnd: () => {},
145
+ onOutputStart: () => {},
146
+ onOutput: (chunk) => {}, // content tokens (visible)
147
+ onOutputEnd: () => {},
148
+
149
+ // Tool lifecycle hooks
150
+ onBeforeToolCall: async (tool, args) => {
151
+ // return false to block the call
152
+ },
153
+ onAfterToolCall: (tool, args, result) => {},
154
+ })
155
+
156
+ result.response // final text response
157
+ result.steps // number of provider calls made
158
+ result.usage // { promptTokens, completionTokens, totalTokens }
159
+ ```
160
+
161
+ ### How the Loop Works
162
+
163
+ ```
164
+ ┌─────────────────────────────────────────────┐
165
+ │ system prompt + ctx.messages → provider │
166
+ │ ↓ │
167
+ │ ┌─ tool calls? ──────────────────────────┐ │
168
+ │ │ YES → execute tools → push results │ │
169
+ │ │ → loop back to provider │ │
170
+ │ ├─ text content? ────────────────────────┤ │
171
+ │ │ YES → push assistant message → return │ │
172
+ │ ├─ reasoning only? ─────────────────────┤ │
173
+ │ │ YES → push reasoning → loop │ │
174
+ │ └────────────────────────────────────────┘ │
175
+ └─────────────────────────────────────────────┘
176
+ ```
177
+
178
+ ## Provider
179
+
180
+ The `Provider` interface is a single method. Implement it for any LLM backend.
181
+
182
+ ```typescript
183
+ interface Provider {
184
+ generate(params: {
185
+ messages: Message[]
186
+ tools?: ToolSpec[]
187
+ signal?: AbortSignal
188
+ stream?: StreamCallbacks
189
+ }): Promise<GenerateResult>
190
+ }
191
+
192
+ type GenerateResult = {
193
+ content?: string
194
+ reasoning?: string
195
+ toolCalls?: ToolCallRequest[]
196
+ usage?: Usage
197
+ }
198
+
199
+ type StreamCallbacks = {
200
+ onReasoning?: (chunk: string) => void
201
+ onContent?: (chunk: string) => void
202
+ }
203
+ ```
204
+
205
+ ### Built-in: OpenAI-Compatible Provider
206
+
207
+ Works with OpenAI, vLLM, OpenRouter, Ollama, LiteLLM, and any OpenAI-compatible API. Supports streaming (SSE) with reasoning model support (`reasoning_content`).
208
+
209
+ ```typescript
210
+ import { createOpenAIProvider } from '@elfenlabs/cog'
211
+
212
+ // OpenAI
213
+ const openai = createOpenAIProvider('https://api.openai.com', 'gpt-4o', {
214
+ apiKey: process.env.OPENAI_API_KEY,
215
+ })
216
+
217
+ // Local vLLM
218
+ const vllm = createOpenAIProvider('http://localhost:8000', 'my-model')
219
+
220
+ // OpenRouter
221
+ const openrouter = createOpenAIProvider('https://openrouter.ai/api', 'anthropic/claude-sonnet-4.5', {
222
+ apiKey: process.env.OPENROUTER_API_KEY,
223
+ temperature: 0.2,
224
+ })
225
+ ```
226
+
227
+ ## Sub-Agent Composition
228
+
229
+ Agents are just functions. Wrap `runAgent` inside a tool to create sub-agents with isolated context.
230
+
231
+ ```typescript
232
+ const searchOrders = createTool({
233
+ id: 'search_orders',
234
+ description: 'Search through paginated orders to find a match',
235
+ schema: {
236
+ query: { type: 'string', description: 'What to search for' },
237
+ },
238
+ execute: async (args) => {
239
+ const { query } = args as { query: string }
240
+
241
+ // Sub-agent gets its own isolated context
242
+ const subCtx = createContext()
243
+ subCtx.push(`Find: ${query}`)
244
+
245
+ const fetchPage = createTool({
246
+ id: 'fetch_page',
247
+ description: 'Fetch a page of orders',
248
+ schema: { page: { type: 'number', description: 'Page number' } },
249
+ execute: async (a) => api.getOrders((a as { page: number }).page),
250
+ })
251
+
252
+ const result = await runAgent({
253
+ ctx: subCtx,
254
+ provider,
255
+ instruction: 'Search through pages until you find the item or exhaust all pages.',
256
+ tools: [fetchPage],
257
+ maxSteps: 20,
258
+ })
259
+
260
+ // Only the final answer bubbles up — no pagination noise in parent context
261
+ return result.response
262
+ },
263
+ })
264
+
265
+ // Parent agent uses the sub-agent as a regular tool
266
+ const result = await runAgent({
267
+ ctx: createContext(),
268
+ provider,
269
+ instruction: 'Use search_orders to look up order information.',
270
+ tools: [searchOrders],
271
+ })
272
+ ```
273
+
274
+ ## Error Handling
275
+
276
+ ```typescript
277
+ import { MaxStepsError, AgentAbortError } from '@elfenlabs/cog'
278
+
279
+ try {
280
+ await runAgent({ ctx, provider, instruction: '...', tools, maxSteps: 10 })
281
+ } catch (err) {
282
+ if (err instanceof MaxStepsError) {
283
+ // Agent exceeded step limit
284
+ }
285
+ if (err instanceof AgentAbortError) {
286
+ // AbortSignal was triggered
287
+ }
288
+ }
289
+ ```
290
+
291
+ Unknown tool calls and tool execution errors are automatically caught and fed back to the model as `tool` messages, letting it recover gracefully.
292
+
293
+ ## License
294
+
295
+ MIT
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Cog v2 — Agent Loop
3
+ *
4
+ * The heart of the library. Calls the model in a loop,
5
+ * executing tool calls until the model responds with text only.
6
+ */
7
+ import type { Context } from './context.js';
8
+ import type { Tool } from './tool.js';
9
+ import type { Provider, Usage } from './types.js';
10
+ export type AgentConfig = {
11
+ ctx: Context;
12
+ provider: Provider;
13
+ instruction: string;
14
+ tools: Tool<any>[];
15
+ maxSteps?: number;
16
+ signal?: AbortSignal;
17
+ onThinkingStart?: () => void;
18
+ onThinking?: (chunk: string) => void;
19
+ onThinkingEnd?: () => void;
20
+ onOutputStart?: () => void;
21
+ onOutput?: (chunk: string) => void;
22
+ onOutputEnd?: () => void;
23
+ onBeforeToolCall?: (tool: Tool<any>, args: Record<string, unknown>) => Promise<boolean | void> | boolean | void;
24
+ onAfterToolCall?: (tool: Tool<any>, args: Record<string, unknown>, result: unknown) => void;
25
+ };
26
+ export type AgentResult = {
27
+ response: string;
28
+ steps: number;
29
+ usage: Usage;
30
+ };
31
+ export declare class MaxStepsError extends Error {
32
+ constructor(maxSteps: number);
33
+ }
34
+ export declare class AgentAbortError extends Error {
35
+ constructor();
36
+ }
37
+ export declare function runAgent(config: AgentConfig): Promise<AgentResult>;
38
+ //# sourceMappingURL=agent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAC3C,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AACrC,OAAO,KAAK,EAAW,QAAQ,EAAmB,KAAK,EAAE,MAAM,YAAY,CAAA;AAI3E,MAAM,MAAM,WAAW,GAAG;IACxB,GAAG,EAAE,OAAO,CAAA;IACZ,QAAQ,EAAE,QAAQ,CAAA;IAClB,WAAW,EAAE,MAAM,CAAA;IACnB,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE,CAAA;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,MAAM,CAAC,EAAE,WAAW,CAAA;IACpB,eAAe,CAAC,EAAE,MAAM,IAAI,CAAA;IAC5B,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IACpC,aAAa,CAAC,EAAE,MAAM,IAAI,CAAA;IAC1B,aAAa,CAAC,EAAE,MAAM,IAAI,CAAA;IAC1B,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IAClC,WAAW,CAAC,EAAE,MAAM,IAAI,CAAA;IACxB,gBAAgB,CAAC,EAAE,CACjB,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,EACf,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC1B,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,GAAG,OAAO,GAAG,IAAI,CAAA;IAC7C,eAAe,CAAC,EAAE,CAChB,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,EACf,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,MAAM,EAAE,OAAO,KACZ,IAAI,CAAA;CACV,CAAA;AAED,MAAM,MAAM,WAAW,GAAG;IACxB,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,KAAK,CAAA;CACb,CAAA;AAID,qBAAa,aAAc,SAAQ,KAAK;gBAC1B,QAAQ,EAAE,MAAM;CAI7B;AAED,qBAAa,eAAgB,SAAQ,KAAK;;CAKzC;AAID,wBAAsB,QAAQ,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,CAwMxE"}
package/dist/agent.js ADDED
@@ -0,0 +1,183 @@
1
+ /**
2
+ * Cog v2 — Agent Loop
3
+ *
4
+ * The heart of the library. Calls the model in a loop,
5
+ * executing tool calls until the model responds with text only.
6
+ */
7
+ // ── Errors ──────────────────────────────────────────────────────────────────
8
+ export class MaxStepsError extends Error {
9
+ constructor(maxSteps) {
10
+ super(`Agent exceeded maximum steps (${maxSteps})`);
11
+ this.name = 'MaxStepsError';
12
+ }
13
+ }
14
+ export class AgentAbortError extends Error {
15
+ constructor() {
16
+ super('Agent was aborted');
17
+ this.name = 'AgentAbortError';
18
+ }
19
+ }
20
+ // ── Agent Loop ──────────────────────────────────────────────────────────────
21
+ export async function runAgent(config) {
22
+ const { ctx, provider, instruction, tools, maxSteps = 50, signal, onThinkingStart, onThinking, onThinkingEnd, onOutputStart, onOutput, onOutputEnd, onBeforeToolCall, onAfterToolCall, } = config;
23
+ const toolMap = new Map(tools.map(t => [t.id, t]));
24
+ const toolSpecs = tools.map(t => t.spec);
25
+ let steps = 0;
26
+ let isThinking = false;
27
+ let isOutputting = false;
28
+ const totalUsage = { promptTokens: 0, completionTokens: 0, totalTokens: 0 };
29
+ /** End reasoning block if one is active */
30
+ const endThinking = () => {
31
+ if (isThinking) {
32
+ isThinking = false;
33
+ onThinkingEnd?.();
34
+ }
35
+ };
36
+ /** End output block if one is active */
37
+ const endOutput = () => {
38
+ if (isOutputting) {
39
+ isOutputting = false;
40
+ onOutputEnd?.();
41
+ }
42
+ };
43
+ while (true) {
44
+ // Check abort
45
+ if (signal?.aborted) {
46
+ throw new AgentAbortError();
47
+ }
48
+ // Check step limit
49
+ if (steps >= maxSteps) {
50
+ throw new MaxStepsError(maxSteps);
51
+ }
52
+ // Build messages: instruction as system prompt + context messages
53
+ const messages = [
54
+ { role: 'system', content: instruction },
55
+ ...ctx.messages,
56
+ ];
57
+ // Build stream callbacks for the provider
58
+ // Wrap onThinking to manage start/end lifecycle
59
+ const wrappedOnThinking = onThinking
60
+ ? (chunk) => {
61
+ if (!isThinking) {
62
+ isThinking = true;
63
+ onThinkingStart?.();
64
+ }
65
+ onThinking(chunk);
66
+ }
67
+ : undefined;
68
+ const wrappedOnOutput = onOutput
69
+ ? (chunk) => {
70
+ if (!isOutputting) {
71
+ isOutputting = true;
72
+ onOutputStart?.();
73
+ }
74
+ onOutput(chunk);
75
+ }
76
+ : undefined;
77
+ const stream = wrappedOnThinking || wrappedOnOutput
78
+ ? {
79
+ onReasoning: wrappedOnThinking,
80
+ onContent: wrappedOnOutput,
81
+ }
82
+ : undefined;
83
+ // Call the provider
84
+ const result = await provider.generate({
85
+ messages,
86
+ tools: toolSpecs.length > 0 ? toolSpecs : undefined,
87
+ signal,
88
+ stream,
89
+ });
90
+ steps++;
91
+ // Accumulate token usage
92
+ if (result.usage) {
93
+ totalUsage.promptTokens += result.usage.promptTokens;
94
+ totalUsage.completionTokens += result.usage.completionTokens;
95
+ totalUsage.totalTokens += result.usage.totalTokens;
96
+ }
97
+ // Case 1: Model returned tool calls → execute and loop
98
+ if (result.toolCalls && result.toolCalls.length > 0) {
99
+ endThinking();
100
+ // Append the assistant message with tool calls to context
101
+ ctx.push({
102
+ role: 'assistant',
103
+ content: result.content ?? '',
104
+ reasoning: result.reasoning,
105
+ toolCalls: result.toolCalls,
106
+ });
107
+ for (const call of result.toolCalls) {
108
+ const tool = toolMap.get(call.name);
109
+ if (!tool) {
110
+ // Unknown tool — append error as tool result so model can recover
111
+ ctx.push({
112
+ role: 'tool',
113
+ content: `Error: unknown tool "${call.name}"`,
114
+ toolCallId: call.id,
115
+ });
116
+ continue;
117
+ }
118
+ // Hook: before
119
+ if (onBeforeToolCall) {
120
+ const allowed = await onBeforeToolCall(tool, call.arguments);
121
+ if (allowed === false) {
122
+ ctx.push({
123
+ role: 'tool',
124
+ content: 'Error: tool call was blocked',
125
+ toolCallId: call.id,
126
+ });
127
+ continue;
128
+ }
129
+ }
130
+ // Execute the tool
131
+ try {
132
+ const toolResult = await tool.execute(call.arguments, ctx);
133
+ const content = typeof toolResult === 'string'
134
+ ? toolResult
135
+ : JSON.stringify(toolResult);
136
+ ctx.push({
137
+ role: 'tool',
138
+ content,
139
+ toolCallId: call.id,
140
+ });
141
+ // Hook: after
142
+ if (onAfterToolCall) {
143
+ onAfterToolCall(tool, call.arguments, toolResult);
144
+ }
145
+ }
146
+ catch (err) {
147
+ const message = err instanceof Error ? err.message : String(err);
148
+ ctx.push({
149
+ role: 'tool',
150
+ content: `Error: ${message}`,
151
+ toolCallId: call.id,
152
+ });
153
+ }
154
+ }
155
+ // Continue the loop
156
+ continue;
157
+ }
158
+ // Case 2: Model returned text only → done
159
+ if (result.content) {
160
+ endThinking();
161
+ endOutput();
162
+ ctx.push({
163
+ role: 'assistant',
164
+ content: result.content,
165
+ reasoning: result.reasoning,
166
+ });
167
+ return { response: result.content, steps, usage: totalUsage };
168
+ }
169
+ // Case 3: Reasoning only (no content, no tool calls) — continue loop
170
+ // Reasoning models sometimes produce a think step before acting.
171
+ if (result.reasoning) {
172
+ ctx.push({
173
+ role: 'assistant',
174
+ content: '',
175
+ reasoning: result.reasoning,
176
+ });
177
+ continue;
178
+ }
179
+ // Case 4: Nothing at all — error
180
+ throw new Error('Provider returned neither content nor tool calls');
181
+ }
182
+ }
183
+ //# sourceMappingURL=agent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent.js","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAsCH,+EAA+E;AAE/E,MAAM,OAAO,aAAc,SAAQ,KAAK;IACtC,YAAY,QAAgB;QAC1B,KAAK,CAAC,iCAAiC,QAAQ,GAAG,CAAC,CAAA;QACnD,IAAI,CAAC,IAAI,GAAG,eAAe,CAAA;IAC7B,CAAC;CACF;AAED,MAAM,OAAO,eAAgB,SAAQ,KAAK;IACxC;QACE,KAAK,CAAC,mBAAmB,CAAC,CAAA;QAC1B,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAA;IAC/B,CAAC;CACF;AAED,+EAA+E;AAE/E,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,MAAmB;IAChD,MAAM,EACJ,GAAG,EACH,QAAQ,EACR,WAAW,EACX,KAAK,EACL,QAAQ,GAAG,EAAE,EACb,MAAM,EACN,eAAe,EACf,UAAU,EACV,aAAa,EACb,aAAa,EACb,QAAQ,EACR,WAAW,EACX,gBAAgB,EAChB,eAAe,GAChB,GAAG,MAAM,CAAA;IAEV,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAA;IAClD,MAAM,SAAS,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAA;IAExC,IAAI,KAAK,GAAG,CAAC,CAAA;IACb,IAAI,UAAU,GAAG,KAAK,CAAA;IACtB,IAAI,YAAY,GAAG,KAAK,CAAA;IACxB,MAAM,UAAU,GAAU,EAAE,YAAY,EAAE,CAAC,EAAE,gBAAgB,EAAE,CAAC,EAAE,WAAW,EAAE,CAAC,EAAE,CAAA;IAElF,2CAA2C;IAC3C,MAAM,WAAW,GAAG,GAAG,EAAE;QACvB,IAAI,UAAU,EAAE,CAAC;YACf,UAAU,GAAG,KAAK,CAAA;YAClB,aAAa,EAAE,EAAE,CAAA;QACnB,CAAC;IACH,CAAC,CAAA;IAED,wCAAwC;IACxC,MAAM,SAAS,GAAG,GAAG,EAAE;QACrB,IAAI,YAAY,EAAE,CAAC;YACjB,YAAY,GAAG,KAAK,CAAA;YACpB,WAAW,EAAE,EAAE,CAAA;QACjB,CAAC;IACH,CAAC,CAAA;IAED,OAAO,IAAI,EAAE,CAAC;QACZ,cAAc;QACd,IAAI,MAAM,EAAE,OAAO,EAAE,CAAC;YACpB,MAAM,IAAI,eAAe,EAAE,CAAA;QAC7B,CAAC;QAED,mBAAmB;QACnB,IAAI,KAAK,IAAI,QAAQ,EAAE,CAAC;YACtB,MAAM,IAAI,aAAa,CAAC,QAAQ,CAAC,CAAA;QACnC,CAAC;QAED,kEAAkE;QAClE,MAAM,QAAQ,GAAc;YAC1B,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,WAAW,EAAE;YACxC,GAAG,GAAG,CAAC,QAAQ;SAChB,CAAA;QAED,0CAA0C;QAC1C,gDAAgD;QAChD,MAAM,iBAAiB,GAAG,UAAU;YAClC,CAAC,CAAC,CAAC,KAAa,EAAE,EAAE;gBAChB,IAAI,CAAC,UAAU,EAAE,CAAC;oBAChB,UAAU,GAAG,IAAI,CAAA;oBACjB,eAAe,EAAE,EAAE,CAAA;gBACrB,CAAC;gBACD,UAAU,CAAC,KAAK,CAAC,CAAA;YACnB,CAAC;YACH,CAAC,CAAC,SAAS,CAAA;QAEb,MAAM,eAAe,GAAG,QAAQ;YAC9B,CAAC,CAAC,CAAC,KAAa,EAAE,EAAE;gBAChB,IAAI,CAAC,YAAY,EAAE,CAAC;oBAClB,YAAY,GAAG,IAAI,CAAA;oBACnB,aAAa,EAAE,EAAE,CAAA;gBACnB,CAAC;gBACD,QAAQ,CAAC,KAAK,CAAC,CAAA;YACjB,CAAC;YACH,CAAC,CAAC,SAAS,CAAA;QAEb,MAAM,MAAM,GACV,iBAAiB,IAAI,eAAe;YAClC,CAAC,CAAC;gBACE,WAAW,EAAE,iBAAiB;gBAC9B,SAAS,EAAE,eAAe;aAC3B;YACH,CAAC,CAAC,SAAS,CAAA;QAEf,oBAAoB;QACpB,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,QAAQ,CAAC;YACrC,QAAQ;YACR,KAAK,EAAE,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS;YACnD,MAAM;YACN,MAAM;SACP,CAAC,CAAA;QAEF,KAAK,EAAE,CAAA;QAEP,yBAAyB;QACzB,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;YACjB,UAAU,CAAC,YAAY,IAAI,MAAM,CAAC,KAAK,CAAC,YAAY,CAAA;YACpD,UAAU,CAAC,gBAAgB,IAAI,MAAM,CAAC,KAAK,CAAC,gBAAgB,CAAA;YAC5D,UAAU,CAAC,WAAW,IAAI,MAAM,CAAC,KAAK,CAAC,WAAW,CAAA;QACpD,CAAC;QAED,uDAAuD;QACvD,IAAI,MAAM,CAAC,SAAS,IAAI,MAAM,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACpD,WAAW,EAAE,CAAA;YACb,0DAA0D;YAC1D,GAAG,CAAC,IAAI,CAAC;gBACP,IAAI,EAAE,WAAW;gBACjB,OAAO,EAAE,MAAM,CAAC,OAAO,IAAI,EAAE;gBAC7B,SAAS,EAAE,MAAM,CAAC,SAAS;gBAC3B,SAAS,EAAE,MAAM,CAAC,SAAS;aAC5B,CAAC,CAAA;YAEF,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;gBACpC,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;gBACnC,IAAI,CAAC,IAAI,EAAE,CAAC;oBACV,kEAAkE;oBAClE,GAAG,CAAC,IAAI,CAAC;wBACP,IAAI,EAAE,MAAM;wBACZ,OAAO,EAAE,wBAAwB,IAAI,CAAC,IAAI,GAAG;wBAC7C,UAAU,EAAE,IAAI,CAAC,EAAE;qBACpB,CAAC,CAAA;oBACF,SAAQ;gBACV,CAAC;gBAED,eAAe;gBACf,IAAI,gBAAgB,EAAE,CAAC;oBACrB,MAAM,OAAO,GAAG,MAAM,gBAAgB,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,CAAA;oBAC5D,IAAI,OAAO,KAAK,KAAK,EAAE,CAAC;wBACtB,GAAG,CAAC,IAAI,CAAC;4BACP,IAAI,EAAE,MAAM;4BACZ,OAAO,EAAE,8BAA8B;4BACvC,UAAU,EAAE,IAAI,CAAC,EAAE;yBACpB,CAAC,CAAA;wBACF,SAAQ;oBACV,CAAC;gBACH,CAAC;gBAED,mBAAmB;gBACnB,IAAI,CAAC;oBACH,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,SAAgB,EAAE,GAAG,CAAC,CAAA;oBACjE,MAAM,OAAO,GACX,OAAO,UAAU,KAAK,QAAQ;wBAC5B,CAAC,CAAC,UAAU;wBACZ,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,CAAA;oBAEhC,GAAG,CAAC,IAAI,CAAC;wBACP,IAAI,EAAE,MAAM;wBACZ,OAAO;wBACP,UAAU,EAAE,IAAI,CAAC,EAAE;qBACpB,CAAC,CAAA;oBAEF,cAAc;oBACd,IAAI,eAAe,EAAE,CAAC;wBACpB,eAAe,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,EAAE,UAAU,CAAC,CAAA;oBACnD,CAAC;gBACH,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;oBAChE,GAAG,CAAC,IAAI,CAAC;wBACP,IAAI,EAAE,MAAM;wBACZ,OAAO,EAAE,UAAU,OAAO,EAAE;wBAC5B,UAAU,EAAE,IAAI,CAAC,EAAE;qBACpB,CAAC,CAAA;gBACJ,CAAC;YACH,CAAC;YAED,oBAAoB;YACpB,SAAQ;QACV,CAAC;QAED,0CAA0C;QAC1C,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACnB,WAAW,EAAE,CAAA;YACb,SAAS,EAAE,CAAA;YACX,GAAG,CAAC,IAAI,CAAC;gBACP,IAAI,EAAE,WAAW;gBACjB,OAAO,EAAE,MAAM,CAAC,OAAO;gBACvB,SAAS,EAAE,MAAM,CAAC,SAAS;aAC5B,CAAC,CAAA;YACF,OAAO,EAAE,QAAQ,EAAE,MAAM,CAAC,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,CAAA;QAC/D,CAAC;QAED,qEAAqE;QACrE,iEAAiE;QACjE,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;YACrB,GAAG,CAAC,IAAI,CAAC;gBACP,IAAI,EAAE,WAAW;gBACjB,OAAO,EAAE,EAAE;gBACX,SAAS,EAAE,MAAM,CAAC,SAAS;aAC5B,CAAC,CAAA;YACF,SAAQ;QACV,CAAC;QAED,iCAAiC;QACjC,MAAM,IAAI,KAAK,CAAC,kDAAkD,CAAC,CAAA;IACrE,CAAC;AACH,CAAC"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Cog v2 — Context
3
+ *
4
+ * Append-only message chain. Push messages in, serialize out.
5
+ */
6
+ import type { Message } from './types.js';
7
+ export type SerializedContext = {
8
+ messages: Message[];
9
+ };
10
+ export type ContextOptions = {
11
+ /** Restore from a serialized snapshot */
12
+ from?: SerializedContext;
13
+ };
14
+ export declare class Context {
15
+ private _messages;
16
+ constructor(opts?: ContextOptions);
17
+ /** All messages in the chain (readonly copy) */
18
+ get messages(): readonly Message[];
19
+ /**
20
+ * Push a message onto the chain.
21
+ * - String → user message
22
+ * - Message object → stored as-is
23
+ */
24
+ push(content: string | Message): void;
25
+ /** Serialize to a JSON-safe snapshot */
26
+ serialize(): SerializedContext;
27
+ }
28
+ export declare function createContext(opts?: ContextOptions): Context;
29
+ //# sourceMappingURL=context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAA;AAIzC,MAAM,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,EAAE,OAAO,EAAE,CAAA;CACpB,CAAA;AAED,MAAM,MAAM,cAAc,GAAG;IAC3B,yCAAyC;IACzC,IAAI,CAAC,EAAE,iBAAiB,CAAA;CACzB,CAAA;AAID,qBAAa,OAAO;IAClB,OAAO,CAAC,SAAS,CAAW;gBAEhB,IAAI,CAAC,EAAE,cAAc;IAIjC,gDAAgD;IAChD,IAAI,QAAQ,IAAI,SAAS,OAAO,EAAE,CAEjC;IAED;;;;OAIG;IACH,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI;IAQrC,wCAAwC;IACxC,SAAS,IAAI,iBAAiB;CAG/B;AAID,wBAAgB,aAAa,CAAC,IAAI,CAAC,EAAE,cAAc,GAAG,OAAO,CAE5D"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Cog v2 — Context
3
+ *
4
+ * Append-only message chain. Push messages in, serialize out.
5
+ */
6
+ // ── Context ─────────────────────────────────────────────────────────────────
7
+ export class Context {
8
+ _messages;
9
+ constructor(opts) {
10
+ this._messages = opts?.from ? structuredClone(opts.from.messages) : [];
11
+ }
12
+ /** All messages in the chain (readonly copy) */
13
+ get messages() {
14
+ return this._messages;
15
+ }
16
+ /**
17
+ * Push a message onto the chain.
18
+ * - String → user message
19
+ * - Message object → stored as-is
20
+ */
21
+ push(content) {
22
+ if (typeof content === 'string') {
23
+ this._messages.push({ role: 'user', content });
24
+ }
25
+ else {
26
+ this._messages.push(content);
27
+ }
28
+ }
29
+ /** Serialize to a JSON-safe snapshot */
30
+ serialize() {
31
+ return { messages: structuredClone(this._messages) };
32
+ }
33
+ }
34
+ // ── Factory ─────────────────────────────────────────────────────────────────
35
+ export function createContext(opts) {
36
+ return new Context(opts);
37
+ }
38
+ //# sourceMappingURL=context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAeH,+EAA+E;AAE/E,MAAM,OAAO,OAAO;IACV,SAAS,CAAW;IAE5B,YAAY,IAAqB;QAC/B,IAAI,CAAC,SAAS,GAAG,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;IACxE,CAAC;IAED,gDAAgD;IAChD,IAAI,QAAQ;QACV,OAAO,IAAI,CAAC,SAAS,CAAA;IACvB,CAAC;IAED;;;;OAIG;IACH,IAAI,CAAC,OAAyB;QAC5B,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;YAChC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAA;QAChD,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;QAC9B,CAAC;IACH,CAAC;IAED,wCAAwC;IACxC,SAAS;QACP,OAAO,EAAE,QAAQ,EAAE,eAAe,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAA;IACtD,CAAC;CACF;AAED,+EAA+E;AAE/E,MAAM,UAAU,aAAa,CAAC,IAAqB;IACjD,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;AAC1B,CAAC"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Cog v2 — A minimal agent SDK for TypeScript
3
+ *
4
+ * Three primitives, infinite composition.
5
+ */
6
+ export { createContext, Context } from './context.js';
7
+ export type { ContextOptions, SerializedContext } from './context.js';
8
+ export { createTool, Tool } from './tool.js';
9
+ export type { ToolConfig } from './tool.js';
10
+ export { runAgent, MaxStepsError, AgentAbortError } from './agent.js';
11
+ export type { AgentConfig, AgentResult } from './agent.js';
12
+ export { createOpenAIProvider } from './providers/openai.js';
13
+ export type { OpenAIProviderOptions } from './providers/openai.js';
14
+ export type { Message, ToolCallRequest, ToolParameter, ToolSpec, GenerateResult, StreamCallbacks, Provider, Usage, } from './types.js';
15
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AACrD,YAAY,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAA;AAErE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAC5C,YAAY,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA;AAE3C,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AACrE,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAE1D,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAA;AAC5D,YAAY,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAA;AAElE,YAAY,EACV,OAAO,EACP,eAAe,EACf,aAAa,EACb,QAAQ,EACR,cAAc,EACd,eAAe,EACf,QAAQ,EACR,KAAK,GACN,MAAM,YAAY,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Cog v2 — A minimal agent SDK for TypeScript
3
+ *
4
+ * Three primitives, infinite composition.
5
+ */
6
+ export { createContext, Context } from './context.js';
7
+ export { createTool, Tool } from './tool.js';
8
+ export { runAgent, MaxStepsError, AgentAbortError } from './agent.js';
9
+ export { createOpenAIProvider } from './providers/openai.js';
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAGrD,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAG5C,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAGrE,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAA"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Cog — OpenAI-compatible Provider
3
+ *
4
+ * Works with OpenAI, vLLM, OpenRouter, and any OpenAI-compatible API.
5
+ * Supports streaming (SSE) with reasoning_content extraction.
6
+ */
7
+ import type { Provider } from '../types.js';
8
+ export type OpenAIProviderOptions = {
9
+ /** API key for authentication (sent as Bearer token) */
10
+ apiKey?: string;
11
+ /** Temperature for generation (default: 0.7) */
12
+ temperature?: number;
13
+ };
14
+ /**
15
+ * Create a provider for any OpenAI-compatible API.
16
+ *
17
+ * Works with: OpenAI, vLLM, OpenRouter, Ollama, LiteLLM, etc.
18
+ *
19
+ * @example
20
+ * ```ts
21
+ * const provider = createOpenAIProvider('https://api.openai.com', 'gpt-4o')
22
+ * const provider = createOpenAIProvider('http://localhost:8000', 'my-model')
23
+ * const provider = createOpenAIProvider('https://openrouter.ai/api', 'anthropic/claude-sonnet-4.5', {
24
+ * apiKey: 'sk-or-...',
25
+ * temperature: 0.2,
26
+ * })
27
+ * ```
28
+ */
29
+ export declare function createOpenAIProvider(baseUrl: string, model: string, opts?: OpenAIProviderOptions): Provider;
30
+ //# sourceMappingURL=openai.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai.d.ts","sourceRoot":"","sources":["../../src/providers/openai.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAA8D,MAAM,aAAa,CAAA;AAIvG,MAAM,MAAM,qBAAqB,GAAG;IAClC,wDAAwD;IACxD,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,gDAAgD;IAChD,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,CAAA;AAwID;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,EACb,IAAI,CAAC,EAAE,qBAAqB,GAC3B,QAAQ,CA2DV"}
@@ -0,0 +1,196 @@
1
+ /**
2
+ * Cog — OpenAI-compatible Provider
3
+ *
4
+ * Works with OpenAI, vLLM, OpenRouter, and any OpenAI-compatible API.
5
+ * Supports streaming (SSE) with reasoning_content extraction.
6
+ */
7
+ // ── Message Conversion ──────────────────────────────────────────────────────
8
+ /** Convert internal Cog messages to OpenAI API wire format */
9
+ function toAPIMessages(messages) {
10
+ return messages.map(m => {
11
+ const msg = { role: m.role, content: m.content };
12
+ if (m.toolCallId)
13
+ msg.tool_call_id = m.toolCallId;
14
+ if (m.toolCalls) {
15
+ msg.tool_calls = m.toolCalls.map(tc => ({
16
+ id: tc.id,
17
+ type: 'function',
18
+ function: { name: tc.name, arguments: JSON.stringify(tc.arguments) },
19
+ }));
20
+ }
21
+ return msg;
22
+ });
23
+ }
24
+ /** Convert internal Cog tool specs to OpenAI function-calling format */
25
+ function toAPITools(tools) {
26
+ return tools.map(t => ({
27
+ type: 'function',
28
+ function: {
29
+ name: t.name,
30
+ description: t.description,
31
+ parameters: {
32
+ type: 'object',
33
+ properties: Object.fromEntries(Object.entries(t.parameters).map(([k, v]) => [
34
+ k,
35
+ { type: v.type, description: v.description },
36
+ ])),
37
+ required: Object.entries(t.parameters)
38
+ .filter(([_, v]) => v.required !== false)
39
+ .map(([k]) => k),
40
+ },
41
+ },
42
+ }));
43
+ }
44
+ /** Parse tool calls from a non-streaming response message */
45
+ function parseToolCalls(toolCalls) {
46
+ if (!toolCalls)
47
+ return undefined;
48
+ return toolCalls.map((tc) => ({
49
+ id: tc.id,
50
+ name: tc.function.name,
51
+ arguments: JSON.parse(tc.function.arguments),
52
+ }));
53
+ }
54
+ // ── SSE Streaming ───────────────────────────────────────────────────────────
55
+ async function readSSEStream(response, stream) {
56
+ let content = '';
57
+ let reasoning = '';
58
+ let usage;
59
+ const toolCallsMap = new Map();
60
+ const reader = response.body.getReader();
61
+ const decoder = new TextDecoder();
62
+ let buffer = '';
63
+ while (true) {
64
+ const { done, value } = await reader.read();
65
+ if (done)
66
+ break;
67
+ buffer += decoder.decode(value, { stream: true });
68
+ const lines = buffer.split('\n');
69
+ buffer = lines.pop();
70
+ for (const line of lines) {
71
+ if (!line.startsWith('data: '))
72
+ continue;
73
+ const payload = line.slice(6).trim();
74
+ if (payload === '[DONE]')
75
+ continue;
76
+ const chunk = JSON.parse(payload);
77
+ // Usage arrives in the final chunk (when stream_options.include_usage is set)
78
+ if (chunk.usage) {
79
+ usage = {
80
+ promptTokens: chunk.usage.prompt_tokens ?? 0,
81
+ completionTokens: chunk.usage.completion_tokens ?? 0,
82
+ totalTokens: chunk.usage.total_tokens ?? 0,
83
+ };
84
+ }
85
+ const delta = chunk.choices?.[0]?.delta;
86
+ if (!delta)
87
+ continue;
88
+ if (delta.reasoning_content) {
89
+ reasoning += delta.reasoning_content;
90
+ stream?.onReasoning?.(delta.reasoning_content);
91
+ }
92
+ if (delta.content) {
93
+ content += delta.content;
94
+ stream?.onContent?.(delta.content);
95
+ }
96
+ if (delta.tool_calls) {
97
+ for (const tc of delta.tool_calls) {
98
+ const idx = tc.index ?? 0;
99
+ if (!toolCallsMap.has(idx)) {
100
+ toolCallsMap.set(idx, { id: tc.id ?? '', name: '', args: '' });
101
+ }
102
+ const entry = toolCallsMap.get(idx);
103
+ if (tc.id)
104
+ entry.id = tc.id;
105
+ if (tc.function?.name)
106
+ entry.name += tc.function.name;
107
+ if (tc.function?.arguments)
108
+ entry.args += tc.function.arguments;
109
+ }
110
+ }
111
+ }
112
+ }
113
+ const toolCalls = toolCallsMap.size > 0
114
+ ? Array.from(toolCallsMap.values()).map(tc => ({
115
+ id: tc.id,
116
+ name: tc.name,
117
+ arguments: JSON.parse(tc.args || '{}'),
118
+ }))
119
+ : undefined;
120
+ return {
121
+ content: content || undefined,
122
+ reasoning: reasoning || undefined,
123
+ toolCalls,
124
+ usage,
125
+ };
126
+ }
127
+ // ── Provider Factory ────────────────────────────────────────────────────────
128
+ /**
129
+ * Create a provider for any OpenAI-compatible API.
130
+ *
131
+ * Works with: OpenAI, vLLM, OpenRouter, Ollama, LiteLLM, etc.
132
+ *
133
+ * @example
134
+ * ```ts
135
+ * const provider = createOpenAIProvider('https://api.openai.com', 'gpt-4o')
136
+ * const provider = createOpenAIProvider('http://localhost:8000', 'my-model')
137
+ * const provider = createOpenAIProvider('https://openrouter.ai/api', 'anthropic/claude-sonnet-4.5', {
138
+ * apiKey: 'sk-or-...',
139
+ * temperature: 0.2,
140
+ * })
141
+ * ```
142
+ */
143
+ export function createOpenAIProvider(baseUrl, model, opts) {
144
+ const temperature = opts?.temperature ?? 0.7;
145
+ return {
146
+ async generate(params) {
147
+ const shouldStream = !!(params.stream?.onReasoning || params.stream?.onContent);
148
+ const body = {
149
+ model,
150
+ messages: toAPIMessages(params.messages),
151
+ temperature,
152
+ stream: shouldStream,
153
+ ...(shouldStream ? { stream_options: { include_usage: true } } : {}),
154
+ };
155
+ const tools = params.tools && params.tools.length > 0 ? toAPITools(params.tools) : undefined;
156
+ if (tools) {
157
+ body.tools = tools;
158
+ body.tool_choice = 'auto';
159
+ }
160
+ const headers = { 'Content-Type': 'application/json' };
161
+ if (opts?.apiKey)
162
+ headers['Authorization'] = `Bearer ${opts.apiKey}`;
163
+ const response = await fetch(`${baseUrl}/v1/chat/completions`, {
164
+ method: 'POST',
165
+ headers,
166
+ body: JSON.stringify(body),
167
+ signal: params.signal,
168
+ });
169
+ if (!response.ok) {
170
+ const text = await response.text();
171
+ throw new Error(`LLM request failed (${response.status}): ${text}`);
172
+ }
173
+ // Non-streaming path
174
+ if (!shouldStream) {
175
+ const data = (await response.json());
176
+ const message = data.choices[0].message;
177
+ const usage = data.usage
178
+ ? {
179
+ promptTokens: data.usage.prompt_tokens ?? 0,
180
+ completionTokens: data.usage.completion_tokens ?? 0,
181
+ totalTokens: data.usage.total_tokens ?? 0,
182
+ }
183
+ : undefined;
184
+ return {
185
+ content: message.content ?? undefined,
186
+ reasoning: message.reasoning_content ?? undefined,
187
+ toolCalls: parseToolCalls(message.tool_calls),
188
+ usage,
189
+ };
190
+ }
191
+ // Streaming path (SSE)
192
+ return readSSEStream(response, params.stream);
193
+ },
194
+ };
195
+ }
196
+ //# sourceMappingURL=openai.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai.js","sourceRoot":"","sources":["../../src/providers/openai.ts"],"names":[],"mappings":"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"}
package/dist/tool.d.ts ADDED
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Cog v2 — Tool
3
+ *
4
+ * A tool is a schema + execute function. Everything is a tool.
5
+ */
6
+ import type { Context } from './context.js';
7
+ import type { ToolParameter, ToolSpec } from './types.js';
8
+ export type ToolConfig<TArgs = Record<string, unknown>> = {
9
+ id: string;
10
+ description: string;
11
+ schema?: Record<string, ToolParameter>;
12
+ execute: (args: TArgs, ctx: Context) => Promise<unknown>;
13
+ };
14
+ export declare class Tool<TArgs = Record<string, unknown>> {
15
+ readonly id: string;
16
+ readonly description: string;
17
+ readonly schema: Record<string, ToolParameter>;
18
+ readonly execute: (args: TArgs, ctx: Context) => Promise<unknown>;
19
+ constructor(config: ToolConfig<TArgs>);
20
+ /** Tool specification for the provider (OpenAI-compatible format) */
21
+ get spec(): ToolSpec;
22
+ }
23
+ export declare function createTool<TArgs = Record<string, unknown>>(config: ToolConfig<TArgs>): Tool<TArgs>;
24
+ //# sourceMappingURL=tool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool.d.ts","sourceRoot":"","sources":["../src/tool.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAC3C,OAAO,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAIzD,MAAM,MAAM,UAAU,CAAC,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI;IACxD,EAAE,EAAE,MAAM,CAAA;IACV,WAAW,EAAE,MAAM,CAAA;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAA;IACtC,OAAO,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;CACzD,CAAA;AAID,qBAAa,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAC/C,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAA;IAC9C,QAAQ,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;gBAErD,MAAM,EAAE,UAAU,CAAC,KAAK,CAAC;IAOrC,qEAAqE;IACrE,IAAI,IAAI,IAAI,QAAQ,CAMnB;CACF;AAID,wBAAgB,UAAU,CAAC,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACxD,MAAM,EAAE,UAAU,CAAC,KAAK,CAAC,GACxB,IAAI,CAAC,KAAK,CAAC,CAEb"}
package/dist/tool.js ADDED
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Cog v2 — Tool
3
+ *
4
+ * A tool is a schema + execute function. Everything is a tool.
5
+ */
6
+ // ── Tool ────────────────────────────────────────────────────────────────────
7
+ export class Tool {
8
+ id;
9
+ description;
10
+ schema;
11
+ execute;
12
+ constructor(config) {
13
+ this.id = config.id;
14
+ this.description = config.description;
15
+ this.schema = config.schema ?? {};
16
+ this.execute = config.execute;
17
+ }
18
+ /** Tool specification for the provider (OpenAI-compatible format) */
19
+ get spec() {
20
+ return {
21
+ name: this.id,
22
+ description: this.description,
23
+ parameters: this.schema,
24
+ };
25
+ }
26
+ }
27
+ // ── Factory ─────────────────────────────────────────────────────────────────
28
+ export function createTool(config) {
29
+ return new Tool(config);
30
+ }
31
+ //# sourceMappingURL=tool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool.js","sourceRoot":"","sources":["../src/tool.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAcH,+EAA+E;AAE/E,MAAM,OAAO,IAAI;IACN,EAAE,CAAQ;IACV,WAAW,CAAQ;IACnB,MAAM,CAA+B;IACrC,OAAO,CAAiD;IAEjE,YAAY,MAAyB;QACnC,IAAI,CAAC,EAAE,GAAG,MAAM,CAAC,EAAE,CAAA;QACnB,IAAI,CAAC,WAAW,GAAG,MAAM,CAAC,WAAW,CAAA;QACrC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,IAAI,EAAE,CAAA;QACjC,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,OAAO,CAAA;IAC/B,CAAC;IAED,qEAAqE;IACrE,IAAI,IAAI;QACN,OAAO;YACL,IAAI,EAAE,IAAI,CAAC,EAAE;YACb,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,UAAU,EAAE,IAAI,CAAC,MAAM;SACxB,CAAA;IACH,CAAC;CACF;AAED,+EAA+E;AAE/E,MAAM,UAAU,UAAU,CACxB,MAAyB;IAEzB,OAAO,IAAI,IAAI,CAAC,MAAM,CAAC,CAAA;AACzB,CAAC"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Cog v2 — Core Types
3
+ */
4
+ /** A tool call request from the model */
5
+ export type ToolCallRequest = {
6
+ id: string;
7
+ name: string;
8
+ arguments: Record<string, unknown>;
9
+ };
10
+ /** A message in the context chain */
11
+ export type Message = {
12
+ role: 'system' | 'user' | 'assistant' | 'tool';
13
+ content: string;
14
+ reasoning?: string;
15
+ toolCallId?: string;
16
+ toolCalls?: ToolCallRequest[];
17
+ };
18
+ /** Parameter definition for a tool */
19
+ export type ToolParameter = {
20
+ type: 'string' | 'number' | 'boolean';
21
+ description: string;
22
+ required?: boolean;
23
+ };
24
+ /** Tool specification sent to the provider */
25
+ export type ToolSpec = {
26
+ name: string;
27
+ description: string;
28
+ parameters: Record<string, ToolParameter>;
29
+ };
30
+ /** Token usage statistics from a provider call */
31
+ export type Usage = {
32
+ promptTokens: number;
33
+ completionTokens: number;
34
+ totalTokens: number;
35
+ };
36
+ /** Result from a provider generate call */
37
+ export type GenerateResult = {
38
+ content?: string;
39
+ reasoning?: string;
40
+ toolCalls?: ToolCallRequest[];
41
+ usage?: Usage;
42
+ };
43
+ /** Streaming callbacks passed to the provider */
44
+ export type StreamCallbacks = {
45
+ onReasoning?: (chunk: string) => void;
46
+ onContent?: (chunk: string) => void;
47
+ };
48
+ /** LLM provider interface — user-supplied */
49
+ export interface Provider {
50
+ generate(params: {
51
+ messages: Message[];
52
+ tools?: ToolSpec[];
53
+ signal?: AbortSignal;
54
+ stream?: StreamCallbacks;
55
+ }): Promise<GenerateResult>;
56
+ }
57
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,yCAAyC;AACzC,MAAM,MAAM,eAAe,GAAG;IAC5B,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACnC,CAAA;AAED,qCAAqC;AACrC,MAAM,MAAM,OAAO,GAAG;IACpB,IAAI,EAAE,QAAQ,GAAG,MAAM,GAAG,WAAW,GAAG,MAAM,CAAA;IAC9C,OAAO,EAAE,MAAM,CAAA;IACf,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,SAAS,CAAC,EAAE,eAAe,EAAE,CAAA;CAC9B,CAAA;AAID,sCAAsC;AACtC,MAAM,MAAM,aAAa,GAAG;IAC1B,IAAI,EAAE,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAAA;IACrC,WAAW,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB,CAAA;AAED,8CAA8C;AAC9C,MAAM,MAAM,QAAQ,GAAG;IACrB,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAA;CAC1C,CAAA;AAID,kDAAkD;AAClD,MAAM,MAAM,KAAK,GAAG;IAClB,YAAY,EAAE,MAAM,CAAA;IACpB,gBAAgB,EAAE,MAAM,CAAA;IACxB,WAAW,EAAE,MAAM,CAAA;CACpB,CAAA;AAED,2CAA2C;AAC3C,MAAM,MAAM,cAAc,GAAG;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,SAAS,CAAC,EAAE,eAAe,EAAE,CAAA;IAC7B,KAAK,CAAC,EAAE,KAAK,CAAA;CACd,CAAA;AAED,iDAAiD;AACjD,MAAM,MAAM,eAAe,GAAG;IAC5B,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IACrC,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;CACpC,CAAA;AAED,6CAA6C;AAC7C,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,MAAM,EAAE;QACf,QAAQ,EAAE,OAAO,EAAE,CAAA;QACnB,KAAK,CAAC,EAAE,QAAQ,EAAE,CAAA;QAClB,MAAM,CAAC,EAAE,WAAW,CAAA;QACpB,MAAM,CAAC,EAAE,eAAe,CAAA;KACzB,GAAG,OAAO,CAAC,cAAc,CAAC,CAAA;CAC5B"}
package/dist/types.js ADDED
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Cog v2 — Core Types
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG"}
package/package.json ADDED
@@ -0,0 +1,48 @@
1
+ {
2
+ "name": "@elfenlabs/cog",
3
+ "version": "0.1.0",
4
+ "description": "A minimal agent SDK for TypeScript — three primitives, infinite composition",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/index.js",
11
+ "types": "./dist/index.d.ts"
12
+ }
13
+ },
14
+ "files": [
15
+ "dist",
16
+ "README.md",
17
+ "LICENSE"
18
+ ],
19
+ "scripts": {
20
+ "build": "tsc",
21
+ "prepublishOnly": "tsc",
22
+ "test": "bun test"
23
+ },
24
+ "keywords": [
25
+ "agent",
26
+ "sdk",
27
+ "llm",
28
+ "context",
29
+ "state-machine",
30
+ "ai",
31
+ "typescript"
32
+ ],
33
+ "author": "Elfenlabs",
34
+ "license": "MIT",
35
+ "repository": {
36
+ "type": "git",
37
+ "url": "git+https://github.com/elfenlabs/cog.git"
38
+ },
39
+ "homepage": "https://github.com/elfenlabs/cog#readme",
40
+ "bugs": {
41
+ "url": "https://github.com/elfenlabs/cog/issues"
42
+ },
43
+ "devDependencies": {
44
+ "@types/bun": "^1.3.9",
45
+ "tsx": "^4.21.0",
46
+ "typescript": "^5.9.3"
47
+ }
48
+ }