@tessar/openai 0.0.0-stage → 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/README.md +131 -3
- package/dist/adapter.d.ts +18 -0
- package/dist/adapter.js +179 -0
- package/dist/adapter.js.map +1 -0
- package/dist/chat-adapter.d.ts +7 -0
- package/dist/chat-adapter.js +180 -0
- package/dist/chat-adapter.js.map +1 -0
- package/dist/chat-codec.d.ts +20 -0
- package/dist/chat-codec.js +157 -0
- package/dist/chat-codec.js.map +1 -0
- package/dist/codec.d.ts +4 -0
- package/dist/codec.js +154 -0
- package/dist/codec.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/metadata.d.ts +3 -0
- package/dist/metadata.js +9 -0
- package/dist/metadata.js.map +1 -0
- package/dist/plugin.d.ts +9 -0
- package/dist/plugin.js +29 -0
- package/dist/plugin.js.map +1 -0
- package/dist/provider.d.ts +43 -0
- package/dist/provider.js +106 -0
- package/dist/provider.js.map +1 -0
- package/package.json +32 -3
package/README.md
CHANGED
|
@@ -1,3 +1,131 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
# @tessar/openai
|
|
2
|
+
|
|
3
|
+
OpenAI Responses and Chat Completions provider with model metadata integration.
|
|
4
|
+
Requires Node 24.14 or newer and uses the official OpenAI SDK.
|
|
5
|
+
|
|
6
|
+
```sh
|
|
7
|
+
npm install @tessar/core @tessar/openai
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
```ts
|
|
11
|
+
import { Agent } from "@tessar/core";
|
|
12
|
+
import { OpenAIProvider } from "@tessar/openai";
|
|
13
|
+
|
|
14
|
+
const model = new OpenAIProvider({
|
|
15
|
+
apiKey: process.env.OPENAI_API_KEY!,
|
|
16
|
+
model: process.env.OPENAI_MODEL!,
|
|
17
|
+
});
|
|
18
|
+
const agent = new Agent({
|
|
19
|
+
id: "assistant",
|
|
20
|
+
model,
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
const result = await agent.generate("Hello");
|
|
24
|
+
console.log(result.output);
|
|
25
|
+
|
|
26
|
+
const stream = agent.stream("Explain briefly", {
|
|
27
|
+
modelOptions: { reasoning: { effort: "low" }, max_output_tokens: 2048 },
|
|
28
|
+
});
|
|
29
|
+
for await (const event of stream) console.log(event);
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Agent runs without Controller or public init/dispose. A string `model` override
|
|
33
|
+
selects another model ID using the same client; another OpenAIProvider instance
|
|
34
|
+
can carry a different endpoint, API key and headers. Request overrides are
|
|
35
|
+
execution-local and replace nested objects rather than deep-merging them.
|
|
36
|
+
|
|
37
|
+
The constructor accepts official SDK client settings (`baseURL`,
|
|
38
|
+
`defaultHeaders`, `maxRetries`, `timeout`, etc.) and native options for its API.
|
|
39
|
+
`api` defaults to `"responses"`; select `"chat-completions"` for that endpoint:
|
|
40
|
+
|
|
41
|
+
```ts
|
|
42
|
+
const chat = new OpenAIProvider({
|
|
43
|
+
api: "chat-completions",
|
|
44
|
+
apiKey: process.env.PROVIDER_API_KEY!,
|
|
45
|
+
baseURL: process.env.PROVIDER_BASE_URL!,
|
|
46
|
+
model: process.env.PROVIDER_MODEL!,
|
|
47
|
+
reasoning_effort: "high",
|
|
48
|
+
max_completion_tokens: 2048,
|
|
49
|
+
});
|
|
50
|
+
const chatAgent = new Agent({ id: "chat", model: chat });
|
|
51
|
+
await chatAgent.generate("Hello", {
|
|
52
|
+
model: "another-model-on-this-connection",
|
|
53
|
+
modelOptions: { reasoning_effort: "low" },
|
|
54
|
+
});
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Choose fields supported by the target provider/model. Responses uses fields such
|
|
58
|
+
as `reasoning` and `max_output_tokens`; Chat Completions uses `reasoning_effort`
|
|
59
|
+
and `max_completion_tokens` (or legacy `max_tokens`). Types follow the selected
|
|
60
|
+
SDK protocol. `providerId` remains optional and defaults to `"openai"`, including
|
|
61
|
+
when using a compatible endpoint. It identifies a Controller registration, not
|
|
62
|
+
the HTTP protocol.
|
|
63
|
+
|
|
64
|
+
`withModel()` and model-ID overrides preserve the selected API and connection.
|
|
65
|
+
To change API, endpoint, credentials or headers, pass a different provider instance
|
|
66
|
+
as the execution's `model`. `api` never enters the request body and cannot be
|
|
67
|
+
changed through `modelOptions`.
|
|
68
|
+
|
|
69
|
+
Runtime-owned model/input/instructions/tools/stream fields cannot be overridden
|
|
70
|
+
through `modelOptions`. Background execution, provider-managed conversations and
|
|
71
|
+
`context_management` compaction are not supported by this loop. HTTP/SDK retries are not a mechanism
|
|
72
|
+
for silently restarting a stream that has already emitted output.
|
|
73
|
+
|
|
74
|
+
Unconfigured settings stay absent: Tessar does not inject temperature, reasoning,
|
|
75
|
+
output limits, store/include, or SDK retry/timeout defaults. The SDK applies its
|
|
76
|
+
own defaults. Configure `maxRetries` and `timeout` in the provider constructor
|
|
77
|
+
when needed. `generate()` preserves native provider exceptions on failure.
|
|
78
|
+
|
|
79
|
+
Ordered instruction sections are joined with `\n\n`: Responses receives one
|
|
80
|
+
`instructions` string; Chat Completions receives one leading system message.
|
|
81
|
+
Section IDs and orders are local metadata. Chat supports text, user images/files
|
|
82
|
+
and function tools, including fragmented parallel calls and native reasoning
|
|
83
|
+
continuity. Unsupported audio/deprecated function-call output is rejected. The
|
|
84
|
+
Agent consumes one completion choice; `n` may be omitted or set to `1`.
|
|
85
|
+
|
|
86
|
+
Chat usage is available only when the endpoint reports it. To request streamed
|
|
87
|
+
usage, explicitly configure `stream_options: { include_usage: true }`. Tessar
|
|
88
|
+
does not add this option; absent usage remains unavailable rather than zero.
|
|
89
|
+
|
|
90
|
+
Implicit prompt caching remains the provider default. Tessar adds no cache
|
|
91
|
+
markers, history breakpoints or cache policy. Stable sections can precede changing
|
|
92
|
+
sections using `order`; native cache options pass through only when configured.
|
|
93
|
+
Cache hits still depend on the endpoint/model and the actual prompt prefix.
|
|
94
|
+
|
|
95
|
+
`model.profile` reads a cached/bundled metadata snapshot without starting network
|
|
96
|
+
requests. `await model.refreshProfile()` explicitly refreshes provider metadata;
|
|
97
|
+
metadata may be incomplete and carries provenance.
|
|
98
|
+
|
|
99
|
+
OpenAIAdapter and OpenAIPlugin remain available for existing Controller/provider
|
|
100
|
+
registrations. Passing an executable model to Controller already registers its
|
|
101
|
+
provider; do not additionally register the same provider ID with a plugin.
|
|
102
|
+
|
|
103
|
+
Each new provider has a separate opaque connection identity; `withModel()` keeps
|
|
104
|
+
the existing client and identity. In-process suspension retains a per-call
|
|
105
|
+
connection until the execution ends. Rebinding these connections after process
|
|
106
|
+
restart is not yet supported by the Controller compatibility bridge.
|
|
107
|
+
|
|
108
|
+
This is an early 0.x release. See the
|
|
109
|
+
[repository](https://github.com/hphucdev-04/tessar) for complete contracts.
|
|
110
|
+
|
|
111
|
+
## Restoring native conversation state
|
|
112
|
+
|
|
113
|
+
For durable conversations, assign a stable, nonsecret connection identity:
|
|
114
|
+
|
|
115
|
+
```ts
|
|
116
|
+
const model = new OpenAIProvider({
|
|
117
|
+
connectionId: "primary-openai",
|
|
118
|
+
model: "your-model",
|
|
119
|
+
apiKey: process.env.OPENAI_API_KEY,
|
|
120
|
+
});
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Recreate that binding after restart. Stored continuity includes provider,
|
|
124
|
+
connection, protocol and effective endpoint; reusing the ID with a different
|
|
125
|
+
endpoint/protocol is rejected. API keys and transport headers are not included
|
|
126
|
+
in the descriptor. Unspecified connection IDs remain random and isolated.
|
|
127
|
+
|
|
128
|
+
Legacy native state has only its old connection ID. An application may explicitly
|
|
129
|
+
reuse that saved ID after verifying the original endpoint/protocol itself; Tessar
|
|
130
|
+
cannot infer or attest that binding during SQLite migration. Neither the
|
|
131
|
+
connection ID nor its descriptor is forwarded as a native request parameter.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import OpenAI, { type ClientOptions } from "openai";
|
|
2
|
+
import { type ModelAdapter, type ModelChunk, type ModelRef, type ModelRequest, type ModelConnectionDescriptor } from "@tessar/core";
|
|
3
|
+
export interface OpenAIOptions extends ClientOptions {
|
|
4
|
+
providerId?: string;
|
|
5
|
+
metadataPartition?: string;
|
|
6
|
+
}
|
|
7
|
+
export declare const clientKeys: readonly ["apiKey", "adminAPIKey", "organization", "project", "webhookSecret", "baseURL", "dataResidency", "timeout", "fetchOptions", "fetch", "maxRetries", "defaultHeaders", "defaultQuery", "dangerouslyAllowBrowser", "logLevel", "logger", "workloadIdentity", "credential", "provider", "x509Transport"];
|
|
8
|
+
export declare function createClient(options: OpenAIOptions): OpenAI;
|
|
9
|
+
export declare class OpenAIAdapter implements ModelAdapter {
|
|
10
|
+
readonly ref: ModelRef;
|
|
11
|
+
readonly connection?: ModelConnectionDescriptor | undefined;
|
|
12
|
+
protected readonly client: OpenAI;
|
|
13
|
+
constructor(options: OpenAIOptions, ref: ModelRef, client?: OpenAI, connection?: ModelConnectionDescriptor | undefined);
|
|
14
|
+
validate(request: ModelRequest): void;
|
|
15
|
+
stream(request: ModelRequest, context: {
|
|
16
|
+
signal: AbortSignal;
|
|
17
|
+
}): AsyncIterable<ModelChunk>;
|
|
18
|
+
}
|
package/dist/adapter.js
ADDED
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import OpenAI, { OpenAIError } from "openai";
|
|
2
|
+
import { errorInfo, MessageCodec, fail, normalizeUsage, } from "@tessar/core";
|
|
3
|
+
import { decodeOutput, encodeInput } from "./codec.js";
|
|
4
|
+
// Connection settings must never enter either protocol's request body.
|
|
5
|
+
export const clientKeys = [
|
|
6
|
+
"apiKey",
|
|
7
|
+
"adminAPIKey",
|
|
8
|
+
"organization",
|
|
9
|
+
"project",
|
|
10
|
+
"webhookSecret",
|
|
11
|
+
"baseURL",
|
|
12
|
+
"dataResidency",
|
|
13
|
+
"timeout",
|
|
14
|
+
"fetchOptions",
|
|
15
|
+
"fetch",
|
|
16
|
+
"maxRetries",
|
|
17
|
+
"defaultHeaders",
|
|
18
|
+
"defaultQuery",
|
|
19
|
+
"dangerouslyAllowBrowser",
|
|
20
|
+
"logLevel",
|
|
21
|
+
"logger",
|
|
22
|
+
"workloadIdentity",
|
|
23
|
+
"credential",
|
|
24
|
+
"provider",
|
|
25
|
+
"x509Transport",
|
|
26
|
+
];
|
|
27
|
+
export function createClient(options) {
|
|
28
|
+
const { providerId, metadataPartition, ...clientOptions } = options;
|
|
29
|
+
return new OpenAI(clientOptions);
|
|
30
|
+
}
|
|
31
|
+
function usage(value) {
|
|
32
|
+
return normalizeUsage({
|
|
33
|
+
inputTokens: value?.input_tokens,
|
|
34
|
+
outputTokens: value?.output_tokens,
|
|
35
|
+
totalTokens: value?.total_tokens,
|
|
36
|
+
cacheReadInputTokens: value?.input_tokens_details?.cached_tokens,
|
|
37
|
+
cacheWriteInputTokens: value?.input_tokens_details?.cache_write_tokens,
|
|
38
|
+
reasoningOutputTokens: value?.output_tokens_details?.reasoning_tokens,
|
|
39
|
+
uncachedInputTokens: value?.input_tokens !== undefined &&
|
|
40
|
+
value?.input_tokens_details?.cached_tokens !== undefined
|
|
41
|
+
? Math.max(0, value.input_tokens - value.input_tokens_details.cached_tokens)
|
|
42
|
+
: null,
|
|
43
|
+
}, value ? JSON.parse(JSON.stringify(value)) : null);
|
|
44
|
+
}
|
|
45
|
+
export class OpenAIAdapter {
|
|
46
|
+
ref;
|
|
47
|
+
connection;
|
|
48
|
+
client;
|
|
49
|
+
constructor(options, ref, client, connection) {
|
|
50
|
+
this.ref = ref;
|
|
51
|
+
this.connection = connection;
|
|
52
|
+
this.client = client ?? createClient(options);
|
|
53
|
+
}
|
|
54
|
+
validate(request) {
|
|
55
|
+
try {
|
|
56
|
+
if (request.model.providerId !== this.ref.providerId ||
|
|
57
|
+
request.model.modelId !== this.ref.modelId)
|
|
58
|
+
fail("UnsupportedContext", "Model identity mismatch");
|
|
59
|
+
if (request.model.connectionId !== this.ref.connectionId)
|
|
60
|
+
fail("UnsupportedContext", "Model connection mismatch");
|
|
61
|
+
for (const key of [
|
|
62
|
+
"connectionId",
|
|
63
|
+
"api",
|
|
64
|
+
"model",
|
|
65
|
+
"input",
|
|
66
|
+
"messages",
|
|
67
|
+
"instructions",
|
|
68
|
+
"tools",
|
|
69
|
+
"stream",
|
|
70
|
+
...clientKeys,
|
|
71
|
+
])
|
|
72
|
+
if (request.options && key in request.options)
|
|
73
|
+
fail("UnsupportedOption", key + " is owned by the model connection or Agent runtime");
|
|
74
|
+
if (request.options?.background === true ||
|
|
75
|
+
request.options?.conversation != null ||
|
|
76
|
+
request.options?.previous_response_id != null ||
|
|
77
|
+
request.options?.context_management != null)
|
|
78
|
+
fail("UnsupportedOption", "Background, provider-managed conversations and compaction are not supported by the Agent loop");
|
|
79
|
+
encodeInput(request, this.connection);
|
|
80
|
+
}
|
|
81
|
+
catch (error) {
|
|
82
|
+
errorInfo(error, { source: "tessar", ...this.ref });
|
|
83
|
+
throw error;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
async *stream(request, context) {
|
|
87
|
+
this.validate(request);
|
|
88
|
+
context.signal.throwIfAborted();
|
|
89
|
+
const failure = (message, code) => {
|
|
90
|
+
const error = Object.assign(new Error(message), { code });
|
|
91
|
+
errorInfo(error, { source: "provider", ...this.ref });
|
|
92
|
+
return error;
|
|
93
|
+
};
|
|
94
|
+
try {
|
|
95
|
+
const stream = await this.client.responses.create({
|
|
96
|
+
...request.options,
|
|
97
|
+
model: this.ref.modelId,
|
|
98
|
+
...(request.instructions.sections.some((section) => section.content.length > 0)
|
|
99
|
+
? {
|
|
100
|
+
instructions: request.instructions.sections
|
|
101
|
+
.map((s) => s.content)
|
|
102
|
+
.join("\n\n"),
|
|
103
|
+
}
|
|
104
|
+
: {}),
|
|
105
|
+
input: encodeInput(request, this.connection),
|
|
106
|
+
...(request.tools.length
|
|
107
|
+
? {
|
|
108
|
+
tools: request.tools.map((t) => ({
|
|
109
|
+
type: "function",
|
|
110
|
+
name: t.name,
|
|
111
|
+
description: t.description,
|
|
112
|
+
parameters: t.inputSchema,
|
|
113
|
+
strict: false,
|
|
114
|
+
})),
|
|
115
|
+
}
|
|
116
|
+
: {}),
|
|
117
|
+
stream: true,
|
|
118
|
+
}, { signal: context.signal });
|
|
119
|
+
let terminal = false;
|
|
120
|
+
for await (const event of stream) {
|
|
121
|
+
context.signal.throwIfAborted();
|
|
122
|
+
switch (event.type) {
|
|
123
|
+
case "response.output_text.delta":
|
|
124
|
+
yield {
|
|
125
|
+
type: "message-delta",
|
|
126
|
+
messageId: event.item_id,
|
|
127
|
+
partId: event.item_id + ":" + event.content_index,
|
|
128
|
+
partKind: "text",
|
|
129
|
+
delta: event.delta,
|
|
130
|
+
};
|
|
131
|
+
break;
|
|
132
|
+
case "response.reasoning_summary_text.delta":
|
|
133
|
+
yield {
|
|
134
|
+
type: "message-delta",
|
|
135
|
+
messageId: event.item_id,
|
|
136
|
+
partId: event.item_id + ":summary:" + event.summary_index,
|
|
137
|
+
partKind: "reasoning",
|
|
138
|
+
delta: event.delta,
|
|
139
|
+
};
|
|
140
|
+
break;
|
|
141
|
+
case "response.completed": {
|
|
142
|
+
terminal = true;
|
|
143
|
+
const normalized = usage(event.response.usage);
|
|
144
|
+
yield { type: "usage", usage: normalized };
|
|
145
|
+
yield {
|
|
146
|
+
type: "response",
|
|
147
|
+
response: {
|
|
148
|
+
message: MessageCodec.encode(decodeOutput(event.response.output, this.ref, event.response.id, this.connection)),
|
|
149
|
+
usage: normalized,
|
|
150
|
+
finishReason: "completed",
|
|
151
|
+
providerRequestId: event.response.id,
|
|
152
|
+
},
|
|
153
|
+
};
|
|
154
|
+
break;
|
|
155
|
+
}
|
|
156
|
+
case "response.incomplete":
|
|
157
|
+
case "response.failed":
|
|
158
|
+
yield { type: "usage", usage: usage(event.response.usage) };
|
|
159
|
+
throw failure(event.response.error?.message ??
|
|
160
|
+
"OpenAI response did not complete", event.response.error?.code ?? "ProviderIncomplete");
|
|
161
|
+
case "error":
|
|
162
|
+
throw failure(event.message, event.code ?? "ProviderError");
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
if (!terminal)
|
|
166
|
+
throw failure("OpenAI stream ended before completion", "ProviderIncomplete");
|
|
167
|
+
}
|
|
168
|
+
catch (error) {
|
|
169
|
+
if (context.signal.aborted)
|
|
170
|
+
throw context.signal.reason;
|
|
171
|
+
errorInfo(error, {
|
|
172
|
+
source: error instanceof OpenAIError ? "provider" : "tessar",
|
|
173
|
+
...this.ref,
|
|
174
|
+
});
|
|
175
|
+
throw error;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
//# sourceMappingURL=adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter.js","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { type ModelCallContext, type ModelChunk, type ModelRequest } from "@tessar/core";
|
|
2
|
+
import { OpenAIAdapter } from "./adapter.js";
|
|
3
|
+
/** Native Chat Completions transport; the Agent consumes the shared ModelChunk contract. */
|
|
4
|
+
export declare class OpenAIChatAdapter extends OpenAIAdapter {
|
|
5
|
+
validate(request: ModelRequest): void;
|
|
6
|
+
stream(request: ModelRequest, context: ModelCallContext): AsyncIterable<ModelChunk>;
|
|
7
|
+
}
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import { errorInfo, fail, MessageCodec, normalizeUsage, TessarError, } from "@tessar/core";
|
|
2
|
+
import { OpenAIAdapter, clientKeys } from "./adapter.js";
|
|
3
|
+
import { chatResponseError, decodeChatMessage, encodeChatMessages, } from "./chat-codec.js";
|
|
4
|
+
function usage(value) {
|
|
5
|
+
const cached = value?.prompt_tokens_details?.cached_tokens;
|
|
6
|
+
return normalizeUsage({
|
|
7
|
+
inputTokens: value?.prompt_tokens,
|
|
8
|
+
outputTokens: value?.completion_tokens,
|
|
9
|
+
totalTokens: value?.total_tokens,
|
|
10
|
+
cacheReadInputTokens: cached,
|
|
11
|
+
cacheWriteInputTokens: value?.prompt_tokens_details?.cache_write_tokens,
|
|
12
|
+
reasoningOutputTokens: value?.completion_tokens_details?.reasoning_tokens,
|
|
13
|
+
uncachedInputTokens: value?.prompt_tokens !== undefined && cached !== undefined
|
|
14
|
+
? Math.max(0, value.prompt_tokens - cached)
|
|
15
|
+
: null,
|
|
16
|
+
}, value ? JSON.parse(JSON.stringify(value)) : null);
|
|
17
|
+
}
|
|
18
|
+
/** Native Chat Completions transport; the Agent consumes the shared ModelChunk contract. */
|
|
19
|
+
export class OpenAIChatAdapter extends OpenAIAdapter {
|
|
20
|
+
validate(request) {
|
|
21
|
+
if (request.model.providerId !== this.ref.providerId ||
|
|
22
|
+
request.model.modelId !== this.ref.modelId ||
|
|
23
|
+
request.model.connectionId !== this.ref.connectionId)
|
|
24
|
+
fail("UnsupportedContext", "Chat model or connection identity mismatch");
|
|
25
|
+
for (const key of [
|
|
26
|
+
"connectionId",
|
|
27
|
+
"api",
|
|
28
|
+
"model",
|
|
29
|
+
"input",
|
|
30
|
+
"messages",
|
|
31
|
+
"instructions",
|
|
32
|
+
"tools",
|
|
33
|
+
"stream",
|
|
34
|
+
"functions",
|
|
35
|
+
"function_call",
|
|
36
|
+
...clientKeys,
|
|
37
|
+
])
|
|
38
|
+
if (request.options && key in request.options)
|
|
39
|
+
fail("UnsupportedOption", key + " is owned by the connection or Agent runtime");
|
|
40
|
+
if (request.options?.n != null && request.options.n !== 1)
|
|
41
|
+
fail("UnsupportedOption", "An Agent consumes one Chat completion choice");
|
|
42
|
+
encodeChatMessages(request, this.connection);
|
|
43
|
+
}
|
|
44
|
+
async *stream(request, context) {
|
|
45
|
+
this.validate(request);
|
|
46
|
+
context.signal.throwIfAborted();
|
|
47
|
+
try {
|
|
48
|
+
const stream = await this.client.chat.completions.create({
|
|
49
|
+
...request.options,
|
|
50
|
+
model: this.ref.modelId,
|
|
51
|
+
messages: encodeChatMessages(request, this.connection),
|
|
52
|
+
...(request.tools.length
|
|
53
|
+
? {
|
|
54
|
+
tools: request.tools.map((tool) => ({
|
|
55
|
+
type: "function",
|
|
56
|
+
function: {
|
|
57
|
+
name: tool.name,
|
|
58
|
+
description: tool.description,
|
|
59
|
+
parameters: tool.inputSchema,
|
|
60
|
+
},
|
|
61
|
+
})),
|
|
62
|
+
}
|
|
63
|
+
: {}),
|
|
64
|
+
stream: true,
|
|
65
|
+
}, { signal: context.signal });
|
|
66
|
+
let responseId = "", finishReason = null, text = "", refusal = "";
|
|
67
|
+
let counts;
|
|
68
|
+
const thinking = {};
|
|
69
|
+
const calls = new Map();
|
|
70
|
+
for await (const chunk of stream) {
|
|
71
|
+
context.signal.throwIfAborted();
|
|
72
|
+
if (chunk.id)
|
|
73
|
+
responseId = chunk.id;
|
|
74
|
+
if (chunk.usage)
|
|
75
|
+
counts = chunk.usage;
|
|
76
|
+
for (const choice of chunk.choices) {
|
|
77
|
+
if (choice.index !== 0)
|
|
78
|
+
throw chatResponseError("Unexpected multiple Chat completion choices");
|
|
79
|
+
const delta = choice.delta;
|
|
80
|
+
if (delta.audio || delta.function_call)
|
|
81
|
+
fail("UnsupportedResponse", "Unsupported Chat audio or deprecated function-call output");
|
|
82
|
+
if (delta.content != null) {
|
|
83
|
+
if (typeof delta.content !== "string")
|
|
84
|
+
throw chatResponseError("Chat content must be text");
|
|
85
|
+
text += delta.content;
|
|
86
|
+
if (delta.content)
|
|
87
|
+
yield {
|
|
88
|
+
type: "message-delta",
|
|
89
|
+
messageId: responseId,
|
|
90
|
+
partId: "text-0",
|
|
91
|
+
partKind: "text",
|
|
92
|
+
delta: delta.content,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
if (delta.refusal) {
|
|
96
|
+
refusal += delta.refusal;
|
|
97
|
+
yield {
|
|
98
|
+
type: "message-delta",
|
|
99
|
+
messageId: responseId,
|
|
100
|
+
partId: "refusal",
|
|
101
|
+
partKind: "text",
|
|
102
|
+
delta: delta.refusal,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
for (const key of ["reasoning_content", "reasoning"]) {
|
|
106
|
+
if (delta[key] === undefined || delta[key] === null)
|
|
107
|
+
continue;
|
|
108
|
+
if (typeof delta[key] !== "string")
|
|
109
|
+
throw chatResponseError("Chat reasoning must be text");
|
|
110
|
+
thinking[key] = (thinking[key] ?? "") + delta[key];
|
|
111
|
+
if (delta[key])
|
|
112
|
+
yield {
|
|
113
|
+
type: "message-delta",
|
|
114
|
+
messageId: responseId,
|
|
115
|
+
partId: key,
|
|
116
|
+
partKind: "reasoning",
|
|
117
|
+
delta: delta[key],
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
for (const call of delta.tool_calls ?? []) {
|
|
121
|
+
if (!Number.isInteger(call.index) ||
|
|
122
|
+
call.index < 0 ||
|
|
123
|
+
(call.type && call.type !== "function"))
|
|
124
|
+
throw chatResponseError("Invalid Chat function-call chunk");
|
|
125
|
+
const saved = calls.get(call.index) ?? {
|
|
126
|
+
id: "",
|
|
127
|
+
type: "function",
|
|
128
|
+
function: { name: "", arguments: "" },
|
|
129
|
+
};
|
|
130
|
+
saved.id += call.id ?? "";
|
|
131
|
+
saved.function.name += call.function?.name ?? "";
|
|
132
|
+
saved.function.arguments += call.function?.arguments ?? "";
|
|
133
|
+
calls.set(call.index, saved);
|
|
134
|
+
}
|
|
135
|
+
if (choice.finish_reason)
|
|
136
|
+
finishReason = choice.finish_reason;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
if (!responseId || !finishReason)
|
|
140
|
+
throw chatResponseError("Chat stream ended before completion", "ProviderIncomplete");
|
|
141
|
+
if (finishReason === "tool_calls" && !calls.size)
|
|
142
|
+
throw chatResponseError("Chat completion ended with missing function calls");
|
|
143
|
+
const message = {
|
|
144
|
+
role: "assistant",
|
|
145
|
+
content: text || null,
|
|
146
|
+
...thinking,
|
|
147
|
+
...(refusal ? { refusal } : {}),
|
|
148
|
+
...(calls.size
|
|
149
|
+
? {
|
|
150
|
+
tool_calls: [...calls]
|
|
151
|
+
.sort(([a], [b]) => a - b)
|
|
152
|
+
.map(([, call]) => call),
|
|
153
|
+
}
|
|
154
|
+
: {}),
|
|
155
|
+
};
|
|
156
|
+
const normalized = usage(counts);
|
|
157
|
+
const decoded = decodeChatMessage(message, this.ref, responseId, this.connection);
|
|
158
|
+
yield { type: "usage", usage: normalized };
|
|
159
|
+
yield {
|
|
160
|
+
type: "response",
|
|
161
|
+
response: {
|
|
162
|
+
message: MessageCodec.encode(decoded),
|
|
163
|
+
usage: normalized,
|
|
164
|
+
finishReason,
|
|
165
|
+
providerRequestId: responseId,
|
|
166
|
+
},
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
catch (error) {
|
|
170
|
+
if (context.signal.aborted)
|
|
171
|
+
throw context.signal.reason;
|
|
172
|
+
errorInfo(error, {
|
|
173
|
+
source: error instanceof TessarError ? "tessar" : "provider",
|
|
174
|
+
...this.ref,
|
|
175
|
+
});
|
|
176
|
+
throw error;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
//# sourceMappingURL=chat-adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chat-adapter.js","sourceRoot":"","sources":["../src/chat-adapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { AssistantMessage, type ModelRef, type ModelRequest, type ModelConnectionDescriptor } from "@tessar/core";
|
|
2
|
+
import type { ChatCompletionMessageParam } from "openai/resources/chat/completions/completions";
|
|
3
|
+
export interface ChatAssistant {
|
|
4
|
+
role: "assistant";
|
|
5
|
+
content: string | null;
|
|
6
|
+
refusal?: string;
|
|
7
|
+
reasoning_content?: string;
|
|
8
|
+
reasoning?: string;
|
|
9
|
+
tool_calls?: {
|
|
10
|
+
id: string;
|
|
11
|
+
type: "function";
|
|
12
|
+
function: {
|
|
13
|
+
name: string;
|
|
14
|
+
arguments: string;
|
|
15
|
+
};
|
|
16
|
+
}[];
|
|
17
|
+
}
|
|
18
|
+
export declare function chatResponseError(message: string, code?: string): Error;
|
|
19
|
+
export declare function encodeChatMessages(request: ModelRequest, connection?: ModelConnectionDescriptor): ChatCompletionMessageParam[];
|
|
20
|
+
export declare function decodeChatMessage(message: ChatAssistant, ref: ModelRef, id: string, connection?: ModelConnectionDescriptor): AssistantMessage;
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { AssistantMessage, fail, } from "@tessar/core";
|
|
2
|
+
export function chatResponseError(message, code = "ProviderResponse") {
|
|
3
|
+
return Object.assign(new Error(message), { code });
|
|
4
|
+
}
|
|
5
|
+
function toolOutput(message) {
|
|
6
|
+
return message.content
|
|
7
|
+
.map((part) => {
|
|
8
|
+
if (part.type === "text")
|
|
9
|
+
return part.text;
|
|
10
|
+
if (part.type === "data")
|
|
11
|
+
return JSON.stringify(part.data);
|
|
12
|
+
return fail("UnsupportedContext", "Chat tool output requires text or JSON data");
|
|
13
|
+
})
|
|
14
|
+
.join("");
|
|
15
|
+
}
|
|
16
|
+
export function encodeChatMessages(request, connection) {
|
|
17
|
+
const messages = [];
|
|
18
|
+
const instructions = request.instructions.sections
|
|
19
|
+
.map((section) => section.content)
|
|
20
|
+
.join("\n\n");
|
|
21
|
+
if (request.instructions.sections.some((section) => section.content.length > 0))
|
|
22
|
+
messages.push({ role: "system", content: instructions });
|
|
23
|
+
for (const message of request.messages) {
|
|
24
|
+
if (message.providerState !== undefined) {
|
|
25
|
+
const state = message.providerState;
|
|
26
|
+
if (!state ||
|
|
27
|
+
state.codec !== "openai.chat-completions" ||
|
|
28
|
+
state.version !== 1 ||
|
|
29
|
+
state.providerId !== request.model.providerId ||
|
|
30
|
+
state.modelId !== request.model.modelId ||
|
|
31
|
+
state.connectionId !== request.model.connectionId ||
|
|
32
|
+
state.message?.role !== "assistant" ||
|
|
33
|
+
(state.connection !== undefined &&
|
|
34
|
+
(state.connection.endpoint !== connection?.endpoint ||
|
|
35
|
+
state.connection.protocol !== connection?.protocol)))
|
|
36
|
+
fail("UnsupportedContext", "Opaque Chat context requires its original model, connection and protocol");
|
|
37
|
+
messages.push(state.message);
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
if (message.content.some((part) => part.type === "reasoning"))
|
|
41
|
+
fail("UnsupportedContext", "Reasoning history requires native provider continuity");
|
|
42
|
+
if (message.role === "tool") {
|
|
43
|
+
if (!message.toolCallId)
|
|
44
|
+
fail("InvalidMessage", "Tool history requires toolCallId");
|
|
45
|
+
messages.push({
|
|
46
|
+
role: "tool",
|
|
47
|
+
tool_call_id: message.toolCallId,
|
|
48
|
+
content: toolOutput(message),
|
|
49
|
+
});
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
if (message.role === "assistant") {
|
|
53
|
+
const text = [], calls = [];
|
|
54
|
+
for (const part of message.content) {
|
|
55
|
+
if (part.type === "text")
|
|
56
|
+
text.push(part.text);
|
|
57
|
+
else if (part.type === "tool-call")
|
|
58
|
+
calls.push({
|
|
59
|
+
id: part.toolCallId,
|
|
60
|
+
type: "function",
|
|
61
|
+
function: {
|
|
62
|
+
name: part.name,
|
|
63
|
+
arguments: JSON.stringify(part.arguments),
|
|
64
|
+
},
|
|
65
|
+
});
|
|
66
|
+
else
|
|
67
|
+
fail("UnsupportedContext", "Unsupported Chat assistant content");
|
|
68
|
+
}
|
|
69
|
+
messages.push({
|
|
70
|
+
role: "assistant",
|
|
71
|
+
content: text.length ? text.join("") : null,
|
|
72
|
+
...(calls.length ? { tool_calls: calls } : {}),
|
|
73
|
+
});
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
if (message.role === "system") {
|
|
77
|
+
if (message.content.some((part) => part.type !== "text"))
|
|
78
|
+
fail("UnsupportedContext", "System content requires text");
|
|
79
|
+
messages.push({
|
|
80
|
+
role: "system",
|
|
81
|
+
content: message.content
|
|
82
|
+
.map((part) => part.text)
|
|
83
|
+
.join(""),
|
|
84
|
+
});
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
if (message.content.every((part) => part.type === "text")) {
|
|
88
|
+
messages.push({
|
|
89
|
+
role: "user",
|
|
90
|
+
content: message.content.map((part) => part.text).join(""),
|
|
91
|
+
});
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
const content = message.content.map((part) => {
|
|
95
|
+
if (part.type === "text")
|
|
96
|
+
return { type: "text", text: part.text };
|
|
97
|
+
if (part.type === "image")
|
|
98
|
+
return {
|
|
99
|
+
type: "image_url",
|
|
100
|
+
image_url: {
|
|
101
|
+
url: /^(https?:|data:)/.test(part.data)
|
|
102
|
+
? part.data
|
|
103
|
+
: `data:${part.mediaType};base64,${part.data}`,
|
|
104
|
+
},
|
|
105
|
+
};
|
|
106
|
+
if (part.type === "file")
|
|
107
|
+
return { type: "file", file: { file_data: part.data } };
|
|
108
|
+
return fail("UnsupportedContext", "Unsupported Chat user content");
|
|
109
|
+
});
|
|
110
|
+
messages.push({ role: "user", content });
|
|
111
|
+
}
|
|
112
|
+
return messages;
|
|
113
|
+
}
|
|
114
|
+
export function decodeChatMessage(message, ref, id, connection) {
|
|
115
|
+
const parts = [];
|
|
116
|
+
for (const text of [message.reasoning_content, message.reasoning])
|
|
117
|
+
if (text)
|
|
118
|
+
parts.push({ type: "reasoning", text });
|
|
119
|
+
if (message.content)
|
|
120
|
+
parts.push({ type: "text", text: message.content });
|
|
121
|
+
if (message.refusal)
|
|
122
|
+
parts.push({ type: "text", text: message.refusal });
|
|
123
|
+
const ids = new Set();
|
|
124
|
+
for (const call of message.tool_calls ?? []) {
|
|
125
|
+
if (!call.id || !call.function.name)
|
|
126
|
+
throw chatResponseError("Missing Chat function identity");
|
|
127
|
+
if (ids.has(call.id))
|
|
128
|
+
throw chatResponseError("Duplicate Chat function identity");
|
|
129
|
+
ids.add(call.id);
|
|
130
|
+
let args;
|
|
131
|
+
try {
|
|
132
|
+
args = JSON.parse(call.function.arguments);
|
|
133
|
+
}
|
|
134
|
+
catch {
|
|
135
|
+
throw chatResponseError("Invalid Chat function arguments");
|
|
136
|
+
}
|
|
137
|
+
if (!args || typeof args !== "object" || Array.isArray(args))
|
|
138
|
+
throw chatResponseError("Chat function arguments must be an object");
|
|
139
|
+
parts.push({
|
|
140
|
+
type: "tool-call",
|
|
141
|
+
toolCallId: call.id,
|
|
142
|
+
name: call.function.name,
|
|
143
|
+
arguments: args,
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
return new AssistantMessage(parts, {
|
|
147
|
+
id,
|
|
148
|
+
providerState: {
|
|
149
|
+
codec: "openai.chat-completions",
|
|
150
|
+
version: 1,
|
|
151
|
+
...ref,
|
|
152
|
+
message,
|
|
153
|
+
...(connection ? { connection: { ...connection } } : {}),
|
|
154
|
+
},
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
//# sourceMappingURL=chat-codec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chat-codec.js","sourceRoot":"","sources":["../src/chat-codec.ts"],"names":[],"mappings":"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"}
|
package/dist/codec.d.ts
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { AssistantMessage, type ModelRef, type ModelRequest, type ModelConnectionDescriptor } from "@tessar/core";
|
|
2
|
+
import type { ResponseInput } from "openai/resources/responses/responses";
|
|
3
|
+
export declare function encodeInput(request: ModelRequest, connection?: ModelConnectionDescriptor): ResponseInput;
|
|
4
|
+
export declare function decodeOutput(items: readonly unknown[], ref: ModelRef, responseId: string, connection?: ModelConnectionDescriptor): AssistantMessage;
|
package/dist/codec.js
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import { AssistantMessage, TessarError, fail, assertJson, } from "@tessar/core";
|
|
2
|
+
function continuity(value) {
|
|
3
|
+
if (!value ||
|
|
4
|
+
typeof value !== "object" ||
|
|
5
|
+
!("codec" in value) ||
|
|
6
|
+
value.codec !== "openai.responses")
|
|
7
|
+
return null;
|
|
8
|
+
const data = value;
|
|
9
|
+
if (data.version !== 1 || !Array.isArray(data.items))
|
|
10
|
+
fail("UnsupportedContext", "Unknown OpenAI continuity version");
|
|
11
|
+
return data;
|
|
12
|
+
}
|
|
13
|
+
export function encodeInput(request, connection) {
|
|
14
|
+
const input = [];
|
|
15
|
+
for (const message of request.messages) {
|
|
16
|
+
const state = continuity(message.providerState);
|
|
17
|
+
if (state) {
|
|
18
|
+
if (state.providerId !== request.model.providerId ||
|
|
19
|
+
state.modelId !== request.model.modelId ||
|
|
20
|
+
state.connectionId !== request.model.connectionId ||
|
|
21
|
+
(state.connection !== undefined &&
|
|
22
|
+
(state.connection.endpoint !== connection?.endpoint ||
|
|
23
|
+
state.connection.protocol !== connection?.protocol)))
|
|
24
|
+
fail("UnsupportedContext", "Opaque OpenAI context requires its original model");
|
|
25
|
+
input.push(...state.items);
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
28
|
+
if (message.providerState !== undefined ||
|
|
29
|
+
message.content.some((p) => p.type === "reasoning"))
|
|
30
|
+
fail("UnsupportedContext", "Unsupported provider continuity");
|
|
31
|
+
if (message.role === "tool") {
|
|
32
|
+
if (message.content.some((p) => p.type !== "text" && p.type !== "data"))
|
|
33
|
+
fail("UnsupportedContext", "OpenAI tool output currently requires text or JSON data parts");
|
|
34
|
+
input.push({
|
|
35
|
+
type: "function_call_output",
|
|
36
|
+
call_id: message.toolCallId,
|
|
37
|
+
output: message.content
|
|
38
|
+
.map((p) => p.type === "text"
|
|
39
|
+
? p.text
|
|
40
|
+
: p.type === "data"
|
|
41
|
+
? JSON.stringify(p.data)
|
|
42
|
+
: "")
|
|
43
|
+
.join(""),
|
|
44
|
+
});
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
const role = message.role;
|
|
48
|
+
let content = [];
|
|
49
|
+
const flush = () => {
|
|
50
|
+
if (content.length) {
|
|
51
|
+
input.push({ role, content });
|
|
52
|
+
content = [];
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
for (const part of message.content) {
|
|
56
|
+
switch (part.type) {
|
|
57
|
+
case "text":
|
|
58
|
+
content.push(message.role === "assistant"
|
|
59
|
+
? { type: "output_text", text: part.text, annotations: [] }
|
|
60
|
+
: { type: "input_text", text: part.text });
|
|
61
|
+
break;
|
|
62
|
+
case "tool-call":
|
|
63
|
+
if (message.role !== "assistant")
|
|
64
|
+
fail("UnsupportedContext", "Tool calls require assistant role");
|
|
65
|
+
flush();
|
|
66
|
+
input.push({
|
|
67
|
+
type: "function_call",
|
|
68
|
+
call_id: part.toolCallId,
|
|
69
|
+
name: part.name,
|
|
70
|
+
arguments: JSON.stringify(part.arguments),
|
|
71
|
+
});
|
|
72
|
+
break;
|
|
73
|
+
case "image":
|
|
74
|
+
if (message.role !== "user")
|
|
75
|
+
fail("UnsupportedContext", "Image input requires user role");
|
|
76
|
+
content.push({
|
|
77
|
+
type: "input_image",
|
|
78
|
+
image_url: part.data.startsWith("https:") || part.data.startsWith("data:")
|
|
79
|
+
? part.data
|
|
80
|
+
: `data:${part.mediaType};base64,${part.data}`,
|
|
81
|
+
detail: "auto",
|
|
82
|
+
});
|
|
83
|
+
break;
|
|
84
|
+
case "file":
|
|
85
|
+
if (message.role !== "user")
|
|
86
|
+
fail("UnsupportedContext", "File input requires user role");
|
|
87
|
+
content.push({
|
|
88
|
+
type: "input_file",
|
|
89
|
+
file_data: part.data,
|
|
90
|
+
filename: message.id,
|
|
91
|
+
});
|
|
92
|
+
break;
|
|
93
|
+
default:
|
|
94
|
+
fail("UnsupportedContext", "Unsupported OpenAI message part");
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
flush();
|
|
98
|
+
}
|
|
99
|
+
return input;
|
|
100
|
+
}
|
|
101
|
+
export function decodeOutput(items, ref, responseId, connection) {
|
|
102
|
+
assertJson(items);
|
|
103
|
+
const parts = [];
|
|
104
|
+
for (const raw of items) {
|
|
105
|
+
const item = raw;
|
|
106
|
+
switch (item.type) {
|
|
107
|
+
case "message":
|
|
108
|
+
for (const content of item.content) {
|
|
109
|
+
if (content.type === "output_text")
|
|
110
|
+
parts.push({ type: "text", text: content.text });
|
|
111
|
+
else if (content.type === "refusal")
|
|
112
|
+
parts.push({ type: "text", text: content.refusal });
|
|
113
|
+
else
|
|
114
|
+
fail("UnsupportedResponse", "Unsupported OpenAI output content");
|
|
115
|
+
}
|
|
116
|
+
break;
|
|
117
|
+
case "reasoning":
|
|
118
|
+
for (const summary of item.summary ?? [])
|
|
119
|
+
parts.push({ type: "reasoning", text: summary.text });
|
|
120
|
+
break;
|
|
121
|
+
case "function_call": {
|
|
122
|
+
let args;
|
|
123
|
+
try {
|
|
124
|
+
args = JSON.parse(item.arguments);
|
|
125
|
+
}
|
|
126
|
+
catch {
|
|
127
|
+
throw new TessarError("ProviderResponse", "Invalid OpenAI function arguments");
|
|
128
|
+
}
|
|
129
|
+
if (!args || typeof args !== "object" || Array.isArray(args))
|
|
130
|
+
fail("ProviderResponse", "Function arguments must be an object");
|
|
131
|
+
parts.push({
|
|
132
|
+
type: "tool-call",
|
|
133
|
+
toolCallId: item.call_id,
|
|
134
|
+
name: item.name,
|
|
135
|
+
arguments: args,
|
|
136
|
+
});
|
|
137
|
+
break;
|
|
138
|
+
}
|
|
139
|
+
default:
|
|
140
|
+
fail("UnsupportedResponse", "Unsupported OpenAI output item");
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return new AssistantMessage(parts, {
|
|
144
|
+
id: responseId,
|
|
145
|
+
providerState: {
|
|
146
|
+
codec: "openai.responses",
|
|
147
|
+
version: 1,
|
|
148
|
+
...ref,
|
|
149
|
+
...(connection ? { connection: { ...connection } } : {}),
|
|
150
|
+
items: items,
|
|
151
|
+
},
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
//# sourceMappingURL=codec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codec.js","sourceRoot":"","sources":["../src/codec.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAsB,MAAM,cAAc,CAAC;AACjE,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EACL,cAAc,GAKf,MAAM,eAAe,CAAC"}
|
package/dist/metadata.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metadata.js","sourceRoot":"","sources":["../src/metadata.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,gBAAgB,CAAC,MAAc;IAC7C,OAAO;QACL,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE,OAAO;YACxB,MAAM,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;YACtE,OAAO,EAAE,CAAC;QACZ,CAAC;KACF,CAAC;AACJ,CAAC"}
|
package/dist/plugin.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Plugin, PluginContext } from "@tessar/core";
|
|
2
|
+
import { type OpenAIOptions } from "./adapter.js";
|
|
3
|
+
export declare class OpenAIPlugin implements Plugin {
|
|
4
|
+
readonly id: string;
|
|
5
|
+
private readonly providerId;
|
|
6
|
+
private readonly options;
|
|
7
|
+
constructor(options: OpenAIOptions);
|
|
8
|
+
setup(tessar: PluginContext): void;
|
|
9
|
+
}
|
package/dist/plugin.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { OpenAIAdapter, createClient } from "./adapter.js";
|
|
2
|
+
import { metadataResolver } from "./metadata.js";
|
|
3
|
+
export class OpenAIPlugin {
|
|
4
|
+
id;
|
|
5
|
+
providerId;
|
|
6
|
+
options;
|
|
7
|
+
constructor(options) {
|
|
8
|
+
this.options = options;
|
|
9
|
+
this.providerId = options.providerId ?? "openai";
|
|
10
|
+
this.id = "provider." + this.providerId;
|
|
11
|
+
}
|
|
12
|
+
setup(tessar) {
|
|
13
|
+
const options = this.options, id = this.providerId;
|
|
14
|
+
const client = createClient(options);
|
|
15
|
+
tessar.models.register({
|
|
16
|
+
id,
|
|
17
|
+
endpoint: options.baseURL ?? "https://api.openai.com/v1",
|
|
18
|
+
metadataPartition: options.metadataPartition,
|
|
19
|
+
metadata: metadataResolver(client),
|
|
20
|
+
catalogModelRef: (ref) => !options.baseURL ||
|
|
21
|
+
options.baseURL.replace(/\/$/, "") === "https://api.openai.com/v1"
|
|
22
|
+
? { providerId: "openai", modelId: ref.modelId }
|
|
23
|
+
: null,
|
|
24
|
+
catalogMappingVersion: 1,
|
|
25
|
+
create: (modelId) => new OpenAIAdapter(options, { providerId: id, modelId }, client),
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=plugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.js","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,YAAY,EAAsB,MAAM,cAAc,CAAC;AAC/E,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,MAAM,OAAO,YAAY;IACd,EAAE,CAAS;IACH,UAAU,CAAS;IACnB,OAAO,CAAgB;IAExC,YAAY,OAAsB;QAChC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,QAAQ,CAAC;QACjD,IAAI,CAAC,EAAE,GAAG,WAAW,GAAG,IAAI,CAAC,UAAU,CAAC;IAC1C,CAAC;IAED,KAAK,CAAC,MAAqB;QACzB,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,EAC1B,EAAE,GAAG,IAAI,CAAC,UAAU,CAAC;QACvB,MAAM,MAAM,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC;QACrC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC;YACrB,EAAE;YACF,QAAQ,EAAE,OAAO,CAAC,OAAO,IAAI,2BAA2B;YACxD,iBAAiB,EAAE,OAAO,CAAC,iBAAiB;YAC5C,QAAQ,EAAE,gBAAgB,CAAC,MAAM,CAAC;YAClC,eAAe,EAAE,CAAC,GAAG,EAAE,EAAE,CACvB,CAAC,OAAO,CAAC,OAAO;gBAChB,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,2BAA2B;gBAChE,CAAC,CAAC,EAAE,UAAU,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE;gBAChD,CAAC,CAAC,IAAI;YACV,qBAAqB,EAAE,CAAC;YACxB,MAAM,EAAE,CAAC,OAAO,EAAE,EAAE,CAClB,IAAI,aAAa,CAAC,OAAO,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,MAAM,CAAC;SAClE,CAAC,CAAC;IACL,CAAC;CACF"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type OpenAI from "openai";
|
|
2
|
+
import type { ResponseCreateParamsStreaming } from "openai/resources/responses/responses";
|
|
3
|
+
import type { ChatCompletionCreateParamsStreaming } from "openai/resources/chat/completions/completions";
|
|
4
|
+
import { ProfileResolver, type ModelProfile, type ModelRequest, type ModelCallContext, type ModelChunk } from "@tessar/core";
|
|
5
|
+
import { OpenAIAdapter, type OpenAIOptions } from "./adapter.js";
|
|
6
|
+
export type OpenAIModelOptions = Omit<ResponseCreateParamsStreaming, "model" | "input" | "instructions" | "tools" | "stream" | "background" | "conversation" | "previous_response_id" | "context_management">;
|
|
7
|
+
export type OpenAIAPI = "responses" | "chat-completions";
|
|
8
|
+
export type OpenAIChatModelOptions = Omit<ChatCompletionCreateParamsStreaming, "model" | "messages" | "tools" | "stream" | "functions" | "function_call" | "n"> & {
|
|
9
|
+
n?: 1;
|
|
10
|
+
};
|
|
11
|
+
type OptionsFor<A extends OpenAIAPI> = A extends "chat-completions" ? OpenAIChatModelOptions : OpenAIModelOptions;
|
|
12
|
+
export type OpenAIProviderOptions<A extends OpenAIAPI = OpenAIAPI> = OpenAIOptions & {
|
|
13
|
+
model: string;
|
|
14
|
+
connectionId?: string;
|
|
15
|
+
} & (A extends "chat-completions" ? {
|
|
16
|
+
api: "chat-completions";
|
|
17
|
+
} & OpenAIChatModelOptions : {
|
|
18
|
+
api?: "responses";
|
|
19
|
+
} & OpenAIModelOptions);
|
|
20
|
+
interface Connection {
|
|
21
|
+
client: OpenAI;
|
|
22
|
+
identity: string;
|
|
23
|
+
resolver: ProfileResolver;
|
|
24
|
+
}
|
|
25
|
+
export declare class OpenAIProvider<A extends OpenAIAPI = "responses"> extends OpenAIAdapter {
|
|
26
|
+
readonly options: Readonly<OptionsFor<A>>;
|
|
27
|
+
readonly api: A;
|
|
28
|
+
private readonly chat?;
|
|
29
|
+
private readonly clientOptions;
|
|
30
|
+
private readonly sharedConnection;
|
|
31
|
+
private readonly registration;
|
|
32
|
+
constructor(configuration: OpenAIProviderOptions<A> & {
|
|
33
|
+
api?: A;
|
|
34
|
+
}, connection?: Connection);
|
|
35
|
+
withModel(modelId: string): OpenAIProvider<A>;
|
|
36
|
+
validate(request: ModelRequest): void;
|
|
37
|
+
stream(request: ModelRequest, context: ModelCallContext): AsyncIterable<ModelChunk>;
|
|
38
|
+
get profile(): Readonly<ModelProfile>;
|
|
39
|
+
refreshProfile(options?: {
|
|
40
|
+
signal?: AbortSignal;
|
|
41
|
+
}): Promise<ModelProfile>;
|
|
42
|
+
}
|
|
43
|
+
export {};
|
package/dist/provider.js
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { ProfileResolver, snapshotModelOptions, requireId, fail, } from "@tessar/core";
|
|
2
|
+
import { OpenAIAdapter, createClient, clientKeys, } from "./adapter.js";
|
|
3
|
+
import { metadataResolver } from "./metadata.js";
|
|
4
|
+
import { OpenAIChatAdapter } from "./chat-adapter.js";
|
|
5
|
+
export class OpenAIProvider extends OpenAIAdapter {
|
|
6
|
+
options;
|
|
7
|
+
api;
|
|
8
|
+
chat;
|
|
9
|
+
clientOptions;
|
|
10
|
+
sharedConnection;
|
|
11
|
+
registration;
|
|
12
|
+
constructor(configuration, connection) {
|
|
13
|
+
const { model, providerId = "openai", metadataPartition, connectionId, api = "responses", ...fields } = configuration;
|
|
14
|
+
if (api !== "responses" && api !== "chat-completions")
|
|
15
|
+
fail("InvalidConfiguration", "Choose responses or chat-completions");
|
|
16
|
+
requireId(model, "model id");
|
|
17
|
+
requireId(providerId, "provider id");
|
|
18
|
+
const clientOptions = Object.fromEntries(clientKeys
|
|
19
|
+
.filter((key) => fields[key] !== undefined)
|
|
20
|
+
.map((key) => [key, fields[key]]));
|
|
21
|
+
const body = Object.fromEntries(Object.entries(fields).filter(([key, value]) => !clientKeys.includes(key) && value !== undefined));
|
|
22
|
+
for (const key of [
|
|
23
|
+
"input",
|
|
24
|
+
"messages",
|
|
25
|
+
"instructions",
|
|
26
|
+
"tools",
|
|
27
|
+
"stream",
|
|
28
|
+
"functions",
|
|
29
|
+
"function_call",
|
|
30
|
+
])
|
|
31
|
+
if (key in body)
|
|
32
|
+
fail("UnsupportedOption", key + " is owned by the Agent runtime");
|
|
33
|
+
if (body.background === true ||
|
|
34
|
+
body.conversation != null ||
|
|
35
|
+
body.previous_response_id != null ||
|
|
36
|
+
body.context_management != null)
|
|
37
|
+
fail("UnsupportedOption", "Background, provider-managed conversations and compaction are not supported by the Agent loop");
|
|
38
|
+
if (api === "chat-completions" && body.n != null && body.n !== 1)
|
|
39
|
+
fail("UnsupportedOption", "An Agent consumes one Chat completion choice");
|
|
40
|
+
const requestOptions = snapshotModelOptions(body);
|
|
41
|
+
const selected = connection ?? {
|
|
42
|
+
client: createClient(clientOptions),
|
|
43
|
+
identity: connectionId === undefined
|
|
44
|
+
? crypto.randomUUID()
|
|
45
|
+
: requireId(connectionId, "connection id"),
|
|
46
|
+
resolver: new ProfileResolver(),
|
|
47
|
+
};
|
|
48
|
+
const descriptor = Object.freeze({
|
|
49
|
+
providerId,
|
|
50
|
+
connectionId: selected.identity,
|
|
51
|
+
protocol: api,
|
|
52
|
+
endpoint: selected.client.baseURL.replace(/\/$/, ""),
|
|
53
|
+
});
|
|
54
|
+
super(clientOptions, Object.freeze({
|
|
55
|
+
providerId,
|
|
56
|
+
modelId: model,
|
|
57
|
+
connectionId: selected.identity,
|
|
58
|
+
}), selected.client, descriptor);
|
|
59
|
+
this.options = requestOptions;
|
|
60
|
+
this.api = api;
|
|
61
|
+
if (api === "chat-completions")
|
|
62
|
+
this.chat = new OpenAIChatAdapter(clientOptions, this.ref, selected.client, descriptor);
|
|
63
|
+
this.clientOptions = { ...clientOptions, providerId, metadataPartition };
|
|
64
|
+
this.sharedConnection = selected;
|
|
65
|
+
const officialEndpoint = !clientOptions.baseURL ||
|
|
66
|
+
clientOptions.baseURL.replace(/\/$/, "") === "https://api.openai.com/v1";
|
|
67
|
+
this.registration = {
|
|
68
|
+
id: providerId,
|
|
69
|
+
create: (modelId) => this.withModel(modelId),
|
|
70
|
+
endpoint: clientOptions.baseURL ?? "https://api.openai.com/v1",
|
|
71
|
+
metadataPartition: metadataPartition ?? selected.identity,
|
|
72
|
+
metadata: metadataResolver(selected.client),
|
|
73
|
+
catalogModelRef: (ref) => officialEndpoint
|
|
74
|
+
? { providerId: "openai", modelId: ref.modelId }
|
|
75
|
+
: null,
|
|
76
|
+
catalogMappingVersion: 1,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
withModel(modelId) {
|
|
80
|
+
return new OpenAIProvider({
|
|
81
|
+
...this.clientOptions,
|
|
82
|
+
...this.options,
|
|
83
|
+
api: this.api,
|
|
84
|
+
model: modelId,
|
|
85
|
+
}, this.sharedConnection);
|
|
86
|
+
}
|
|
87
|
+
validate(request) {
|
|
88
|
+
if (this.chat)
|
|
89
|
+
this.chat.validate(request);
|
|
90
|
+
else
|
|
91
|
+
super.validate(request);
|
|
92
|
+
}
|
|
93
|
+
async *stream(request, context) {
|
|
94
|
+
if (this.chat)
|
|
95
|
+
yield* this.chat.stream(request, context);
|
|
96
|
+
else
|
|
97
|
+
yield* super.stream(request, context);
|
|
98
|
+
}
|
|
99
|
+
get profile() {
|
|
100
|
+
return this.sharedConnection.resolver.current(this.ref, this.registration);
|
|
101
|
+
}
|
|
102
|
+
refreshProfile(options = {}) {
|
|
103
|
+
return this.sharedConnection.resolver.resolve(this.ref, this.registration, options.signal);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.js","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,35 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tessar/openai",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "OpenAI Responses and Chat Completions provider with model metadata integration for Tessar.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"engines": {
|
|
7
|
+
"node": ">=24.14.0"
|
|
8
|
+
},
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist"
|
|
17
|
+
],
|
|
18
|
+
"repository": {
|
|
19
|
+
"type": "git",
|
|
20
|
+
"url": "git+https://github.com/hphucdev-04/tessar.git",
|
|
21
|
+
"directory": "packages/openai"
|
|
22
|
+
},
|
|
23
|
+
"publishConfig": {
|
|
24
|
+
"access": "public",
|
|
25
|
+
"registry": "https://registry.npmjs.org/"
|
|
26
|
+
},
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"openai": "7.34.0",
|
|
29
|
+
"@tessar/core": "0.1.0"
|
|
30
|
+
},
|
|
31
|
+
"scripts": {
|
|
32
|
+
"build": "tsc -p tsconfig.json",
|
|
33
|
+
"typecheck": "tsc --noEmit -p tsconfig.json"
|
|
34
|
+
}
|
|
6
35
|
}
|