@volter/twin-openai 0.1.1 → 2.0.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 +33 -30
- package/defaults/handlers.json +10 -0
- package/dist/defaults/handlers.json +10 -0
- package/dist/src/cli.d.ts +2 -0
- package/dist/src/cli.js +29 -0
- package/dist/src/generated/surface.gen.json +1 -0
- package/dist/src/generated/ui.gen.json +1 -0
- package/dist/src/index.d.ts +19 -0
- package/dist/src/index.js +72 -0
- package/dist/src/manifest.d.ts +6 -0
- package/dist/src/manifest.js +323 -0
- package/dist/src/openai-budget.d.ts +53 -0
- package/dist/src/openai-budget.js +147 -0
- package/dist/src/openai-capabilities.d.ts +4 -0
- package/dist/src/openai-capabilities.js +1569 -0
- package/dist/src/openai-conformance.d.ts +13 -0
- package/dist/src/openai-conformance.js +116 -0
- package/dist/src/openai-connector.d.ts +86 -0
- package/dist/src/openai-connector.js +291 -0
- package/dist/src/openai-media.d.ts +43 -0
- package/dist/src/openai-media.js +257 -0
- package/dist/src/openai-models.d.ts +74 -0
- package/dist/src/openai-models.js +148 -0
- package/dist/src/openai-scenario.d.ts +51 -0
- package/dist/src/openai-scenario.js +166 -0
- package/dist/src/openai-server.d.ts +40 -0
- package/dist/src/openai-server.js +126 -0
- package/dist/src/openai-stub.d.ts +82 -0
- package/dist/src/openai-stub.js +256 -0
- package/dist/src/openai-twin.d.ts +182 -0
- package/dist/src/openai-twin.js +1117 -0
- package/dist/src/openai-types.d.ts +194 -0
- package/dist/src/openai-types.js +4 -0
- package/dist/src/openai-webhooks.d.ts +47 -0
- package/dist/src/openai-webhooks.js +99 -0
- package/dist/src/screens/api-keys.d.ts +16 -0
- package/dist/src/screens/api-keys.js +131 -0
- package/dist/src/screens/session.d.ts +22 -0
- package/dist/src/screens/session.js +115 -0
- package/dist/src/semantics/assistants.d.ts +2 -0
- package/dist/src/semantics/assistants.js +331 -0
- package/dist/src/semantics/audio.d.ts +2 -0
- package/dist/src/semantics/audio.js +27 -0
- package/dist/src/semantics/batches.d.ts +4 -0
- package/dist/src/semantics/batches.js +86 -0
- package/dist/src/semantics/chat-completions.d.ts +3 -0
- package/dist/src/semantics/chat-completions.js +58 -0
- package/dist/src/semantics/containers.d.ts +2 -0
- package/dist/src/semantics/containers.js +147 -0
- package/dist/src/semantics/embeddings.d.ts +2 -0
- package/dist/src/semantics/embeddings.js +13 -0
- package/dist/src/semantics/evals.d.ts +2 -0
- package/dist/src/semantics/evals.js +173 -0
- package/dist/src/semantics/files.d.ts +13 -0
- package/dist/src/semantics/files.js +59 -0
- package/dist/src/semantics/fine-tuning.d.ts +4 -0
- package/dist/src/semantics/fine-tuning.js +178 -0
- package/dist/src/semantics/images.d.ts +2 -0
- package/dist/src/semantics/images.js +18 -0
- package/dist/src/semantics/index.d.ts +8 -0
- package/dist/src/semantics/index.js +46 -0
- package/dist/src/semantics/models.d.ts +2 -0
- package/dist/src/semantics/models.js +34 -0
- package/dist/src/semantics/moderations.d.ts +2 -0
- package/dist/src/semantics/moderations.js +12 -0
- package/dist/src/semantics/organization.d.ts +2 -0
- package/dist/src/semantics/organization.js +67 -0
- package/dist/src/semantics/progress.d.ts +22 -0
- package/dist/src/semantics/progress.js +63 -0
- package/dist/src/semantics/responses.d.ts +3 -0
- package/dist/src/semantics/responses.js +153 -0
- package/dist/src/semantics/shared.d.ts +32 -0
- package/dist/src/semantics/shared.js +69 -0
- package/dist/src/semantics/uploads.d.ts +2 -0
- package/dist/src/semantics/uploads.js +84 -0
- package/dist/src/semantics/vector-stores.d.ts +2 -0
- package/dist/src/semantics/vector-stores.js +281 -0
- package/dist/test-fixtures/openai-openapi-operations.SOURCE.md +18 -0
- package/dist/test-fixtures/openai-openapi-operations.json +1849 -0
- package/package.json +21 -10
- package/src/cli.ts +9 -7
- package/src/generated/surface.gen.json +1 -0
- package/src/generated/ui.gen.json +1 -0
- package/src/index.ts +20 -10
- package/src/manifest.ts +343 -0
- package/src/openai-budget.ts +4 -4
- package/src/openai-capabilities.ts +177 -195
- package/src/openai-conformance.ts +1 -1
- package/src/openai-connector.ts +40 -43
- package/src/openai-media.ts +225 -0
- package/src/openai-models.ts +145 -15
- package/src/openai-scenario.ts +46 -10
- package/src/openai-server.ts +65 -108
- package/src/openai-stub.ts +54 -30
- package/src/openai-twin.ts +760 -1665
- package/src/openai-types.ts +24 -6
- package/src/openai-webhooks.ts +2 -1
- package/src/screens/api-keys.tsx +138 -0
- package/src/screens/session.tsx +131 -0
- package/src/semantics/assistants.ts +336 -0
- package/src/semantics/audio.ts +31 -0
- package/src/semantics/batches.ts +88 -0
- package/src/semantics/chat-completions.ts +66 -0
- package/src/semantics/containers.ts +151 -0
- package/src/semantics/embeddings.ts +19 -0
- package/src/semantics/evals.ts +182 -0
- package/src/semantics/files.ts +67 -0
- package/src/semantics/fine-tuning.ts +185 -0
- package/src/semantics/images.ts +23 -0
- package/src/semantics/index.ts +52 -0
- package/src/semantics/models.ts +41 -0
- package/src/semantics/moderations.ts +14 -0
- package/src/semantics/organization.ts +76 -0
- package/src/semantics/progress.ts +72 -0
- package/src/semantics/responses.ts +151 -0
- package/src/semantics/shared.ts +82 -0
- package/src/semantics/uploads.ts +92 -0
- package/src/semantics/vector-stores.ts +279 -0
- package/test-fixtures/openai-openapi-operations.SOURCE.md +4 -5
- package/test-fixtures/openai-openapi-operations.json +224 -1334
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
A local, faithful **OpenAI API** twin your real `openai` SDK talks to unmodified — point the
|
|
4
4
|
SDK at the twin's `baseURL` and `chat.completions.create`, streaming, the Responses API,
|
|
5
5
|
`embeddings`, `models`, `moderations`, `files`, `batches`, fine-tuning jobs, and vector stores
|
|
6
|
-
all work. Built on the shared `@volter/
|
|
6
|
+
all work. Built on the shared `@volter/world-core` kernel; see [the model](../../../docs/concepts/the-model.md) for storage and branching;
|
|
7
7
|
no parallel side store.
|
|
8
8
|
|
|
9
9
|
```ts
|
|
@@ -27,6 +27,19 @@ stub (it carries a `[twin-stub:<model>]` marker and echoes your prompt), and `PO
|
|
|
27
27
|
returns **deterministic pseudo-vectors** (seeded from the input hash). They **never** pretend to
|
|
28
28
|
be real model output / real embedding values.
|
|
29
29
|
|
|
30
|
+
Responses uses the same file-authored scenario handlers as Chat Completions, including text,
|
|
31
|
+
function calls, faults, and labeled misses. Stored input items retain their vendor structure;
|
|
32
|
+
scenario matching uses a separate messages projection. `previous_response_id` carries the
|
|
33
|
+
accumulated input and output items forward once, including tool call identities. Top-level
|
|
34
|
+
`instructions` apply only to the current request. This follows OpenAI's
|
|
35
|
+
[conversation-state model](https://developers.openai.com/api/docs/guides/conversation-state)
|
|
36
|
+
and [function-calling loop](https://developers.openai.com/api/docs/guides/function-calling).
|
|
37
|
+
|
|
38
|
+
Background requests retain the scenario decision selected at creation; the first poll completes
|
|
39
|
+
that decision without matching handlers again. Stored response identities are allocated from
|
|
40
|
+
the kernel's current state under its atomic write lock, so repeated requests cannot overwrite
|
|
41
|
+
one another.
|
|
42
|
+
|
|
30
43
|
What **is** faithful is the **entire protocol envelope**:
|
|
31
44
|
|
|
32
45
|
- chat response shape — `{ id:'chatcmpl-…', object:'chat.completion', created, model, choices:[{index, message:{role:'assistant', content}, finish_reason}], usage:{prompt_tokens, completion_tokens, total_tokens}, system_fingerprint }`
|
|
@@ -58,15 +71,15 @@ world-openai conformance [--root DIR] # offline envel
|
|
|
58
71
|
```
|
|
59
72
|
|
|
60
73
|
(OpenAI is an API-first vendor with no meaningful product UI worth mirroring — see
|
|
61
|
-
|
|
74
|
+
../../../docs/contributing/architecture.md C1b — so this pack ships **no mirror**.)
|
|
62
75
|
|
|
63
|
-
##
|
|
76
|
+
## Observation and execution
|
|
64
77
|
|
|
65
|
-
`syncOpenAIFromReal`
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
78
|
+
`syncOpenAIFromReal` observes files, batches, fine-tuning jobs and vector stores through an injected client.
|
|
79
|
+
The kernel invokes `performOpenAIAction` for supported real-system writes and owns landing and
|
|
80
|
+
receipts. The package adapter owns vendor request/response semantics; it does not run a second
|
|
81
|
+
pending-action deployment loop. See the [deployment guide](../../../docs/guides/deploy-from-a-shared-world.md)
|
|
82
|
+
for the World workflow and the capability manifest for supported operations.
|
|
70
83
|
|
|
71
84
|
## Coverage
|
|
72
85
|
|
|
@@ -115,8 +128,7 @@ deterministically. Run `bun scripts/twin-capabilities.ts openai` for the live nu
|
|
|
115
128
|
- **Errors / protocol** — 404, `invalid_request_error` envelope, read-only 405 guard, modeled
|
|
116
129
|
auth (`401` on a missing/invalid credential when a request carries an auth surface; trusted
|
|
117
130
|
in-process + real-SDK calls pass), rate-limit `429` (deterministic opt-in trigger header →
|
|
118
|
-
vendor envelope + `Retry-After` + `x-ratelimit-*`),
|
|
119
|
-
the same response/id; a new key → a new result), cursor pagination (`after`/`limit` +
|
|
131
|
+
vendor envelope + `Retry-After` + `x-ratelimit-*`), cursor pagination (`after`/`limit` +
|
|
120
132
|
`has_more`/`first_id`/`last_id`)
|
|
121
133
|
- **Connector** — read surface, pull+map (offline), push+confirm (offline), unsupported-op fails,
|
|
122
134
|
full bi-directional sync (push-then-pull, idempotent)
|
|
@@ -128,24 +140,15 @@ deterministically. Run `bun scripts/twin-capabilities.ts openai` for the live nu
|
|
|
128
140
|
- **Background responses** — `background:true` → queued status + poll + cancel
|
|
129
141
|
- **Fine-tuning** — job pause / resume
|
|
130
142
|
- **Webhooks** — event signature verification (signing-secret HMAC)
|
|
143
|
+
- **Image URLs that resolve** — serve deterministic placeholder bytes at the URLs the twin
|
|
144
|
+
returns (today they point at the dead `twin.invalid` host)
|
|
145
|
+
- **Binary file content** — persist and return arbitrary bytes, not only supplied text
|
|
146
|
+
- **Responses built-in tools** — web_search / file_search / computer_use / code_interpreter with a
|
|
147
|
+
deterministic, labeled twin-stub result, exactly as chat stubs generation
|
|
148
|
+
- **Realtime API** — the websocket session protocol with deterministic labeled stub events
|
|
131
149
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
returns a deterministic stub; the protocol envelope is faithful.
|
|
135
|
-
- **`openai.embeddings.real_vectors`** — *real embedding values.* The twin returns deterministic
|
|
136
|
-
pseudo-vectors; the shape/dimensions/determinism are faithful.
|
|
137
|
-
- **`openai.images.real_pixels`** — *real generated image bytes.* The response shape is faithful;
|
|
138
|
-
the URL is a placeholder.
|
|
139
|
-
- **`openai.files.real_bytes`** — *arbitrary binary blob storage.* Metadata + supplied text
|
|
140
|
-
content are faithful; the twin is not a binary object store.
|
|
141
|
-
- **`openai.responses.tools`** — *hosted built-in tools (web_search / computer_use /
|
|
142
|
-
code_interpreter).* These require live model + infrastructure side effects that cannot be
|
|
143
|
-
reproduced offline without fabricating output; user-defined function tools ARE modeled.
|
|
144
|
-
- **`openai.audio.realtime`** — *Realtime API (WebSocket sessions).* A live bidirectional audio
|
|
145
|
-
socket to a running speech model — both the transport and the inference are irreproducible in
|
|
146
|
-
the offline, HTTP `verify()` harness.
|
|
147
|
-
|
|
148
|
-
Everything else is covered by default and is either done or planned.
|
|
150
|
+
Every capability is done or todo. The labeled stub completion and the deterministic pseudo-vector are
|
|
151
|
+
the twin's answer, not a shortfall from a "real" one; every capability is done or todo.
|
|
149
152
|
|
|
150
153
|
## Rate budget — the fail-closed backstop on live calls
|
|
151
154
|
|
|
@@ -160,9 +163,9 @@ validated by *method identity*, so a subclass or a `Proxy` that replaces `checkB
|
|
|
160
163
|
|
|
161
164
|
The declared numbers: **60 weighted units / 60s at weight 2 = 30 calls/minute — exactly the kernel's austere fallback**, because OpenAI publishes *no* scalar per-key request limit (limits are per org/project, per model, per tier, and live only on the account's limits page). The one documented scalar that can bind this pack is Vector Store ingestion at 300 requests/minute per store. The declaration therefore buys **resolution, not headroom**: inference paths cost 5, vector-store ingestion 4, and nothing is cheaper than the fallback would price it.
|
|
162
165
|
|
|
163
|
-
The mechanism is **shared and vendor-agnostic** — it lives in the kernel (`@volter/
|
|
164
|
-
`
|
|
166
|
+
The mechanism is **shared and vendor-agnostic** — it lives in the kernel (`@volter/world-core` →
|
|
167
|
+
`packages/world-core/src/rateBudget.ts`); what lives here in [`src/openai-budget.ts`](src/openai-budget.ts) is this vendor's
|
|
165
168
|
**declaration** (window, ceiling, per-endpoint weights, and a `reason` citing the limits above) plus
|
|
166
169
|
the vendor-bound `OpenAIBudget`. The rule is ratified as
|
|
167
|
-
[
|
|
170
|
+
[../../../docs/contributing/architecture.md](../../../docs/contributing/architecture.md) **D8**, and the kernel module's header documents what the
|
|
168
171
|
guard does *not* guarantee — read that before trusting it.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$comment": "[twin-demo] Starter handlers, copied visibly into your world dir by init — yours to edit or delete. Ordered first-match; GET /twin on the twin explains the grammar; GET /twin/scenario lists these with match/miss counts.",
|
|
3
|
+
"handlers": [
|
|
4
|
+
{
|
|
5
|
+
"$comment": "[twin-demo] A narrow smoke beat: prove scripting works end-to-end, then write your own.",
|
|
6
|
+
"on": { "userTextIncludes": "twin-demo ping" },
|
|
7
|
+
"respond": { "text": "twin-demo pong — scripted by handlers/openai.json. Edit that file to script your own beats." }
|
|
8
|
+
}
|
|
9
|
+
]
|
|
10
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$comment": "[twin-demo] Starter handlers, copied visibly into your world dir by init — yours to edit or delete. Ordered first-match; GET /twin on the twin explains the grammar; GET /twin/scenario lists these with match/miss counts.",
|
|
3
|
+
"handlers": [
|
|
4
|
+
{
|
|
5
|
+
"$comment": "[twin-demo] A narrow smoke beat: prove scripting works end-to-end, then write your own.",
|
|
6
|
+
"on": { "userTextIncludes": "twin-demo ping" },
|
|
7
|
+
"respond": { "text": "twin-demo pong — scripted by handlers/openai.json. Edit that file to script your own beats." }
|
|
8
|
+
}
|
|
9
|
+
]
|
|
10
|
+
}
|
package/dist/src/cli.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { keepProcessAlive } from '@volter/world-core/lifecycle';
|
|
3
|
+
// world-openai CLI: serve the OpenAI API twin or run conformance. OpenAI is an API-first
|
|
4
|
+
// vendor with no meaningful product UI worth mirroring (docs/contributing/architecture.md C1b), so this pack
|
|
5
|
+
// ships no mirror.
|
|
6
|
+
import { hasFlag, optionValue } from '@volter/world-core/args';
|
|
7
|
+
import "./index.js"; // the pack registers itself on load (protocol 2)
|
|
8
|
+
import { createOpenAITwinServer } from "./openai-server.js";
|
|
9
|
+
const [cmd, ...rest] = process.argv.slice(2);
|
|
10
|
+
const port = Number(optionValue(rest, '--port', '0')) || undefined;
|
|
11
|
+
const root = optionValue(rest, '--root') || undefined;
|
|
12
|
+
const readOnly = hasFlag(rest, '--read-only'); // a twin accepts writes unless started read-only
|
|
13
|
+
const scenario = optionValue(rest, '--scenario') || undefined; // scripted completions (JSON file)
|
|
14
|
+
if (cmd === 'serve') {
|
|
15
|
+
const s = await createOpenAITwinServer({ readOnly, ...(root ? { root } : {}), ...(port ? { port } : {}), ...(scenario ? { scenarioPath: scenario } : {}) });
|
|
16
|
+
process.stdout.write(`openai twin (chat/responses/embeddings output is a deterministic stub)${readOnly ? ' [read-only]' : ''} at http://127.0.0.1:${s.port}\n`);
|
|
17
|
+
await keepProcessAlive();
|
|
18
|
+
}
|
|
19
|
+
else if (cmd === 'conformance') {
|
|
20
|
+
// dev-only; lazy so the bin runs without @volter/world-tooling
|
|
21
|
+
const { checkOpenAIConformance } = await import("./openai-conformance.js");
|
|
22
|
+
const report = await checkOpenAIConformance({ ...(root ? { root } : {}) });
|
|
23
|
+
process.stdout.write(`${JSON.stringify(report, null, 2)}\n`);
|
|
24
|
+
if (!report.ok)
|
|
25
|
+
process.exitCode = 1;
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
process.stdout.write('Usage: world-openai serve|conformance [--port N] [--root DIR] [--read-only] [--scenario FILE]\n');
|
|
29
|
+
}
|