@t54-labs/clawcredit-blockrun-sdk 0.1.2 → 0.1.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.
@@ -108,6 +108,34 @@ function createClawCreditFetch(config) {
108
108
 
109
109
  // src/server.ts
110
110
  import { createServer } from "http";
111
+ import { appendFileSync, mkdirSync } from "fs";
112
+ import { dirname } from "path";
113
+ import { randomUUID } from "crypto";
114
+ var VALID_ROLES = /* @__PURE__ */ new Set(["system", "user", "assistant", "tool", "function"]);
115
+ var ROLE_MAPPINGS = {
116
+ developer: "system",
117
+ model: "assistant"
118
+ };
119
+ function normalizeMessageRoles(messages) {
120
+ if (messages.length === 0) return messages;
121
+ let hasChanges = false;
122
+ const normalized = messages.map((msg) => {
123
+ const role = msg.role;
124
+ if (typeof role !== "string") {
125
+ hasChanges = true;
126
+ return { ...msg, role: "user" };
127
+ }
128
+ if (VALID_ROLES.has(role)) return msg;
129
+ const mappedRole = ROLE_MAPPINGS[role];
130
+ if (mappedRole) {
131
+ hasChanges = true;
132
+ return { ...msg, role: mappedRole };
133
+ }
134
+ hasChanges = true;
135
+ return { ...msg, role: "user" };
136
+ });
137
+ return hasChanges ? normalized : messages;
138
+ }
111
139
  function readBody(req) {
112
140
  return new Promise((resolve, reject) => {
113
141
  const chunks = [];
@@ -136,17 +164,51 @@ function normalizePayloadForGateway(body) {
136
164
  try {
137
165
  const parsed = JSON.parse(body.toString("utf-8"));
138
166
  if (parsed.stream === true) parsed.stream = false;
167
+ if (Array.isArray(parsed.messages)) {
168
+ parsed.messages = normalizeMessageRoles(parsed.messages);
169
+ }
139
170
  return Buffer.from(JSON.stringify(parsed));
140
171
  } catch {
141
172
  return body;
142
173
  }
143
174
  }
175
+ function parseJsonIfPossible(text) {
176
+ try {
177
+ return JSON.parse(text);
178
+ } catch {
179
+ return text;
180
+ }
181
+ }
182
+ function safeHeadersObject(headers) {
183
+ const out = {};
184
+ headers.forEach((value, key) => {
185
+ out[key] = value;
186
+ });
187
+ return out;
188
+ }
189
+ function createCaptureWriter() {
190
+ const enabled = process.env.GATEWAY_CAPTURE === "1" || process.env.GATEWAY_CAPTURE === "true";
191
+ const file = (process.env.GATEWAY_CAPTURE_FILE || "/tmp/clawcredit-blockrun-gateway/.run/capture.jsonl").trim();
192
+ if (!enabled) {
193
+ return (_entry) => {
194
+ };
195
+ }
196
+ mkdirSync(dirname(file), { recursive: true });
197
+ return (entry) => {
198
+ try {
199
+ appendFileSync(file, `${JSON.stringify(entry)}
200
+ `, "utf-8");
201
+ } catch {
202
+ }
203
+ };
204
+ }
144
205
  async function startGateway(options) {
145
206
  const host = options.host ?? "127.0.0.1";
146
207
  const port = options.port ?? 3402;
147
208
  const apiBase = (options.blockrunApiBase ?? "https://blockrun.ai/api").replace(/\/+$/, "");
148
209
  const defaultAmountUsd = Number.isFinite(options.defaultAmountUsd) ? Number(options.defaultAmountUsd) : 0.1;
149
210
  const payFetch = createClawCreditFetch(options.clawCredit);
211
+ const writeCapture = createCaptureWriter();
150
212
  const server = createServer(async (req, res) => {
151
213
  if (req.url === "/health") {
152
214
  return sendJson(res, 200, {
@@ -159,8 +221,11 @@ async function startGateway(options) {
159
221
  return sendJson(res, 404, { error: "Not found" });
160
222
  }
161
223
  try {
224
+ const requestId = randomUUID();
225
+ const startedAt = Date.now();
162
226
  const body = await readBody(req);
163
227
  const normalized = normalizePayloadForGateway(body);
228
+ const normalizedText = normalized.toString("utf-8");
164
229
  const maxTokens = extractMaxTokens(normalized);
165
230
  const estimatedMicros = String(
166
231
  Math.max(1e4, Math.round(defaultAmountUsd * 1e6 + maxTokens * 8))
@@ -176,6 +241,20 @@ async function startGateway(options) {
176
241
  if (!headers.has("content-type")) {
177
242
  headers.set("content-type", "application/json");
178
243
  }
244
+ writeCapture({
245
+ kind: "request",
246
+ requestId,
247
+ at: (/* @__PURE__ */ new Date()).toISOString(),
248
+ source: {
249
+ userAgent: req.headers["user-agent"] || null,
250
+ xOpenClawSession: req.headers["x-openclaw-session-id"] || null
251
+ },
252
+ method: "POST",
253
+ target: upstreamUrl,
254
+ estimatedMicros,
255
+ headers: safeHeadersObject(headers),
256
+ body: parseJsonIfPossible(normalizedText)
257
+ });
179
258
  const upstream = await payFetch(
180
259
  upstreamUrl,
181
260
  {
@@ -186,12 +265,26 @@ async function startGateway(options) {
186
265
  { estimatedAmount: estimatedMicros }
187
266
  );
188
267
  const responseBody = await upstream.text();
268
+ writeCapture({
269
+ kind: "response",
270
+ requestId,
271
+ at: (/* @__PURE__ */ new Date()).toISOString(),
272
+ durationMs: Date.now() - startedAt,
273
+ status: upstream.status,
274
+ headers: safeHeadersObject(upstream.headers),
275
+ body: parseJsonIfPossible(responseBody)
276
+ });
189
277
  res.writeHead(upstream.status, {
190
278
  "content-type": upstream.headers.get("content-type") || "application/json"
191
279
  });
192
280
  res.end(responseBody);
193
281
  } catch (err) {
194
282
  const msg = err instanceof Error ? err.message : String(err);
283
+ writeCapture({
284
+ kind: "error",
285
+ at: (/* @__PURE__ */ new Date()).toISOString(),
286
+ message: msg
287
+ });
195
288
  sendJson(res, 502, { error: msg });
196
289
  }
197
290
  });
@@ -214,4 +307,4 @@ export {
214
307
  createClawCreditFetch,
215
308
  startGateway
216
309
  };
217
- //# sourceMappingURL=chunk-K57GMQDY.js.map
310
+ //# sourceMappingURL=chunk-VFHQPROQ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/clawcredit.ts","../src/server.ts"],"sourcesContent":["import { ClawCredit, withTrace } from \"@t54-labs/clawcredit-sdk\";\n\nconst DEFAULT_SERVICE_URL = \"https://api.claw.credit\";\n\nexport type ClawCreditConfig = {\n baseUrl?: string;\n apiToken: string;\n chain: string;\n asset: string;\n agent?: string;\n agentId?: string;\n};\n\nexport type PreAuthParams = {\n estimatedAmount: string;\n};\n\ntype SdkClient = {\n pay: (args: {\n transaction: {\n recipient: string;\n amount: number;\n chain: string;\n asset: string;\n amount_unit?: \"human\" | \"atomic\";\n };\n request_body: Record<string, unknown>;\n context?: {\n reasoning_process?: string;\n current_task?: string;\n };\n idempotencyKey?: string;\n }) => Promise<{ merchant_response?: unknown }>;\n};\n\nfunction headersToObject(headersInit?: HeadersInit): Record<string, string> {\n if (!headersInit) return {};\n const headers = new Headers(headersInit);\n const out: Record<string, string> = {};\n headers.forEach((value, key) => {\n const lower = key.toLowerCase();\n if (lower === \"host\" || lower === \"content-length\" || lower === \"connection\") return;\n out[key] = value;\n });\n return out;\n}\n\nfunction parseJsonBody(body: RequestInit[\"body\"]): unknown {\n if (body == null) return undefined;\n\n let raw = \"\";\n if (typeof body === \"string\") {\n raw = body;\n } else if (body instanceof Uint8Array) {\n raw = Buffer.from(body).toString(\"utf-8\");\n } else if (body instanceof ArrayBuffer) {\n raw = Buffer.from(body).toString(\"utf-8\");\n } else {\n return undefined;\n }\n\n if (!raw.trim()) return undefined;\n try {\n return JSON.parse(raw);\n } catch {\n return undefined;\n }\n}\n\nfunction microsToUsd(estimatedAmount?: string): number {\n const micros = Number(estimatedAmount ?? \"\");\n if (!Number.isFinite(micros) || micros <= 0) return 0.01;\n return Number((micros / 1_000_000).toFixed(6));\n}\n\nfunction inferStatusCode(err: unknown): number {\n const msg = err instanceof Error ? err.message : String(err);\n const match = msg.match(/ClawCredit API Error:\\s*(\\d{3})\\s*-/i);\n if (match) return parseInt(match[1], 10);\n if (/payment required/i.test(msg)) return 402;\n if (/prequalification_pending/i.test(msg)) return 403;\n if (/unauthorized/i.test(msg)) return 401;\n return 502;\n}\n\nexport function createClawCreditFetch(config: ClawCreditConfig) {\n const serviceUrl = (config.baseUrl || DEFAULT_SERVICE_URL).replace(/\\/+$/, \"\");\n const chain = config.chain.toUpperCase();\n const asset = config.asset;\n const apiToken = config.apiToken.trim();\n\n if (!apiToken) {\n throw new Error(\"CLAWCREDIT_API_TOKEN is required for claw.credit payment mode\");\n }\n\n const credit = new ClawCredit({\n serviceUrl,\n apiToken,\n agent: config.agent,\n agentId: config.agentId,\n }) as SdkClient;\n\n return async (\n input: RequestInfo | URL,\n init?: RequestInit,\n preAuth?: PreAuthParams,\n ): Promise<Response> => {\n const upstreamUrl =\n typeof input === \"string\" ? input : input instanceof URL ? input.href : input.url;\n const method = (init?.method || \"POST\").toUpperCase();\n const headers = headersToObject(init?.headers);\n const idempotencyKey = new Headers(init?.headers).get(\"idempotency-key\") || undefined;\n const requestBody = parseJsonBody(init?.body);\n const amountUsd = microsToUsd(preAuth?.estimatedAmount);\n\n try {\n const result = await withTrace(async () =>\n credit.pay({\n transaction: {\n recipient: upstreamUrl,\n amount: amountUsd,\n chain,\n asset,\n },\n request_body: {\n http: {\n url: upstreamUrl,\n method,\n headers,\n },\n body: requestBody,\n },\n context: {\n current_task: \"blockrun_inference_via_clawcredit_blockrun_gateway\",\n reasoning_process: \"Pay BlockRun inference through claw.credit SDK\",\n },\n idempotencyKey,\n }),\n );\n\n const merchantResponse =\n result && typeof result === \"object\" && \"merchant_response\" in result\n ? (result as { merchant_response?: unknown }).merchant_response\n : result;\n\n return new Response(JSON.stringify(merchantResponse ?? {}), {\n status: 200,\n headers: { \"content-type\": \"application/json\" },\n });\n } catch (err) {\n const status = inferStatusCode(err);\n const message = err instanceof Error ? err.message : String(err);\n return new Response(JSON.stringify({ error: message }), {\n status,\n headers: { \"content-type\": \"application/json\" },\n });\n }\n };\n}\n","import { createServer, type IncomingMessage, type ServerResponse } from \"node:http\";\nimport type { AddressInfo } from \"node:net\";\nimport { appendFileSync, mkdirSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\nimport { randomUUID } from \"node:crypto\";\nimport { createClawCreditFetch, type ClawCreditConfig } from \"./clawcredit.js\";\n\nexport type GatewayOptions = {\n port?: number;\n host?: string;\n blockrunApiBase?: string;\n clawCredit: ClawCreditConfig;\n defaultAmountUsd?: number;\n};\n\nexport type GatewayInstance = {\n port: number;\n baseUrl: string;\n close: () => Promise<void>;\n};\n\ntype CompletionRequest = {\n model?: string;\n stream?: boolean;\n max_tokens?: number;\n messages?: Array<Record<string, unknown>>;\n};\n\nconst VALID_ROLES = new Set([\"system\", \"user\", \"assistant\", \"tool\", \"function\"]);\nconst ROLE_MAPPINGS: Record<string, string> = {\n developer: \"system\",\n model: \"assistant\",\n};\n\nfunction normalizeMessageRoles(messages: Array<Record<string, unknown>>): Array<Record<string, unknown>> {\n if (messages.length === 0) return messages;\n\n let hasChanges = false;\n const normalized = messages.map((msg) => {\n const role = msg.role;\n if (typeof role !== \"string\") {\n hasChanges = true;\n return { ...msg, role: \"user\" };\n }\n if (VALID_ROLES.has(role)) return msg;\n\n const mappedRole = ROLE_MAPPINGS[role];\n if (mappedRole) {\n hasChanges = true;\n return { ...msg, role: mappedRole };\n }\n\n hasChanges = true;\n return { ...msg, role: \"user\" };\n });\n\n return hasChanges ? normalized : messages;\n}\n\nfunction readBody(req: IncomingMessage): Promise<Buffer> {\n return new Promise((resolve, reject) => {\n const chunks: Buffer[] = [];\n req.on(\"data\", (chunk) => chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)));\n req.on(\"end\", () => resolve(Buffer.concat(chunks)));\n req.on(\"error\", reject);\n });\n}\n\nfunction sendJson(res: ServerResponse, status: number, payload: unknown): void {\n const text = JSON.stringify(payload);\n res.writeHead(status, {\n \"content-type\": \"application/json\",\n \"content-length\": Buffer.byteLength(text).toString(),\n });\n res.end(text);\n}\n\nfunction extractMaxTokens(body: Buffer): number {\n try {\n const parsed = JSON.parse(body.toString(\"utf-8\")) as CompletionRequest;\n return parsed.max_tokens && Number.isFinite(parsed.max_tokens) ? parsed.max_tokens : 512;\n } catch {\n return 512;\n }\n}\n\nfunction normalizePayloadForGateway(body: Buffer): Buffer {\n try {\n const parsed = JSON.parse(body.toString(\"utf-8\")) as CompletionRequest;\n if (parsed.stream === true) parsed.stream = false;\n if (Array.isArray(parsed.messages)) {\n parsed.messages = normalizeMessageRoles(parsed.messages);\n }\n return Buffer.from(JSON.stringify(parsed));\n } catch {\n return body;\n }\n}\n\nfunction parseJsonIfPossible(text: string): unknown {\n try {\n return JSON.parse(text);\n } catch {\n return text;\n }\n}\n\nfunction safeHeadersObject(headers: Headers): Record<string, string> {\n const out: Record<string, string> = {};\n headers.forEach((value, key) => {\n out[key] = value;\n });\n return out;\n}\n\nfunction createCaptureWriter() {\n const enabled =\n process.env.GATEWAY_CAPTURE === \"1\" || process.env.GATEWAY_CAPTURE === \"true\";\n const file =\n (process.env.GATEWAY_CAPTURE_FILE || \"/tmp/clawcredit-blockrun-gateway/.run/capture.jsonl\").trim();\n\n if (!enabled) {\n return (_entry: unknown) => {};\n }\n\n mkdirSync(dirname(file), { recursive: true });\n return (entry: unknown) => {\n try {\n appendFileSync(file, `${JSON.stringify(entry)}\\n`, \"utf-8\");\n } catch {\n // Best-effort debug capture only.\n }\n };\n}\n\nexport async function startGateway(options: GatewayOptions): Promise<GatewayInstance> {\n const host = options.host ?? \"127.0.0.1\";\n const port = options.port ?? 3402;\n const apiBase = (options.blockrunApiBase ?? \"https://blockrun.ai/api\").replace(/\\/+$/, \"\");\n const defaultAmountUsd = Number.isFinite(options.defaultAmountUsd)\n ? Number(options.defaultAmountUsd)\n : 0.1;\n const payFetch = createClawCreditFetch(options.clawCredit);\n const writeCapture = createCaptureWriter();\n\n const server = createServer(async (req, res) => {\n if (req.url === \"/health\") {\n return sendJson(res, 200, {\n status: \"ok\",\n service: \"clawcredit-blockrun-gateway\",\n payment_mode: \"clawcredit\",\n });\n }\n\n if (req.url !== \"/v1/chat/completions\" || req.method !== \"POST\") {\n return sendJson(res, 404, { error: \"Not found\" });\n }\n\n try {\n const requestId = randomUUID();\n const startedAt = Date.now();\n const body = await readBody(req);\n const normalized = normalizePayloadForGateway(body);\n const normalizedText = normalized.toString(\"utf-8\");\n const maxTokens = extractMaxTokens(normalized);\n\n const estimatedMicros = String(\n Math.max(10_000, Math.round(defaultAmountUsd * 1_000_000 + maxTokens * 8)),\n );\n\n const upstreamUrl = `${apiBase}/v1/chat/completions`;\n\n const headers = new Headers();\n for (const [key, value] of Object.entries(req.headers)) {\n if (typeof value !== \"string\") continue;\n const lower = key.toLowerCase();\n if (lower === \"host\" || lower === \"content-length\" || lower === \"connection\") continue;\n headers.set(key, value);\n }\n if (!headers.has(\"content-type\")) {\n headers.set(\"content-type\", \"application/json\");\n }\n\n writeCapture({\n kind: \"request\",\n requestId,\n at: new Date().toISOString(),\n source: {\n userAgent: req.headers[\"user-agent\"] || null,\n xOpenClawSession: req.headers[\"x-openclaw-session-id\"] || null,\n },\n method: \"POST\",\n target: upstreamUrl,\n estimatedMicros,\n headers: safeHeadersObject(headers),\n body: parseJsonIfPossible(normalizedText),\n });\n\n const upstream = await payFetch(\n upstreamUrl,\n {\n method: \"POST\",\n headers,\n body: new Uint8Array(normalized),\n },\n { estimatedAmount: estimatedMicros },\n );\n\n const responseBody = await upstream.text();\n writeCapture({\n kind: \"response\",\n requestId,\n at: new Date().toISOString(),\n durationMs: Date.now() - startedAt,\n status: upstream.status,\n headers: safeHeadersObject(upstream.headers),\n body: parseJsonIfPossible(responseBody),\n });\n res.writeHead(upstream.status, {\n \"content-type\": upstream.headers.get(\"content-type\") || \"application/json\",\n });\n res.end(responseBody);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n writeCapture({\n kind: \"error\",\n at: new Date().toISOString(),\n message: msg,\n });\n sendJson(res, 502, { error: msg });\n }\n });\n\n await new Promise<void>((resolve, reject) => {\n server.once(\"error\", reject);\n server.listen(port, host, () => {\n server.removeListener(\"error\", reject);\n resolve();\n });\n });\n\n const actualPort = (server.address() as AddressInfo).port;\n return {\n port: actualPort,\n baseUrl: `http://${host}:${actualPort}`,\n close: () => new Promise<void>((resolve, reject) => server.close((err) => (err ? reject(err) : resolve()))),\n };\n}\n"],"mappings":"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","names":[]}
package/dist/cli.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  startGateway
4
- } from "./chunk-K57GMQDY.js";
4
+ } from "./chunk-VFHQPROQ.js";
5
5
 
6
6
  // src/cli.ts
7
7
  var DEFAULT_ASSET = "USDC";
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  createClawCreditFetch,
3
3
  startGateway
4
- } from "./chunk-K57GMQDY.js";
4
+ } from "./chunk-VFHQPROQ.js";
5
5
  export {
6
6
  createClawCreditFetch,
7
7
  startGateway
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@t54-labs/clawcredit-blockrun-sdk",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "SDK and standalone OpenAI-compatible gateway for BlockRun inference paid via claw.credit",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/clawcredit.ts","../src/server.ts"],"sourcesContent":["import { ClawCredit, withTrace } from \"@t54-labs/clawcredit-sdk\";\n\nconst DEFAULT_SERVICE_URL = \"https://api.claw.credit\";\n\nexport type ClawCreditConfig = {\n baseUrl?: string;\n apiToken: string;\n chain: string;\n asset: string;\n agent?: string;\n agentId?: string;\n};\n\nexport type PreAuthParams = {\n estimatedAmount: string;\n};\n\ntype SdkClient = {\n pay: (args: {\n transaction: {\n recipient: string;\n amount: number;\n chain: string;\n asset: string;\n amount_unit?: \"human\" | \"atomic\";\n };\n request_body: Record<string, unknown>;\n context?: {\n reasoning_process?: string;\n current_task?: string;\n };\n idempotencyKey?: string;\n }) => Promise<{ merchant_response?: unknown }>;\n};\n\nfunction headersToObject(headersInit?: HeadersInit): Record<string, string> {\n if (!headersInit) return {};\n const headers = new Headers(headersInit);\n const out: Record<string, string> = {};\n headers.forEach((value, key) => {\n const lower = key.toLowerCase();\n if (lower === \"host\" || lower === \"content-length\" || lower === \"connection\") return;\n out[key] = value;\n });\n return out;\n}\n\nfunction parseJsonBody(body: RequestInit[\"body\"]): unknown {\n if (body == null) return undefined;\n\n let raw = \"\";\n if (typeof body === \"string\") {\n raw = body;\n } else if (body instanceof Uint8Array) {\n raw = Buffer.from(body).toString(\"utf-8\");\n } else if (body instanceof ArrayBuffer) {\n raw = Buffer.from(body).toString(\"utf-8\");\n } else {\n return undefined;\n }\n\n if (!raw.trim()) return undefined;\n try {\n return JSON.parse(raw);\n } catch {\n return undefined;\n }\n}\n\nfunction microsToUsd(estimatedAmount?: string): number {\n const micros = Number(estimatedAmount ?? \"\");\n if (!Number.isFinite(micros) || micros <= 0) return 0.01;\n return Number((micros / 1_000_000).toFixed(6));\n}\n\nfunction inferStatusCode(err: unknown): number {\n const msg = err instanceof Error ? err.message : String(err);\n const match = msg.match(/ClawCredit API Error:\\s*(\\d{3})\\s*-/i);\n if (match) return parseInt(match[1], 10);\n if (/payment required/i.test(msg)) return 402;\n if (/prequalification_pending/i.test(msg)) return 403;\n if (/unauthorized/i.test(msg)) return 401;\n return 502;\n}\n\nexport function createClawCreditFetch(config: ClawCreditConfig) {\n const serviceUrl = (config.baseUrl || DEFAULT_SERVICE_URL).replace(/\\/+$/, \"\");\n const chain = config.chain.toUpperCase();\n const asset = config.asset;\n const apiToken = config.apiToken.trim();\n\n if (!apiToken) {\n throw new Error(\"CLAWCREDIT_API_TOKEN is required for claw.credit payment mode\");\n }\n\n const credit = new ClawCredit({\n serviceUrl,\n apiToken,\n agent: config.agent,\n agentId: config.agentId,\n }) as SdkClient;\n\n return async (\n input: RequestInfo | URL,\n init?: RequestInit,\n preAuth?: PreAuthParams,\n ): Promise<Response> => {\n const upstreamUrl =\n typeof input === \"string\" ? input : input instanceof URL ? input.href : input.url;\n const method = (init?.method || \"POST\").toUpperCase();\n const headers = headersToObject(init?.headers);\n const idempotencyKey = new Headers(init?.headers).get(\"idempotency-key\") || undefined;\n const requestBody = parseJsonBody(init?.body);\n const amountUsd = microsToUsd(preAuth?.estimatedAmount);\n\n try {\n const result = await withTrace(async () =>\n credit.pay({\n transaction: {\n recipient: upstreamUrl,\n amount: amountUsd,\n chain,\n asset,\n },\n request_body: {\n http: {\n url: upstreamUrl,\n method,\n headers,\n },\n body: requestBody,\n },\n context: {\n current_task: \"blockrun_inference_via_clawcredit_blockrun_gateway\",\n reasoning_process: \"Pay BlockRun inference through claw.credit SDK\",\n },\n idempotencyKey,\n }),\n );\n\n const merchantResponse =\n result && typeof result === \"object\" && \"merchant_response\" in result\n ? (result as { merchant_response?: unknown }).merchant_response\n : result;\n\n return new Response(JSON.stringify(merchantResponse ?? {}), {\n status: 200,\n headers: { \"content-type\": \"application/json\" },\n });\n } catch (err) {\n const status = inferStatusCode(err);\n const message = err instanceof Error ? err.message : String(err);\n return new Response(JSON.stringify({ error: message }), {\n status,\n headers: { \"content-type\": \"application/json\" },\n });\n }\n };\n}\n","import { createServer, type IncomingMessage, type ServerResponse } from \"node:http\";\nimport type { AddressInfo } from \"node:net\";\nimport { createClawCreditFetch, type ClawCreditConfig } from \"./clawcredit.js\";\n\nexport type GatewayOptions = {\n port?: number;\n host?: string;\n blockrunApiBase?: string;\n clawCredit: ClawCreditConfig;\n defaultAmountUsd?: number;\n};\n\nexport type GatewayInstance = {\n port: number;\n baseUrl: string;\n close: () => Promise<void>;\n};\n\ntype CompletionRequest = {\n model?: string;\n stream?: boolean;\n max_tokens?: number;\n};\n\nfunction readBody(req: IncomingMessage): Promise<Buffer> {\n return new Promise((resolve, reject) => {\n const chunks: Buffer[] = [];\n req.on(\"data\", (chunk) => chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)));\n req.on(\"end\", () => resolve(Buffer.concat(chunks)));\n req.on(\"error\", reject);\n });\n}\n\nfunction sendJson(res: ServerResponse, status: number, payload: unknown): void {\n const text = JSON.stringify(payload);\n res.writeHead(status, {\n \"content-type\": \"application/json\",\n \"content-length\": Buffer.byteLength(text).toString(),\n });\n res.end(text);\n}\n\nfunction extractMaxTokens(body: Buffer): number {\n try {\n const parsed = JSON.parse(body.toString(\"utf-8\")) as CompletionRequest;\n return parsed.max_tokens && Number.isFinite(parsed.max_tokens) ? parsed.max_tokens : 512;\n } catch {\n return 512;\n }\n}\n\nfunction normalizePayloadForGateway(body: Buffer): Buffer {\n try {\n const parsed = JSON.parse(body.toString(\"utf-8\")) as CompletionRequest;\n if (parsed.stream === true) parsed.stream = false;\n return Buffer.from(JSON.stringify(parsed));\n } catch {\n return body;\n }\n}\n\nexport async function startGateway(options: GatewayOptions): Promise<GatewayInstance> {\n const host = options.host ?? \"127.0.0.1\";\n const port = options.port ?? 3402;\n const apiBase = (options.blockrunApiBase ?? \"https://blockrun.ai/api\").replace(/\\/+$/, \"\");\n const defaultAmountUsd = Number.isFinite(options.defaultAmountUsd)\n ? Number(options.defaultAmountUsd)\n : 0.1;\n const payFetch = createClawCreditFetch(options.clawCredit);\n\n const server = createServer(async (req, res) => {\n if (req.url === \"/health\") {\n return sendJson(res, 200, {\n status: \"ok\",\n service: \"clawcredit-blockrun-gateway\",\n payment_mode: \"clawcredit\",\n });\n }\n\n if (req.url !== \"/v1/chat/completions\" || req.method !== \"POST\") {\n return sendJson(res, 404, { error: \"Not found\" });\n }\n\n try {\n const body = await readBody(req);\n const normalized = normalizePayloadForGateway(body);\n const maxTokens = extractMaxTokens(normalized);\n\n const estimatedMicros = String(\n Math.max(10_000, Math.round(defaultAmountUsd * 1_000_000 + maxTokens * 8)),\n );\n\n const upstreamUrl = `${apiBase}/v1/chat/completions`;\n\n const headers = new Headers();\n for (const [key, value] of Object.entries(req.headers)) {\n if (typeof value !== \"string\") continue;\n const lower = key.toLowerCase();\n if (lower === \"host\" || lower === \"content-length\" || lower === \"connection\") continue;\n headers.set(key, value);\n }\n if (!headers.has(\"content-type\")) {\n headers.set(\"content-type\", \"application/json\");\n }\n\n const upstream = await payFetch(\n upstreamUrl,\n {\n method: \"POST\",\n headers,\n body: new Uint8Array(normalized),\n },\n { estimatedAmount: estimatedMicros },\n );\n\n const responseBody = await upstream.text();\n res.writeHead(upstream.status, {\n \"content-type\": upstream.headers.get(\"content-type\") || \"application/json\",\n });\n res.end(responseBody);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n sendJson(res, 502, { error: msg });\n }\n });\n\n await new Promise<void>((resolve, reject) => {\n server.once(\"error\", reject);\n server.listen(port, host, () => {\n server.removeListener(\"error\", reject);\n resolve();\n });\n });\n\n const actualPort = (server.address() as AddressInfo).port;\n return {\n port: actualPort,\n baseUrl: `http://${host}:${actualPort}`,\n close: () => new Promise<void>((resolve, reject) => server.close((err) => (err ? reject(err) : resolve()))),\n };\n}\n"],"mappings":"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","names":[]}