@volter/twin-openai 2.0.1 → 2.0.3
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.
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
// The surface is a plain `fetch` (`createOpenAITwinFetch`) and the SERVER is one line of
|
|
11
11
|
// `Bun.serve` around it — see that factory's docstring for why (a serverless entry has no
|
|
12
12
|
// port to bind, so it mounts the fetch in-process).
|
|
13
|
-
import { bindSemantics, coreFor, createDerivedFetch, crossCutting, semanticsContext, serveHttp, vendorError } from '@volter/world-core';
|
|
13
|
+
import { bindSemantics, coreFor, createDerivedFetch, crossCutting, derivedRequestScopes, runAsVendorMove, semanticsContext, serveHttp, vendorError } from '@volter/world-core';
|
|
14
14
|
import surface from './generated/surface.gen.json' with { type: 'json' };
|
|
15
15
|
import { manifest } from "./manifest.js";
|
|
16
16
|
import { openaiSemantics } from "./semantics/index.js";
|
|
@@ -89,21 +89,24 @@ export function createOpenAITwinFetch(options) {
|
|
|
89
89
|
const useKey = projectKeyUse(scope);
|
|
90
90
|
// and a read of the files observes the work whose outputs are files (a batch's output, a fine-tuning job's results)
|
|
91
91
|
// first, as a read of that batch or job does: the files a read lists never depend on which other read came before it
|
|
92
|
-
|
|
92
|
+
// time's moves and a key's recorded use are OpenAI's own, not the caller's: they land under a read-only request
|
|
93
|
+
// too (runAsVendorMove)
|
|
94
|
+
const catchUp = (request) => runAsVendorMove(async () => {
|
|
93
95
|
const ctx = await semanticsContext(manifest, new Request(request.url), filesClock, scope);
|
|
94
96
|
await expireFiles(ctx);
|
|
95
97
|
if (request.method === 'GET' && /^\/v1\/files(\/|$)/.test(new URL(request.url).pathname))
|
|
96
98
|
for (const observe of [observeBatches, observeJobs])
|
|
97
99
|
await observe(ctx);
|
|
98
|
-
};
|
|
99
|
-
|
|
100
|
+
});
|
|
101
|
+
// a read-only request (x-volter-read-only) writes nothing, answered with OpenAI's read-only error
|
|
102
|
+
return derivedRequestScopes(manifest, Object.assign(async (request) => {
|
|
100
103
|
const opened = door(request);
|
|
101
104
|
if (opened)
|
|
102
105
|
return opened;
|
|
103
106
|
if (!readOnly)
|
|
104
107
|
await catchUp(request);
|
|
105
108
|
if (!readOnly) {
|
|
106
|
-
const refused = await useKey(request);
|
|
109
|
+
const refused = await runAsVendorMove(() => useKey(request));
|
|
107
110
|
if (refused)
|
|
108
111
|
return refused;
|
|
109
112
|
}
|
|
@@ -114,7 +117,7 @@ export function createOpenAITwinFetch(options) {
|
|
|
114
117
|
return page;
|
|
115
118
|
}
|
|
116
119
|
return handle(request);
|
|
117
|
-
}, { owners: inner.owners });
|
|
120
|
+
}, { owners: inner.owners }));
|
|
118
121
|
}
|
|
119
122
|
export async function createOpenAITwinServer(options) {
|
|
120
123
|
const server = await serveHttp({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@volter/twin-openai",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.3",
|
|
4
4
|
"description": "Local OpenAI twin — a faithful, stateful local OpenAI API your real `openai` SDK talks to unmodified. The model is stubbed (deterministic) and embeddings are deterministic pseudo-vectors, but the protocol envelope (chat completions/streaming/tool_calls, the Responses API, embeddings, models, files, batches, moderations, fine-tuning, vector stores) is vendor-faithful. Built on @volter/world-core.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"twin",
|
|
@@ -54,10 +54,10 @@
|
|
|
54
54
|
"postpack": "node ../../../scripts/publish/prepare-publish.mjs postpack"
|
|
55
55
|
},
|
|
56
56
|
"peerDependencies": {
|
|
57
|
-
"@volter/world-core": "2.0.
|
|
57
|
+
"@volter/world-core": "2.0.3"
|
|
58
58
|
},
|
|
59
59
|
"devDependencies": {
|
|
60
|
-
"@volter/world-core": "2.0.
|
|
60
|
+
"@volter/world-core": "2.0.3",
|
|
61
61
|
"@volter/world-tooling": "0.1.0",
|
|
62
62
|
"openai": "^4.104.0",
|
|
63
63
|
"@types/bun": "^1.2.20",
|
|
@@ -68,6 +68,6 @@
|
|
|
68
68
|
"node": ">=22.3"
|
|
69
69
|
},
|
|
70
70
|
"dependencies": {
|
|
71
|
-
"@volter/world-ui": "0.1.
|
|
71
|
+
"@volter/world-ui": "0.1.3"
|
|
72
72
|
}
|
|
73
73
|
}
|
package/src/openai-server.ts
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
// The surface is a plain `fetch` (`createOpenAITwinFetch`) and the SERVER is one line of
|
|
11
11
|
// `Bun.serve` around it — see that factory's docstring for why (a serverless entry has no
|
|
12
12
|
// port to bind, so it mounts the fetch in-process).
|
|
13
|
-
import { bindSemantics, coreFor, createDerivedFetch, crossCutting, semanticsContext, serveHttp, vendorError } from '@volter/world-core';
|
|
13
|
+
import { bindSemantics, coreFor, createDerivedFetch, crossCutting, derivedRequestScopes, runAsVendorMove, semanticsContext, serveHttp, vendorError } from '@volter/world-core';
|
|
14
14
|
import surface from './generated/surface.gen.json' with { type: 'json' };
|
|
15
15
|
import { manifest } from './manifest.ts';
|
|
16
16
|
import { openaiSemantics } from './semantics/index.ts';
|
|
@@ -99,19 +99,22 @@ export function createOpenAITwinFetch(options: OpenAITwinFetchOptions): (request
|
|
|
99
99
|
const useKey = projectKeyUse(scope);
|
|
100
100
|
// and a read of the files observes the work whose outputs are files (a batch's output, a fine-tuning job's results)
|
|
101
101
|
// first, as a read of that batch or job does: the files a read lists never depend on which other read came before it
|
|
102
|
-
|
|
102
|
+
// time's moves and a key's recorded use are OpenAI's own, not the caller's: they land under a read-only request
|
|
103
|
+
// too (runAsVendorMove)
|
|
104
|
+
const catchUp = (request: Request): Promise<void> => runAsVendorMove(async () => {
|
|
103
105
|
const ctx = await semanticsContext(manifest, new Request(request.url), filesClock, scope);
|
|
104
106
|
await expireFiles(ctx);
|
|
105
107
|
if (request.method === 'GET' && /^\/v1\/files(\/|$)/.test(new URL(request.url).pathname)) for (const observe of [observeBatches, observeJobs]) await observe(ctx);
|
|
106
|
-
};
|
|
107
|
-
|
|
108
|
+
});
|
|
109
|
+
// a read-only request (x-volter-read-only) writes nothing, answered with OpenAI's read-only error
|
|
110
|
+
return derivedRequestScopes(manifest, Object.assign(async (request: Request): Promise<Response> => {
|
|
108
111
|
const opened = door(request);
|
|
109
112
|
if (opened) return opened;
|
|
110
113
|
if (!readOnly) await catchUp(request);
|
|
111
|
-
if (!readOnly) { const refused = await useKey(request); if (refused) return refused; }
|
|
114
|
+
if (!readOnly) { const refused = await runAsVendorMove(() => useKey(request)); if (refused) return refused; }
|
|
112
115
|
if (!readOnly) for (const screen of screens) { const page = await screen(request); if (page) return page; }
|
|
113
116
|
return handle(request);
|
|
114
|
-
}, { owners: inner.owners });
|
|
117
|
+
}, { owners: inner.owners }));
|
|
115
118
|
}
|
|
116
119
|
|
|
117
120
|
export async function createOpenAITwinServer(options: { root?: string; port?: number; readOnly?: boolean; scenarioPath?: string }): Promise<{ port: number; stop: () => void }> {
|