@maxceem/agw 0.14.0 → 0.15.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.
- package/dist/agw.mjs +105 -63
- package/package.json +3 -1
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.
|
|
9
|
+
var define_AGW_MANIFEST_default = { version: "0.15.1", wrangler: "4.96.0", upgradeFrom: ["0.15.1", "0.15.0", "0.14.0", "0.13.1", "0.13.0", "0.12.1", "0.12.0", "0.11.2", "0.11.1", "0.11.0", "0.10.11", "0.10.10", "0.10.9", "0.10.8", "0.10.7", "0.10.6", "0.10.5", "0.10.4", "0.10.3", "0.10.2", "0.10.1", "0.10.0", "0.9.3", "0.9.2", "0.9.1", "0.9.0", "0.8.3", "0.8.2", "0.8.1", "0.8.0", "0.7.2", "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.15.1/gateway-0.15.1.tar.gz", sha256: "b5938517a50f09ea3ce3f966efd949dde8e9f0f2c195d47bb0dfdcbc7ec8eda0", manifest: "888f171f040d7547b37c40b41c01a53d1f284c9671e0bdc98083e9474c4ecdab" } };
|
|
10
10
|
|
|
11
11
|
// src/main.ts
|
|
12
12
|
import { Writable as Writable2 } from "node:stream";
|
|
@@ -20509,25 +20509,76 @@ var ENDPOINT_PROVIDER_TYPES = PROVIDER_TYPES.filter(
|
|
|
20509
20509
|
var APP_STATUSES = ["active", "disabled"];
|
|
20510
20510
|
|
|
20511
20511
|
// ../src/shared/token-rates.ts
|
|
20512
|
-
var
|
|
20513
|
-
|
|
20514
|
-
|
|
20515
|
-
|
|
20516
|
-
|
|
20517
|
-
|
|
20518
|
-
|
|
20519
|
-
|
|
20520
|
-
|
|
20521
|
-
|
|
20522
|
-
|
|
20523
|
-
|
|
20524
|
-
|
|
20525
|
-
|
|
20526
|
-
|
|
20527
|
-
|
|
20528
|
-
|
|
20529
|
-
|
|
20512
|
+
var TOKEN_VARIANTS = {
|
|
20513
|
+
cache_write: {
|
|
20514
|
+
// Anthropic: a write kept for an hour bills at 2x input, against 1.25x for
|
|
20515
|
+
// the default five minutes. `usage.cache_creation` splits the write by TTL.
|
|
20516
|
+
"1h": {
|
|
20517
|
+
label: "1h cache write",
|
|
20518
|
+
description: "USD per 1M tokens written to a one-hour cache, where it costs more than the default cache write.",
|
|
20519
|
+
reportedAt: ["cache_creation", "ephemeral_1h_input_tokens"]
|
|
20520
|
+
},
|
|
20521
|
+
// OpenAI (Responses API): a write kept for 12 hours bills at 2.5x input,
|
|
20522
|
+
// against 1.25x for the default 30 minutes.
|
|
20523
|
+
"12h": {
|
|
20524
|
+
label: "12h cache write",
|
|
20525
|
+
description: "USD per 1M tokens written to a 12-hour cache, where it costs more than the default cache write.",
|
|
20526
|
+
reportedAt: ["input_tokens_details", "cache_write_tokens_details", "ttl_12h_tokens"]
|
|
20527
|
+
}
|
|
20528
|
+
}
|
|
20529
|
+
};
|
|
20530
|
+
var VARIANTS = Object.entries(TOKEN_VARIANTS).flatMap(
|
|
20531
|
+
([bucket, variants]) => Object.entries(variants).map(([name, spec]) => ({
|
|
20532
|
+
...spec,
|
|
20533
|
+
bucket,
|
|
20534
|
+
name,
|
|
20535
|
+
field: `${bucket}_${name}`
|
|
20536
|
+
}))
|
|
20537
|
+
);
|
|
20538
|
+
var BUCKETS = ["input", "cached_input", "cache_write", "output"];
|
|
20539
|
+
var MODALITY_RATES = ["image_input", "audio_input", "video_input", "image_output"];
|
|
20540
|
+
var BASE_RATES = {
|
|
20541
|
+
input: { label: "input" },
|
|
20542
|
+
cached_input: { label: "cached" },
|
|
20543
|
+
cache_write: { label: "cache write" },
|
|
20544
|
+
output: { label: "output" },
|
|
20545
|
+
image_input: {
|
|
20546
|
+
label: "image input",
|
|
20547
|
+
description: "USD per 1M image input tokens, where they are priced apart from text input."
|
|
20548
|
+
},
|
|
20549
|
+
audio_input: {
|
|
20550
|
+
label: "audio input",
|
|
20551
|
+
description: "USD per 1M audio input tokens, where they are priced apart from text input."
|
|
20552
|
+
},
|
|
20553
|
+
video_input: {
|
|
20554
|
+
label: "video input",
|
|
20555
|
+
description: "USD per 1M video input tokens, where they are priced apart from text input."
|
|
20556
|
+
},
|
|
20557
|
+
image_output: {
|
|
20558
|
+
label: "image output",
|
|
20559
|
+
description: "USD per 1M generated image tokens, where they cost more than text output."
|
|
20560
|
+
}
|
|
20561
|
+
};
|
|
20562
|
+
var BUCKET_FIELDS = BUCKETS.flatMap((bucket) => [
|
|
20563
|
+
bucket,
|
|
20564
|
+
...VARIANTS.filter((variant) => variant.bucket === bucket).map((variant) => variant.field)
|
|
20565
|
+
]);
|
|
20566
|
+
var LONG_RATE_FIELDS = BUCKET_FIELDS.map((field) => `long_${field}`);
|
|
20567
|
+
var TOKEN_RATE_FIELDS = [...BUCKET_FIELDS, ...MODALITY_RATES, ...LONG_RATE_FIELDS];
|
|
20568
|
+
var SHORT_INFO = new Map([
|
|
20569
|
+
...Object.entries(BASE_RATES),
|
|
20570
|
+
...VARIANTS.map((variant) => [variant.field, variant])
|
|
20571
|
+
]);
|
|
20572
|
+
var RATE_LABELS = Object.fromEntries(
|
|
20573
|
+
TOKEN_RATE_FIELDS.map((field) => {
|
|
20574
|
+
const short = field.startsWith("long_") ? field.slice("long_".length) : field;
|
|
20575
|
+
const label = SHORT_INFO.get(short)?.label ?? short;
|
|
20576
|
+
return [field, short === field ? label : `long ${label}`];
|
|
20577
|
+
})
|
|
20530
20578
|
);
|
|
20579
|
+
function rateDescription(field) {
|
|
20580
|
+
return SHORT_INFO.get(field)?.description;
|
|
20581
|
+
}
|
|
20531
20582
|
|
|
20532
20583
|
// ../src/contracts/schemas.ts
|
|
20533
20584
|
var ISSUER_PROVIDERS = ["firebase", "supabase", "auth0", "clerk", "custom"];
|
|
@@ -22622,7 +22673,7 @@ function snippetRemedy(code, appId, language) {
|
|
|
22622
22673
|
|
|
22623
22674
|
// src/conversations.ts
|
|
22624
22675
|
import { mkdir as mkdir2, readFile as readFile3, stat, writeFile } from "node:fs/promises";
|
|
22625
|
-
import { dirname,
|
|
22676
|
+
import { dirname, isAbsolute, relative, resolve as resolve2 } from "node:path";
|
|
22626
22677
|
import { gunzipSync } from "node:zlib";
|
|
22627
22678
|
|
|
22628
22679
|
// src/usage.ts
|
|
@@ -22686,6 +22737,14 @@ async function sizeOf(path) {
|
|
|
22686
22737
|
return null;
|
|
22687
22738
|
}
|
|
22688
22739
|
}
|
|
22740
|
+
function inside(output2, name) {
|
|
22741
|
+
const path = resolve2(output2, name);
|
|
22742
|
+
const rel = relative(output2, path);
|
|
22743
|
+
if (rel === "" || rel.startsWith("..") || isAbsolute(rel)) {
|
|
22744
|
+
fail("invalid_response", "The deployment named a conversation file outside the export folder.", void 0, 3);
|
|
22745
|
+
}
|
|
22746
|
+
return path;
|
|
22747
|
+
}
|
|
22689
22748
|
async function save(path, bytes) {
|
|
22690
22749
|
await mkdir2(dirname(path), { recursive: true });
|
|
22691
22750
|
await writeFile(path, bytes);
|
|
@@ -22715,7 +22774,7 @@ async function conversationsCommand(ctx, appId, flags) {
|
|
|
22715
22774
|
})).data;
|
|
22716
22775
|
for (const file2 of page2.files) {
|
|
22717
22776
|
result.files += 1;
|
|
22718
|
-
const path =
|
|
22777
|
+
const path = inside(output2, file2.name);
|
|
22719
22778
|
batches.push(path);
|
|
22720
22779
|
if (await sizeOf(path) === file2.size) continue;
|
|
22721
22780
|
const bytes = await ctx.client.download("getAppConversationFile", {
|
|
@@ -22735,7 +22794,7 @@ async function conversationsCommand(ctx, appId, flags) {
|
|
|
22735
22794
|
for (const match of text2.matchAll(MEDIA_REFERENCE)) names.add(match[1]);
|
|
22736
22795
|
}
|
|
22737
22796
|
for (const name of names) {
|
|
22738
|
-
const path =
|
|
22797
|
+
const path = inside(output2, name);
|
|
22739
22798
|
if (await sizeOf(path) !== null) continue;
|
|
22740
22799
|
const bytes = await ctx.client.download("getAppConversationFile", {
|
|
22741
22800
|
params: { app: appId },
|
|
@@ -23685,40 +23744,23 @@ var UsageRepriceResponseSchema = external_exports.object({
|
|
|
23685
23744
|
recalculated_cost_usd: external_exports.number(),
|
|
23686
23745
|
delta_usd: external_exports.number()
|
|
23687
23746
|
});
|
|
23747
|
+
var CATALOG_TOKEN_RATES = Object.fromEntries(
|
|
23748
|
+
TOKEN_RATE_FIELDS.map((field) => {
|
|
23749
|
+
const description = rateDescription(field);
|
|
23750
|
+
return [field, description ? external_exports.number().optional().meta({ description }) : external_exports.number().optional()];
|
|
23751
|
+
})
|
|
23752
|
+
);
|
|
23688
23753
|
var ModelPriceSchema = external_exports.object({
|
|
23689
23754
|
kind: external_exports.enum(MODEL_KINDS).meta({
|
|
23690
23755
|
description: "What the model does: text, image (generation), speech (text to speech), transcription (speech to text), embedding, or realtime (served only over a realtime session). A custom endpoint serves models of its own kind only."
|
|
23691
23756
|
}),
|
|
23692
|
-
|
|
23693
|
-
output: external_exports.number().optional(),
|
|
23694
|
-
image_input: external_exports.number().optional().meta({
|
|
23695
|
-
description: "USD per 1M image input tokens, where they are priced apart from text input."
|
|
23696
|
-
}),
|
|
23697
|
-
audio_input: external_exports.number().optional().meta({
|
|
23698
|
-
description: "USD per 1M audio input tokens, where they are priced apart from text input."
|
|
23699
|
-
}),
|
|
23700
|
-
video_input: external_exports.number().optional().meta({
|
|
23701
|
-
description: "USD per 1M video input tokens, where they are priced apart from text input."
|
|
23702
|
-
}),
|
|
23703
|
-
image_output: external_exports.number().optional().meta({
|
|
23704
|
-
description: "USD per 1M generated image tokens, where they cost more than text output."
|
|
23705
|
-
}),
|
|
23706
|
-
cached_input: external_exports.number().optional(),
|
|
23707
|
-
cache_write: external_exports.number().optional(),
|
|
23708
|
-
cache_write_1h: external_exports.number().optional().meta({
|
|
23709
|
-
description: "USD per 1M tokens written to a one-hour cache, where it costs more than the default cache write."
|
|
23710
|
-
}),
|
|
23757
|
+
...CATALOG_TOKEN_RATES,
|
|
23711
23758
|
per_minute: external_exports.number().optional(),
|
|
23712
23759
|
per_hour: external_exports.number().optional(),
|
|
23713
23760
|
per_image: external_exports.number().optional().meta({
|
|
23714
23761
|
description: "USD per generated image, for a model billed per image rather than per token."
|
|
23715
23762
|
}),
|
|
23716
23763
|
long_context_threshold: external_exports.number().optional(),
|
|
23717
|
-
long_input: external_exports.number().optional(),
|
|
23718
|
-
long_output: external_exports.number().optional(),
|
|
23719
|
-
long_cached_input: external_exports.number().optional(),
|
|
23720
|
-
long_cache_write: external_exports.number().optional(),
|
|
23721
|
-
long_cache_write_1h: external_exports.number().optional(),
|
|
23722
23764
|
retirement_date: external_exports.string().optional().meta({
|
|
23723
23765
|
description: "The day (YYYY-MM-DD) the provider stops, or stopped, serving this model. The model stays priced after it."
|
|
23724
23766
|
})
|
|
@@ -26322,11 +26364,11 @@ async function openBrowser(url2) {
|
|
|
26322
26364
|
// src/deployment.ts
|
|
26323
26365
|
import { createHash as createHash4, randomUUID } from "node:crypto";
|
|
26324
26366
|
import { writeFile as writeFile4, unlink as unlink2 } from "node:fs/promises";
|
|
26325
|
-
import { join as
|
|
26367
|
+
import { join as join4 } from "node:path";
|
|
26326
26368
|
|
|
26327
26369
|
// src/release.ts
|
|
26328
26370
|
import { readFile as readFile4, lstat as lstat2, mkdir as mkdir3, rename as rename2, rm, writeFile as writeFile2 } from "node:fs/promises";
|
|
26329
|
-
import { join as
|
|
26371
|
+
import { join as join2, dirname as dirname2 } from "node:path";
|
|
26330
26372
|
import { fileURLToPath } from "node:url";
|
|
26331
26373
|
import { createHash as createHash3, randomBytes as randomBytes3 } from "node:crypto";
|
|
26332
26374
|
|
|
@@ -26451,7 +26493,7 @@ async function fetchArchive(url2) {
|
|
|
26451
26493
|
async function extract(archive, directory) {
|
|
26452
26494
|
await mkdir3(directory, { recursive: true, mode: 448 });
|
|
26453
26495
|
for (const entry of readArchive(archive)) {
|
|
26454
|
-
const path =
|
|
26496
|
+
const path = join2(directory, entry.path);
|
|
26455
26497
|
if (entry.directory) {
|
|
26456
26498
|
await mkdir3(path, { recursive: true, mode: 448 });
|
|
26457
26499
|
continue;
|
|
@@ -26461,9 +26503,9 @@ async function extract(archive, directory) {
|
|
|
26461
26503
|
}
|
|
26462
26504
|
}
|
|
26463
26505
|
async function cachedRelease(version2, integrity, source) {
|
|
26464
|
-
const root = source.cache ??
|
|
26465
|
-
const directory =
|
|
26466
|
-
const cached2 = await readFile4(
|
|
26506
|
+
const root = source.cache ?? join2(cacheDirectory(), "releases");
|
|
26507
|
+
const directory = join2(root, version2);
|
|
26508
|
+
const cached2 = await readFile4(join2(directory, "manifest.json")).catch(() => null);
|
|
26467
26509
|
if (cached2 && digest(cached2) === integrity.manifest) return directory;
|
|
26468
26510
|
const supplied = source.archive ?? process.env["AGW_RELEASE_ARCHIVE"] ?? void 0;
|
|
26469
26511
|
let archive;
|
|
@@ -26487,10 +26529,10 @@ async function cachedRelease(version2, integrity, source) {
|
|
|
26487
26529
|
4
|
|
26488
26530
|
);
|
|
26489
26531
|
await protectedDirectory(root);
|
|
26490
|
-
const staging =
|
|
26532
|
+
const staging = join2(root, `.${version2}-${randomBytes3(8).toString("hex")}`);
|
|
26491
26533
|
try {
|
|
26492
26534
|
await extract(archive, staging);
|
|
26493
|
-
const manifest2 = await readFile4(
|
|
26535
|
+
const manifest2 = await readFile4(join2(staging, "manifest.json")).catch(() => null);
|
|
26494
26536
|
if (!manifest2 || digest(manifest2) !== integrity.manifest)
|
|
26495
26537
|
fail(
|
|
26496
26538
|
"release_integrity",
|
|
@@ -26516,7 +26558,7 @@ async function release2(requested = VERSION, base = dirname2(fileURLToPath(impor
|
|
|
26516
26558
|
if (major === void 0 || minor === void 0 || major < 22 || major === 22 && minor < 19)
|
|
26517
26559
|
fail("unsupported_runtime", "Node.js 22.19.0 or newer is required.");
|
|
26518
26560
|
const integrity = source.integrity === void 0 ? RELEASE : source.integrity;
|
|
26519
|
-
const packaged =
|
|
26561
|
+
const packaged = join2(base, "release", requested);
|
|
26520
26562
|
const local = await lstat2(packaged).catch(() => null);
|
|
26521
26563
|
let directory;
|
|
26522
26564
|
if (local?.isDirectory()) directory = packaged;
|
|
@@ -26530,7 +26572,7 @@ async function release2(requested = VERSION, base = dirname2(fileURLToPath(impor
|
|
|
26530
26572
|
);
|
|
26531
26573
|
let serialized;
|
|
26532
26574
|
try {
|
|
26533
|
-
serialized = await readFile4(
|
|
26575
|
+
serialized = await readFile4(join2(directory, "manifest.json"), "utf8");
|
|
26534
26576
|
} catch {
|
|
26535
26577
|
fail(
|
|
26536
26578
|
"release_missing",
|
|
@@ -26550,7 +26592,7 @@ async function release2(requested = VERSION, base = dirname2(fileURLToPath(impor
|
|
|
26550
26592
|
for (const [path, hash2] of Object.entries(manifest2.files)) {
|
|
26551
26593
|
if (path.startsWith("/") || path.split(/[\\/]/).some((p) => p === ".." || p === ""))
|
|
26552
26594
|
fail("release_integrity", "Release includes an unsafe path.");
|
|
26553
|
-
const file2 =
|
|
26595
|
+
const file2 = join2(directory, path);
|
|
26554
26596
|
const info = await lstat2(file2);
|
|
26555
26597
|
if (!info.isFile() || info.isSymbolicLink() || digest(await readFile4(file2)) !== hash2)
|
|
26556
26598
|
fail("release_integrity", "Release asset integrity check failed.");
|
|
@@ -26559,7 +26601,7 @@ async function release2(requested = VERSION, base = dirname2(fileURLToPath(impor
|
|
|
26559
26601
|
directory,
|
|
26560
26602
|
manifest: manifest2,
|
|
26561
26603
|
config: JSON.parse(
|
|
26562
|
-
await readFile4(
|
|
26604
|
+
await readFile4(join2(directory, "wrangler.json"), "utf8")
|
|
26563
26605
|
)
|
|
26564
26606
|
};
|
|
26565
26607
|
}
|
|
@@ -26816,7 +26858,7 @@ async function whileWarming(run, sleep = delay3, report = (line) => process.stde
|
|
|
26816
26858
|
|
|
26817
26859
|
// src/installation.ts
|
|
26818
26860
|
import { cp, writeFile as writeFile3 } from "node:fs/promises";
|
|
26819
|
-
import { join as
|
|
26861
|
+
import { join as join3 } from "node:path";
|
|
26820
26862
|
import { setTimeout as delay4 } from "node:timers/promises";
|
|
26821
26863
|
async function advance(ctx, journal, phase, patch = {}) {
|
|
26822
26864
|
const fields = journal;
|
|
@@ -26843,9 +26885,9 @@ function selectedInstallation(ctx) {
|
|
|
26843
26885
|
};
|
|
26844
26886
|
}
|
|
26845
26887
|
async function configFile(ctx, journal, artifact) {
|
|
26846
|
-
const directory =
|
|
26888
|
+
const directory = join3(ctx.store.directory, "deployments", journal.id);
|
|
26847
26889
|
await protectedDirectory(directory);
|
|
26848
|
-
await cp(artifact.directory,
|
|
26890
|
+
await cp(artifact.directory, join3(directory, "release"), { recursive: true });
|
|
26849
26891
|
const config2 = {
|
|
26850
26892
|
...artifact.config,
|
|
26851
26893
|
name: journal.name,
|
|
@@ -26873,7 +26915,7 @@ async function configFile(ctx, journal, artifact) {
|
|
|
26873
26915
|
}))
|
|
26874
26916
|
} : {}
|
|
26875
26917
|
};
|
|
26876
|
-
const path =
|
|
26918
|
+
const path = join3(directory, "wrangler.json");
|
|
26877
26919
|
await writeFile3(path, JSON.stringify(config2, null, 2), { mode: 384 });
|
|
26878
26920
|
return { path, directory, config: config2 };
|
|
26879
26921
|
}
|
|
@@ -27220,7 +27262,7 @@ async function install(ctx, cf, journal, artifact, url2, domain2) {
|
|
|
27220
27262
|
// the account is this CLI's however soon anyone else finds the address.
|
|
27221
27263
|
CLI_BOOTSTRAP_TOKEN_DIGEST: createHash4("sha256").update(journal.bootstrap.token).digest("hex")
|
|
27222
27264
|
};
|
|
27223
|
-
const secretPath =
|
|
27265
|
+
const secretPath = join4(file2.directory, "secrets.json");
|
|
27224
27266
|
await writeFile4(secretPath, JSON.stringify(secrets), {
|
|
27225
27267
|
mode: 384
|
|
27226
27268
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@maxceem/agw",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.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": [
|
|
@@ -26,6 +26,8 @@
|
|
|
26
26
|
},
|
|
27
27
|
"bugs": "https://github.com/maxceem/app-ai-gateway/issues",
|
|
28
28
|
"upgradeFrom": [
|
|
29
|
+
"0.15.0",
|
|
30
|
+
"0.14.0",
|
|
29
31
|
"0.13.1",
|
|
30
32
|
"0.13.0",
|
|
31
33
|
"0.12.1",
|