@maxceem/agw 0.7.0 → 0.7.1

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/agw.mjs +56 -11
  2. package/package.json +13 -2
package/dist/agw.mjs CHANGED
@@ -6,7 +6,7 @@ var __export = (target, all) => {
6
6
  };
7
7
 
8
8
  // <define:__AGW_MANIFEST__>
9
- var define_AGW_MANIFEST_default = { version: "0.7.0", wrangler: "4.96.0", upgradeFrom: ["0.7.0", "0.6.4", "0.6.3", "0.6.2", "0.6.1", "0.6.0", "0.5.2", "0.5.1", "0.5.0", "0.4.0"], release: { url: "https://github.com/maxceem/app-ai-gateway/releases/download/v0.7.0/gateway-0.7.0.tar.gz", sha256: "9cbcb05a1b611470c03e522af7e34d786a4d7e9889b589bac7603695187575bd", manifest: "707e02868d2133307ff4d71a3fbcb7abe6d0b62cbc9498fab5b7d3f6d2d96fb0" } };
9
+ var define_AGW_MANIFEST_default = { version: "0.7.1", wrangler: "4.96.0", upgradeFrom: ["0.7.1", "0.7.0", "0.6.4", "0.6.3", "0.6.2", "0.6.1", "0.6.0", "0.5.2", "0.5.1", "0.5.0", "0.4.0"], release: { url: "https://github.com/maxceem/app-ai-gateway/releases/download/v0.7.1/gateway-0.7.1.tar.gz", sha256: "1b3ac4141c993b30bf1e90404dee7a21785a38b686c3f2562ec7b0c07fd4534d", manifest: "8455d531a2dc7df63af0fcbe1d8a181c3b6c74796e5f5a69cacf7890ca2dc42a" } };
10
10
 
11
11
  // src/main.ts
12
12
  import { Writable as Writable2 } from "node:stream";
@@ -14699,7 +14699,9 @@ var GATEWAY_DESCRIPTORS = {
14699
14699
  { key: "accountId", label: "Cloudflare Account ID" },
14700
14700
  { key: "gatewayId", label: "Cloudflare Gateway ID" }
14701
14701
  ],
14702
- routes: CF_AIG_ROUTES
14702
+ routes: CF_AIG_ROUTES,
14703
+ // A proxy in front of the provider's own API: the body is the provider's.
14704
+ relaysProviderResponses: true
14703
14705
  },
14704
14706
  vercel: {
14705
14707
  label: "Vercel AI Gateway",
@@ -14715,7 +14717,11 @@ var GATEWAY_DESCRIPTORS = {
14715
14717
  description: "Vercel's origin is fixed in adapter code, so it has no configuration of its own."
14716
14718
  }),
14717
14719
  connectionFields: [],
14718
- routes: VERCEL_ROUTES
14720
+ routes: VERCEL_ROUTES,
14721
+ // Vercel answers through its own client APIs, translating between them and
14722
+ // the serving provider's protocol, so a provider's own fields are not part
14723
+ // of the contract.
14724
+ relaysProviderResponses: false
14719
14725
  }
14720
14726
  };
14721
14727
  var GATEWAY_TYPES = Object.keys(GATEWAY_DESCRIPTORS);
@@ -14767,9 +14773,18 @@ function reportedByok(root, usage2) {
14767
14773
  return upstreamInferenceCost(usage2) !== null;
14768
14774
  }
