@p4code/cli 0.6.51 → 0.6.53

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/bin.mjs CHANGED
@@ -263,7 +263,7 @@ const make$123 = () => {
263
263
  const layer$124 = Layer.sync(NetService, make$123);
264
264
  //#endregion
265
265
  //#region package.json
266
- var version$1 = "0.6.51";
266
+ var version$1 = "0.6.53";
267
267
  //#endregion
268
268
  //#region ../../packages/shared/src/serverInstance.ts
269
269
  /**
@@ -7950,9 +7950,18 @@ const RESET_CREDIT_IDEMPOTENCY_KEY_MAX_LENGTH = 128;
7950
7950
  * the request never produced an answer - the provider may or may not have
7951
7951
  * acted, so retrying with the same `idempotencyKey` is the safe next step.
7952
7952
  */
7953
+ /** A Codex account a usage source pools, named by the source and the source's account id. */
7954
+ const UsageLimitSourceAccountRef = Schema$1.Struct({
7955
+ sourceId: UsageLimitSourceId,
7956
+ accountId: TrimmedNonEmptyString
7957
+ });
7958
+ /** Whose reset credit: a native provider instance, or an account a usage source pools. */
7959
+ const ResetCreditTarget = Schema$1.Union([Schema$1.Struct({ instanceId: ProviderInstanceId }), Schema$1.Struct({ sourceAccount: UsageLimitSourceAccountRef })]);
7953
7960
  const ProviderResetCreditAttempt = Schema$1.Struct({
7954
7961
  idempotencyKey: TrimmedNonEmptyString,
7955
- instanceId: ProviderInstanceId,
7962
+ /** Set for a native instance's attempt; `sourceAccount` is set instead for a pooled account. */
7963
+ instanceId: Schema$1.optional(ProviderInstanceId),
7964
+ sourceAccount: Schema$1.optional(UsageLimitSourceAccountRef),
7956
7965
  /** The credit this attempt named, fixed at its first try so a retry cannot switch credits. */
7957
7966
  creditId: Schema$1.optional(TrimmedNonEmptyString),
7958
7967
  requestedAt: IsoDateTime,
@@ -7960,15 +7969,27 @@ const ProviderResetCreditAttempt = Schema$1.Struct({
7960
7969
  detail: Schema$1.optional(TrimmedNonEmptyString),
7961
7970
  completedAt: Schema$1.optional(IsoDateTime)
7962
7971
  });
7963
- const ConsumeProviderResetCreditInput = Schema$1.Struct({
7964
- instanceId: ProviderInstanceId,
7972
+ const ConsumeProviderResetCreditFields = {
7965
7973
  /** One logical attempt; resend the same key to retry it without spending twice. */
7966
7974
  idempotencyKey: TrimmedNonEmptyString.check(Schema$1.isMaxLength(RESET_CREDIT_IDEMPOTENCY_KEY_MAX_LENGTH)),
7967
- /** The credit the client was shown; omitted lets the provider pick the next one. */
7975
+ /**
7976
+ * The credit the client was shown; omitted lets the provider pick the next
7977
+ * one. Required for a pooled account, whose source may since hold another
7978
+ * login: naming the credit makes Codex refuse instead of spending its reset.
7979
+ */
7968
7980
  creditId: Schema$1.optional(TrimmedNonEmptyString)
7969
- });
7970
- var ProviderResetCreditError = class extends Schema$1.TaggedErrorClass()("ProviderResetCreditError", {
7981
+ };
7982
+ const ConsumeProviderResetCreditInput = Schema$1.Union([Schema$1.Struct({
7971
7983
  instanceId: ProviderInstanceId,
7984
+ ...ConsumeProviderResetCreditFields
7985
+ }), Schema$1.Struct({
7986
+ sourceAccount: UsageLimitSourceAccountRef,
7987
+ ...ConsumeProviderResetCreditFields,
7988
+ creditId: TrimmedNonEmptyString
7989
+ })]);
7990
+ var ProviderResetCreditError = class extends Schema$1.TaggedErrorClass()("ProviderResetCreditError", {
7991
+ instanceId: Schema$1.optionalKey(ProviderInstanceId),
7992
+ sourceAccount: Schema$1.optionalKey(UsageLimitSourceAccountRef),
7972
7993
  detail: Schema$1.String,
7973
7994
  /** True once the request reached Codex, so a reset may have been used. */
7974
7995
  consumeSent: Schema$1.optionalKey(Schema$1.Boolean),
@@ -16276,17 +16297,18 @@ const WsServerGetProviderUsageRpc = Rpc.make(WS_METHODS.serverGetProviderUsage,
16276
16297
  error: Schema$1.Union([TextGenerationError, EnvironmentAuthorizationError])
16277
16298
  });
16278
16299
  /**
16279
- * Redeem one of the account's banked reset credits. Only providers that can
16280
- * redeem natively answer; the rest fail with `ProviderResetCreditError`.
16300
+ * Redeem one of the account's banked reset credits: natively for a Codex
16301
+ * instance, or through the usage source for a pooled Codex account. Anything
16302
+ * else fails with `ProviderResetCreditError`.
16281
16303
  */
16282
16304
  const WsServerConsumeProviderResetCreditRpc = Rpc.make(WS_METHODS.serverConsumeProviderResetCredit, {
16283
16305
  payload: ConsumeProviderResetCreditInput,
16284
16306
  success: Schema$1.Struct({ attempt: ProviderResetCreditAttempt }),
16285
16307
  error: Schema$1.Union([ProviderResetCreditError, EnvironmentAuthorizationError])
16286
16308
  });
16287
- /** Redemptions started through P4 for one instance, newest first. */
16309
+ /** Redemptions started through P4 for one instance or pooled account, newest first. */
16288
16310
  const WsServerListProviderResetCreditAttemptsRpc = Rpc.make(WS_METHODS.serverListProviderResetCreditAttempts, {
16289
- payload: Schema$1.Struct({ instanceId: ProviderInstanceId }),
16311
+ payload: ResetCreditTarget,
16290
16312
  success: Schema$1.Struct({ attempts: Schema$1.Array(ProviderResetCreditAttempt) }),
16291
16313
  error: Schema$1.Union([ProviderResetCreditError, EnvironmentAuthorizationError])
16292
16314
  });
@@ -33511,7 +33533,7 @@ const ManifestFile = Schema$1.Struct({
33511
33533
  directories: Schema$1.Record(Schema$1.String, Schema$1.Array(ManifestEntry))
33512
33534
  });
33513
33535
  const ManifestFileFromJson = Schema$1.fromJsonString(ManifestFile);
33514
- const decodeManifest$1 = Schema$1.decodeUnknownEffect(ManifestFileFromJson);
33536
+ const decodeManifest = Schema$1.decodeUnknownEffect(ManifestFileFromJson);
33515
33537
  const encodeManifest = Schema$1.encodeEffect(ManifestFileFromJson);
33516
33538
  const EMPTY = {
33517
33539
  version: 1,
@@ -33528,7 +33550,7 @@ const EMPTY = {
33528
33550
  const readSkillManifest = Effect.fn("skillManifest.read")(function* (manifestPath) {
33529
33551
  const raw = yield* (yield* FileSystem.FileSystem).readFileString(manifestPath).pipe(Effect.orElseSucceed(() => void 0));
33530
33552
  if (raw === void 0) return EMPTY;
33531
- return yield* decodeManifest$1(raw).pipe(Effect.orElseSucceed(() => EMPTY));
33553
+ return yield* decodeManifest(raw).pipe(Effect.orElseSucceed(() => EMPTY));
33532
33554
  });
33533
33555
  const entriesFor = (manifest, skillsRoot) => manifest.directories[skillsRoot] ?? [];
33534
33556
  const withEntriesFor = (manifest, skillsRoot, entries) => ({
@@ -37146,7 +37168,7 @@ function collectForkedAttachmentCopies(threadId, rows) {
37146
37168
  }
37147
37169
  return copies;
37148
37170
  }
37149
- function isRecord$6(value) {
37171
+ function isRecord$7(value) {
37150
37172
  return value !== null && typeof value === "object" && !Array.isArray(value);
37151
37173
  }
37152
37174
  /**
@@ -37157,7 +37179,7 @@ function isRecord$6(value) {
37157
37179
  function buildForkedProviderBinding(threadId, source) {
37158
37180
  if (source === void 0) return { rejection: "no-binding" };
37159
37181
  if (!FORKABLE_PROVIDERS.has(source.provider)) return { rejection: "provider-cannot-fork" };
37160
- if (!isRecord$6(source.resumeCursor) || typeof source.resumeCursor.resume !== "string") return { rejection: "no-resume-cursor" };
37182
+ if (!isRecord$7(source.resumeCursor) || typeof source.resumeCursor.resume !== "string") return { rejection: "no-resume-cursor" };
37161
37183
  return { binding: {
37162
37184
  threadId,
37163
37185
  provider: source.provider,
@@ -62754,18 +62776,18 @@ function deriveToolActivityPresentation(input) {
62754
62776
  }
62755
62777
  //#endregion
62756
62778
  //#region src/provider/acp/AcpRuntimeModel.ts
62757
- function isRecord$5(value) {
62779
+ function isRecord$6(value) {
62758
62780
  return typeof value === "object" && value !== null && !Array.isArray(value);
62759
62781
  }
62760
62782
  function isSessionModelState(value) {
62761
- if (!isRecord$5(value) || typeof value.currentModelId !== "string") return false;
62783
+ if (!isRecord$6(value) || typeof value.currentModelId !== "string") return false;
62762
62784
  if (!Array.isArray(value.availableModels)) return false;
62763
- return value.availableModels.every((model) => isRecord$5(model) && typeof model.modelId === "string" && typeof model.name === "string" && (model.description === void 0 || model.description === null || typeof model.description === "string"));
62785
+ return value.availableModels.every((model) => isRecord$6(model) && typeof model.modelId === "string" && typeof model.name === "string" && (model.description === void 0 || model.description === null || typeof model.description === "string"));
62764
62786
  }
62765
62787
  function isSessionModeState(value) {
62766
- if (!isRecord$5(value) || typeof value.currentModeId !== "string") return false;
62788
+ if (!isRecord$6(value) || typeof value.currentModeId !== "string") return false;
62767
62789
  if (!Array.isArray(value.availableModes)) return false;
62768
- return value.availableModes.every((mode) => isRecord$5(mode) && typeof mode.id === "string" && typeof mode.name === "string" && (mode.description === void 0 || typeof mode.description === "string"));
62790
+ return value.availableModes.every((mode) => isRecord$6(mode) && typeof mode.id === "string" && typeof mode.name === "string" && (mode.description === void 0 || typeof mode.description === "string"));
62769
62791
  }
62770
62792
  function extractModelConfigId(sessionResponse) {
62771
62793
  const configOptions = sessionResponse.configOptions;
@@ -62841,7 +62863,7 @@ function extractCommandFromTitle(title) {
62841
62863
  return /`([^`]+)`/.exec(title)?.[1]?.trim() || void 0;
62842
62864
  }
62843
62865
  function extractToolCallCommand(rawInput, title) {
62844
- if (isRecord$5(rawInput)) {
62866
+ if (isRecord$6(rawInput)) {
62845
62867
  const directCommand = normalizeCommandValue(rawInput.command);
62846
62868
  if (directCommand) return directCommand;
62847
62869
  const executable = typeof rawInput.executable === "string" ? rawInput.executable.trim() : "";
@@ -62963,7 +62985,7 @@ function parsePermissionRequest(params) {
62963
62985
  }
62964
62986
  function sessionUpdateIsReplay(params) {
62965
62987
  const meta = params._meta;
62966
- return isRecord$5(meta) && meta.isReplay === true;
62988
+ return isRecord$6(meta) && meta.isReplay === true;
62967
62989
  }
62968
62990
  const waitForSessionLoadReplayIdle = (input) => Effect.gen(function* () {
62969
62991
  const pollInterval = Duration.millis(25);
@@ -62978,8 +63000,8 @@ const waitForSessionLoadReplayIdle = (input) => Effect.gen(function* () {
62978
63000
  });
62979
63001
  function syntheticLoadSessionResponseFromInitialize(initializeResult) {
62980
63002
  const meta = initializeResult._meta;
62981
- const modelState = isRecord$5(meta) ? meta.modelState : void 0;
62982
- const modeState = isRecord$5(meta) ? meta.modeState : void 0;
63003
+ const modelState = isRecord$6(meta) ? meta.modelState : void 0;
63004
+ const modeState = isRecord$6(meta) ? meta.modeState : void 0;
62983
63005
  const models = isSessionModelState(modelState) ? modelState : void 0;
62984
63006
  const modes = isSessionModeState(modeState) ? modeState : void 0;
62985
63007
  return {
@@ -67083,24 +67105,426 @@ function hasValidClaudeManifestAdapters(manifest) {
67083
67105
  return Object.values(catalog.profiles).every((profile) => Option.isSome(decodeClaudeProfileAdapter(profile.adapter ?? {}))) && catalog.models.every((model) => Option.isSome(decodeClaudeModelAdapter(model.adapter ?? {})));
67084
67106
  }
67085
67107
  //#endregion
67108
+ //#region src/usage/usageSourceHttp.ts
67109
+ const MAX_RESPONSE_BYTES$1 = 1024 * 1024;
67110
+ const LOOPBACK_HOSTS$1 = /* @__PURE__ */ new Set([
67111
+ "localhost",
67112
+ "127.0.0.1",
67113
+ "[::1]"
67114
+ ]);
67115
+ /** The management key stays on the configured origin, including redirects. */
67116
+ async function readManagementJson(config, path, body, signal) {
67117
+ const base = new URL(config.url);
67118
+ if (base.username || base.password || base.search || base.hash || base.protocol !== "https:" && !(base.protocol === "http:" && LOOPBACK_HOSTS$1.has(base.hostname))) throw new Error("Invalid usage source origin");
67119
+ if (path !== "auth-files" && path !== "api-call" && !/^model-definitions\/[a-z0-9-]+$/.test(path)) throw new Error("Unsupported management operation");
67120
+ const response = await fetch(new URL(`/v0/management/${path}`, base), {
67121
+ method: body === void 0 ? "GET" : "POST",
67122
+ redirect: "error",
67123
+ signal,
67124
+ headers: {
67125
+ authorization: `Bearer ${config.managementKey}`,
67126
+ "content-type": "application/json"
67127
+ },
67128
+ ...body === void 0 ? {} : { body: JSON.stringify(body) }
67129
+ });
67130
+ if (!response.ok || !response.body) {
67131
+ await response.body?.cancel();
67132
+ throw new UsageLimitSourceError({ detail: response.status === 401 || response.status === 403 ? `The usage source rejected its management key (HTTP ${response.status}). Edit the source under Usage sources to update the management key; a provider API key cannot replace it.` : `The usage source management request failed (HTTP ${response.status}). Check the source URL and management API availability.` });
67133
+ }
67134
+ const reader = response.body.getReader();
67135
+ const chunks = [];
67136
+ let total = 0;
67137
+ try {
67138
+ for (;;) {
67139
+ const chunk = await reader.read();
67140
+ if (chunk.done) break;
67141
+ total += chunk.value.byteLength;
67142
+ if (total > MAX_RESPONSE_BYTES$1) throw new Error("Usage source response too large");
67143
+ chunks.push(chunk.value);
67144
+ }
67145
+ return JSON.parse(Buffer.concat(chunks).toString("utf8"));
67146
+ } finally {
67147
+ await reader.cancel().catch(() => void 0);
67148
+ reader.releaseLock();
67149
+ }
67150
+ }
67151
+ //#endregion
67152
+ //#region src/provider/externalModelCatalog.ts
67153
+ /**
67154
+ * External model list folded over the bundled manifest. Sources in order: the
67155
+ * user's CLIProxyAPI (CPA) usage source, models.dev, then OpenRouter. Each
67156
+ * provider comes from the first source that lists it.
67157
+ *
67158
+ * The external list decides which Anthropic, OpenAI and Google models exist,
67159
+ * their names, context sizes and which one is current in each family. The
67160
+ * bundled manifest keeps what only P4 Code knows: Claude Code option profiles
67161
+ * (ultracode, effort mapping), minimum CLI versions, aliases and Antigravity's
67162
+ * effort-suffixed slugs. A model the bundle does not know yet inherits the
67163
+ * newest bundled model of its family.
67164
+ */
67165
+ const MODELS_DEV_URL = "https://models.dev/api.json";
67166
+ const OPENROUTER_MODELS_URL = "https://openrouter.ai/api/v1/models";
67167
+ const ExternalProvider = Schema$1.Literals([
67168
+ "anthropic",
67169
+ "openai",
67170
+ "google"
67171
+ ]);
67172
+ const EXTERNAL_PROVIDERS = [
67173
+ "anthropic",
67174
+ "openai",
67175
+ "google"
67176
+ ];
67177
+ /** CPA `model-definitions` channels per provider. Its Google channels trail models.dev. */
67178
+ const CPA_CHANNELS = [
67179
+ {
67180
+ provider: "anthropic",
67181
+ channel: "claude"
67182
+ },
67183
+ {
67184
+ provider: "openai",
67185
+ channel: "codex-pro"
67186
+ },
67187
+ {
67188
+ provider: "openai",
67189
+ channel: "codex-plus"
67190
+ },
67191
+ {
67192
+ provider: "openai",
67193
+ channel: "codex-team"
67194
+ },
67195
+ {
67196
+ provider: "openai",
67197
+ channel: "codex-free"
67198
+ }
67199
+ ];
67200
+ const ExternalModel = Schema$1.Struct({
67201
+ provider: ExternalProvider,
67202
+ id: Schema$1.String,
67203
+ name: Schema$1.String,
67204
+ family: Schema$1.String,
67205
+ /** ISO date; the newest model of a family is its current one. */
67206
+ releaseDate: Schema$1.optional(Schema$1.String),
67207
+ contextTokens: Schema$1.optional(Schema$1.Number),
67208
+ /** Effort levels the model accepts, when the source lists them. */
67209
+ effort: Schema$1.optional(Schema$1.Array(Schema$1.String)),
67210
+ /** Whether a fast mode exists, when the source says. */
67211
+ fastMode: Schema$1.optional(Schema$1.Boolean)
67212
+ });
67213
+ const isRecord$5 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
67214
+ const stringOr = (value) => typeof value === "string" && value.trim() !== "" ? value.trim() : void 0;
67215
+ const numberOr = (value) => typeof value === "number" && Number.isFinite(value) && value > 0 ? value : void 0;
67216
+ /** Coding agents only run tool-calling models that answer in text; image, audio and TTS models share families with them. */
67217
+ const isTextOnly = (modalities) => Array.isArray(modalities) && modalities.length === 1 && modalities[0] === "text";
67218
+ /** Family of a model id with its version tokens removed: `claude-opus-5-5` is `claude-opus`. */
67219
+ function familyOf(id) {
67220
+ return id.split("-").filter((token) => !/^\d+(\.\d+)*$/.test(token)).join("-");
67221
+ }
67222
+ /** Parse one CPA `/v0/management/model-definitions/:channel` response. */
67223
+ function parseCpaModelDefinitions(json, provider) {
67224
+ if (!isRecord$5(json) || !Array.isArray(json.models)) return [];
67225
+ return json.models.flatMap((raw) => {
67226
+ if (!isRecord$5(raw)) return [];
67227
+ const id = stringOr(raw.id);
67228
+ const output = raw.supportedOutputModalities;
67229
+ if (!id || output !== void 0 && !isTextOnly(output)) return [];
67230
+ const created = numberOr(raw.created);
67231
+ const contextTokens = numberOr(raw.context_length) ?? numberOr(raw.inputTokenLimit);
67232
+ const levels = isRecord$5(raw.thinking) ? raw.thinking.levels : void 0;
67233
+ return [{
67234
+ provider,
67235
+ id,
67236
+ name: stringOr(raw.display_name) ?? id,
67237
+ family: familyOf(id),
67238
+ ...created ? { releaseDate: (/* @__PURE__ */ new Date(created * 1e3)).toISOString() } : {},
67239
+ ...contextTokens ? { contextTokens } : {},
67240
+ ...Array.isArray(levels) ? { effort: levels.filter((level) => typeof level === "string") } : {}
67241
+ }];
67242
+ });
67243
+ }
67244
+ /** Parse `https://models.dev/api.json`; null when it lists none of our providers. */
67245
+ function parseModelsDev(json) {
67246
+ if (!isRecord$5(json)) return null;
67247
+ const models = [];
67248
+ for (const provider of EXTERNAL_PROVIDERS) {
67249
+ const entry = json[provider];
67250
+ if (!isRecord$5(entry) || !isRecord$5(entry.models)) continue;
67251
+ for (const raw of Object.values(entry.models)) {
67252
+ if (!isRecord$5(raw)) continue;
67253
+ const id = stringOr(raw.id);
67254
+ const output = isRecord$5(raw.modalities) ? raw.modalities.output : void 0;
67255
+ if (!id || raw.tool_call !== true || !isTextOnly(output)) continue;
67256
+ const effort = Array.isArray(raw.reasoning_options) ? raw.reasoning_options.find((option) => isRecord$5(option) && option.type === "effort") : void 0;
67257
+ const effortValues = isRecord$5(effort) && Array.isArray(effort.values) ? effort.values.filter((value) => typeof value === "string") : void 0;
67258
+ const modes = isRecord$5(raw.experimental) ? raw.experimental.modes : void 0;
67259
+ const releaseDate = stringOr(raw.release_date);
67260
+ const contextTokens = isRecord$5(raw.limit) ? numberOr(raw.limit.context) : void 0;
67261
+ models.push({
67262
+ provider,
67263
+ id,
67264
+ name: stringOr(raw.name) ?? id,
67265
+ family: stringOr(raw.family) ?? familyOf(id),
67266
+ ...releaseDate ? { releaseDate } : {},
67267
+ ...contextTokens ? { contextTokens } : {},
67268
+ ...effortValues ? { effort: effortValues } : {},
67269
+ fastMode: isRecord$5(modes) && modes.fast !== void 0
67270
+ });
67271
+ }
67272
+ }
67273
+ return models.length > 0 ? models : null;
67274
+ }
67275
+ /** Parse `https://openrouter.ai/api/v1/models`; null when it lists none of our providers. */
67276
+ function parseOpenRouter(json) {
67277
+ if (!isRecord$5(json) || !Array.isArray(json.data)) return null;
67278
+ const models = [];
67279
+ for (const raw of json.data) {
67280
+ if (!isRecord$5(raw)) continue;
67281
+ const fullId = stringOr(raw.id);
67282
+ if (!fullId || fullId.includes(":")) continue;
67283
+ const output = isRecord$5(raw.architecture) ? raw.architecture.output_modalities : void 0;
67284
+ const parameters = Array.isArray(raw.supported_parameters) ? raw.supported_parameters : [];
67285
+ if (!isTextOnly(output) || !parameters.includes("tools")) continue;
67286
+ const [prefix, rawId] = fullId.split("/", 2);
67287
+ const provider = EXTERNAL_PROVIDERS.find((candidate) => candidate === prefix);
67288
+ if (!provider || !rawId) continue;
67289
+ const id = provider === "anthropic" ? rawId.replace(/(\d)\.(\d)/g, "$1-$2") : rawId;
67290
+ const created = numberOr(raw.created);
67291
+ const contextTokens = numberOr(raw.context_length);
67292
+ models.push({
67293
+ provider,
67294
+ id,
67295
+ name: (stringOr(raw.name) ?? id).replace(/^[^:]+:\s*/, ""),
67296
+ family: familyOf(id),
67297
+ ...created ? { releaseDate: (/* @__PURE__ */ new Date(created * 1e3)).toISOString() } : {},
67298
+ ...contextTokens ? { contextTokens } : {}
67299
+ });
67300
+ }
67301
+ return models.length > 0 ? models : null;
67302
+ }
67303
+ /** Providers the list has no models for. */
67304
+ function missingProviders(models) {
67305
+ return EXTERNAL_PROVIDERS.filter((provider) => !models.some((model) => model.provider === provider));
67306
+ }
67307
+ /** Add `next` for the providers `models` lacks; ids already present win. */
67308
+ function fillMissingProviders(models, next) {
67309
+ const missing = new Set(missingProviders(models));
67310
+ return [...models, ...next.filter((model) => missing.has(model.provider))];
67311
+ }
67312
+ const DATED_SNAPSHOT = /-\d{8}$/;
67313
+ const releaseMs = (model) => {
67314
+ const parsed = model?.releaseDate ? Date.parse(model.releaseDate) : NaN;
67315
+ return Number.isNaN(parsed) ? 0 : parsed;
67316
+ };
67317
+ /** A family the bundle never listed is retired once its newest release trails the provider's by this much. */
67318
+ const CURRENT_FAMILY_WINDOW_MS = 4320 * 60 * 60 * 1e3;
67319
+ /**
67320
+ * Ids that are current: the newest release of each family, and `-latest`
67321
+ * pointers. Families the bundle lists keep their newest model current however
67322
+ * long the next release takes; other families and `-latest` pointers must be
67323
+ * recent enough to still be shipping.
67324
+ */
67325
+ function currentIds(models, bundledFamilies) {
67326
+ const newest = /* @__PURE__ */ new Map();
67327
+ let providerNewest = 0;
67328
+ for (const model of models) {
67329
+ const released = releaseMs(model);
67330
+ newest.set(model.family, Math.max(newest.get(model.family) ?? 0, released));
67331
+ providerNewest = Math.max(providerNewest, released);
67332
+ }
67333
+ return new Set(models.filter((model) => {
67334
+ const released = releaseMs(model);
67335
+ const recent = providerNewest - released <= CURRENT_FAMILY_WINDOW_MS;
67336
+ if (model.id.endsWith("-latest")) return recent;
67337
+ return released === newest.get(model.family) && (recent || bundledFamilies.has(model.family));
67338
+ }).map((model) => model.id));
67339
+ }
67340
+ /** Effort values only Claude Code offers, with the API effort each one needs. */
67341
+ const CLAUDE_CODE_EFFORTS = {
67342
+ ultracode: "xhigh",
67343
+ ultrathink: null
67344
+ };
67345
+ /** Template profile narrowed to what the external entry says the model supports. */
67346
+ function deriveClaudeProfile(template, model) {
67347
+ const descriptors = (template?.capabilities?.optionDescriptors ?? []).flatMap((descriptor) => {
67348
+ if (descriptor.id === "fastMode" && model.fastMode === false) return [];
67349
+ if (descriptor.id !== "effort" || descriptor.type !== "select" || !model.effort) return [descriptor];
67350
+ const supported = new Set(model.effort);
67351
+ const options = descriptor.options.filter((option) => {
67352
+ const needs = CLAUDE_CODE_EFFORTS[option.id];
67353
+ return supported.has(option.id) || needs === null || needs !== void 0 && supported.has(needs);
67354
+ });
67355
+ return options.length > 0 ? [{
67356
+ ...descriptor,
67357
+ options
67358
+ }] : [];
67359
+ });
67360
+ const adapter = isRecord$5(template?.adapter) ? template.adapter : {};
67361
+ const claudeCode = isRecord$5(adapter.claudeCode) ? adapter.claudeCode : {};
67362
+ const hasContextPicker = descriptors.some((descriptor) => descriptor.id === "contextWindow");
67363
+ return {
67364
+ capabilities: { optionDescriptors: descriptors },
67365
+ adapter: {
67366
+ ...adapter,
67367
+ claudeCode: {
67368
+ ...claudeCode,
67369
+ ...!hasContextPicker && model.contextTokens ? { fixedContextWindowTokens: model.contextTokens } : {}
67370
+ }
67371
+ }
67372
+ };
67373
+ }
67374
+ /** `claude-opus-6-1` reads `opus-6.1` and `claude-opus-6.1`; `claude-opus-6` reads `opus-6`. */
67375
+ function shortAliases(slug) {
67376
+ const dotted = slug.replace(/-(\d+)-(\d+)$/, "-$1.$2");
67377
+ return [.../* @__PURE__ */ new Set([dotted.replace(/^claude-/, ""), dotted])].filter((alias) => alias !== slug);
67378
+ }
67379
+ function deriveClaudeCatalog(catalog, external) {
67380
+ const models = external.filter((model) => !DATED_SNAPSHOT.test(model.id));
67381
+ const current = currentIds(models, new Set(catalog.models.map((entry) => familyOf(entry.slug))));
67382
+ const byId = new Map(models.map((model) => [model.id, model]));
67383
+ const profiles = { ...catalog.profiles };
67384
+ const entries = catalog.models.map((entry) => {
67385
+ if (!byId.get(entry.slug)) return { ...entry };
67386
+ return {
67387
+ ...entry,
67388
+ status: current.has(entry.slug) ? "current" : "legacy"
67389
+ };
67390
+ });
67391
+ const bundledSlugs = new Set(catalog.models.map((entry) => entry.slug));
67392
+ for (const model of models) {
67393
+ if (bundledSlugs.has(model.id) || !current.has(model.id)) continue;
67394
+ const template = catalog.models.filter((entry) => familyOf(entry.slug) === model.family).toSorted((left, right) => releaseMs(byId.get(right.slug)) - releaseMs(byId.get(left.slug))).at(0);
67395
+ const profileKey = `models.dev:${model.id}`;
67396
+ profiles[profileKey] = deriveClaudeProfile(template?.profile ? catalog.profiles[template.profile] : void 0, model);
67397
+ const aliases = shortAliases(model.id);
67398
+ entries.push({
67399
+ slug: model.id,
67400
+ name: model.name,
67401
+ ...aliases.length > 0 ? { aliases } : {},
67402
+ status: "current",
67403
+ profile: profileKey,
67404
+ ...template?.adapter !== void 0 ? { adapter: template.adapter } : {}
67405
+ });
67406
+ }
67407
+ for (const entry of entries) {
67408
+ const familyAlias = familyOf(entry.slug).replace(/^claude-/, "");
67409
+ if (entry.status === "current" || !entry.aliases?.includes(familyAlias)) continue;
67410
+ const successor = entries.find((candidate) => candidate.status === "current" && familyOf(candidate.slug) === familyOf(entry.slug));
67411
+ if (!successor) continue;
67412
+ entry.aliases = entry.aliases.filter((alias) => alias !== familyAlias);
67413
+ successor.aliases = [familyAlias, ...successor.aliases ?? []];
67414
+ }
67415
+ return {
67416
+ catalog: {
67417
+ ...catalog,
67418
+ ...withCurrentDefault(catalog, entries),
67419
+ profiles,
67420
+ models: entries
67421
+ },
67422
+ current: entries.filter((entry) => entry.status === "current").map((entry) => entry.slug)
67423
+ };
67424
+ }
67425
+ /** Keep the chat default; when it went legacy, move it to its family's current model. */
67426
+ function withCurrentDefault(catalog, entries, matches = (candidate, previous) => familyOf(candidate.slug) === familyOf(previous.slug)) {
67427
+ const chat = catalog.defaults?.chat;
67428
+ const previous = entries.find((entry) => entry.slug === chat);
67429
+ if (!previous || previous.status === "current") return { defaults: catalog.defaults };
67430
+ const next = entries.find((entry) => entry.status === "current" && matches(entry, previous));
67431
+ return { defaults: {
67432
+ ...catalog.defaults,
67433
+ chat: next?.slug ?? chat
67434
+ } };
67435
+ }
67436
+ const ANTIGRAVITY_EFFORT_SUFFIX = /-(high|medium|low|minimal)$/;
67437
+ const effortLabel = (effort) => effort.charAt(0).toUpperCase() + effort.slice(1);
67438
+ /**
67439
+ * Antigravity slugs carry their effort (`gemini-3.8-flash-high`). Every current
67440
+ * Google model in a family the bundle already offers gets the same variants.
67441
+ */
67442
+ function deriveAntigravityCatalog(catalog, external) {
67443
+ const byId = new Map(external.map((model) => [model.id, model]));
67444
+ const baseOf = (slug) => slug.replace(ANTIGRAVITY_EFFORT_SUFFIX, "");
67445
+ const suffixes = [...new Set(catalog.models.flatMap((entry) => entry.slug.match(ANTIGRAVITY_EFFORT_SUFFIX)?.[1] ?? []))];
67446
+ const families = new Set(catalog.models.flatMap((entry) => byId.get(baseOf(entry.slug))?.family ?? []));
67447
+ const current = currentIds(external, families);
67448
+ const entries = catalog.models.map((entry) => {
67449
+ const known = byId.get(baseOf(entry.slug));
67450
+ if (!known) return entry;
67451
+ return {
67452
+ ...entry,
67453
+ status: current.has(known.id) ? "current" : "legacy"
67454
+ };
67455
+ });
67456
+ const slugs = new Set(entries.map((entry) => entry.slug));
67457
+ for (const model of external) {
67458
+ if (!families.has(model.family) || !current.has(model.id) || model.id.endsWith("-latest")) continue;
67459
+ for (const suffix of suffixes) {
67460
+ const slug = `${model.id}-${suffix}`;
67461
+ if (slugs.has(slug) || model.effort && !model.effort.includes(suffix)) continue;
67462
+ slugs.add(slug);
67463
+ entries.push({
67464
+ slug,
67465
+ name: `${model.name} (${effortLabel(suffix)})`,
67466
+ status: "current"
67467
+ });
67468
+ }
67469
+ }
67470
+ return {
67471
+ catalog: {
67472
+ ...catalog,
67473
+ ...withCurrentDefault(catalog, entries, (candidate, previous) => candidate.slug.match(ANTIGRAVITY_EFFORT_SUFFIX)?.[1] === previous.slug.match(ANTIGRAVITY_EFFORT_SUFFIX)?.[1]),
67474
+ models: entries
67475
+ },
67476
+ current: entries.filter((entry) => entry.status === "current").map((entry) => entry.slug)
67477
+ };
67478
+ }
67479
+ /** Codex discovers its own models; the manifest only says which are current. */
67480
+ function deriveCodexCurrent(bundledCurrent, external) {
67481
+ const byId = new Map(external.map((model) => [model.id, model]));
67482
+ const current = currentIds(external, new Set(bundledCurrent.map((slug) => byId.get(slug)?.family ?? familyOf(slug))));
67483
+ const known = new Set(byId.keys());
67484
+ return [.../* @__PURE__ */ new Set([...current, ...bundledCurrent.filter((slug) => !known.has(slug))])];
67485
+ }
67486
+ /** Fold the external model list over the bundled manifest. */
67487
+ function deriveModelManifest(bundled, external) {
67488
+ const forProvider = (provider) => external.filter((model) => model.provider === provider);
67489
+ const providers = { ...bundled.providers };
67490
+ const currentModels = { ...bundled.currentModels };
67491
+ const claude = bundled.providers?.claudeAgent;
67492
+ if (claude) {
67493
+ const derived = deriveClaudeCatalog(claude, forProvider("anthropic"));
67494
+ providers.claudeAgent = derived.catalog;
67495
+ currentModels.claudeAgent = derived.current;
67496
+ }
67497
+ const antigravity = bundled.providers?.antigravity;
67498
+ if (antigravity) {
67499
+ const derived = deriveAntigravityCatalog(antigravity, forProvider("google"));
67500
+ providers.antigravity = derived.catalog;
67501
+ currentModels.antigravity = derived.current;
67502
+ }
67503
+ currentModels.codex = deriveCodexCurrent(bundled.currentModels.codex ?? [], forProvider("openai"));
67504
+ return {
67505
+ ...bundled,
67506
+ currentModels,
67507
+ providers
67508
+ };
67509
+ }
67510
+ //#endregion
67086
67511
  //#region src/provider/model-manifest.json
67087
67512
  var model_manifest_default = {
67088
67513
  version: 1,
67089
- updatedAt: "2026-09-28T20:00:00Z",
67514
+ updatedAt: "2026-10-07T19:00:00Z",
67090
67515
  currentModels: {
67091
67516
  "codex": [
67092
67517
  "gpt-6-astra",
67093
- "gpt-5.6-luna",
67094
- "gpt-5.6-terra",
67095
- "gpt-5.6-sol",
67518
+ "gpt-6.1-sol",
67519
+ "gpt-6-luna",
67096
67520
  "gpt-daybreak-blue-latest",
67097
67521
  "gpt-daybreak-red-latest"
67098
67522
  ],
67099
67523
  "claudeAgent": [
67100
67524
  "claude-fable-5-1",
67101
- "claude-opus-5",
67525
+ "claude-opus-5-5",
67102
67526
  "claude-sonnet-5-5",
67103
- "claude-sonnet-5"
67527
+ "claude-haiku-5-5"
67104
67528
  ],
67105
67529
  "antigravity": [
67106
67530
  "gemini-3.8-flash-high",
@@ -67110,7 +67534,7 @@ var model_manifest_default = {
67110
67534
  },
67111
67535
  providers: {
67112
67536
  "claudeAgent": {
67113
- "defaults": { "chat": "claude-sonnet-5" },
67537
+ "defaults": { "chat": "claude-fable-5-1" },
67114
67538
  "profiles": {
67115
67539
  "fable-5": {
67116
67540
  "capabilities": { "optionDescriptors": [{
@@ -67124,13 +67548,60 @@ var model_manifest_default = {
67124
67548
  },
67125
67549
  {
67126
67550
  "id": "medium",
67127
- "label": "Medium"
67551
+ "label": "Medium",
67552
+ "isDefault": true
67128
67553
  },
67129
67554
  {
67130
67555
  "id": "high",
67131
- "label": "High",
67556
+ "label": "High"
67557
+ },
67558
+ {
67559
+ "id": "xhigh",
67560
+ "label": "Extra High"
67561
+ },
67562
+ {
67563
+ "id": "max",
67564
+ "label": "Max"
67565
+ },
67566
+ {
67567
+ "id": "ultracode",
67568
+ "label": "Ultracode",
67569
+ "description": "xhigh effort plus multi-agent workflow orchestration"
67570
+ },
67571
+ {
67572
+ "id": "ultrathink",
67573
+ "label": "Ultrathink"
67574
+ }
67575
+ ],
67576
+ "promptInjectedValues": ["ultrathink"]
67577
+ }] },
67578
+ "adapter": { "claudeCode": {
67579
+ "effortMap": {
67580
+ "ultracode": "xhigh",
67581
+ "ultrathink": null
67582
+ },
67583
+ "fixedContextWindowTokens": 1e6
67584
+ } }
67585
+ },
67586
+ "opus-5-5": {
67587
+ "capabilities": { "optionDescriptors": [{
67588
+ "id": "effort",
67589
+ "label": "Reasoning",
67590
+ "type": "select",
67591
+ "options": [
67592
+ {
67593
+ "id": "low",
67594
+ "label": "Low"
67595
+ },
67596
+ {
67597
+ "id": "medium",
67598
+ "label": "Medium",
67132
67599
  "isDefault": true
67133
67600
  },
67601
+ {
67602
+ "id": "high",
67603
+ "label": "High"
67604
+ },
67134
67605
  {
67135
67606
  "id": "xhigh",
67136
67607
  "label": "Extra High"
@@ -67151,99 +67622,67 @@ var model_manifest_default = {
67151
67622
  ],
67152
67623
  "promptInjectedValues": ["ultrathink"]
67153
67624
  }, {
67154
- "id": "contextWindow",
67155
- "label": "Context Window",
67156
- "type": "select",
67157
- "options": [{
67158
- "id": "200k",
67159
- "label": "200k"
67160
- }, {
67161
- "id": "1m",
67162
- "label": "1M",
67163
- "isDefault": true
67164
- }]
67625
+ "id": "fastMode",
67626
+ "label": "Fast Mode",
67627
+ "type": "boolean"
67165
67628
  }] },
67166
67629
  "adapter": { "claudeCode": {
67167
67630
  "effortMap": {
67168
67631
  "ultracode": "xhigh",
67169
67632
  "ultrathink": null
67170
67633
  },
67171
- "modelSuffixes": { "contextWindow": { "1m": "[1m]" } },
67172
- "contextWindowTokens": {
67173
- "200k": 2e5,
67174
- "1m": 1e6
67175
- }
67634
+ "fixedContextWindowTokens": 1e6
67176
67635
  } }
67177
67636
  },
67178
67637
  "opus-5": {
67179
- "capabilities": { "optionDescriptors": [
67180
- {
67181
- "id": "effort",
67182
- "label": "Reasoning",
67183
- "type": "select",
67184
- "options": [
67185
- {
67186
- "id": "low",
67187
- "label": "Low"
67188
- },
67189
- {
67190
- "id": "medium",
67191
- "label": "Medium"
67192
- },
67193
- {
67194
- "id": "high",
67195
- "label": "High",
67196
- "isDefault": true
67197
- },
67198
- {
67199
- "id": "xhigh",
67200
- "label": "Extra High"
67201
- },
67202
- {
67203
- "id": "max",
67204
- "label": "Max"
67205
- },
67206
- {
67207
- "id": "ultracode",
67208
- "label": "Ultracode",
67209
- "description": "xhigh effort plus multi-agent workflow orchestration"
67210
- },
67211
- {
67212
- "id": "ultrathink",
67213
- "label": "Ultrathink"
67214
- }
67215
- ],
67216
- "promptInjectedValues": ["ultrathink"]
67217
- },
67218
- {
67219
- "id": "fastMode",
67220
- "label": "Fast Mode",
67221
- "type": "boolean"
67222
- },
67223
- {
67224
- "id": "contextWindow",
67225
- "label": "Context Window",
67226
- "type": "select",
67227
- "options": [{
67228
- "id": "200k",
67229
- "label": "200k"
67230
- }, {
67231
- "id": "1m",
67232
- "label": "1M",
67638
+ "capabilities": { "optionDescriptors": [{
67639
+ "id": "effort",
67640
+ "label": "Reasoning",
67641
+ "type": "select",
67642
+ "options": [
67643
+ {
67644
+ "id": "low",
67645
+ "label": "Low"
67646
+ },
67647
+ {
67648
+ "id": "medium",
67649
+ "label": "Medium"
67650
+ },
67651
+ {
67652
+ "id": "high",
67653
+ "label": "High",
67233
67654
  "isDefault": true
67234
- }]
67235
- }
67236
- ] },
67655
+ },
67656
+ {
67657
+ "id": "xhigh",
67658
+ "label": "Extra High"
67659
+ },
67660
+ {
67661
+ "id": "max",
67662
+ "label": "Max"
67663
+ },
67664
+ {
67665
+ "id": "ultracode",
67666
+ "label": "Ultracode",
67667
+ "description": "xhigh effort plus multi-agent workflow orchestration"
67668
+ },
67669
+ {
67670
+ "id": "ultrathink",
67671
+ "label": "Ultrathink"
67672
+ }
67673
+ ],
67674
+ "promptInjectedValues": ["ultrathink"]
67675
+ }, {
67676
+ "id": "fastMode",
67677
+ "label": "Fast Mode",
67678
+ "type": "boolean"
67679
+ }] },
67237
67680
  "adapter": { "claudeCode": {
67238
67681
  "effortMap": {
67239
67682
  "ultracode": "xhigh",
67240
67683
  "ultrathink": null
67241
67684
  },
67242
- "modelSuffixes": { "contextWindow": { "1m": "[1m]" } },
67243
- "contextWindowTokens": {
67244
- "200k": 2e5,
67245
- "1m": 1e6
67246
- }
67685
+ "fixedContextWindowTokens": 1e6
67247
67686
  } }
67248
67687
  },
67249
67688
  "opus-4-8": {
@@ -67431,7 +67870,7 @@ var model_manifest_default = {
67431
67870
  "label": "Fast Mode",
67432
67871
  "type": "boolean"
67433
67872
  }] },
67434
- "adapter": { "claudeCode": {} }
67873
+ "adapter": { "claudeCode": { "fixedContextWindowTokens": 2e5 } }
67435
67874
  },
67436
67875
  "sonnet-5": {
67437
67876
  "capabilities": { "optionDescriptors": [{
@@ -67466,26 +67905,10 @@ var model_manifest_default = {
67466
67905
  }
67467
67906
  ],
67468
67907
  "promptInjectedValues": ["ultrathink"]
67469
- }, {
67470
- "id": "contextWindow",
67471
- "label": "Context Window",
67472
- "type": "select",
67473
- "options": [{
67474
- "id": "200k",
67475
- "label": "200k",
67476
- "isDefault": true
67477
- }, {
67478
- "id": "1m",
67479
- "label": "1M"
67480
- }]
67481
67908
  }] },
67482
67909
  "adapter": { "claudeCode": {
67483
67910
  "effortMap": { "ultrathink": null },
67484
- "modelSuffixes": { "contextWindow": { "1m": "[1m]" } },
67485
- "contextWindowTokens": {
67486
- "200k": 2e5,
67487
- "1m": 1e6
67488
- }
67911
+ "fixedContextWindowTokens": 1e6
67489
67912
  } }
67490
67913
  },
67491
67914
  "sonnet-4-6": {
@@ -67542,16 +67965,81 @@ var model_manifest_default = {
67542
67965
  }
67543
67966
  } }
67544
67967
  },
67968
+ "haiku-5-5": {
67969
+ "capabilities": { "optionDescriptors": [{
67970
+ "id": "effort",
67971
+ "label": "Reasoning",
67972
+ "type": "select",
67973
+ "options": [
67974
+ {
67975
+ "id": "low",
67976
+ "label": "Low"
67977
+ },
67978
+ {
67979
+ "id": "medium",
67980
+ "label": "Medium",
67981
+ "isDefault": true
67982
+ },
67983
+ {
67984
+ "id": "high",
67985
+ "label": "High"
67986
+ },
67987
+ {
67988
+ "id": "xhigh",
67989
+ "label": "Extra High"
67990
+ },
67991
+ {
67992
+ "id": "max",
67993
+ "label": "Max"
67994
+ },
67995
+ {
67996
+ "id": "ultrathink",
67997
+ "label": "Ultrathink"
67998
+ }
67999
+ ],
68000
+ "promptInjectedValues": ["ultrathink"]
68001
+ }] },
68002
+ "adapter": { "claudeCode": {
68003
+ "effortMap": { "ultrathink": null },
68004
+ "fixedContextWindowTokens": 1e6
68005
+ } }
68006
+ },
67545
68007
  "haiku-4-5": {
67546
68008
  "capabilities": { "optionDescriptors": [{
67547
68009
  "id": "thinking",
67548
68010
  "label": "Thinking",
67549
68011
  "type": "boolean"
67550
68012
  }] },
67551
- "adapter": { "claudeCode": {} }
68013
+ "adapter": { "claudeCode": { "fixedContextWindowTokens": 2e5 } }
67552
68014
  }
67553
68015
  },
67554
68016
  "models": [
68017
+ {
68018
+ "slug": "claude-opus-5-5",
68019
+ "name": "Claude Opus 5.5",
68020
+ "aliases": [
68021
+ "opus",
68022
+ "opus-5.5",
68023
+ "claude-opus-5.5"
68024
+ ],
68025
+ "status": "current",
68026
+ "badge": "new",
68027
+ "profile": "opus-5-5",
68028
+ "adapter": { "claudeCode": { "minVersion": "2.1.280" } }
68029
+ },
68030
+ {
68031
+ "slug": "claude-sonnet-5-5",
68032
+ "name": "Claude Sonnet 5.5",
68033
+ "aliases": [
68034
+ "sonnet",
68035
+ "sonnet-5.5",
68036
+ "claude-sonnet-5.5"
68037
+ ],
68038
+ "status": "current",
68039
+ "badge": "new",
68040
+ "profile": "sonnet-5",
68041
+ "adapter": { "claudeCode": { "minVersion": "2.1.284" } }
68042
+ },
67555
68043
  {
67556
68044
  "slug": "claude-fable-5-1",
67557
68045
  "name": "Claude Fable 5.1",
@@ -67561,7 +68049,6 @@ var model_manifest_default = {
67561
68049
  "claude-fable-5.1"
67562
68050
  ],
67563
68051
  "status": "current",
67564
- "badge": "new",
67565
68052
  "profile": "fable-5",
67566
68053
  "adapter": { "claudeCode": { "minVersion": "2.1.257" } }
67567
68054
  },
@@ -67576,12 +68063,11 @@ var model_manifest_default = {
67576
68063
  "slug": "claude-opus-5",
67577
68064
  "name": "Claude Opus 5",
67578
68065
  "aliases": [
67579
- "opus",
67580
68066
  "opus-5",
67581
68067
  "claude-opus-5.0",
67582
68068
  "claude-opus-5-0"
67583
68069
  ],
67584
- "status": "current",
68070
+ "status": "legacy",
67585
68071
  "profile": "opus-5",
67586
68072
  "adapter": { "claudeCode": { "minVersion": "2.1.219" } }
67587
68073
  },
@@ -67618,25 +68104,15 @@ var model_manifest_default = {
67618
68104
  "status": "legacy",
67619
68105
  "profile": "opus-4-5"
67620
68106
  },
67621
- {
67622
- "slug": "claude-sonnet-5-5",
67623
- "name": "Claude Sonnet 5.5",
67624
- "aliases": ["sonnet-5.5", "claude-sonnet-5.5"],
67625
- "status": "current",
67626
- "badge": "new",
67627
- "profile": "sonnet-5",
67628
- "adapter": { "claudeCode": { "minVersion": "2.1.284" } }
67629
- },
67630
68107
  {
67631
68108
  "slug": "claude-sonnet-5",
67632
68109
  "name": "Claude Sonnet 5",
67633
68110
  "aliases": [
67634
- "sonnet",
67635
68111
  "sonnet-5",
67636
68112
  "claude-sonnet-5.0",
67637
68113
  "claude-sonnet-5-0"
67638
68114
  ],
67639
- "status": "current",
68115
+ "status": "legacy",
67640
68116
  "profile": "sonnet-5"
67641
68117
  },
67642
68118
  {
@@ -67650,11 +68126,23 @@ var model_manifest_default = {
67650
68126
  "status": "legacy",
67651
68127
  "profile": "sonnet-4-6"
67652
68128
  },
68129
+ {
68130
+ "slug": "claude-haiku-5-5",
68131
+ "name": "Claude Haiku 5.5",
68132
+ "aliases": [
68133
+ "haiku",
68134
+ "haiku-5.5",
68135
+ "claude-haiku-5.5"
68136
+ ],
68137
+ "status": "current",
68138
+ "badge": "new",
68139
+ "profile": "haiku-5-5",
68140
+ "adapter": { "claudeCode": { "minVersion": "2.1.293" } }
68141
+ },
67653
68142
  {
67654
68143
  "slug": "claude-haiku-4-5",
67655
68144
  "name": "Claude Haiku 4.5",
67656
68145
  "aliases": [
67657
- "haiku",
67658
68146
  "haiku-4.5",
67659
68147
  "claude-haiku-4.5",
67660
68148
  "claude-haiku-4-5-20251001"
@@ -67690,27 +68178,27 @@ var model_manifest_default = {
67690
68178
  //#endregion
67691
68179
  //#region src/provider/ModelManifest.ts
67692
68180
  /**
67693
- * ModelManifest — remote provider-model metadata with a bundled offline
67694
- * fallback.
68181
+ * ModelManifest — provider-model metadata: the bundled manifest folded with
68182
+ * the external model list from models.dev (OpenRouter as fallback).
67695
68183
  *
67696
- * Provider catalogs and legacy classification live in `model-manifest.json`.
67697
- * The bundled copy ships with every release; at runtime the service refreshes
67698
- * it from the same file on `main`. Preference order is remote, then the last
67699
- * successful on-disk copy, then the bundle. A failed fetch never fails a
67700
- * provider check.
68184
+ * Provider catalogs and legacy classification live in `model-manifest.json`,
68185
+ * which ships with every release. At runtime the service fetches the external
68186
+ * list and derives the manifest from both (`externalModelCatalog.ts`).
68187
+ * Preference order is a fresh fetch, then the last successful list on disk,
68188
+ * then the bundle alone. A failed fetch never fails a provider check.
67701
68189
  *
67702
68190
  * Providers with authoritative discovery can use only the classification
67703
68191
  * overlay. Providers with static catalogs can resolve presentation and
67704
68192
  * capabilities from `providers`, then decode their own allowlisted adapter
67705
68193
  * payload separately.
67706
68194
  */
67707
- const MODEL_MANIFEST_URL = "https://raw.githubusercontent.com/pingdotgg/t3code/main/apps/server/src/provider/model-manifest.json";
67708
68195
  /** How long a fetched manifest stays fresh before the next probe re-fetches. */
67709
68196
  const MANIFEST_TTL_MS = 3600 * 1e3;
67710
68197
  /** Minimum gap between fetch attempts after a failure, so an offline server
67711
68198
  * does not pay a network timeout on every provider check. */
67712
68199
  const MANIFEST_RETRY_MS = 300 * 1e3;
67713
- const FETCH_TIMEOUT_MS = 1e4;
68200
+ /** models.dev serves about 0.5 MB compressed, so allow more than a small JSON. */
68201
+ const FETCH_TIMEOUT_MS = 2e4;
67714
68202
  const ManifestModelStatus = Schema$1.Literals(["current", "legacy"]);
67715
68203
  const ManifestModelProfile = Schema$1.Struct({
67716
68204
  capabilities: Schema$1.optional(ModelCapabilities),
@@ -67738,11 +68226,7 @@ const ManifestProviderCatalog = Schema$1.Struct({
67738
68226
  */
67739
68227
  const ModelManifestEnvelopeSchema = Schema$1.Struct({
67740
68228
  version: Schema$1.Literal(1),
67741
- /**
67742
- * ISO date of the last edit. A release bundles its manifest, and a disk
67743
- * cache of an older edit must not outrank it. Optional so older remote
67744
- * files still decode; they count as older than any dated bundle.
67745
- */
68229
+ /** ISO date of the last edit. */
67746
68230
  updatedAt: Schema$1.optional(Schema$1.String),
67747
68231
  currentModels: Schema$1.Record(Schema$1.String, Schema$1.Array(Schema$1.String)),
67748
68232
  providers: Schema$1.optional(Schema$1.Record(Schema$1.String, ManifestProviderCatalog))
@@ -67756,13 +68240,22 @@ const hasValidProviderCatalogReferences = (manifest) => Object.values(manifest.p
67756
68240
  }) && (catalog.defaults?.chat === void 0 || slugs.has(catalog.defaults.chat));
67757
68241
  });
67758
68242
  const ModelManifestSchema = ModelManifestEnvelopeSchema.pipe(Schema$1.check(Schema$1.makeFilter(hasValidProviderCatalogReferences, { expected: "unique model slugs and existing model and profile references" }), Schema$1.makeFilter(hasValidClaudeManifestAdapters, { expected: "valid Claude adapter metadata" })));
67759
- const decodeManifest = Schema$1.decodeUnknownEffect(ModelManifestSchema);
68243
+ const decodeManifestOption = Schema$1.decodeUnknownOption(ModelManifestSchema);
68244
+ /** Public sources after the user's CPA, in order. */
68245
+ const PUBLIC_SOURCES = [{
68246
+ url: MODELS_DEV_URL,
68247
+ parse: parseModelsDev
68248
+ }, {
68249
+ url: OPENROUTER_MODELS_URL,
68250
+ parse: parseOpenRouter
68251
+ }];
67760
68252
  const BUNDLED_MODEL_MANIFEST = Schema$1.decodeUnknownSync(ModelManifestSchema)(model_manifest_default);
67761
- /** Epoch millis of the manifest's `updatedAt`, or 0 when absent or unparsable. */
67762
- function manifestUpdatedAtMs(manifest) {
67763
- if (manifest.updatedAt === void 0) return 0;
67764
- const parsed = Date.parse(manifest.updatedAt);
67765
- return Number.isNaN(parsed) ? 0 : parsed;
68253
+ /**
68254
+ * The bundle folded with an external list. A derived manifest that fails the
68255
+ * catalog checks is dropped in favour of the bundle alone.
68256
+ */
68257
+ function manifestFromExternalModels(external) {
68258
+ return Option.getOrNull(decodeManifestOption(deriveModelManifest(BUNDLED_MODEL_MANIFEST, external)));
67766
68259
  }
67767
68260
  /** Resolve provider-neutral model presentation and capability data. */
67768
68261
  function resolveProviderCatalog(manifest, driverKind) {
@@ -67798,13 +68291,12 @@ function resolveProviderCatalog(manifest, driverKind) {
67798
68291
  defaults: { chat: catalog.defaults?.chat }
67799
68292
  };
67800
68293
  }
67801
- /** On-disk shape of the last successfully fetched manifest. */
68294
+ /** On-disk shape of the last successfully fetched external model list. */
67802
68295
  const ManifestCacheFile = Schema$1.Struct({
67803
68296
  fetchedAtMs: Schema$1.Number,
67804
- manifest: ModelManifestSchema
68297
+ models: Schema$1.Array(ExternalModel)
67805
68298
  });
67806
68299
  const decodeManifestCache = Schema$1.decodeUnknownEffect(Schema$1.fromJsonString(ManifestCacheFile));
67807
- /** Exported for tests that seed the disk cache. */
67808
68300
  const encodeManifestCache = Schema$1.encodeEffect(Schema$1.fromJsonString(ManifestCacheFile));
67809
68301
  /** True when the manifest classifies `slug` as legacy for `driverKind`. */
67810
68302
  function isLegacyModel(manifest, driverKind, slug) {
@@ -67885,7 +68377,7 @@ const make$76 = Effect.gen(function* () {
67885
68377
  const settingsService = yield* ServerSettingsService;
67886
68378
  const httpClient = yield* HttpClient.HttpClient;
67887
68379
  const serviceScope = yield* Effect.scope;
67888
- const cachePath = path.join(config.stateDir, "model-manifest.json");
68380
+ const cachePath = path.join(config.stateDir, "external-models.json");
67889
68381
  let manifest = BUNDLED_MODEL_MANIFEST;
67890
68382
  let fetchedAtMs = null;
67891
68383
  let lastAttemptMs = null;
@@ -67893,10 +68385,26 @@ const make$76 = Effect.gen(function* () {
67893
68385
  const ensureDiskCacheLoaded = yield* Effect.cached(Effect.gen(function* () {
67894
68386
  const fromDisk = yield* fileSystem.readFileString(cachePath).pipe(Effect.flatMap((raw) => decodeManifestCache(raw)), Effect.catchCause(() => Effect.succeed(null)));
67895
68387
  if (fromDisk === null) return;
67896
- if (manifestUpdatedAtMs(BUNDLED_MODEL_MANIFEST) > manifestUpdatedAtMs(fromDisk.manifest)) return;
67897
- manifest = fromDisk.manifest;
68388
+ const derived = manifestFromExternalModels(fromDisk.models);
68389
+ if (derived === null) return;
68390
+ manifest = derived;
67898
68391
  fetchedAtMs = fromDisk.fetchedAtMs;
67899
68392
  }));
68393
+ const fetchPublic = (source) => httpClient.get(source.url).pipe(Effect.flatMap(HttpClientResponse.filterStatusOk), Effect.flatMap((response) => response.json), Effect.map((json) => source.parse(json) ?? []), Effect.timeout(FETCH_TIMEOUT_MS), Effect.catchCause(() => Effect.succeed([])));
68394
+ /** Static model definitions from the first enabled CPA usage source; credentials do not matter. */
68395
+ const fetchCpa = (sources) => {
68396
+ const source = Object.values(sources).find((candidate) => candidate.enabled && candidate.managementKey !== "");
68397
+ if (!source) return Effect.succeed([]);
68398
+ return Effect.forEach(CPA_CHANNELS, ({ provider, channel }) => Effect.tryPromise((signal) => readManagementJson(source, `model-definitions/${channel}`, void 0, signal)).pipe(Effect.map((json) => parseCpaModelDefinitions(json, provider)), Effect.timeout(FETCH_TIMEOUT_MS), Effect.catchCause(() => Effect.succeed([]))), { concurrency: "unbounded" }).pipe(Effect.map((lists) => {
68399
+ const seen = /* @__PURE__ */ new Set();
68400
+ return lists.flat().filter((model) => {
68401
+ const key = `${model.provider}:${model.id}`;
68402
+ if (seen.has(key)) return false;
68403
+ seen.add(key);
68404
+ return true;
68405
+ });
68406
+ }));
68407
+ };
67900
68408
  const refresh = Effect.fn("ModelManifest.refresh")(function* () {
67901
68409
  yield* ensureDiskCacheLoaded;
67902
68410
  const now = yield* Clock.currentTimeMillis;
@@ -67906,13 +68414,18 @@ const make$76 = Effect.gen(function* () {
67906
68414
  const settings = yield* settingsService.getSettings.pipe(Effect.catchCause(() => Effect.succeed(null)));
67907
68415
  if (settings !== null && !settings.enableProviderUpdateChecks) return manifest;
67908
68416
  lastAttemptMs = now;
67909
- const fetched = yield* httpClient.get(MODEL_MANIFEST_URL).pipe(Effect.flatMap(HttpClientResponse.filterStatusOk), Effect.flatMap((response) => response.json), Effect.flatMap((json) => decodeManifest(json)), Effect.timeout(FETCH_TIMEOUT_MS), Effect.catchCause(() => Effect.succeed(null)));
68417
+ let models = settings === null ? [] : yield* fetchCpa(settings.usageLimitSources);
68418
+ for (const source of PUBLIC_SOURCES) {
68419
+ if (missingProviders(models).length === 0) break;
68420
+ models = fillMissingProviders(models, yield* fetchPublic(source));
68421
+ }
68422
+ const fetched = models.length === 0 ? null : manifestFromExternalModels(models);
67910
68423
  if (fetched === null) return manifest;
67911
68424
  manifest = fetched;
67912
68425
  fetchedAtMs = now;
67913
68426
  yield* encodeManifestCache({
67914
68427
  fetchedAtMs: now,
67915
- manifest: fetched
68428
+ models
67916
68429
  }).pipe(Effect.flatMap((serialized) => fileSystem.writeFileString(cachePath, serialized)), Effect.catchCause(() => Effect.void));
67917
68430
  return manifest;
67918
68431
  });
@@ -69891,7 +70404,7 @@ const makeClaudeTextGeneration = Effect.fn("makeClaudeTextGeneration")(function*
69891
70404
  const baseUrl = claudeEnvironment.ANTHROPIC_BASE_URL?.trim();
69892
70405
  return yield* new TextGenerationError({
69893
70406
  operation,
69894
- detail: baseUrl && !/^https:\/\/api\.anthropic\.com\/?$/i.test(baseUrl) ? "This Claude instance uses a custom API endpoint. The CLI did not report subscription limits. For pooled accounts, open Subscription limits > Manage usage sources and configure the proxy's management URL and management key." : "Claude CLI did not return subscription limits. API-key accounts do not report subscription allowances here. If this instance should use a subscription, check its login and CLAUDE_CONFIG_DIR."
70407
+ detail: baseUrl && !/^https:\/\/api\.anthropic\.com\/?$/i.test(baseUrl) ? "This Claude instance uses a custom API endpoint. The CLI did not report subscription limits. For pooled accounts, open Subscription limits > Usage sources and configure the proxy's management URL and management key." : "Claude CLI did not return subscription limits. API-key accounts do not report subscription allowances here. If this instance should use a subscription, check its login and CLAUDE_CONFIG_DIR."
69895
70408
  });
69896
70409
  }
69897
70410
  return { report };
@@ -71765,6 +72278,10 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
71765
72278
  rawMethod: "claude/stream_event/message_delta",
71766
72279
  rawPayload: message
71767
72280
  });
72281
+ if (!context.contextBreakdownRequested) {
72282
+ context.contextBreakdownRequested = true;
72283
+ yield* queryCurrentContextUsage(context, context.lastKnownTotalProcessedTokens).pipe(Effect.flatMap((usage) => emitThreadTokenUsage(context, usage, { rawMethod: "claude/get_context_usage" })), Effect.forkChild);
72284
+ }
71768
72285
  return;
71769
72286
  }
71770
72287
  if (event.type === "content_block_delta") {
@@ -73042,6 +73559,7 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
73042
73559
  lastKnownContextWindow: initialContextWindow,
73043
73560
  lastKnownTokenUsage: void 0,
73044
73561
  lastKnownTotalProcessedTokens: void 0,
73562
+ contextBreakdownRequested: false,
73045
73563
  lastAssistantUuid: resumeState?.resumeSessionAt,
73046
73564
  lastThreadStartedId: void 0,
73047
73565
  interruptRequested: false,
@@ -103153,50 +103671,6 @@ const makeProviderInstallation = Effect.fn("makeProviderInstallation")(function*
103153
103671
  };
103154
103672
  });
103155
103673
  //#endregion
103156
- //#region src/usage/usageSourceHttp.ts
103157
- const MAX_RESPONSE_BYTES$1 = 1024 * 1024;
103158
- const LOOPBACK_HOSTS$1 = /* @__PURE__ */ new Set([
103159
- "localhost",
103160
- "127.0.0.1",
103161
- "[::1]"
103162
- ]);
103163
- /** The management key stays on the configured origin, including redirects. */
103164
- async function readManagementJson(config, path, body, signal) {
103165
- const base = new URL(config.url);
103166
- if (base.username || base.password || base.search || base.hash || base.protocol !== "https:" && !(base.protocol === "http:" && LOOPBACK_HOSTS$1.has(base.hostname))) throw new Error("Invalid usage source origin");
103167
- if (path !== "auth-files" && path !== "api-call") throw new Error("Unsupported management operation");
103168
- const response = await fetch(new URL(`/v0/management/${path}`, base), {
103169
- method: body === void 0 ? "GET" : "POST",
103170
- redirect: "error",
103171
- signal,
103172
- headers: {
103173
- authorization: `Bearer ${config.managementKey}`,
103174
- "content-type": "application/json"
103175
- },
103176
- ...body === void 0 ? {} : { body: JSON.stringify(body) }
103177
- });
103178
- if (!response.ok || !response.body) {
103179
- await response.body?.cancel();
103180
- throw new UsageLimitSourceError({ detail: response.status === 401 || response.status === 403 ? `The usage source rejected its management key (HTTP ${response.status}). Update the management key in Manage usage sources; a provider API key cannot replace it.` : `The usage source management request failed (HTTP ${response.status}). Check the source URL and management API availability.` });
103181
- }
103182
- const reader = response.body.getReader();
103183
- const chunks = [];
103184
- let total = 0;
103185
- try {
103186
- for (;;) {
103187
- const chunk = await reader.read();
103188
- if (chunk.done) break;
103189
- total += chunk.value.byteLength;
103190
- if (total > MAX_RESPONSE_BYTES$1) throw new Error("Usage source response too large");
103191
- chunks.push(chunk.value);
103192
- }
103193
- return JSON.parse(Buffer.concat(chunks).toString("utf8"));
103194
- } finally {
103195
- await reader.cancel().catch(() => void 0);
103196
- reader.releaseLock();
103197
- }
103198
- }
103199
- //#endregion
103200
103674
  //#region src/usage/cliproxyApi.ts
103201
103675
  const isUsageLimitSourceError$1 = Schema$1.is(UsageLimitSourceError);
103202
103676
  const MAX_SOURCE_ACCOUNTS = 128;
@@ -103261,7 +103735,21 @@ const CreditList = Schema$1.Struct({ credits: Schema$1.Array(Schema$1.Struct({
103261
103735
  reset_type: Schema$1.String,
103262
103736
  expires_at: Schema$1.String
103263
103737
  })) });
103738
+ /** Codex's answer to a consume request (openai/codex backend-client `ConsumeRateLimitResetCreditResponse`). */
103739
+ const ConsumeResponse = Schema$1.Struct({ code: Schema$1.Literals([
103740
+ "reset",
103741
+ "nothing_to_reset",
103742
+ "no_credit",
103743
+ "already_redeemed"
103744
+ ]) });
103745
+ const CONSUME_OUTCOMES = {
103746
+ reset: "reset",
103747
+ nothing_to_reset: "nothingToReset",
103748
+ no_credit: "noCredit",
103749
+ already_redeemed: "alreadyRedeemed"
103750
+ };
103264
103751
  const decodeAuthFiles = Schema$1.decodeUnknownEffect(AuthFiles);
103752
+ const decodeConsumeResponse = Schema$1.decodeUnknownEffect(Schema$1.fromJsonString(ConsumeResponse));
103265
103753
  const encodeJson$5 = Schema$1.encodeEffect(Schema$1.fromJsonString(Schema$1.Unknown));
103266
103754
  const decodeApiResponse = Schema$1.decodeUnknownEffect(ApiResponse);
103267
103755
  const decodeCreditList = Schema$1.decodeUnknownEffect(Schema$1.fromJsonString(CreditList));
@@ -103269,6 +103757,7 @@ const decodeClaudeUsage = Schema$1.decodeUnknownEffect(Schema$1.fromJsonString(C
103269
103757
  const decodeCodexUsage = Schema$1.decodeUnknownEffect(Schema$1.fromJsonString(CodexUsage));
103270
103758
  const CODEX_BASE = "https://chatgpt.com/backend-api/wham";
103271
103759
  const CREDIT_URL = `${CODEX_BASE}/rate-limit-reset-credits`;
103760
+ const CONSUME_URL = `${CREDIT_URL}/consume`;
103272
103761
  const makeCliproxyApi = Effect.gen(function* () {
103273
103762
  const management = (config, path, body) => Effect.tryPromise({
103274
103763
  try: (signal) => readManagementJson(config, path, body, signal),
@@ -103389,10 +103878,32 @@ const makeCliproxyApi = Effect.gen(function* () {
103389
103878
  })
103390
103879
  })));
103391
103880
  });
103392
- return { readAccounts: Effect.fn("CliproxyApi.readAccounts")(function* (config) {
103393
- const accounts = yield* authFiles(config).pipe(Effect.mapError((cause) => isUsageLimitSourceError$1(cause) ? cause : new UsageLimitSourceError({ detail: "The usage source returned an unsupported account list." })));
103394
- return yield* Effect.forEach(accounts.filter((account) => !account.disabled && (account.provider === "codex" || account.provider === "claude")), (account) => readAccount(config, account), { concurrency: ACCOUNT_READ_CONCURRENCY });
103395
- }) };
103881
+ return {
103882
+ readAccounts: Effect.fn("CliproxyApi.readAccounts")(function* (config) {
103883
+ const accounts = yield* authFiles(config).pipe(Effect.mapError((cause) => isUsageLimitSourceError$1(cause) ? cause : new UsageLimitSourceError({ detail: "The usage source returned an unsupported account list." })));
103884
+ return yield* Effect.forEach(accounts.filter((account) => !account.disabled && (account.provider === "codex" || account.provider === "claude")), (account) => readAccount(config, account), { concurrency: ACCOUNT_READ_CONCURRENCY });
103885
+ }),
103886
+ consumeResetCredit: Effect.fn("CliproxyApi.consumeResetCredit")(function* (config, accountId, input) {
103887
+ const notSent = (detail) => ({
103888
+ detail,
103889
+ sent: false
103890
+ });
103891
+ const account = (yield* authFiles(config).pipe(Effect.mapError((cause) => notSent(isUsageLimitSourceError$1(cause) ? cause.detail : "The usage source returned an unsupported account list.")))).find((file) => file.id === accountId && file.provider === "codex" && !file.disabled);
103892
+ if (!account) return yield* Effect.fail(notSent("The usage source no longer has this Codex account. Refresh and try again."));
103893
+ const body = yield* apiCall(config, account, CONSUME_URL, {
103894
+ redeem_request_id: input.idempotencyKey,
103895
+ credit_id: input.creditId
103896
+ }).pipe(Effect.mapError((cause) => ({
103897
+ detail: isUsageLimitSourceError$1(cause) ? cause.detail : "The usage source could not send the reset request.",
103898
+ sent: true
103899
+ })));
103900
+ const response = yield* decodeConsumeResponse(body).pipe(Effect.mapError(() => ({
103901
+ detail: "Codex answered the reset request in a form P4 does not understand.",
103902
+ sent: true
103903
+ })));
103904
+ return CONSUME_OUTCOMES[response.code];
103905
+ })
103906
+ };
103396
103907
  });
103397
103908
  //#endregion
103398
103909
  //#region src/usage/UsageLimitSources.ts
@@ -103441,9 +103952,21 @@ const makeWithReader = (api) => Effect.gen(function* () {
103441
103952
  yield* settings.streamChanges.pipe(Stream.map((value) => value.usageLimitSources), Stream.changes, Stream.switchMap(() => Stream.fromEffect(publish([]).pipe(Effect.andThen(refresh)))), Stream.runDrain, Effect.forkScoped);
103442
103953
  yield* Effect.forever(Effect.sleep(REFRESH_INTERVAL).pipe(Effect.andThen(refresh))).pipe(Effect.forkScoped);
103443
103954
  yield* refresh.pipe(Effect.forkScoped);
103955
+ const consumeResetCredit = (account, input) => Effect.gen(function* () {
103956
+ const config = (yield* settings.getSettings.pipe(Effect.mapError(() => ({
103957
+ detail: "Could not read the usage source settings.",
103958
+ sent: false
103959
+ })))).usageLimitSources[account.sourceId];
103960
+ if (!config?.enabled || !config.managementKey) return yield* Effect.fail({
103961
+ detail: "This usage source is off or has no management key.",
103962
+ sent: false
103963
+ });
103964
+ return yield* api.consumeResetCredit(config, account.accountId, input);
103965
+ });
103444
103966
  return {
103445
103967
  current: Ref.get(state),
103446
103968
  refresh,
103969
+ consumeResetCredit,
103447
103970
  streamChanges: Stream.unwrap(Effect.gen(function* () {
103448
103971
  const subscription = yield* PubSub.subscribe(changes);
103449
103972
  return Stream.concat(Stream.make(yield* Ref.get(state)), Stream.fromSubscription(subscription)).pipe(Stream.changes);
@@ -130256,10 +130779,18 @@ const make$27 = Effect.gen(function* PreviewManagerMake() {
130256
130779
  }).pipe(Effect.withSpan("PreviewManager.make"));
130257
130780
  const layer$19 = Layer.effect(PreviewManager, make$27);
130258
130781
  const isStoredOutcome = Schema$1.is(Schema$1.Union([ProviderResetCreditOutcome, Schema$1.Literal("failed")]));
130259
- function toAttempt(row) {
130782
+ /**
130783
+ * The `instance_id` column holds the target's owner key. Instance ids never
130784
+ * contain a colon, so a pooled account's `source:` key cannot collide with one,
130785
+ * and the JSON keeps any source id unambiguous.
130786
+ */
130787
+ function resetCreditOwnerKey(target) {
130788
+ return "instanceId" in target ? target.instanceId : `source:${JSON.stringify([target.sourceAccount.sourceId, target.sourceAccount.accountId])}`;
130789
+ }
130790
+ function toAttempt(row, target) {
130260
130791
  return {
130261
130792
  idempotencyKey: row.idempotency_key,
130262
- instanceId: ProviderInstanceId.make(row.instance_id),
130793
+ ...target,
130263
130794
  ...row.credit_id ? { creditId: row.credit_id } : {},
130264
130795
  requestedAt: row.requested_at,
130265
130796
  ...row.outcome !== null && isStoredOutcome(row.outcome) ? { outcome: row.outcome } : {},
@@ -130272,28 +130803,39 @@ function toAttempt(row) {
130272
130803
  * attempt already wrote. The stored row wins: its credit is the one a retry
130273
130804
  * must ask about, whatever the retry itself sent.
130274
130805
  *
130275
- * A new attempt is refused while another attempt for the same provider has no
130806
+ * A new attempt is refused while another attempt for the same target has no
130276
130807
  * answer; `blockedBy` is that attempt, which the caller must retry instead.
130277
130808
  * The partial unique index makes the refusal hold across concurrent clients.
130809
+ * `foreign` marks a key already used for another target.
130278
130810
  */
130279
130811
  const beginResetCreditAttempt = Effect.fn("ProviderResetCreditAttempts.begin")(function* (input) {
130280
130812
  const sql = yield* SqlClient.SqlClient;
130813
+ const owner = resetCreditOwnerKey(input.target);
130281
130814
  yield* sql`INSERT INTO provider_reset_credit_attempts
130282
130815
  (idempotency_key, instance_id, credit_id, requested_at)
130283
- VALUES (${input.idempotencyKey}, ${input.instanceId}, ${input.creditId ?? null},
130816
+ VALUES (${input.idempotencyKey}, ${owner}, ${input.creditId ?? null},
130284
130817
  ${input.requestedAt})
130285
130818
  ON CONFLICT DO NOTHING`;
130286
130819
  const own = yield* sql`SELECT * FROM provider_reset_credit_attempts
130287
130820
  WHERE idempotency_key = ${input.idempotencyKey}`;
130288
- if (own[0] !== void 0) return {
130289
- attempt: toAttempt(own[0]),
130290
- blockedBy: null
130291
- };
130821
+ if (own[0] !== void 0) {
130822
+ if (own[0].instance_id !== owner) return {
130823
+ attempt: null,
130824
+ blockedBy: null,
130825
+ foreign: true
130826
+ };
130827
+ return {
130828
+ attempt: toAttempt(own[0], input.target),
130829
+ blockedBy: null,
130830
+ foreign: false
130831
+ };
130832
+ }
130292
130833
  const unresolved = yield* sql`SELECT * FROM provider_reset_credit_attempts
130293
- WHERE instance_id = ${input.instanceId} AND (outcome IS NULL OR outcome = 'failed')`;
130834
+ WHERE instance_id = ${owner} AND (outcome IS NULL OR outcome = 'failed')`;
130294
130835
  return {
130295
130836
  attempt: null,
130296
- blockedBy: unresolved[0] === void 0 ? null : toAttempt(unresolved[0])
130837
+ blockedBy: unresolved[0] === void 0 ? null : toAttempt(unresolved[0], input.target),
130838
+ foreign: false
130297
130839
  };
130298
130840
  });
130299
130841
  /** Write what the provider answered, or `failed` when no answer came back. */
@@ -130305,15 +130847,15 @@ const completeResetCreditAttempt = Effect.fn("ProviderResetCreditAttempts.comple
130305
130847
  WHERE idempotency_key = ${input.idempotencyKey}
130306
130848
  AND (outcome IS NULL OR outcome = 'failed')
130307
130849
  RETURNING *`;
130308
- if (rows[0] !== void 0) return toAttempt(rows[0]);
130850
+ if (rows[0] !== void 0) return toAttempt(rows[0], input.target);
130309
130851
  return toAttempt((yield* sql`SELECT * FROM provider_reset_credit_attempts
130310
- WHERE idempotency_key = ${input.idempotencyKey}`)[0]);
130852
+ WHERE idempotency_key = ${input.idempotencyKey}`)[0], input.target);
130311
130853
  });
130312
- /** This instance's attempts, newest first. */
130313
- const listResetCreditAttempts = Effect.fn("ProviderResetCreditAttempts.list")(function* (instanceId) {
130854
+ /** This target's attempts, newest first. */
130855
+ const listResetCreditAttempts = Effect.fn("ProviderResetCreditAttempts.list")(function* (target) {
130314
130856
  return (yield* (yield* SqlClient.SqlClient)`SELECT * FROM provider_reset_credit_attempts
130315
- WHERE instance_id = ${instanceId}
130316
- ORDER BY requested_at DESC LIMIT ${20}`).map(toAttempt);
130857
+ WHERE instance_id = ${resetCreditOwnerKey(target)}
130858
+ ORDER BY requested_at DESC LIMIT ${20}`).map((row) => toAttempt(row, target));
130317
130859
  });
130318
130860
  //#endregion
130319
130861
  //#region src/workspace/WorkspaceSearchIndex.ts
@@ -133715,35 +134257,51 @@ const makeWsRpcLayer = (currentSession, previewAutomationBroker, computerUseBrok
133715
134257
  detail: "This provider does not report account usage."
133716
134258
  })), { "rpc.aggregate": "server" }),
133717
134259
  [WS_METHODS.serverConsumeProviderResetCredit]: (input) => {
134260
+ const target = "instanceId" in input ? { instanceId: input.instanceId } : { sourceAccount: input.sourceAccount };
133718
134261
  let consumeSent = false;
133719
134262
  return observeRpcEffect$1(WS_METHODS.serverConsumeProviderResetCredit, Effect.gen(function* () {
133720
134263
  const fail = (detail, cause) => new ProviderResetCreditError({
133721
- instanceId: input.instanceId,
134264
+ ...target,
133722
134265
  detail,
133723
134266
  ...consumeSent ? { consumeSent } : {},
133724
134267
  ...cause === void 0 ? {} : { cause }
133725
134268
  });
133726
134269
  const begun = yield* beginResetCreditAttempt({
133727
134270
  idempotencyKey: input.idempotencyKey,
133728
- instanceId: input.instanceId,
134271
+ target,
133729
134272
  creditId: input.creditId,
133730
134273
  requestedAt: yield* nowIso$2
133731
134274
  });
134275
+ if (begun.foreign) return yield* fail("This attempt belongs to another account.");
133732
134276
  const started = begun.attempt;
133733
134277
  if (started === null) return yield* fail(begun.blockedBy === null ? "Another reset request just finished. Check the count and try again." : "An earlier reset request has no answer from Codex yet. Retry it before starting another.");
133734
- if (started.instanceId !== input.instanceId) return yield* fail("This attempt belongs to another provider.");
133735
134278
  if (started.outcome !== void 0 && started.outcome !== "failed") return { attempt: started };
133736
- const consume = textGeneration.consumeResetCredit;
133737
- if (!consume) return yield* fail("This provider cannot redeem resets from P4.");
134279
+ const creditId = started.creditId;
134280
+ let send;
134281
+ let refresh;
134282
+ if ("instanceId" in target) {
134283
+ const consume = textGeneration.consumeResetCredit;
134284
+ if (!consume) return yield* fail("This provider cannot redeem resets from P4.");
134285
+ send = consume({
134286
+ instanceId: target.instanceId,
134287
+ idempotencyKey: input.idempotencyKey,
134288
+ creditId
134289
+ }).pipe(Effect.map((answer) => answer.outcome));
134290
+ refresh = providerRegistry.refreshInstance(target.instanceId).pipe(Effect.ignoreCause({ log: true }));
134291
+ } else {
134292
+ send = usageLimitSources.consumeResetCredit(target.sourceAccount, {
134293
+ idempotencyKey: input.idempotencyKey,
134294
+ creditId: creditId ?? ("sourceAccount" in input ? input.creditId : "")
134295
+ });
134296
+ refresh = usageLimitSources.refresh;
134297
+ }
133738
134298
  consumeSent = true;
133739
- const result = yield* consume({
133740
- instanceId: input.instanceId,
133741
- idempotencyKey: input.idempotencyKey,
133742
- creditId: started.creditId
133743
- }).pipe(Effect.result);
134299
+ const result = yield* send.pipe(Effect.result);
133744
134300
  if (Result$1.isFailure(result)) {
134301
+ if (result.failure.sent === false) consumeSent = false;
133745
134302
  const recorded = yield* completeResetCreditAttempt({
133746
134303
  idempotencyKey: input.idempotencyKey,
134304
+ target,
133747
134305
  outcome: "failed",
133748
134306
  detail: result.failure.detail,
133749
134307
  completedAt: yield* nowIso$2
@@ -133753,20 +134311,21 @@ const makeWsRpcLayer = (currentSession, previewAutomationBroker, computerUseBrok
133753
134311
  }
133754
134312
  const attempt = yield* completeResetCreditAttempt({
133755
134313
  idempotencyKey: input.idempotencyKey,
133756
- outcome: result.success.outcome,
134314
+ target,
134315
+ outcome: result.success,
133757
134316
  completedAt: yield* nowIso$2
133758
134317
  });
133759
- yield* providerRegistry.refreshInstance(input.instanceId).pipe(Effect.ignoreCause({ log: true }));
134318
+ yield* refresh;
133760
134319
  return { attempt };
133761
134320
  }).pipe(Effect.catchTag("SqlError", (cause) => Effect.fail(new ProviderResetCreditError({
133762
- instanceId: input.instanceId,
134321
+ ...target,
133763
134322
  detail: "Could not record the reset attempt.",
133764
134323
  ...consumeSent ? { consumeSent } : {},
133765
134324
  cause
133766
134325
  }))), Effect.provideService(SqlClient.SqlClient, sql)), { "rpc.aggregate": "server" });
133767
134326
  },
133768
- [WS_METHODS.serverListProviderResetCreditAttempts]: (input) => observeRpcEffect$1(WS_METHODS.serverListProviderResetCreditAttempts, listResetCreditAttempts(input.instanceId).pipe(Effect.map((attempts) => ({ attempts })), Effect.catchTag("SqlError", (cause) => Effect.fail(new ProviderResetCreditError({
133769
- instanceId: input.instanceId,
134327
+ [WS_METHODS.serverListProviderResetCreditAttempts]: (input) => observeRpcEffect$1(WS_METHODS.serverListProviderResetCreditAttempts, listResetCreditAttempts(input).pipe(Effect.map((attempts) => ({ attempts })), Effect.catchTag("SqlError", (cause) => Effect.fail(new ProviderResetCreditError({
134328
+ ...input,
133770
134329
  detail: "Could not read reset history.",
133771
134330
  cause
133772
134331
  }))), Effect.provideService(SqlClient.SqlClient, sql)), { "rpc.aggregate": "server" }),