mtok-bridge 0.1.0 → 0.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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/bridge.mjs +26 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mtok-bridge",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Serve any model as an OpenAI-compatible API with a key. No payment, no market, runs anywhere node runs. The transport core behind mtok.market's seller relay.",
5
5
  "type": "module",
6
6
  "bin": {
package/src/bridge.mjs CHANGED
@@ -69,3 +69,29 @@ export function httpUpstream({ baseUrl, key }) {
69
69
  return json;
70
70
  };
71
71
  }
72
+
73
+ // The SECOND upstream mode (#566): a Cloudflare Workers AI binding instead of an HTTP endpoint.
74
+ // `ai` is the Worker's `env.AI` (has `.run(model, { messages, max_tokens })`). Returns the same
75
+ // upstream(payload) contract as httpUpstream, normalizing Workers AI's output (native `{ response,
76
+ // usage }` OR an already-OpenAI-shaped `{ choices, usage }`) into a standard chat.completion, so a
77
+ // caller reads one shape no matter which upstream it composed. Leaves `id`/`created` to the caller
78
+ // (the house seller keys its id to bookingId), and passes max_tokens through only when set.
79
+ export function workersAiUpstream(ai) {
80
+ return async (payload) => {
81
+ const out = await ai.run(payload.model, {
82
+ messages: payload.messages,
83
+ ...(payload.max_tokens != null ? { max_tokens: Math.max(1, Number(payload.max_tokens)) } : {}),
84
+ });
85
+ const content = out?.response ?? out?.choices?.[0]?.message?.content ?? '';
86
+ const usage = out?.usage || {};
87
+ return {
88
+ object: 'chat.completion',
89
+ model: payload.model,
90
+ choices: [{ index: 0, message: { role: 'assistant', content }, finish_reason: 'stop' }],
91
+ usage: {
92
+ prompt_tokens: Number(usage.prompt_tokens ?? usage.input_tokens ?? 0) || 0,
93
+ completion_tokens: Number(usage.completion_tokens ?? usage.output_tokens ?? 0) || 0,
94
+ },
95
+ };
96
+ };
97
+ }