14769
14775
  var OPENROUTER_COST_REPORT = {
14776
+ // Only chat completions carry `usage.cost`, which is why it is the only
14777
+ // style the provider type offers at all.
14778
+ styles: ["chat_completions"],
14770
14779
  // Which host actually served a request is opt-in per request; without this
14771
14780
  // header the response names no serving provider at all.
14772
14781
  requestHeaders: { "x-openrouter-metadata": "enabled" },
14782
+ // `credentialSource` is deliberately not required: it is a claim that is
14783
+ // simply absent on a non-BYOK request, so waiting for it would mean walking
14784
+ // every chunk of every stream. The response that carries it carries the cost
14785
+ // too.
14786
+ settled: (report) => report.costUsd !== null && report.servedProvider !== null && report.servedModel !== null,
14787
+ readsCredentialSource: true,
14773
14788
  read(root, report) {
14774
14789
  let said = false;
14775
14790
  const usage2 = asRecord(root.usage);
@@ -14801,6 +14816,23 @@ var OPENROUTER_COST_REPORT = {
14801
14816
  return said;
14802
14817
  }
14803
14818
  };
14819
+ var XAI_TICKS_PER_USD = 1e10;
14820
+ var XAI_COST_REPORT = {
14821
+ // Images and videos are provider-native operations, `other` to this gateway.
14822
+ // Its Anthropic-compatible Messages API and `v1/stt` are not documented to
14823
+ // report a cost, so they keep billing on the catalog.
14824
+ styles: ["chat_completions", "responses", "other"],
14825
+ settled: (report) => report.costUsd !== null,
14826
+ readsCredentialSource: false,
14827
+ read(root, report) {
14828
+ if (report.costUsd !== null) return false;
14829
+ const usage2 = asRecord(root.usage) ?? asRecord(asRecord(root.response)?.usage);
14830
+ const ticks = usage2 ? finiteNumber(usage2.cost_in_usd_ticks) : null;
14831
+ if (ticks === null || ticks < 0) return false;
14832
+ report.costUsd = ticks / XAI_TICKS_PER_USD;
14833
+ return true;
14834
+ }
14835
+ };
14804
14836
 
14805
14837
  // ../src/shared/providers.ts
14806
14838
  var PROVIDER_DESCRIPTORS = {
@@ -14844,6 +14876,11 @@ var PROVIDER_DESCRIPTORS = {
14844
14876
  // Native provider paths: xAI transcribes at `v1/stt`, where OpenAI serves
14845
14877
  // `v1/audio/transcriptions`.
14846
14878
  endpointPaths: { responses: "v1/responses", audio_transcription: "v1/stt" },
14879
+ // Every Chat Completions, Responses, image and video answer carries
14880
+ // `usage.cost_in_usd_ticks`, what xAI actually billed for it. An image
14881
+ // reports nothing else, so this is the only way to bill one; on the token
14882
+ // APIs it beats the catalog's estimate, which knows no discounts.
14883
+ costReport: XAI_COST_REPORT,
14847
14884
  modelAuthor: "xAI"
14848
14885
  },
14849
14886
  gemini: {
@@ -15015,9 +15052,6 @@ var PROVIDER_TYPES = Object.keys(PROVIDER_DESCRIPTORS);
15015
15052
  function providerDescriptor(type) {
15016
15053
  return PROVIDER_DESCRIPTORS[type];
15017
15054
  }
15018
- function isProviderType(value) {
15019
- return typeof value === "string" && Object.hasOwn(PROVIDER_DESCRIPTORS, value);
15020
- }
15021
15055
  var PROVIDER_CREDENTIAL_HEADERS = [
15022
15056
  ...new Set(
15023
15057
  PROVIDER_TYPES.map((type) => providerDescriptor(type).auth.header.toLowerCase())
@@ -15033,10 +15067,6 @@ function providerCapability(provider) {
15033
15067
  var ENDPOINT_PROVIDER_TYPES = PROVIDER_TYPES.filter(
15034
15068
  (type) => providerCapability(type).endpointStyles.length > 0
15035
15069
  );
15036
- function reportsCost(type) {
15037
- return isProviderType(type) && providerDescriptor(type).costReport !== void 0;
15038
- }
15039
- var COST_REPORTING_PROVIDER_TYPES = PROVIDER_TYPES.filter(reportsCost);
15040
15070
 
15041
15071
  // ../src/shared/app-status.ts
15042
15072
  var APP_STATUSES = ["active", "disabled"];
@@ -17849,7 +17879,7 @@ var UsageRepriceResponseSchema = external_exports.object({
17849
17879
  description: "Matched events that carried no readable usage, and so were repriced to the zero their zero counts imply while keeping whatever cost_source they had. A non-zero number means the month contains spend nothing could meter, which repricing cannot fix and must not appear to have fixed."
17850
17880
  }),
17851
17881
  unpriced_events: external_exports.number().int().meta({
17852
- description: "Dry-run only: matched events whose serving instance can no longer price them."
17882
+ description: "Dry-run only: matched events whose serving instance can no longer price them, or that predate the modality breakdown their model's price depends on."
17853
17883
  }),
17854
17884
  unpriced_cost_usd: external_exports.number(),
17855
17885
  previous_cost_usd: external_exports.number(),
@@ -17859,10 +17889,25 @@ var UsageRepriceResponseSchema = external_exports.object({
17859
17889
  var ModelPriceSchema = external_exports.object({
17860
17890
  input: external_exports.number().optional(),
17861
17891
  output: external_exports.number().optional(),
17892
+ image_input: external_exports.number().optional().meta({
17893
+ description: "USD per 1M image input tokens, where they are priced apart from text input."
17894
+ }),
17895
+ audio_input: external_exports.number().optional().meta({
17896
+ description: "USD per 1M audio input tokens, where they are priced apart from text input."
17897
+ }),
17898
+ video_input: external_exports.number().optional().meta({
17899
+ description: "USD per 1M video input tokens, where they are priced apart from text input."
17900
+ }),
17901
+ image_output: external_exports.number().optional().meta({
17902
+ description: "USD per 1M generated image tokens, where they cost more than text output."
17903
+ }),
17862
17904
  cached_input: external_exports.number().optional(),
17863
17905
  cache_write: external_exports.number().optional(),
17864
17906
  per_minute: external_exports.number().optional(),
17865
17907
  per_hour: external_exports.number().optional(),
17908
+ per_image: external_exports.number().optional().meta({
17909
+ description: "USD per generated image, for a model billed per image rather than per token."
17910
+ }),
17866
17911
  long_context_threshold: external_exports.number().optional(),
17867
17912
  long_input: external_exports.number().optional(),
17868
17913
  long_output: external_exports.number().optional(),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@maxceem/agw",
3
- "version": "0.7.0",
3
+ "version": "0.7.1",
4
4
  "type": "module",
5
5
  "description": "Manage App AI Gateway from a terminal or coding agent: providers, iOS and server apps, usage, and self-hosted deployment on Cloudflare",
6
6
  "keywords": [
@@ -25,7 +25,18 @@
25
25
  "directory": "cli"
26
26
  },
27
27
  "bugs": "https://github.com/maxceem/app-ai-gateway/issues",
28
- "upgradeFrom": ["0.6.4", "0.6.3", "0.6.2", "0.6.1", "0.6.0", "0.5.2", "0.5.1", "0.5.0", "0.4.0"],
28
+ "upgradeFrom": [
29
+ "0.7.0",
30
+ "0.6.4",
31
+ "0.6.3",
32
+ "0.6.2",
33
+ "0.6.1",
34
+ "0.6.0",
35
+ "0.5.2",
36
+ "0.5.1",
37
+ "0.5.0",
38
+ "0.4.0"
39
+ ],
29
40
  "license": "Apache-2.0",
30
41
  "bin": {
31
42
  "agw": "dist/agw.mjs"