@cogitator-ai/openai-compat 21.1.13 → 21.2.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 +183 -46
- package/dist/client/openai-adapter.d.ts +35 -7
- package/dist/client/openai-adapter.d.ts.map +1 -1
- package/dist/client/openai-adapter.js +139 -57
- package/dist/client/openai-adapter.js.map +1 -1
- package/dist/client/thread-manager.d.ts +4 -3
- package/dist/client/thread-manager.d.ts.map +1 -1
- package/dist/client/thread-manager.js +7 -5
- package/dist/client/thread-manager.js.map +1 -1
- package/dist/index.d.ts +7 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -3
- package/dist/index.js.map +1 -1
- package/dist/server/agents/agent-turn.d.ts +134 -0
- package/dist/server/agents/agent-turn.d.ts.map +1 -0
- package/dist/server/agents/agent-turn.js +340 -0
- package/dist/server/agents/agent-turn.js.map +1 -0
- package/dist/server/agents/shared.d.ts +62 -0
- package/dist/server/agents/shared.d.ts.map +1 -0
- package/dist/server/agents/shared.js +136 -0
- package/dist/server/agents/shared.js.map +1 -0
- package/dist/server/api-server.d.ts +50 -10
- package/dist/server/api-server.d.ts.map +1 -1
- package/dist/server/api-server.js +61 -24
- package/dist/server/api-server.js.map +1 -1
- package/dist/server/routes/chat-completions.d.ts +15 -0
- package/dist/server/routes/chat-completions.d.ts.map +1 -0
- package/dist/server/routes/chat-completions.js +305 -0
- package/dist/server/routes/chat-completions.js.map +1 -0
- package/dist/server/routes/models.d.ts +8 -0
- package/dist/server/routes/models.d.ts.map +1 -0
- package/dist/server/routes/models.js +27 -0
- package/dist/server/routes/models.js.map +1 -0
- package/dist/server/routes/responses.d.ts +229 -0
- package/dist/server/routes/responses.d.ts.map +1 -0
- package/dist/server/routes/responses.js +484 -0
- package/dist/server/routes/responses.js.map +1 -0
- package/dist/server/routes/runs.d.ts +5 -1
- package/dist/server/routes/runs.d.ts.map +1 -1
- package/dist/server/routes/runs.js +16 -6
- package/dist/server/routes/runs.js.map +1 -1
- package/dist/types/openai-types.d.ts +3 -1
- package/dist/types/openai-types.d.ts.map +1 -1
- package/package.json +11 -7
package/README.md
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
# @cogitator-ai/openai-compat
|
|
2
2
|
|
|
3
|
-
OpenAI
|
|
3
|
+
OpenAI-compatible server for Cogitator agents. Register your agents and every client that speaks the OpenAI API (the official SDKs, Open WebUI, LibreChat, LangChain, Vercel AI SDK and the like) talks to them through `POST /v1/chat/completions` or `POST /v1/responses`, with the agent's name as the `model`. The Assistants API is served too, for existing integrations.
|
|
4
4
|
|
|
5
5
|
Full guide: [cogitator.app/docs/integrations/openai-compat](https://cogitator.app/docs/integrations/openai-compat)
|
|
6
6
|
|
|
7
|
+
> **The Assistants API is deprecated.** OpenAI sunset it on 2026-08-26 and current clients use Chat Completions or Responses. The `/v1/assistants`, `/v1/threads` and run endpoints keep working, but new integrations should use [Chat Completions](#chat-completions) or [Responses](#responses).
|
|
8
|
+
|
|
7
9
|
## Installation
|
|
8
10
|
|
|
9
11
|
```bash
|
|
@@ -17,54 +19,162 @@ pnpm add openai
|
|
|
17
19
|
|
|
18
20
|
## Features
|
|
19
21
|
|
|
20
|
-
- **
|
|
21
|
-
- **
|
|
22
|
-
- **
|
|
23
|
-
- **
|
|
24
|
-
- **
|
|
25
|
-
- **
|
|
26
|
-
- **Function Calling** - Assistant `function` tools pause the run with `requires_action` until the client submits outputs
|
|
27
|
-
- **Server-side tools** - Cogitator tools passed to the server run inside Cogitator for every run
|
|
28
|
-
- **Vision & JSON output** - `image_url` / image `image_file` parts reach the model; `response_format` supports `json_object` and `json_schema`
|
|
22
|
+
- **Chat Completions** - `POST /v1/chat/completions`, streaming and not, with tool calls, usage and images
|
|
23
|
+
- **Responses** - `POST /v1/responses` with the streaming events of the API, `previous_response_id`, function calls, and `GET` / `DELETE` of stored responses
|
|
24
|
+
- **Agents as models** - `model` names a registered agent, which answers with its own instructions, model and tools. `GET /v1/models` lists them
|
|
25
|
+
- **Client functions** - Functions a client declares come back as tool calls, and the outputs it sends resume the same run
|
|
26
|
+
- **Assistants API (deprecated)** - Assistants, threads, messages, runs and files over pluggable storage (in-memory, Redis, PostgreSQL)
|
|
27
|
+
- **OpenAI errors** - Every error in the OpenAI error format, with the parameter at fault
|
|
29
28
|
- **Authentication** - Optional API keys (constant-time check, `/health` stays public)
|
|
29
|
+
- **Abort on disconnect** - A client that goes away stops the agent run
|
|
30
30
|
- **CORS** - Configurable cross-origin requests
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
There are no run steps or vector stores, and `code_interpreter` and `file_search` assistant tools are stored but not executed.
|
|
33
33
|
|
|
34
34
|
---
|
|
35
35
|
|
|
36
36
|
## Quick Start
|
|
37
37
|
|
|
38
|
-
### Server Mode
|
|
39
|
-
|
|
40
38
|
```typescript
|
|
41
39
|
import { createOpenAIServer } from '@cogitator-ai/openai-compat';
|
|
42
|
-
import { Cogitator, tool } from '@cogitator-ai/core';
|
|
40
|
+
import { Agent, Cogitator, tool } from '@cogitator-ai/core';
|
|
43
41
|
import { z } from 'zod';
|
|
44
42
|
|
|
45
|
-
const
|
|
46
|
-
name: '
|
|
47
|
-
description: '
|
|
48
|
-
parameters: z.object({
|
|
49
|
-
execute: async ({
|
|
43
|
+
const lookupOrder = tool({
|
|
44
|
+
name: 'lookup_order',
|
|
45
|
+
description: 'Find an order by id',
|
|
46
|
+
parameters: z.object({ id: z.string() }),
|
|
47
|
+
execute: async ({ id }) => ({ id, status: 'shipped' }),
|
|
50
48
|
});
|
|
51
49
|
|
|
52
|
-
const
|
|
53
|
-
|
|
50
|
+
const support = new Agent({
|
|
51
|
+
name: 'support',
|
|
52
|
+
model: 'openai/gpt-6-luna',
|
|
53
|
+
instructions: 'You are the support agent of an online shop.',
|
|
54
|
+
tools: [lookupOrder],
|
|
54
55
|
});
|
|
55
56
|
|
|
56
|
-
const server = createOpenAIServer(
|
|
57
|
+
const server = createOpenAIServer(new Cogitator(), {
|
|
57
58
|
port: 8080,
|
|
58
|
-
|
|
59
|
+
agents: { support },
|
|
59
60
|
apiKeys: ['sk-my-secret-key'],
|
|
60
|
-
defaultModel: 'openai/gpt-6-luna', // used for the advertised `cogitator` model id
|
|
61
61
|
});
|
|
62
62
|
|
|
63
63
|
await server.start();
|
|
64
64
|
console.log(server.getBaseUrl()); // http://localhost:8080/v1
|
|
65
65
|
```
|
|
66
66
|
|
|
67
|
-
|
|
67
|
+
```typescript
|
|
68
|
+
import OpenAI from 'openai';
|
|
69
|
+
|
|
70
|
+
const openai = new OpenAI({ baseURL: 'http://localhost:8080/v1', apiKey: 'sk-my-secret-key' });
|
|
71
|
+
|
|
72
|
+
const completion = await openai.chat.completions.create({
|
|
73
|
+
model: 'support',
|
|
74
|
+
messages: [{ role: 'user', content: 'Where is order A-1?' }],
|
|
75
|
+
});
|
|
76
|
+
console.log(completion.choices[0].message.content);
|
|
77
|
+
|
|
78
|
+
const response = await openai.responses.create({ model: 'support', input: 'Where is order A-1?' });
|
|
79
|
+
console.log(response.output_text);
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Point Open WebUI, LibreChat or any other OpenAI client at `http://localhost:8080/v1` with the API key, and pick the agent from the model list.
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## Agents as models
|
|
87
|
+
|
|
88
|
+
`agents` maps model ids to Cogitator agents. A request whose `model` is not one of them answers `404` with code `model_not_found`. `GET /v1/models` lists the agents, and the `cogitator` model of the Assistants API.
|
|
89
|
+
|
|
90
|
+
For each request the server runs the agent with:
|
|
91
|
+
|
|
92
|
+
- its own instructions first, then the client's `system` / `developer` messages (or the Responses `instructions`) after them,
|
|
93
|
+
- the request's `temperature`, `top_p`, token limit, `stop` and response format,
|
|
94
|
+
- its own tools, plus the functions the client declares in `tools` (a client function with the name of an agent tool is left out).
|
|
95
|
+
|
|
96
|
+
The conversation the client sends is replayed to the agent: the last user message is the input and the turns before it come as a transcript, so the APIs stay stateless and nothing is written to the agent's memory. Only the images of the last user message reach the model.
|
|
97
|
+
|
|
98
|
+
### Client functions
|
|
99
|
+
|
|
100
|
+
When the model calls a function the client declared, the turn ends with the call (`finish_reason: 'tool_calls'`, or a `function_call` output item) and the run waits. When the client sends the outputs back for every call (a `tool` message, or a `function_call_output` item), the same run goes on from where it stopped, with the outputs as the function results. The call ids the client gets are generated by the server, so only the client that got them can answer. A run waits 10 minutes, or until 1000 newer runs wait, and outputs for a run that no longer waits are replayed to the agent as part of the conversation instead.
|
|
101
|
+
|
|
102
|
+
Agent tools that need an approval (`requiresApproval`) are not run when nothing approves them (`guardrails.onToolApproval`): the model is told the tool was not run.
|
|
103
|
+
|
|
104
|
+
`tool_choice: 'none'` runs the agent without any tool. `required` and `{ type: 'function', ... }` become the run's `toolChoice`: the model must call a tool (or the named one) before it answers, and the run goes back to `auto` once it has.
|
|
105
|
+
|
|
106
|
+
## Chat Completions
|
|
107
|
+
|
|
108
|
+
```typescript
|
|
109
|
+
const stream = await openai.chat.completions.create({
|
|
110
|
+
model: 'support',
|
|
111
|
+
messages: [
|
|
112
|
+
{ role: 'system', content: 'Answer in one sentence.' },
|
|
113
|
+
{ role: 'user', content: 'Where is order A-1?' },
|
|
114
|
+
],
|
|
115
|
+
stream: true,
|
|
116
|
+
stream_options: { include_usage: true },
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
for await (const chunk of stream) {
|
|
120
|
+
process.stdout.write(chunk.choices[0]?.delta.content ?? '');
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
| Parameter | Support |
|
|
125
|
+
| --------------------------------------------- | -------------------------------------------------------------------------------------------------------- |
|
|
126
|
+
| `model` | A registered agent |
|
|
127
|
+
| `messages` | `system`, `developer`, `user` (text and `image_url` parts), `assistant` (text and `tool_calls`), `tool` |
|
|
128
|
+
| `stream`, `stream_options.include_usage` | Chunks with `delta.content` and `delta.tool_calls`, the finish reason, then the usage chunk and `[DONE]` |
|
|
129
|
+
| `tools`, `tool_choice`, `parallel_tool_calls` | Function tools, see [Client functions](#client-functions) |
|
|
130
|
+
| `temperature`, `top_p` | Passed to the agent |
|
|
131
|
+
| `max_completion_tokens` (`max_tokens`) | The agent's output token limit |
|
|
132
|
+
| `stop` | Stop sequences |
|
|
133
|
+
| `response_format` | `text`, `json_object`, `json_schema` |
|
|
134
|
+
| `n` | Only `1` |
|
|
135
|
+
|
|
136
|
+
`finish_reason` is `stop`, `tool_calls`, `length` when the answer hit the token limit, or `content_filter` when the provider withheld it. A refusal comes back in `message.refusal`. `usage` carries `prompt_tokens_details.cached_tokens` and `completion_tokens_details.reasoning_tokens`. Other parameters are ignored.
|
|
137
|
+
|
|
138
|
+
## Responses
|
|
139
|
+
|
|
140
|
+
```typescript
|
|
141
|
+
const first = await openai.responses.create({
|
|
142
|
+
model: 'support',
|
|
143
|
+
instructions: 'Answer in one sentence.',
|
|
144
|
+
input: 'Where is order A-1?',
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
const next = await openai.responses.create({
|
|
148
|
+
model: 'support',
|
|
149
|
+
previous_response_id: first.id,
|
|
150
|
+
input: 'And order B-2?',
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
const stream = openai.responses.stream({ model: 'support', input: 'Summarize our talk' });
|
|
154
|
+
stream.on('response.output_text.delta', (event) => process.stdout.write(event.delta));
|
|
155
|
+
const final = await stream.finalResponse();
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
| Parameter | Support |
|
|
159
|
+
| --------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
160
|
+
| `model` | A registered agent |
|
|
161
|
+
| `input` | A string, or message items (`input_text`, `input_image` with `image_url`, `output_text`), `function_call` and `function_call_output` items |
|
|
162
|
+
| `instructions` | After the agent's own instructions, for this response only |
|
|
163
|
+
| `previous_response_id` | Continues the conversation of a stored response |
|
|
164
|
+
| `tools`, `tool_choice`, `parallel_tool_calls` | Function tools only |
|
|
165
|
+
| `temperature`, `top_p`, `max_output_tokens` | Passed to the agent |
|
|
166
|
+
| `text.format` | `text`, `json_object`, `json_schema` |
|
|
167
|
+
| `store` | Keep the response (default `true`) |
|
|
168
|
+
| `stream` | The Responses streaming events |
|
|
169
|
+
| `metadata` | Returned with the response |
|
|
170
|
+
|
|
171
|
+
A streamed response sends `response.created`, `response.in_progress`, the output items (`response.output_item.added`, `response.content_part.added`, `response.output_text.delta`, `response.output_text.done`, `response.content_part.done`, `response.output_item.done`, and `response.function_call_arguments.delta` / `.done` for function calls), then `response.completed`, `response.incomplete` or `response.failed`, every event with its `sequence_number`. A response cut by `max_output_tokens` is `incomplete` with `incomplete_details.reason: 'max_output_tokens'` (`content_filter` when the provider withheld it).
|
|
172
|
+
|
|
173
|
+
Stored responses live in memory (`maxStoredResponses`, default 1000, the oldest dropped first): `GET /v1/responses/{id}`, `GET /v1/responses/{id}/input_items` and `DELETE /v1/responses/{id}`. `previous_response_id` carries the conversation, not the earlier `instructions`. Built-in tools (web search, file search, computer use), `background` and file inputs are not supported.
|
|
174
|
+
|
|
175
|
+
---
|
|
176
|
+
|
|
177
|
+
## Assistants API (deprecated)
|
|
68
178
|
|
|
69
179
|
```typescript
|
|
70
180
|
import OpenAI from 'openai';
|
|
@@ -101,13 +211,13 @@ const stream = openai.beta.threads.runs
|
|
|
101
211
|
await stream.finalRun();
|
|
102
212
|
```
|
|
103
213
|
|
|
104
|
-
Assistant `model` values are Cogitator model strings (`openai/gpt-6.1-sol`, `ollama/llama3.2:latest`, ...). `GET /v1/models`
|
|
214
|
+
The Assistants API runs assistants the client creates, not the registered agents. Assistant `model` values are Cogitator model strings (`openai/gpt-6.1-sol`, `ollama/llama3.2:latest`, ...). The `cogitator` model listed by `GET /v1/models` maps to the server's `defaultModel`, and runs that use it fail when no `defaultModel` is configured. Server-side `tools` are available to every run.
|
|
105
215
|
|
|
106
216
|
---
|
|
107
217
|
|
|
108
218
|
## OpenAI Server
|
|
109
219
|
|
|
110
|
-
The `OpenAIServer` exposes Cogitator as an OpenAI-compatible REST API.
|
|
220
|
+
The `OpenAIServer` exposes Cogitator agents as an OpenAI-compatible REST API.
|
|
111
221
|
|
|
112
222
|
### Configuration
|
|
113
223
|
|
|
@@ -120,6 +230,8 @@ const server = new OpenAIServer(cogitator, {
|
|
|
120
230
|
|
|
121
231
|
apiKeys: ['sk-key1', 'sk-key2'],
|
|
122
232
|
|
|
233
|
+
agents: { support, researcher },
|
|
234
|
+
|
|
123
235
|
tools: [calculator, datetime, webSearch],
|
|
124
236
|
|
|
125
237
|
logging: true,
|
|
@@ -133,18 +245,27 @@ const server = new OpenAIServer(cogitator, {
|
|
|
133
245
|
|
|
134
246
|
### Configuration Options
|
|
135
247
|
|
|
136
|
-
| Option
|
|
137
|
-
|
|
|
138
|
-
| `port`
|
|
139
|
-
| `host`
|
|
140
|
-
| `apiKeys`
|
|
141
|
-
| `
|
|
142
|
-
| `
|
|
143
|
-
| `
|
|
144
|
-
| `
|
|
145
|
-
| `
|
|
146
|
-
| `
|
|
147
|
-
| `
|
|
248
|
+
| Option | Type | Default | Description |
|
|
249
|
+
| ---------------------------------- | ------------------------------- | -------------------------------------- | --------------------------------------------------------------------------- |
|
|
250
|
+
| `port` | `number` | `8080` | Port to listen on (`0` picks a free port) |
|
|
251
|
+
| `host` | `string` | `'127.0.0.1'` | Host to bind to. A public host needs `apiKeys` |
|
|
252
|
+
| `apiKeys` | `string[]` | `[]` | API keys for authentication. Empty disables auth |
|
|
253
|
+
| `allowUnauthenticatedPublicAccess` | `boolean` | `false` | Serve a public host without `apiKeys` (behind a gateway that authenticates) |
|
|
254
|
+
| `sseHeartbeatMs` | `number` | `5000` | Heartbeat comment interval on streams, `0` turns it off |
|
|
255
|
+
| `agents` | `Record<string, Agent>` | `{}` | Agents served by Chat Completions and Responses, by model id |
|
|
256
|
+
| `maxRequestBodyBytes` | `number` | `20 MB` | Body limit of `/v1/chat/completions` and `/v1/responses` |
|
|
257
|
+
| `maxStoredResponses` | `number` | `1000` | Responses kept in memory for `previous_response_id` and `GET` |
|
|
258
|
+
| `tools` | `Tool[]` | `[]` | Server-side tools available to every Assistants API run |
|
|
259
|
+
| `defaultModel` | `string` | - | Model the Assistants API uses for the `cogitator` model id |
|
|
260
|
+
| `storage` | `ThreadStorage` | in-memory | Persistence backend (connect before passing) |
|
|
261
|
+
| `maxFileSize` | `number` | `512 MB` | Upload limit for `POST /v1/files`, in bytes |
|
|
262
|
+
| `logging` | `boolean` | `false` | Enable Fastify request logging (JSON logs) |
|
|
263
|
+
| `cors.origin` | `string \| string[] \| boolean` | no CORS | Origins browsers may call from. Without `cors` no cross-origin page can |
|
|
264
|
+
| `cors.methods` | `string[]` | `['GET', 'POST', 'DELETE', 'OPTIONS']` | Allowed HTTP methods |
|
|
265
|
+
|
|
266
|
+
### Exposure
|
|
267
|
+
|
|
268
|
+
The server binds `127.0.0.1` by default, so only this machine reaches it. Without `apiKeys` anyone who reaches it can create assistants with any instructions and run the server's tools, so `start()` refuses a public host (`0.0.0.0`, `::` or an external address) unless `apiKeys` are set or `allowUnauthenticatedPublicAccess: true` says a gateway in front authenticates callers. CORS is off unless `cors.origin` names the origins browsers may call from, so a web page on another origin cannot drive the server from a visitor's browser. Run streams write a heartbeat comment every `sseHeartbeatMs` while a run is silent, so proxies do not cut a run that waits on a slow tool.
|
|
148
269
|
|
|
149
270
|
### Server Lifecycle
|
|
150
271
|
|
|
@@ -177,7 +298,7 @@ curl http://localhost:8080/health
|
|
|
177
298
|
|
|
178
299
|
---
|
|
179
300
|
|
|
180
|
-
## OpenAI Adapter
|
|
301
|
+
## OpenAI Adapter (Assistants API, deprecated)
|
|
181
302
|
|
|
182
303
|
The `OpenAIAdapter` provides in-process access without running a server. The server uses one internally (`server.getAdapter()`).
|
|
183
304
|
|
|
@@ -282,6 +403,8 @@ Runs live in the adapter's memory, unlike assistants, threads, messages and file
|
|
|
282
403
|
|
|
283
404
|
Server-side `tools` run inside Cogitator. Assistant tools of type `function` are executed by the API client: when the model calls one, the run moves to `requires_action` with the pending calls, and continues after all outputs are submitted (runs waiting longer than 10 minutes expire). Outputs must cover every pending call; missing or unknown `tool_call_id`s are rejected. With the OpenAI SDK use `submitToolOutputsAndPoll` / `submitToolOutputsStream`.
|
|
284
405
|
|
|
406
|
+
Server-side tools that need approval (`requiresApproval`, or the guardrails) come to the client the same way, as calls of functions it never declared: the run waits in `requires_action` instead of completing without them. The output decides the call: `{"approved": true}` (or `approve`) runs it, `{"approved": false, "reason": "..."}` declines it with the reason, and any other text declines it with that text, so nothing ambiguous runs a server tool. A configured `guardrails.onToolApproval` decides server tools itself and they never reach the client. While the run waits it is paused rather than running, so the run timeout (`limits.defaultTimeout`, 120 s by default) does not count the client's time: only `expires_at` (10 minutes per wait) does.
|
|
407
|
+
|
|
285
408
|
```typescript
|
|
286
409
|
const run = adapter.getRun(thread.id, runId);
|
|
287
410
|
|
|
@@ -568,10 +691,23 @@ All endpoints except `/health` live under `/v1`. List endpoints for assistants,
|
|
|
568
691
|
|
|
569
692
|
### Models
|
|
570
693
|
|
|
571
|
-
| Method | Endpoint
|
|
572
|
-
| ------ |
|
|
573
|
-
| GET | `/v1/models`
|
|
574
|
-
| GET | `/
|
|
694
|
+
| Method | Endpoint | Description |
|
|
695
|
+
| ------ | ---------------- | ----------------------------------------------------- |
|
|
696
|
+
| GET | `/v1/models` | Lists the registered agents and the `cogitator` model |
|
|
697
|
+
| GET | `/v1/models/:id` | Gets one model |
|
|
698
|
+
| GET | `/health` | Health check (public, no auth) |
|
|
699
|
+
|
|
700
|
+
### Chat Completions and Responses
|
|
701
|
+
|
|
702
|
+
| Method | Endpoint | Description |
|
|
703
|
+
| ------ | ------------------------------- | ------------------------------------------- |
|
|
704
|
+
| POST | `/v1/chat/completions` | Chat completion (SSE with `stream: true`) |
|
|
705
|
+
| POST | `/v1/responses` | Create a response (SSE with `stream: true`) |
|
|
706
|
+
| GET | `/v1/responses/:id` | Get a stored response |
|
|
707
|
+
| GET | `/v1/responses/:id/input_items` | List the input items of a response |
|
|
708
|
+
| DELETE | `/v1/responses/:id` | Delete a stored response |
|
|
709
|
+
|
|
710
|
+
The Assistants API endpoints below are deprecated.
|
|
575
711
|
|
|
576
712
|
### Assistants
|
|
577
713
|
|
|
@@ -700,12 +836,12 @@ queued → in_progress → completed
|
|
|
700
836
|
→ failed
|
|
701
837
|
→ requires_action → in_progress → ...
|
|
702
838
|
→ expired (no outputs within 10 minutes)
|
|
703
|
-
→ incomplete (last message exceeds max_prompt_tokens)
|
|
839
|
+
→ incomplete (last message exceeds max_prompt_tokens, or the answer hit max_completion_tokens)
|
|
704
840
|
|
|
705
841
|
queued / in_progress / requires_action → cancelling → cancelled
|
|
706
842
|
```
|
|
707
843
|
|
|
708
|
-
`incomplete`
|
|
844
|
+
A run is `incomplete` with `incomplete_details.reason: 'max_prompt_tokens'` when the last message alone does not fit in `max_prompt_tokens` (see [Run Execution](#run-execution)), and with `'max_completion_tokens'` when the answer stopped at the output token limit (`max_completion_tokens`, or the model's own). The answer is then kept as a message with `status: 'incomplete'` and `incomplete_details.reason: 'max_tokens'`, and the stream sends `thread.message.incomplete` and `thread.run.incomplete` instead of the `completed` events. An answer the provider's content filter withheld is an `incomplete` message with reason `content_filter` in a `completed` run.
|
|
709
845
|
|
|
710
846
|
### Polling for Completion
|
|
711
847
|
|
|
@@ -794,6 +930,7 @@ type EmittedEvent =
|
|
|
794
930
|
| { event: 'thread.message.in_progress'; data: Message }
|
|
795
931
|
| { event: 'thread.message.delta'; data: MessageDelta }
|
|
796
932
|
| { event: 'thread.message.completed'; data: Message }
|
|
933
|
+
| { event: 'thread.message.incomplete'; data: Message }
|
|
797
934
|
| { event: 'done'; data: '[DONE]' };
|
|
798
935
|
```
|
|
799
936
|
|
|
@@ -4,12 +4,13 @@
|
|
|
4
4
|
* Implements the OpenAI Assistants API semantics on top of Cogitator.
|
|
5
5
|
*/
|
|
6
6
|
import { type Cogitator } from '@cogitator-ai/core';
|
|
7
|
-
import { type Tool } from '@cogitator-ai/types';
|
|
7
|
+
import { type ResponseFormat as AgentResponseFormat, type Tool, type ToolApprovalDecision } from '@cogitator-ai/types';
|
|
8
8
|
import { EventEmitter } from 'events';
|
|
9
|
+
import { z } from 'zod';
|
|
9
10
|
import { ThreadManager } from './thread-manager.js';
|
|
10
11
|
import type { ThreadStorage } from './storage.js';
|
|
11
12
|
import type { Assistant, AssistantTool, CreateMessageRequest, Run, RunStep, Message, MessageDelta, CreateRunRequest, ResponseFormat, SubmitToolOutputsRequest } from '../types/openai-types.js';
|
|
12
|
-
export type StreamEventType = 'thread.run.created' | 'thread.run.queued' | 'thread.run.in_progress' | 'thread.run.requires_action' | 'thread.run.completed' | 'thread.run.failed' | 'thread.run.cancelling' | 'thread.run.cancelled' | 'thread.run.expired' | 'thread.run.incomplete' | 'thread.run.step.created' | 'thread.run.step.in_progress' | 'thread.run.step.completed' | 'thread.message.created' | 'thread.message.in_progress' | 'thread.message.delta' | 'thread.message.completed' | 'done' | 'error';
|
|
13
|
+
export type StreamEventType = 'thread.run.created' | 'thread.run.queued' | 'thread.run.in_progress' | 'thread.run.requires_action' | 'thread.run.completed' | 'thread.run.failed' | 'thread.run.cancelling' | 'thread.run.cancelled' | 'thread.run.expired' | 'thread.run.incomplete' | 'thread.run.step.created' | 'thread.run.step.in_progress' | 'thread.run.step.completed' | 'thread.message.created' | 'thread.message.in_progress' | 'thread.message.delta' | 'thread.message.completed' | 'thread.message.incomplete' | 'done' | 'error';
|
|
13
14
|
export type StreamEventData = Run | RunStep | Message | MessageDelta | string;
|
|
14
15
|
export interface StreamEmitterEvents {
|
|
15
16
|
event: [type: StreamEventType, data: StreamEventData];
|
|
@@ -38,6 +39,20 @@ export interface OpenAIAdapterOptions {
|
|
|
38
39
|
storage?: ThreadStorage;
|
|
39
40
|
}
|
|
40
41
|
export declare const COGITATOR_MODEL_ID = "cogitator";
|
|
42
|
+
/** The agent response format and extra instructions for an OpenAI `response_format`. */
|
|
43
|
+
export declare function toAgentResponseFormat(format: ResponseFormat | undefined): {
|
|
44
|
+
responseFormat?: AgentResponseFormat;
|
|
45
|
+
instructions?: string;
|
|
46
|
+
};
|
|
47
|
+
/** A Zod schema from the JSON Schema of a function, accepting any object when it cannot be converted. */
|
|
48
|
+
export declare function toZodParameters(schema: Record<string, unknown> | undefined): z.ZodType;
|
|
49
|
+
/**
|
|
50
|
+
* The decision a client gives as the output of a server tool call that needs approval:
|
|
51
|
+
* `{"approved": true}` or `approve` lets it run, `{"approved": false, "reason": "..."}` declines it
|
|
52
|
+
* with the reason, and any other output declines it with that output as the reason, so nothing
|
|
53
|
+
* ambiguous ever runs the tool.
|
|
54
|
+
*/
|
|
55
|
+
export declare function toolOutputToDecision(output: string): ToolApprovalDecision;
|
|
41
56
|
/**
|
|
42
57
|
* OpenAI SDK Adapter
|
|
43
58
|
*
|
|
@@ -126,8 +141,9 @@ export declare class OpenAIAdapter {
|
|
|
126
141
|
*/
|
|
127
142
|
cancelRun(threadId: string, runId: string): Run | undefined;
|
|
128
143
|
/**
|
|
129
|
-
* Submit outputs for the tool calls of a run that requires action.
|
|
130
|
-
*
|
|
144
|
+
* Submit outputs for the tool calls of a run that requires action. Outputs for every pending
|
|
145
|
+
* tool call must be provided: the result of a client-side function, or the decision on a
|
|
146
|
+
* server tool that needs approval (see `toolOutputToDecision`).
|
|
131
147
|
*/
|
|
132
148
|
submitToolOutputs(threadId: string, runId: string, request: SubmitToolOutputsRequest): Promise<Run | undefined>;
|
|
133
149
|
/**
|
|
@@ -158,11 +174,23 @@ export declare class OpenAIAdapter {
|
|
|
158
174
|
private clientErrorMessage;
|
|
159
175
|
private resolveModel;
|
|
160
176
|
/**
|
|
161
|
-
* Turn assistant `function` tools into Cogitator tools
|
|
162
|
-
*
|
|
177
|
+
* Turn assistant `function` tools into Cogitator tools the API client executes. Each one needs
|
|
178
|
+
* approval, so the run pauses before calling it and the call reaches the client through
|
|
179
|
+
* `requires_action`; the run resumes once the client submitted its output, which the tool then
|
|
180
|
+
* returns. While the client works the run is paused, not running, so its timeout does not run
|
|
181
|
+
* against the client's time (the run's `expires_at` bounds that).
|
|
163
182
|
*/
|
|
164
183
|
private createClientTools;
|
|
165
|
-
|
|
184
|
+
/**
|
|
185
|
+
* Put the run in `requires_action` with `calls` and wait for the client's outputs, or for the
|
|
186
|
+
* run to be cancelled or to expire (`RUN_TTL_SECONDS`).
|
|
187
|
+
*/
|
|
188
|
+
private awaitToolOutputs;
|
|
189
|
+
/**
|
|
190
|
+
* The decisions that resume a paused run: a client function runs (it returns the output the
|
|
191
|
+
* client submitted), a server tool that needs approval runs or not as the client's output says.
|
|
192
|
+
*/
|
|
193
|
+
private toDecisions;
|
|
166
194
|
/**
|
|
167
195
|
* The input of a run: the last user message, preceded by the transcript of
|
|
168
196
|
* the thread before it. With `max_prompt_tokens` the oldest messages are
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"openai-adapter.d.ts","sourceRoot":"","sources":["../../src/client/openai-adapter.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,KAAK,SAAS,
|
|
1
|
+
{"version":3,"file":"openai-adapter.d.ts","sourceRoot":"","sources":["../../src/client/openai-adapter.ts"],"names":[],"mappings":"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"}
|