@isaacthoman/pulpo 0.135.0 → 0.137.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.
package/README.md CHANGED
@@ -172,3 +172,7 @@ Use `speech-model preset --adapter mistral` for the Voxtral preset. The
172
172
  repair, looping watermark settings, synthesized previews, and retryable cleanup.
173
173
  See [the speech administration guide](../../docs/speech.md) for complete commands,
174
174
  upload limits, billing behavior, and FFmpeg setup.
175
+
176
+ Provider attempts and payload cleanup status are available through `pulpo usage diagnostics`,
177
+ `pulpo usage diagnostic-payloads <id>`, and `pulpo usage retention-status`.
178
+ See [diagnostic logging and retention](../../docs/diagnostic-logging.md) for capture fidelity and expiry behavior.
package/dist/index.js CHANGED
@@ -14532,6 +14532,21 @@ var imageGenerationPreferencesSchema = external_exports.object({
14532
14532
  enabled: external_exports.boolean().default(false),
14533
14533
  modelId: external_exports.string().max(120).nullable().default(null)
14534
14534
  }).default(() => ({ enabled: false, modelId: null }));
14535
+ var imageDefaultsSchema = external_exports.object({
14536
+ modelId: external_exports.string().regex(/^[a-z0-9][a-z0-9._-]{0,119}$/).nullable().default(null)
14537
+ });
14538
+ var price = external_exports.number().int().min(0).max(1e12);
14539
+ var imageTokenPricesSchema = external_exports.object({
14540
+ input: price.nullable().default(null),
14541
+ cachedInput: price.nullable().default(null),
14542
+ output: price.nullable().default(null),
14543
+ imageInput: price.nullable().default(null),
14544
+ cachedImageInput: price.nullable().default(null),
14545
+ imageOutput: price.nullable().default(null)
14546
+ });
14547
+ function imageTokenRateKeys(adapter) {
14548
+ return adapter === "openai-images" ? ["input", "cachedInput", "imageInput", "cachedImageInput", "output", "imageOutput"] : ["input", "cachedInput", "output"];
14549
+ }
14535
14550
  var imageModelSchema = external_exports.object({
14536
14551
  id: external_exports.string().regex(/^[a-z0-9][a-z0-9._-]{0,119}$/),
14537
14552
  providerConnectionId: external_exports.uuid(),
@@ -14541,7 +14556,23 @@ var imageModelSchema = external_exports.object({
14541
14556
  enabled: external_exports.boolean().default(false),
14542
14557
  sortOrder: external_exports.number().int().min(0).default(0),
14543
14558
  billUsers: external_exports.boolean().default(false),
14544
- imagePriceMicros: external_exports.number().int().min(0).max(1e12).default(0)
14559
+ imagePriceMicros: price.default(0),
14560
+ billingUnit: external_exports.enum(["images", "tokens"]).default("images"),
14561
+ tokenPrices: imageTokenPricesSchema.default(() => imageTokenPricesSchema.parse({})),
14562
+ reservationMicros: price.default(0)
14563
+ }).superRefine((model, ctx) => {
14564
+ if (model.billingUnit !== "tokens")
14565
+ return;
14566
+ if (model.adapter === "azure-mai")
14567
+ ctx.addIssue({ code: "custom", path: ["billingUnit"], message: "Azure MAI does not report token usage; use per-image pricing." });
14568
+ if (!model.billUsers)
14569
+ return;
14570
+ if (model.reservationMicros <= 0)
14571
+ ctx.addIssue({ code: "custom", path: ["reservationMicros"], message: "Enter a positive upfront reservation." });
14572
+ for (const key of imageTokenRateKeys(model.adapter)) {
14573
+ if (model.tokenPrices[key] === null)
14574
+ ctx.addIssue({ code: "custom", path: ["tokenPrices", key], message: "Enter a token rate (zero is allowed)." });
14575
+ }
14545
14576
  });
14546
14577
  var AZURE_MAI_IMAGE_PRESET = {
14547
14578
  adapter: "azure-mai",
@@ -14550,7 +14581,10 @@ var AZURE_MAI_IMAGE_PRESET = {
14550
14581
  enabled: false,
14551
14582
  sortOrder: 0,
14552
14583
  billUsers: false,
14553
- imagePriceMicros: 0
14584
+ imagePriceMicros: 0,
14585
+ billingUnit: "images",
14586
+ tokenPrices: imageTokenPricesSchema.parse({}),
14587
+ reservationMicros: 0
14554
14588
  };
14555
14589
  var META_MUSE_IMAGE_PRESET = {
14556
14590
  ...AZURE_MAI_IMAGE_PRESET,
@@ -14562,7 +14596,9 @@ var OPENAI_IMAGE_PRESET = {
14562
14596
  ...AZURE_MAI_IMAGE_PRESET,
14563
14597
  adapter: "openai-images",
14564
14598
  name: "GPT Image 2.5 Flare",
14565
- upstreamModelId: "gpt-image-2.5-flare"
14599
+ upstreamModelId: "gpt-image-2.5-flare",
14600
+ // Microdollars / 1M tokens, verified 2026-09-13: developers.openai.com/api/docs/models/gpt-image-2.5-flare
14601
+ tokenPrices: { input: 5e6, cachedInput: 125e4, imageInput: 8e6, cachedImageInput: 2e6, output: 0, imageOutput: 3e7 }
14566
14602
  };
14567
14603
  var IMAGE_GENERATION_MAX_BYTES = 20 * 1024 * 1024;
14568
14604
  var imageGenerationInputSchema = external_exports.object({
@@ -14597,7 +14633,7 @@ var speechPreferencesSchema = external_exports.object({
14597
14633
  speed: external_exports.number().min(0.25).max(4).default(1)
14598
14634
  })).default({})
14599
14635
  }).default(() => ({ modelId: null, models: {} }));
14600
- var price = external_exports.number().int().min(0).max(1e12);
14636
+ var price2 = external_exports.number().int().min(0).max(1e12);
14601
14637
  var speechModelSchema = external_exports.object({
14602
14638
  id: external_exports.string().regex(/^[a-z0-9][a-z0-9._-]{0,119}$/),
14603
14639
  providerConnectionId: external_exports.string().uuid(),
@@ -14618,10 +14654,10 @@ var speechModelSchema = external_exports.object({
14618
14654
  supportsSse: external_exports.boolean().default(false),
14619
14655
  billUsers: external_exports.boolean().default(false),
14620
14656
  billingUnit: external_exports.enum(["tokens", "characters", "duration"]).default("characters"),
14621
- inputPriceMicros: price.default(0),
14622
- outputPriceMicros: price.default(0),
14623
- characterPriceMicros: price.default(0),
14624
- minutePriceMicros: price.default(0)
14657
+ inputPriceMicros: price2.default(0),
14658
+ outputPriceMicros: price2.default(0),
14659
+ characterPriceMicros: price2.default(0),
14660
+ minutePriceMicros: price2.default(0)
14625
14661
  }).superRefine((model, ctx) => {
14626
14662
  if ((model.enabled || model.voices.length || model.defaultVoice) && !model.voices.some((v) => v.id === model.defaultVoice))
14627
14663
  ctx.addIssue({ code: "custom", path: ["defaultVoice"], message: "Default voice must be in the voice list" });
@@ -20759,7 +20795,7 @@ async function runModelTest(input) {
20759
20795
  }
20760
20796
 
20761
20797
  // src/index.ts
20762
- var CLI_VERSION = true ? "0.135.0" : "0.1.0";
20798
+ var CLI_VERSION = true ? "0.137.0" : "0.1.0";
20763
20799
  var CLI_BUNDLED = true;
20764
20800
  var commandIo = /* @__PURE__ */ new WeakMap();
20765
20801
  var commandClientFactory = /* @__PURE__ */ new WeakMap();
@@ -21443,6 +21479,18 @@ function createProgram(io = processIo, dependencies = {}) {
21443
21479
  const payloads = await client.request(`/api/management/v1/usage/requests/${encodeURIComponent(id)}/payloads`);
21444
21480
  writeOutput(io, payloads, true);
21445
21481
  });
21482
+ usage.command("diagnostics [requestId]").description("List provider/tool attempts, optionally for a model call or request log").action(async (requestId, _options, command) => {
21483
+ const { client } = await clientFor(command);
21484
+ writeOutput(io, await client.request(requestId ? `/api/management/v1/usage/requests/${encodeURIComponent(requestId)}/diagnostics` : "/api/management/v1/usage/diagnostics"), true);
21485
+ });
21486
+ usage.command("diagnostic-payloads <id>").description("Inspect retained payloads and capture fidelity for one diagnostic attempt").action(async (id, _options, command) => {
21487
+ const { client } = await clientFor(command);
21488
+ writeOutput(io, await client.request(`/api/management/v1/usage/diagnostics/${encodeURIComponent(id)}/payloads`), true);
21489
+ });
21490
+ usage.command("retention-status").action(async (_options, command) => {
21491
+ const { client } = await clientFor(command);
21492
+ writeOutput(io, await client.request("/api/management/v1/usage/diagnostics/retention"), true);
21493
+ });
21446
21494
  usage.command("request <id>").action(async (id, _options, command) => {
21447
21495
  const { client } = await clientFor(command);
21448
21496
  emit(io, command, await client.request(`/api/management/v1/usage/requests/${encodeURIComponent(id)}`));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@isaacthoman/pulpo",
3
- "version": "0.135.0",
3
+ "version": "0.137.0",
4
4
  "description": "Operator-first command-line client for Pulpo",
5
5
  "type": "module",
6
6
  "bin": {