pullfrog 0.1.84 → 0.1.85

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.
@@ -26,6 +26,8 @@ export { createLeapingProgressComment, deleteProgressCommentApi, getProgressComm
26
26
  export { PROVIDER_DASHBOARDS, type ProviderDashboard } from "../utils/providerDashboards.ts";
27
27
  export type { RunStatusCheckConclusion, RunStatusCheckOctokit, } from "../utils/runStatusCheck.ts";
28
28
  export { APPROVAL_CHECK_NAME, createRunStatusCheck, finalizeRunStatusCheck, RUN_STATUS_CHECK_NAME, runStatusCheckNeedsFinalizing, } from "../utils/runStatusCheck.ts";
29
+ export * from "../utils/subscriptionCredentials.ts";
30
+ export { probeSubscription, SubscriptionCredentialError, subscriptionIdentity, } from "../utils/subscriptionProbe.ts";
29
31
  export { isValidTimeString, parseTimeString, TIMEOUT_DISABLED, } from "../utils/time.ts";
30
32
  export type { XaiAuthBody } from "../utils/xaiOAuth.ts";
31
33
  export { parseXaiAuthBody, refreshXaiAuthBody, stringifyXaiAuthBody, } from "../utils/xaiOAuth.ts";
package/dist/internal.js CHANGED
@@ -8,7 +8,7 @@ var __export = (target, all) => {
8
8
  // package.json
9
9
  var package_default = {
10
10
  name: "pullfrog",
11
- version: "0.1.84",
11
+ version: "0.1.85",
12
12
  cliContractVersion: "1",
13
13
  type: "module",
14
14
  bin: {
@@ -15000,6 +15000,17 @@ var providers = {
15000
15000
  // see the big-pickle note above (#1077).
15001
15001
  isFree: true
15002
15002
  },
15003
+ // Zen's FREE Meituan preview (listed 2026-09-25). Zen's docs: zero
15004
+ // retention, no training. Go lists the same free id, but one key reaches
15005
+ // both, so the promo gets one row, here with the other free ones.
15006
+ "longcat-preview": {
15007
+ displayName: "LongCat Preview",
15008
+ description: "Meituan preview, free for a limited time",
15009
+ resolve: "opencode/longcat-2.5-preview-free",
15010
+ // free to run, still gated on the provider's own OPENCODE_API_KEY —
15011
+ // see the big-pickle note above (#1077).
15012
+ isFree: true
15013
+ },
15003
15014
  // Zen's live free MiMo, and the second free row in a menu that big-pickle
15004
15015
  // was alone in since `mimo-v2-pro-free` lost its model.
15005
15016
  mimo: {
@@ -15633,7 +15644,7 @@ function isRouterTier(value) {
15633
15644
  }
15634
15645
  var PROVIDER_LADDERS = {
15635
15646
  anthropic: {
15636
- minimal: "anthropic/claude-haiku",
15647
+ minimal: "anthropic/claude-sonnet",
15637
15648
  light: "anthropic/claude-sonnet",
15638
15649
  standard: "anthropic/claude-opus",
15639
15650
  deep: "anthropic/claude-opus"
@@ -16211,35 +16222,25 @@ var modes = computeModes("opencode");
16211
16222
 
16212
16223
  // utils/billingErrors.ts
16213
16224
  function commercialPaywallBody(params) {
16214
- const pitch = "Pro is required on private organization repos like this one: a flat $30/month per organization for unlimited runs, members, and repos.";
16225
+ let action;
16215
16226
  switch (params.reason) {
16216
16227
  case "commercial":
16217
- return [
16218
- `**${params.ownerLogin}'s Pullfrog trial has expired.**`,
16219
- "",
16220
- pitch,
16221
- "",
16222
- `[Upgrade now \u2192](${params.url})`
16223
- ].join("\n");
16228
+ action = "upgrade";
16229
+ break;
16224
16230
  case "subscription_ended":
16225
- return [
16226
- `**${params.ownerLogin}'s Pullfrog Pro subscription has ended.**`,
16227
- "",
16228
- pitch,
16229
- "",
16230
- `[Resubscribe \u2192](${params.url})`
16231
- ].join("\n");
16231
+ action = "resubscribe";
16232
+ break;
16232
16233
  case "subscription_unpaid":
16233
- return [
16234
- `**Pullfrog paused runs on ${params.ownerLogin}: the Pro renewal failed.**`,
16235
- "",
16236
- "Update the card on file to resume runs.",
16237
- "",
16238
- `[Update billing \u2192](${params.url})`
16239
- ].join("\n");
16234
+ action = "update billing";
16235
+ break;
16240
16236
  default:
16241
16237
  return params.reason;
16242
16238
  }
16239
+ return [
16240
+ `**Pullfrog is ${params.freshReply ? "still paused" : "paused"} for ${params.ownerLogin}.**`,
16241
+ "",
16242
+ `An org owner can [${action}](${params.url}) to resume private-repo runs.`
16243
+ ].join("\n");
16243
16244
  }
16244
16245
 
16245
16246
  // utils/buildPullfrogFooter.ts
@@ -16935,19 +16936,47 @@ async function runStatusCheckNeedsFinalizing(params) {
16935
16936
  }
16936
16937
  }
16937
16938
 
16938
- // utils/time.ts
16939
- var TIMEOUT_DISABLED = "none";
16940
- var TIME_STRING_REGEX = /^(?:(\d+)h)?(?:(\d+)m)?(?:(\d+)s)?$/;
16941
- function parseTimeString(input) {
16942
- const match = input.match(TIME_STRING_REGEX);
16943
- if (!match || !match[1] && !match[2] && !match[3]) return null;
16944
- const hours = parseInt(match[1] || "0", 10);
16945
- const minutes = parseInt(match[2] || "0", 10);
16946
- const seconds = parseInt(match[3] || "0", 10);
16947
- return (hours * 3600 + minutes * 60 + seconds) * 1e3;
16948
- }
16949
- function isValidTimeString(input) {
16950
- return parseTimeString(input) !== null;
16939
+ // utils/subscriptionCredentials.ts
16940
+ var subscriptionNameSchema = external_exports.enum([
16941
+ "CLAUDE_CODE_OAUTH_TOKEN",
16942
+ "CODEX_AUTH_JSON",
16943
+ "GROK_AUTH_JSON"
16944
+ ]);
16945
+ var subscriptionSchema = external_exports.object({
16946
+ id: external_exports.string(),
16947
+ credentialId: external_exports.string(),
16948
+ name: subscriptionNameSchema,
16949
+ label: external_exports.string(),
16950
+ owner: external_exports.string(),
16951
+ inherited: external_exports.boolean(),
16952
+ shared: external_exports.boolean(),
16953
+ registeredAt: external_exports.string()
16954
+ });
16955
+ var subscriptionListSchema = external_exports.object({
16956
+ subscriptions: external_exports.array(subscriptionSchema),
16957
+ writable: external_exports.boolean()
16958
+ });
16959
+ var subscriptionInputSchema = external_exports.object({
16960
+ name: subscriptionNameSchema,
16961
+ value: external_exports.string().trim().min(1).refine((value) => Buffer.byteLength(value, "utf8") <= 49152),
16962
+ replaceId: external_exports.string().optional()
16963
+ });
16964
+ var credentialCandidateSchema = external_exports.object({
16965
+ id: external_exports.string(),
16966
+ name: external_exports.string(),
16967
+ source: external_exports.enum(["repo", "account", "personal"])
16968
+ });
16969
+ var credentialAccessSchema = external_exports.object({
16970
+ token: external_exports.string(),
16971
+ candidates: external_exports.array(credentialCandidateSchema)
16972
+ });
16973
+ var selectedCredentialSchema = external_exports.object({
16974
+ name: external_exports.string(),
16975
+ value: external_exports.string(),
16976
+ receipt: external_exports.string()
16977
+ });
16978
+ function subscriptionLabel(input) {
16979
+ return input.email ?? `\u2022\u2022\u2022\u2022 ${input.suffix}`;
16951
16980
  }
16952
16981
 
16953
16982
  // utils/xaiOAuth.ts
@@ -17012,6 +17041,137 @@ function stringifyXaiAuthBody(body) {
17012
17041
  return `${JSON.stringify(body, null, 2)}
17013
17042
  `;
17014
17043
  }
17044
+
17045
+ // utils/subscriptionProbe.ts
17046
+ var identitySchema = external_exports.object({
17047
+ email: external_exports.string().email().optional(),
17048
+ sub: external_exports.string().optional(),
17049
+ user_id: external_exports.string().optional(),
17050
+ account_id: external_exports.string().optional(),
17051
+ email_verified: external_exports.boolean().optional()
17052
+ });
17053
+ var codexUsageSchema = external_exports.object({
17054
+ rate_limit: external_exports.object({ allowed: external_exports.boolean(), limit_reached: external_exports.boolean() }).optional()
17055
+ });
17056
+ var SubscriptionCredentialError = class extends Error {
17057
+ };
17058
+ async function subscriptionIdentity(input) {
17059
+ const empty = { email: null, subject: null };
17060
+ if (input.name === "CLAUDE_CODE_OAUTH_TOKEN") return empty;
17061
+ const codex = input.name === "CODEX_AUTH_JSON" ? parseCodexAuthBody(input.value) : null;
17062
+ const grok = input.name === "GROK_AUTH_JSON" ? parseXaiAuthBody(input.value) : null;
17063
+ const token = codex?.tokens.access_token ?? grok?.tokens.access_token;
17064
+ if (!token) throw new SubscriptionCredentialError("invalid subscription credential");
17065
+ const response = await readSubscriptionEndpoint({
17066
+ url: codex ? "https://chatgpt.com/backend-api/wham/usage" : "https://auth.x.ai/oauth2/userinfo",
17067
+ token,
17068
+ accountId: codex?.tokens.account_id
17069
+ });
17070
+ if (response?.status === 401)
17071
+ throw new SubscriptionCredentialError("subscription credential was rejected");
17072
+ if (!response?.ok) return empty;
17073
+ const parsed = identitySchema.safeParse(await response.json().catch(() => null));
17074
+ if (!parsed.success) return empty;
17075
+ const subject = parsed.data.sub ?? parsed.data.user_id;
17076
+ return {
17077
+ email: parsed.data.email_verified === false ? null : parsed.data.email ?? null,
17078
+ subject: subject ? `${subject}:${parsed.data.account_id ?? ""}` : null
17079
+ };
17080
+ }
17081
+ async function readSubscriptionEndpoint(input) {
17082
+ const headers = new Headers({ authorization: `Bearer ${input.token}` });
17083
+ if (input.accountId) headers.set("ChatGPT-Account-Id", input.accountId);
17084
+ if (input.grokBilling) headers.set("x-xai-token-auth", "xai-grok-cli");
17085
+ return fetch(input.url, {
17086
+ headers,
17087
+ redirect: "error",
17088
+ signal: AbortSignal.timeout(1e4)
17089
+ }).catch(() => null);
17090
+ }
17091
+ async function probeSubscription(input) {
17092
+ if (input.name === "CLAUDE_CODE_OAUTH_TOKEN") {
17093
+ const result = await preflightClaudeSubscription({ token: input.value, model: input.model });
17094
+ return result.usable ? "usable" : "rejected";
17095
+ }
17096
+ const codex = input.name === "CODEX_AUTH_JSON" ? parseCodexAuthBody(input.value) : null;
17097
+ const grok = input.name === "GROK_AUTH_JSON" ? parseXaiAuthBody(input.value) : null;
17098
+ const auth = codex ?? grok;
17099
+ if (!auth || auth.refresh_rejected_at) return "rejected";
17100
+ if (grok && input.model)
17101
+ return probeInference({
17102
+ name: "XAI_API_KEY",
17103
+ value: grok.tokens.access_token,
17104
+ model: input.model
17105
+ });
17106
+ const response = await readSubscriptionEndpoint({
17107
+ url: codex ? "https://chatgpt.com/backend-api/wham/usage" : "https://cli-chat-proxy.grok.com/v1/billing?format=credits",
17108
+ token: auth.tokens.access_token,
17109
+ accountId: codex?.tokens.account_id,
17110
+ grokBilling: !!grok
17111
+ });
17112
+ if (response?.status === 401) return "rejected";
17113
+ if (!response?.ok) return "unknown";
17114
+ const body = await response.json().catch(() => null);
17115
+ if (codex) {
17116
+ const parsed = codexUsageSchema.safeParse(body);
17117
+ const limit = parsed.success ? parsed.data.rate_limit : void 0;
17118
+ if (!limit) return "unknown";
17119
+ return limit.allowed && !limit.limit_reached ? "usable" : "rejected";
17120
+ }
17121
+ return "unknown";
17122
+ }
17123
+ async function probeInference(input) {
17124
+ const anthropic = input.name === "ANTHROPIC_API_KEY";
17125
+ const openai = input.name === "OPENAI_API_KEY";
17126
+ if (!anthropic && !openai && input.name !== "XAI_API_KEY") {
17127
+ const result = await verifyCredential({ envVar: input.name, value: input.value });
17128
+ return result === "dead" ? "rejected" : result === "alive" ? "usable" : "unknown";
17129
+ }
17130
+ const headers = new Headers({ "content-type": "application/json" });
17131
+ if (anthropic) {
17132
+ headers.set("x-api-key", input.value);
17133
+ headers.set("anthropic-version", "2023-06-01");
17134
+ } else headers.set("authorization", `Bearer ${input.value}`);
17135
+ const response = await fetch(
17136
+ anthropic ? "https://api.anthropic.com/v1/messages" : openai ? "https://api.openai.com/v1/responses" : "https://api.x.ai/v1/chat/completions",
17137
+ {
17138
+ method: "POST",
17139
+ headers,
17140
+ body: JSON.stringify(
17141
+ openai ? { model: input.model, input: "Reply OK.", max_output_tokens: 16, store: false } : {
17142
+ model: input.model,
17143
+ messages: [{ role: "user", content: "Reply OK." }],
17144
+ max_tokens: 1
17145
+ }
17146
+ ),
17147
+ redirect: "error",
17148
+ signal: AbortSignal.timeout(1e4)
17149
+ }
17150
+ ).catch(() => null);
17151
+ if (response?.status === 400 && input.name === "XAI_API_KEY") {
17152
+ const error48 = external_exports.object({ error: external_exports.string() }).safeParse(await response.json().catch(() => null));
17153
+ return error48.success && error48.data.error.startsWith("Incorrect API key provided.") ? "rejected" : "unknown";
17154
+ }
17155
+ await response?.body?.cancel();
17156
+ if (!response) return "unknown";
17157
+ if (response.ok) return "usable";
17158
+ return [401, 402, 403, 429].includes(response.status) ? "rejected" : "unknown";
17159
+ }
17160
+
17161
+ // utils/time.ts
17162
+ var TIMEOUT_DISABLED = "none";
17163
+ var TIME_STRING_REGEX = /^(?:(\d+)h)?(?:(\d+)m)?(?:(\d+)s)?$/;
17164
+ function parseTimeString(input) {
17165
+ const match = input.match(TIME_STRING_REGEX);
17166
+ if (!match || !match[1] && !match[2] && !match[3]) return null;
17167
+ const hours = parseInt(match[1] || "0", 10);
17168
+ const minutes = parseInt(match[2] || "0", 10);
17169
+ const seconds = parseInt(match[3] || "0", 10);
17170
+ return (hours * 3600 + minutes * 60 + seconds) * 1e3;
17171
+ }
17172
+ function isValidTimeString(input) {
17173
+ return parseTimeString(input) !== null;
17174
+ }
17015
17175
  export {
17016
17176
  APPROVAL_CHECK_NAME,
17017
17177
  AUTO_EFFICIENT,
@@ -17036,6 +17196,7 @@ export {
17036
17196
  ROUTER_TIERS,
17037
17197
  RUN_STATUS_CHECK_NAME,
17038
17198
  SUBSIDY_RUNG,
17199
+ SubscriptionCredentialError,
17039
17200
  TIMEOUT_DISABLED,
17040
17201
  autoLadder,
17041
17202
  autoRoutedSlug,
@@ -17048,6 +17209,8 @@ export {
17048
17209
  countOutstandingPullfrogThreads,
17049
17210
  createLeapingProgressComment,
17050
17211
  createRunStatusCheck,
17212
+ credentialAccessSchema,
17213
+ credentialCandidateSchema,
17051
17214
  decodeJwtExpMs,
17052
17215
  defaultAutoTier,
17053
17216
  deleteProgressCommentApi,
@@ -17081,6 +17244,7 @@ export {
17081
17244
  parseModel,
17082
17245
  parseTimeString,
17083
17246
  parseXaiAuthBody,
17247
+ probeSubscription,
17084
17248
  providers,
17085
17249
  pullfrogMcpName,
17086
17250
  refreshCodexAuthBody,
@@ -17096,9 +17260,16 @@ export {
17096
17260
  runStatusCheckNeedsFinalizing,
17097
17261
  rungLabel,
17098
17262
  rungPosition,
17263
+ selectedCredentialSchema,
17099
17264
  stringifyCodexAuthBody,
17100
17265
  stringifyXaiAuthBody,
17101
17266
  stripExistingFooter,
17267
+ subscriptionIdentity,
17268
+ subscriptionInputSchema,
17269
+ subscriptionLabel,
17270
+ subscriptionListSchema,
17271
+ subscriptionNameSchema,
17272
+ subscriptionSchema,
17102
17273
  truncateAtLineBoundary,
17103
17274
  updateProgressComment,
17104
17275
  verifyCredential
@@ -63,6 +63,7 @@ export declare function commercialPaywallBody(params: {
63
63
  reason: CommercialRefusal;
64
64
  ownerLogin: string;
65
65
  url: string;
66
+ freshReply?: boolean | undefined;
66
67
  }): string;
67
68
  /**
68
69
  * commercial-gate copy for action runs, linked to the account billing card.
@@ -1,3 +1,4 @@
1
+ export declare function clearInstalledSubscription(name: "CODEX_AUTH_JSON" | "GROK_AUTH_JSON"): void;
1
2
  /** sandbox-hidden home for pullfrog-managed on-disk secrets in CI. bash via
2
3
  * MCP shell tmpfs-overlays this path; opencode's internal auth module
3
4
  * bypasses external_directory and reaches the real file. mirrors the
@@ -0,0 +1,10 @@
1
+ import type { RunContextData } from "./runContextData.ts";
2
+ /** load one subscription per provider for model discovery; keep the pool unflattened. */
3
+ export declare function initializeCredentialPool(ctx: RunContextData, model?: string): Promise<void>;
4
+ export declare function resolvePoolModel(input: {
5
+ codexAgent: boolean;
6
+ }): string | undefined;
7
+ export declare function selectConfiguredCredential(input: {
8
+ ctx: RunContextData;
9
+ model: string | undefined;
10
+ }): Promise<boolean>;
@@ -2,6 +2,7 @@ import type { PushPermission, ShellPermission } from "../external.ts";
2
2
  import type { RouterTier } from "../models.ts";
3
3
  import type { CommercialRefusal } from "./billingErrors.ts";
4
4
  import type { RepoContext } from "./github.ts";
5
+ import type { CredentialAccess } from "./subscriptionCredentials.ts";
5
6
  export interface Mode {
6
7
  id: string;
7
8
  name: string;
@@ -57,6 +58,7 @@ export interface RepoSettings {
57
58
  */
58
59
  export type AccountPlan = "none" | "payg";
59
60
  export interface RunContext {
61
+ credentialAccess?: CredentialAccess | undefined;
60
62
  settings: RepoSettings;
61
63
  apiToken: string;
62
64
  oss: boolean;
@@ -3,7 +3,9 @@ import type { RouterTier } from "../models.ts";
3
3
  import type { CommercialRefusal } from "./billingErrors.ts";
4
4
  import { type OctokitWithPlugins } from "./github.ts";
5
5
  import { type AccountPlan, type RepoSettings } from "./runContext.ts";
6
+ import type { CredentialAccess } from "./subscriptionCredentials.ts";
6
7
  export interface RunContextData {
8
+ credentialAccess?: CredentialAccess | undefined;
7
9
  repo: {
8
10
  owner: string;
9
11
  name: string;
@@ -5,9 +5,15 @@ export interface SetupOptions {
5
5
  tempDir: string;
6
6
  }
7
7
  /**
8
- * Create a shared temp directory for the action
8
+ * Create a shared temp directory for the action, removed when the run's scope
9
+ * exits. a persistent self-hosted runner never wipes `/tmp`, so every run used
10
+ * to leave its tree (the OpenCode install alone is hundreds of MB) until the
11
+ * disk filled and every job on the runner died.
9
12
  */
10
- export declare function createTempDirectory(): string;
13
+ export declare function createTempDirectory(): {
14
+ path: string;
15
+ [Symbol.dispose]: () => void;
16
+ };
11
17
  /**
12
18
  * snapshot-and-delete the GHA runner's known credential leak surfaces inside
13
19
  * `$RUNNER_TEMP` before the agent spawns. without this, a shell-capable agent
@@ -0,0 +1,80 @@
1
+ import { z } from "zod";
2
+ export declare const subscriptionNameSchema: z.ZodEnum<{
3
+ CLAUDE_CODE_OAUTH_TOKEN: "CLAUDE_CODE_OAUTH_TOKEN";
4
+ CODEX_AUTH_JSON: "CODEX_AUTH_JSON";
5
+ GROK_AUTH_JSON: "GROK_AUTH_JSON";
6
+ }>;
7
+ export type SubscriptionName = z.infer<typeof subscriptionNameSchema>;
8
+ export declare const subscriptionSchema: z.ZodObject<{
9
+ id: z.ZodString;
10
+ credentialId: z.ZodString;
11
+ name: z.ZodEnum<{
12
+ CLAUDE_CODE_OAUTH_TOKEN: "CLAUDE_CODE_OAUTH_TOKEN";
13
+ CODEX_AUTH_JSON: "CODEX_AUTH_JSON";
14
+ GROK_AUTH_JSON: "GROK_AUTH_JSON";
15
+ }>;
16
+ label: z.ZodString;
17
+ owner: z.ZodString;
18
+ inherited: z.ZodBoolean;
19
+ shared: z.ZodBoolean;
20
+ registeredAt: z.ZodString;
21
+ }, z.core.$strip>;
22
+ export type Subscription = z.infer<typeof subscriptionSchema>;
23
+ export declare const subscriptionListSchema: z.ZodObject<{
24
+ subscriptions: z.ZodArray<z.ZodObject<{
25
+ id: z.ZodString;
26
+ credentialId: z.ZodString;
27
+ name: z.ZodEnum<{
28
+ CLAUDE_CODE_OAUTH_TOKEN: "CLAUDE_CODE_OAUTH_TOKEN";
29
+ CODEX_AUTH_JSON: "CODEX_AUTH_JSON";
30
+ GROK_AUTH_JSON: "GROK_AUTH_JSON";
31
+ }>;
32
+ label: z.ZodString;
33
+ owner: z.ZodString;
34
+ inherited: z.ZodBoolean;
35
+ shared: z.ZodBoolean;
36
+ registeredAt: z.ZodString;
37
+ }, z.core.$strip>>;
38
+ writable: z.ZodBoolean;
39
+ }, z.core.$strip>;
40
+ export declare const subscriptionInputSchema: z.ZodObject<{
41
+ name: z.ZodEnum<{
42
+ CLAUDE_CODE_OAUTH_TOKEN: "CLAUDE_CODE_OAUTH_TOKEN";
43
+ CODEX_AUTH_JSON: "CODEX_AUTH_JSON";
44
+ GROK_AUTH_JSON: "GROK_AUTH_JSON";
45
+ }>;
46
+ value: z.ZodString;
47
+ replaceId: z.ZodOptional<z.ZodString>;
48
+ }, z.core.$strip>;
49
+ export declare const credentialCandidateSchema: z.ZodObject<{
50
+ id: z.ZodString;
51
+ name: z.ZodString;
52
+ source: z.ZodEnum<{
53
+ repo: "repo";
54
+ account: "account";
55
+ personal: "personal";
56
+ }>;
57
+ }, z.core.$strip>;
58
+ export type CredentialCandidate = z.infer<typeof credentialCandidateSchema>;
59
+ export declare const credentialAccessSchema: z.ZodObject<{
60
+ token: z.ZodString;
61
+ candidates: z.ZodArray<z.ZodObject<{
62
+ id: z.ZodString;
63
+ name: z.ZodString;
64
+ source: z.ZodEnum<{
65
+ repo: "repo";
66
+ account: "account";
67
+ personal: "personal";
68
+ }>;
69
+ }, z.core.$strip>>;
70
+ }, z.core.$strip>;
71
+ export type CredentialAccess = z.infer<typeof credentialAccessSchema>;
72
+ export declare const selectedCredentialSchema: z.ZodObject<{
73
+ name: z.ZodString;
74
+ value: z.ZodString;
75
+ receipt: z.ZodString;
76
+ }, z.core.$strip>;
77
+ export declare function subscriptionLabel(input: {
78
+ email: string | null;
79
+ suffix: string;
80
+ }): string;
@@ -0,0 +1,22 @@
1
+ import type { SubscriptionName } from "./subscriptionCredentials.ts";
2
+ export declare class SubscriptionCredentialError extends Error {
3
+ }
4
+ export declare function subscriptionIdentity(input: {
5
+ name: SubscriptionName;
6
+ value: string;
7
+ }): Promise<{
8
+ email: string | null;
9
+ subject: string | null;
10
+ }>;
11
+ /** unknown quota is not a reason to skip a credential or change who pays. */
12
+ export declare function probeSubscription(input: {
13
+ name: SubscriptionName;
14
+ value: string;
15
+ model?: string | undefined;
16
+ }): Promise<"usable" | "rejected" | "unknown">;
17
+ /** probe the chosen model, not a models-list permission a restricted key may lack. */
18
+ export declare function probeInference(input: {
19
+ name: string;
20
+ value: string;
21
+ model: string;
22
+ }): Promise<"usable" | "rejected" | "unknown">;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pullfrog",
3
- "version": "0.1.84",
3
+ "version": "0.1.85",
4
4
  "cliContractVersion": "1",
5
5
  "type": "module",
6
6
  "bin": {