@skydiveai/pi-server 0.1.0-beta.267 → 0.1.0-beta.445

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/dist/index.mjs +89 -0
  2. package/package.json +1 -1
package/dist/index.mjs CHANGED
@@ -1379,6 +1379,51 @@ function create$2(options) {
1379
1379
  };
1380
1380
  }
1381
1381
  //#endregion
1382
+ //#region src/billing-blocked-provider-signal.ts
1383
+ const BILLING_BLOCKED_PROVIDER_SIGNAL_PREFIX = "ANYONE_BILLING_BLOCKED_V1:";
1384
+ const payloadSchema = z.object({
1385
+ blockReason: z.literal("insufficient_balance"),
1386
+ message: z.string()
1387
+ }).strict();
1388
+ const nestedProxyEnvelopeSchema = z.object({
1389
+ error: z.object({
1390
+ type: z.literal("billing_blocked"),
1391
+ code: z.literal("billing_blocked"),
1392
+ message: z.string()
1393
+ }).strict(),
1394
+ blockReason: z.literal("insufficient_balance"),
1395
+ message: z.string()
1396
+ }).strict();
1397
+ function parsePrefixedSignal(message) {
1398
+ const normalized = message.startsWith("402 ") ? message.slice(4) : message;
1399
+ if (!normalized.startsWith(BILLING_BLOCKED_PROVIDER_SIGNAL_PREFIX)) return null;
1400
+ try {
1401
+ const parsed = payloadSchema.safeParse(JSON.parse(normalized.slice(26)));
1402
+ return parsed.success ? parsed.data : null;
1403
+ } catch {
1404
+ return null;
1405
+ }
1406
+ }
1407
+ /**
1408
+ * Decode only the versioned platform envelope. Anthropic and OpenAI prefix the
1409
+ * nested error message with HTTP 402. Google's SDK instead preserves the full
1410
+ * proxy response as JSON, so that outer shape is validated separately.
1411
+ */
1412
+ function parseBillingBlockedProviderSignal(message) {
1413
+ const direct = parsePrefixedSignal(message);
1414
+ if (direct) return direct;
1415
+ try {
1416
+ const envelope = nestedProxyEnvelopeSchema.safeParse(JSON.parse(message));
1417
+ if (!envelope.success) return null;
1418
+ const nested = parsePrefixedSignal(envelope.data.error.message);
1419
+ const topLevel = parsePrefixedSignal(envelope.data.message);
1420
+ if (!nested || nested.blockReason !== envelope.data.blockReason || envelope.data.message !== nested.message && (!topLevel || topLevel.blockReason !== nested.blockReason || topLevel.message !== nested.message)) return null;
1421
+ return nested;
1422
+ } catch {
1423
+ return null;
1424
+ }
1425
+ }
1426
+ //#endregion
1382
1427
  //#region src/protocols/chat-completions.ts
1383
1428
  /**
1384
1429
  * OpenAI Chat Completions–compatible protocol handler.
@@ -1922,6 +1967,22 @@ function runStream$1({ session, sm, prompt, images, sessionId, created, reqStart
1922
1967
  postPrompt
1923
1968
  });
1924
1969
  if (capturedModelError !== null) {
1970
+ const billingBlocked = parseBillingBlockedProviderSignal(capturedModelError);
1971
+ if (billingBlocked) {
1972
+ log.warn({
1973
+ event: "billing_blocked",
1974
+ chatcmpl_id: sessionId,
1975
+ source: "stop_reason_error"
1976
+ }, "forwarding platform billing block to client");
1977
+ emitBillingBlocked({
1978
+ writer,
1979
+ sessionId,
1980
+ created,
1981
+ billingBlocked
1982
+ });
1983
+ writer.write("data: [DONE]\n\n");
1984
+ return;
1985
+ }
1925
1986
  const providerError = toModelProviderError(new Error(capturedModelError));
1926
1987
  log.warn({
1927
1988
  event: "model_provider_error",
@@ -1957,6 +2018,17 @@ function runStream$1({ session, sm, prompt, images, sessionId, created, reqStart
1957
2018
  err
1958
2019
  }, "chat error");
1959
2020
  if (isModelProviderError(err)) {
2021
+ const billingBlocked = parseBillingBlockedProviderSignal(err instanceof Error ? err.message : String(err));
2022
+ if (billingBlocked) {
2023
+ emitBillingBlocked({
2024
+ writer,
2025
+ sessionId,
2026
+ created,
2027
+ billingBlocked
2028
+ });
2029
+ writer.write("data: [DONE]\n\n");
2030
+ return;
2031
+ }
1960
2032
  const providerError = toModelProviderError(err);
1961
2033
  log.warn({
1962
2034
  event: "model_provider_error",
@@ -2030,6 +2102,23 @@ function emitModelProviderError({ writer, sessionId, created, providerError }) {
2030
2102
  };
2031
2103
  writer.write(`data: ${JSON.stringify(chunk)}\n\n`);
2032
2104
  }
2105
+ function emitBillingBlocked({ writer, sessionId, created, billingBlocked }) {
2106
+ const chunk = {
2107
+ id: sessionId,
2108
+ object: "chat.completion.chunk",
2109
+ created,
2110
+ choices: [{
2111
+ index: 0,
2112
+ delta: {},
2113
+ finish_reason: "stop"
2114
+ }],
2115
+ x_billing_blocked: {
2116
+ block_reason: billingBlocked.blockReason,
2117
+ message: billingBlocked.message
2118
+ }
2119
+ };
2120
+ writer.write(`data: ${JSON.stringify(chunk)}\n\n`);
2121
+ }
2033
2122
  async function runBlocking$1({ session, sm, prompt, images, sessionId, created, reqStart, upstreamStartMs, log, postPrompt, registry, pendingSteerIds }) {
2034
2123
  const baselineMessageCount = sm.buildSessionContext().messages.length;
2035
2124
  let content = "";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@skydiveai/pi-server",
3
- "version": "0.1.0-beta.267",
3
+ "version": "0.1.0-beta.445",
4
4
  "homepage": "https://skydive.com",
5
5
  "license": "MIT",
6
6
  "author": "Create, Inc.",