scaledthought 0.3.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +8 -0
  2. package/dist/index.js +1163 -210
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -553,7 +553,7 @@ import { join } from "node:path";
553
553
  // package.json
554
554
  var package_default = {
555
555
  name: "scaledthought",
556
- version: "0.3.0",
556
+ version: "0.3.1",
557
557
  description: "Headless open-model inference, run by your agent. Prepaid, pay per token. US or Canada.",
558
558
  license: "MIT",
559
559
  keywords: [
@@ -661,7 +661,7 @@ var HINTS = {
661
661
  free_tier_limit: "Accounts that haven't bought credits have lower limits. The first credit purchase lifts them: run `billing topup --amount-usd 20` and show your human the approval_url.",
662
662
  free_tier_key_limit: "Accounts that haven't bought credits have at most 5 active keys. Revoke one with `keys revoke <id>`, or buy credits with `billing topup`.",
663
663
  too_many_pending_topups: "Two approval links are still unpaid. Ask your human to use one (see `billing status` pending_topups), or wait for them to expire.",
664
- daily_topup_limit: "Top-ups are limited to $2,000 per account per rolling 24 hours (open links and auto-reloads included). Use a smaller amount (see available_usd) or wait.",
664
+ daily_topup_limit: "Top-ups are limited to $2,000 per account per rolling 24 hours (open links and auto-reloads included). Use a smaller amount (see available_usd) or wait. Need more than $2,000 a day? Invoiced prepayment: sales@scaledthought.com",
665
665
  billing_upgrade_removed: "Run `billing topup --amount-usd 20` and show your human the approval_url.",
666
666
  gone: "This endpoint was removed. For credits use `billing topup --amount-usd 20`.",
667
667
  fine_tuning_requires_self_hosted: "This base model can't be fine-tuned in your region (it isn't served on our own GPUs). Choose another base model.",
@@ -7898,6 +7898,179 @@ var AD_WRITE_CREDENTIAL_ENV = {
7898
7898
  microsoft: "AD_WRITE_MICROSOFT_CREDENTIALS"
7899
7899
  };
7900
7900
  var AD_WRITE_CREDENTIAL_ENV_NAMES = Object.values(AD_WRITE_CREDENTIAL_ENV);
7901
+ // ../../packages/growth/src/portfolio.ts
7902
+ var PORTFOLIO_LIMITS = {
7903
+ weeklyBudgetMicros: 1e9,
7904
+ founders: ["alexey-scaled-throught", "josh-scaledthought"],
7905
+ effortDayMicros: 50000000
7906
+ };
7907
+ var FUNNEL_STAGES = ["click", "fetch", "signup", "activated", "paid"];
7908
+ var EXPERIMENT_KINDS = ["paid", "owned", "onboarding", "lifecycle", "community", "research"];
7909
+ var AGENT_ROLES = [
7910
+ "growth-lead",
7911
+ "analyst",
7912
+ "onboarding",
7913
+ "seo",
7914
+ "paid-ads",
7915
+ "landing",
7916
+ "lifecycle",
7917
+ "content",
7918
+ "community",
7919
+ "research",
7920
+ "integrations",
7921
+ "canada"
7922
+ ];
7923
+ var EXPERIMENT_STATUSES = ["proposed", "approved", "running", "read", "killed", "scaled"];
7924
+ var EXPERIMENT_METRICS = [
7925
+ "ctr",
7926
+ "fetch_rate",
7927
+ "agent_fetches",
7928
+ "human_visits",
7929
+ "signups",
7930
+ "activation_rate",
7931
+ "paid_rate",
7932
+ "topup_request_rate",
7933
+ "topup_completion_rate",
7934
+ "cost_per_activated",
7935
+ "cost_per_payer",
7936
+ "onboarding_success_rate",
7937
+ "time_to_first_call",
7938
+ "npm_downloads",
7939
+ "github_stars",
7940
+ "registry_installs"
7941
+ ];
7942
+ var SURFACE_TYPES = [
7943
+ "page",
7944
+ "copy",
7945
+ "code",
7946
+ "listing",
7947
+ "cli",
7948
+ "notice",
7949
+ "ad",
7950
+ "post",
7951
+ "email",
7952
+ "external",
7953
+ "price"
7954
+ ];
7955
+ var TIER2_SURFACES = new Set(["ad", "post", "email", "price", "listing", "external"]);
7956
+ var SURFACE_RE = new RegExp(`^(${SURFACE_TYPES.join("|")}):[^\\s*]+\\*?$`);
7957
+ var EXPERIMENT_ID_RE = /^[a-z0-9]+(-[a-z0-9]+)*$/;
7958
+ var CAMPAIGN_ID_RE = /^gcm_[0-9A-HJKMNP-TV-Z]{26}$/;
7959
+ var Day = string2().refine(isDay, "a UTC day, YYYY-MM-DD");
7960
+ var Bps = number2().int().min(0).max(1e4);
7961
+ var Micros = number2().int().min(0);
7962
+ var DecisionRule = discriminatedUnion("kind", [
7963
+ object({ kind: literal("p_better"), threshold: number2().min(0.5).max(0.999) }),
7964
+ object({ kind: literal("rate_at_least"), bps: Bps }),
7965
+ object({ kind: literal("cost_at_most"), micros: Micros })
7966
+ ]);
7967
+ var ExperimentSpec = object({
7968
+ id: string2().max(64).regex(EXPERIMENT_ID_RE, "kebab-case, the file name without .yaml"),
7969
+ title: string2().min(5).max(120),
7970
+ hypothesis: string2().min(20).max(600),
7971
+ owner: _enum(AGENT_ROLES),
7972
+ kind: _enum(EXPERIMENT_KINDS),
7973
+ stage: _enum(FUNNEL_STAGES),
7974
+ tier: union([literal(0), literal(1), literal(2)]),
7975
+ status: _enum(EXPERIMENT_STATUSES),
7976
+ created: Day,
7977
+ surfaces: array(string2().regex(SURFACE_RE, "<type>:<target>, e.g. page:/docs/cursor")).min(1),
7978
+ codes: array(CodeSchema).default([]),
7979
+ metric: object({ primary: _enum(EXPERIMENT_METRICS), guardrail: _enum(EXPERIMENT_METRICS).optional() }),
7980
+ design: object({
7981
+ type: _enum(["ab", "single", "discovery", "synthetic"]),
7982
+ variants: array(string2().min(1).max(40)).optional(),
7983
+ arms: record(string2().min(1).max(40), array(CodeSchema).min(1)).optional()
7984
+ }),
7985
+ run: object({ from: Day, to: Day }).optional(),
7986
+ decision: object({ read_on: Day, min_n: number2().int().min(1), rule: DecisionRule }),
7987
+ budget: object({ weekly_micros: Micros }).default({ weekly_micros: 0 }),
7988
+ estimate: object({
7989
+ p_win_bps: Bps,
7990
+ lift_bps: number2().int().min(1).max(1e5),
7991
+ baseline_per_week: number2().min(0),
7992
+ effort_days: number2().min(0).max(30)
7993
+ }),
7994
+ approval: object({ by: string2().optional(), on: Day.optional(), note: string2().min(3).max(300).optional() }).strict().optional(),
7995
+ campaigns: array(string2().regex(CAMPAIGN_ID_RE, "a console campaign id, gcm_<ulid>")).max(10).default([]),
7996
+ result: object({
7997
+ read: Day,
7998
+ outcome: _enum(["win", "loss", "inconclusive", "stopped"]),
7999
+ summary: string2().min(10).max(1000)
8000
+ }).optional()
8001
+ }).strict();
8002
+
8003
+ // ../../packages/growth/src/campaigns.ts
8004
+ var KEYWORD_MATCH_TYPES = ["exact", "phrase", "broad"];
8005
+ var GOOGLE_AD_LIMITS = {
8006
+ headline: 30,
8007
+ description: 90,
8008
+ path: 15,
8009
+ headlinesMin: 3,
8010
+ headlinesMax: 15,
8011
+ descriptionsMin: 2,
8012
+ descriptionsMax: 4,
8013
+ keyword: 80,
8014
+ keywordWords: 10,
8015
+ adGroups: 20,
8016
+ keywordsPerAdGroup: 200,
8017
+ adsPerAdGroup: 3,
8018
+ negativeKeywords: 500
8019
+ };
8020
+ var CampaignId = string2().regex(CAMPAIGN_ID_RE, "a campaign id, gcm_<ulid>");
8021
+ var Line = (max, what) => string2().trim().min(1).refine((s) => [...s].length <= max, `${what}: at most ${max} characters`);
8022
+ var Keyword = object({
8023
+ text: Line(GOOGLE_AD_LIMITS.keyword, "keyword").refine((s) => s.split(/\s+/).length <= GOOGLE_AD_LIMITS.keywordWords, `keyword: at most ${GOOGLE_AD_LIMITS.keywordWords} words`),
8024
+ match: _enum(KEYWORD_MATCH_TYPES)
8025
+ }).strict();
8026
+ var SearchAd = object({
8027
+ headlines: array(Line(GOOGLE_AD_LIMITS.headline, "headline")).min(GOOGLE_AD_LIMITS.headlinesMin).max(GOOGLE_AD_LIMITS.headlinesMax),
8028
+ descriptions: array(Line(GOOGLE_AD_LIMITS.description, "description")).min(GOOGLE_AD_LIMITS.descriptionsMin).max(GOOGLE_AD_LIMITS.descriptionsMax),
8029
+ path1: Line(GOOGLE_AD_LIMITS.path, "path").optional(),
8030
+ path2: Line(GOOGLE_AD_LIMITS.path, "path").optional()
8031
+ }).strict().refine((a) => !a.path2 || a.path1, "path2 needs path1");
8032
+ var AdGroup2 = object({
8033
+ name: string2().trim().min(1).max(255),
8034
+ keywords: array(Keyword).min(1).max(GOOGLE_AD_LIMITS.keywordsPerAdGroup),
8035
+ ads: array(SearchAd).min(1).max(GOOGLE_AD_LIMITS.adsPerAdGroup),
8036
+ negative_keywords: array(Keyword).max(GOOGLE_AD_LIMITS.negativeKeywords).default([])
8037
+ }).strict();
8038
+ var CampaignContent = object({
8039
+ ad_groups: array(AdGroup2).min(1).max(GOOGLE_AD_LIMITS.adGroups),
8040
+ negative_keywords: array(Keyword).max(GOOGLE_AD_LIMITS.negativeKeywords).default([])
8041
+ }).strict();
8042
+ var CAMPAIGN_NETWORKS = ["search", "search_partners", "display"];
8043
+ var CampaignTargeting = object({
8044
+ locations: array(string2().trim().min(2).max(80)).min(1).max(50),
8045
+ location_mode: _enum(["presence", "presence_or_interest"]).default("presence"),
8046
+ languages: array(string2().trim().min(2).max(10)).min(1).max(20),
8047
+ networks: array(_enum(CAMPAIGN_NETWORKS)).min(1).max(3).default(["search"])
8048
+ }).strict();
8049
+ var Day2 = string2().refine(isDay, "a UTC day, YYYY-MM-DD");
8050
+ var Budget = number2().int().positive().max(PORTFOLIO_LIMITS.weeklyBudgetMicros);
8051
+ var CAMPAIGN_FIELD_SHAPE = {
8052
+ name: string2().trim().min(3).max(120),
8053
+ code: CodeSchema,
8054
+ experiment_id: string2().max(64).regex(EXPERIMENT_ID_RE).nullable(),
8055
+ ad_account_id: string2().trim().min(1).max(64).nullable(),
8056
+ final_url: string2().trim().max(200),
8057
+ daily_budget_micros: Budget.nullable(),
8058
+ weekly_budget_micros: Budget.nullable(),
8059
+ run_from: Day2,
8060
+ run_to: Day2,
8061
+ targeting: CampaignTargeting,
8062
+ content: CampaignContent,
8063
+ notes: string2().trim().max(4000).nullable()
8064
+ };
8065
+ var CampaignFields = object({
8066
+ ...CAMPAIGN_FIELD_SHAPE,
8067
+ experiment_id: CAMPAIGN_FIELD_SHAPE.experiment_id.default(null),
8068
+ ad_account_id: CAMPAIGN_FIELD_SHAPE.ad_account_id.default(null),
8069
+ daily_budget_micros: CAMPAIGN_FIELD_SHAPE.daily_budget_micros.default(null),
8070
+ weekly_budget_micros: CAMPAIGN_FIELD_SHAPE.weekly_budget_micros.default(null),
8071
+ notes: CAMPAIGN_FIELD_SHAPE.notes.default(null)
8072
+ }).strict();
8073
+ var CampaignFieldsPatch = object(CAMPAIGN_FIELD_SHAPE).partial().strict();
7901
8074
  // ../../packages/growth/src/sinks/google.ts
7902
8075
  var GOOGLE_DATA_MANAGER_URL = "https://datamanager.googleapis.com/v1/events:ingest";
7903
8076
  var GOOGLE_TOKEN_URL = "https://oauth2.googleapis.com/token";
@@ -8208,35 +8381,9 @@ var PERMANENT_FIRST_PURCHASE_SKIPS = new Set([
8208
8381
  "account_not_active"
8209
8382
  ]);
8210
8383
  // ../../packages/growth/src/experiments.ts
8211
- var EXPERIMENTS = {
8212
- "first-paying-customers": {
8213
- title: "First paying customers",
8214
- hypothesis: "Developers who use coding agents will pay for open models when their agent sets everything up from one pasted prompt.",
8215
- spend: { from: "2026-10-06", to: "2026-10-19" },
8216
- tailDays: 7,
8217
- payWindowDays: 14,
8218
- activationDays: 7,
8219
- passCostMicros: 20000000,
8220
- stopCostMicros: 40000000,
8221
- minPaidRateBps: 500,
8222
- lowPaidRateBps: 200,
8223
- minPayers: 12,
8224
- verdictMinSpendMicros: 300000000,
8225
- verdictMinActivations: 15,
8226
- pauseCheckDay: 10,
8227
- readMinMatured: 30,
8228
- excludedAccountIds: [],
8229
- messages: { A: "Agent", B: "Free", C: "Private" },
8230
- platforms: ["reddit", "google", "x", "ethicalads"],
8231
- plan: {
8232
- fetchPerClickBps: 2000,
8233
- activatedPerFetchBps: 7500,
8234
- paidPerActivatedBps: 500,
8235
- costPerPayerMicros: 333000000
8236
- }
8237
- }
8238
- };
8384
+ var EXPERIMENTS = {};
8239
8385
  var EXPERIMENT_KEYS = Object.keys(EXPERIMENTS);
8386
+ var DEFAULT_EXPERIMENT_KEY = EXPERIMENT_KEYS[0] ?? null;
8240
8387
  var EXPERIMENT_PHASES = ["before", "spending", "reading_payment", "payment_read", "tail_read"];
8241
8388
  // ../../packages/growth/src/go-hits.ts
8242
8389
  var GO_HIT_KINDS = ["human", "agent"];
@@ -8297,13 +8444,13 @@ var EthicalAdsCredentials = object({
8297
8444
  var credentials3 = (creds) => parseCredentialsJson(creds[ENV7], EthicalAdsCredentials);
8298
8445
  var ethicalAdsApiAccount = (creds) => credentials3(creds).advertiser;
8299
8446
  var Num3 = union([number2(), string2()]).nullable().optional();
8300
- var Day = object({ date: string2().optional(), index: string2().optional(), views: Num3, clicks: Num3, cost: Num3 });
8447
+ var Day3 = object({ date: string2().optional(), index: string2().optional(), views: Num3, clicks: Num3, cost: Num3 });
8301
8448
  var Report = object({
8302
- days: array(Day).default([]),
8449
+ days: array(Day3).default([]),
8303
8450
  flights: array(object({
8304
8451
  name: string2().nullable().optional(),
8305
8452
  slug: string2(),
8306
- report: object({ days: array(Day).default([]) }).nullable().optional()
8453
+ report: object({ days: array(Day3).default([]) }).nullable().optional()
8307
8454
  })).default([])
8308
8455
  });
8309
8456
  var dayOf2 = (d) => (d.date ?? d.index ?? "").slice(0, 10);
@@ -8949,102 +9096,8 @@ var ethicalAds2 = withApi(ethicalAds, "ethicalads", pullEthicalAds, ethicalAdsAp
8949
9096
  var microsoftAds2 = withApi(microsoftAds, "microsoft", pullMicrosoftAds, microsoftApiAccount);
8950
9097
  var linkedInAds2 = withApi(linkedInAds, "linkedin", pullLinkedInAds, linkedInApiAccount);
8951
9098
  var metaAds2 = withApi(metaAds, "meta", pullMetaAds, metaApiAccount);
8952
- // ../../packages/growth/src/portfolio.ts
8953
- var FUNNEL_STAGES = ["click", "fetch", "signup", "activated", "paid"];
8954
- var EXPERIMENT_KINDS = ["paid", "owned", "onboarding", "lifecycle", "community", "research"];
8955
- var AGENT_ROLES = [
8956
- "growth-lead",
8957
- "analyst",
8958
- "onboarding",
8959
- "seo",
8960
- "paid-ads",
8961
- "landing",
8962
- "lifecycle",
8963
- "content",
8964
- "community",
8965
- "research",
8966
- "integrations",
8967
- "canada"
8968
- ];
8969
- var EXPERIMENT_STATUSES = ["proposed", "approved", "running", "read", "killed", "scaled"];
8970
- var EXPERIMENT_METRICS = [
8971
- "ctr",
8972
- "fetch_rate",
8973
- "agent_fetches",
8974
- "human_visits",
8975
- "signups",
8976
- "activation_rate",
8977
- "paid_rate",
8978
- "topup_request_rate",
8979
- "topup_completion_rate",
8980
- "cost_per_activated",
8981
- "cost_per_payer",
8982
- "onboarding_success_rate",
8983
- "time_to_first_call",
8984
- "npm_downloads",
8985
- "github_stars",
8986
- "registry_installs"
8987
- ];
8988
- var SURFACE_TYPES = [
8989
- "page",
8990
- "copy",
8991
- "code",
8992
- "listing",
8993
- "cli",
8994
- "notice",
8995
- "ad",
8996
- "post",
8997
- "email",
8998
- "external",
8999
- "price"
9000
- ];
9001
- var TIER2_SURFACES = new Set(["ad", "post", "email", "price", "listing", "external"]);
9002
- var SURFACE_RE = new RegExp(`^(${SURFACE_TYPES.join("|")}):[^\\s*]+\\*?$`);
9003
- var EXPERIMENT_ID_RE = /^[a-z0-9]+(-[a-z0-9]+)*$/;
9004
- var Day2 = string2().refine(isDay, "a UTC day, YYYY-MM-DD");
9005
- var Bps = number2().int().min(0).max(1e4);
9006
- var Micros = number2().int().min(0);
9007
- var DecisionRule = discriminatedUnion("kind", [
9008
- object({ kind: literal("p_better"), threshold: number2().min(0.5).max(0.999) }),
9009
- object({ kind: literal("rate_at_least"), bps: Bps }),
9010
- object({ kind: literal("cost_at_most"), micros: Micros })
9011
- ]);
9012
- var ExperimentSpec = object({
9013
- id: string2().max(64).regex(EXPERIMENT_ID_RE, "kebab-case, the file name without .yaml"),
9014
- title: string2().min(5).max(120),
9015
- hypothesis: string2().min(20).max(600),
9016
- owner: _enum(AGENT_ROLES),
9017
- kind: _enum(EXPERIMENT_KINDS),
9018
- stage: _enum(FUNNEL_STAGES),
9019
- tier: union([literal(0), literal(1), literal(2)]),
9020
- status: _enum(EXPERIMENT_STATUSES),
9021
- created: Day2,
9022
- surfaces: array(string2().regex(SURFACE_RE, "<type>:<target>, e.g. page:/docs/cursor")).min(1),
9023
- codes: array(CodeSchema).default([]),
9024
- metric: object({ primary: _enum(EXPERIMENT_METRICS), guardrail: _enum(EXPERIMENT_METRICS).optional() }),
9025
- design: object({
9026
- type: _enum(["ab", "single", "discovery", "synthetic"]),
9027
- variants: array(string2().min(1).max(40)).optional(),
9028
- arms: record(string2().min(1).max(40), array(CodeSchema).min(1)).optional()
9029
- }),
9030
- run: object({ from: Day2, to: Day2 }).optional(),
9031
- decision: object({ read_on: Day2, min_n: number2().int().min(1), rule: DecisionRule }),
9032
- budget: object({ weekly_micros: Micros }).default({ weekly_micros: 0 }),
9033
- estimate: object({
9034
- p_win_bps: Bps,
9035
- lift_bps: number2().int().min(1).max(1e5),
9036
- baseline_per_week: number2().min(0),
9037
- effort_days: number2().min(0).max(30)
9038
- }),
9039
- approval: object({ by: string2(), on: Day2 }).optional(),
9040
- result: object({
9041
- read: Day2,
9042
- outcome: _enum(["win", "loss", "inconclusive", "stopped"]),
9043
- summary: string2().min(10).max(1000)
9044
- }).optional()
9045
- }).strict();
9046
9099
  // ../../packages/growth/src/results-schema.ts
9047
- var Day3 = string2().regex(/^\d{4}-\d{2}-\d{2}$/);
9100
+ var Day4 = string2().regex(/^\d{4}-\d{2}-\d{2}$/);
9048
9101
  var Micros2 = number2().int();
9049
9102
  var Count = number2().int().nonnegative();
9050
9103
  var Bps2 = number2().int();
@@ -9076,7 +9129,7 @@ var CodeResultRow = ResultRow.extend({
9076
9129
  channel: string2(),
9077
9130
  message: string2().nullable(),
9078
9131
  status: string2(),
9079
- paused_on: Day3.nullable(),
9132
+ paused_on: Day4.nullable(),
9080
9133
  sample_ok: boolean2(),
9081
9134
  pause_suggested: boolean2(),
9082
9135
  leading: boolean2(),
@@ -9108,8 +9161,8 @@ var Scorecard = object({
9108
9161
  real_use: object({ eligible: Count, returned: Count, rate_bps: Bps2.nullable() })
9109
9162
  });
9110
9163
  var Read = object({
9111
- signups_from: Day3,
9112
- signups_to: Day3,
9164
+ signups_from: Day4,
9165
+ signups_to: Day4,
9113
9166
  scorecard: Scorecard,
9114
9167
  by_message: array(ResultRow),
9115
9168
  by_channel: array(ResultRow),
@@ -9131,7 +9184,7 @@ var RuleOutcome = _enum([
9131
9184
  ]);
9132
9185
  var Rule = object({
9133
9186
  id: RuleId,
9134
- date: Day3,
9187
+ date: Day4,
9135
9188
  status: RuleStatus,
9136
9189
  outcome: RuleOutcome,
9137
9190
  codes: array(string2()),
@@ -9140,7 +9193,7 @@ var Rule = object({
9140
9193
  var PlatformFinality = object({
9141
9194
  platform: string2(),
9142
9195
  spend_micros: Micros2,
9143
- final_through: Day3.nullable(),
9196
+ final_through: Day4.nullable(),
9144
9197
  last_import_at: string2().nullable(),
9145
9198
  last_import_source: _enum(["csv", "api", "manual"]).nullable()
9146
9199
  });
@@ -9165,13 +9218,13 @@ var Checks = object({
9165
9218
  }),
9166
9219
  spread: array(object({
9167
9220
  code: string2(),
9168
- paused_on: Day3,
9221
+ paused_on: Day4,
9169
9222
  signups_after: Count,
9170
9223
  verdict_changes: boolean2()
9171
9224
  })),
9172
9225
  spend: object({
9173
9226
  final: boolean2(),
9174
- final_through: Day3.nullable(),
9227
+ final_through: Day4.nullable(),
9175
9228
  platforms: array(PlatformFinality),
9176
9229
  unattributed_micros: Micros2,
9177
9230
  unattributed_rows: Count
@@ -9197,13 +9250,13 @@ var GrowthResults = object({
9197
9250
  key: string2(),
9198
9251
  title: string2(),
9199
9252
  hypothesis: string2(),
9200
- spend: object({ from: Day3, to: Day3 }),
9253
+ spend: object({ from: Day4, to: Day4 }),
9201
9254
  dates: object({
9202
- pause_check: Day3,
9203
- cost_read: Day3,
9204
- payment_read: Day3,
9205
- tail_read: Day3,
9206
- tail_signups_to: Day3
9255
+ pause_check: Day4,
9256
+ cost_read: Day4,
9257
+ payment_read: Day4,
9258
+ tail_read: Day4,
9259
+ tail_signups_to: Day4
9207
9260
  }),
9208
9261
  thresholds: object({
9209
9262
  pass_cost_micros: Micros2,
@@ -9224,7 +9277,7 @@ var GrowthResults = object({
9224
9277
  cost_per_payer_micros: Micros2
9225
9278
  })
9226
9279
  }),
9227
- as_of: Day3,
9280
+ as_of: Day4,
9228
9281
  day: number2().int(),
9229
9282
  phase: _enum(EXPERIMENT_PHASES),
9230
9283
  read: Read,
@@ -9236,7 +9289,7 @@ var GrowthResults = object({
9236
9289
  decisions: array(GrowthDecision)
9237
9290
  });
9238
9291
  // ../../packages/schemas/src/legal.ts
9239
- var TERMS_VERSION = "2026-10-10";
9292
+ var TERMS_VERSION = "2026-10-11";
9240
9293
  var LEGAL_SITE = "https://scaledthought.com";
9241
9294
  var LEGAL_PATHS = {
9242
9295
  index: "/legal",
@@ -9244,7 +9297,6 @@ var LEGAL_PATHS = {
9244
9297
  privacy: "/legal/privacy",
9245
9298
  acceptableUse: "/legal/acceptable-use",
9246
9299
  creditsAndRefunds: "/legal/credits-and-refunds",
9247
- subprocessors: "/legal/subprocessors",
9248
9300
  security: "/legal/security"
9249
9301
  };
9250
9302
  var TERMS_URL = `${LEGAL_SITE}${LEGAL_PATHS.terms}`;
@@ -9392,7 +9444,6 @@ function machineStore(env, platform = process.platform) {
9392
9444
  }
9393
9445
 
9394
9446
  // src/connect.ts
9395
- var NPX = "npx -y scaledthought@0.3";
9396
9447
  var LOGIN_DIR = ".scaledthought";
9397
9448
  var LOGIN_FILE = join4(LOGIN_DIR, "login.json");
9398
9449
  var KEY_SAVED_TO = ".env (ST_API_KEY, ST_BASE_URL)";
@@ -9742,10 +9793,10 @@ async function readCodeFrom(stream) {
9742
9793
  }
9743
9794
 
9744
9795
  // src/commands.ts
9745
- var NPX2 = "npx -y scaledthought@0.3";
9796
+ var NPX = "npx -y scaledthought@0.3";
9746
9797
  var FIRST_TOPUP_USD = 20;
9747
- var TOPUP_COMMAND = `${NPX2} billing topup --amount-usd ${FIRST_TOPUP_USD}`;
9748
- var WAIT_COMMAND = `${NPX2} billing wait`;
9798
+ var TOPUP_COMMAND = `${NPX} billing topup --amount-usd ${FIRST_TOPUP_USD}`;
9799
+ var WAIT_COMMAND = `${NPX} billing wait`;
9749
9800
  var WAIT_PATIENCE_MIN = 15;
9750
9801
  var CREDIT_STEPS = [
9751
9802
  `Inference is prepaid and this account has no credits yet: completions return 402 insufficient_credits until your human pays. Do these first, in order:`,
@@ -9757,10 +9808,10 @@ var CREDIT_STEPS = [
9757
9808
  function nextSteps(model, needsCredits) {
9758
9809
  return [
9759
9810
  ...needsCredits ? CREDIT_STEPS : [],
9760
- model ? `Verify with one real completion: ${NPX2} chat -m ${model} "Reply with OK" (or POST $ST_BASE_URL/chat/completions with that model)` : `No chat model is live in this region right now. Check again with: ${NPX2} models --live`,
9761
- `Or let the router pick: ${NPX2} chat -m auto "Reply with OK"`,
9811
+ model ? `Verify with one real completion: ${NPX} chat -m ${model} "Reply with OK" (or POST $ST_BASE_URL/chat/completions with that model)` : `No chat model is live in this region right now. Check again with: ${NPX} models --live`,
9812
+ `Or let the router pick: ${NPX} chat -m auto "Reply with OK"`,
9762
9813
  "Use it from code: any OpenAI SDK with base_url=$ST_BASE_URL and api_key=$ST_API_KEY (both are in .env)",
9763
- `Optional, connect MCP: ${NPX2} mcp`,
9814
+ `Optional, connect MCP: ${NPX} mcp`,
9764
9815
  ...needsCredits ? [] : [`More credits when needed: ${TOPUP_COMMAND} returns an approval_url for your human (inference is prepaid)`]
9765
9816
  ];
9766
9817
  }
@@ -9780,7 +9831,7 @@ async function liveSummary(ctx, region, balanceUsd) {
9780
9831
  return {
9781
9832
  balance_usd: balanceUsd ?? 0,
9782
9833
  needs_credits: needsCredits,
9783
- next_command: needsCredits ? TOPUP_COMMAND : `${NPX2} chat -m ${suggested ?? "auto"} "Reply with OK"`,
9834
+ next_command: needsCredits ? TOPUP_COMMAND : `${NPX} chat -m ${suggested ?? "auto"} "Reply with OK"`,
9784
9835
  newest_models: live.slice(0, 5),
9785
9836
  suggested_model: suggested,
9786
9837
  next_steps: nextSteps(suggested, needsCredits)
@@ -10222,7 +10273,7 @@ async function billingTopupAndWait(ctx, o) {
10222
10273
  let t = created;
10223
10274
  while (!TOPUP_DONE.has(t.status ?? "")) {
10224
10275
  if (Date.now() > deadline)
10225
- throw new CliError("topup_wait_timeout", `Top-up ${id} is still ${t.status}.`, `The link may still work. Check later with: ${NPX2} billing status`, { topup_id: id });
10276
+ throw new CliError("topup_wait_timeout", `Top-up ${id} is still ${t.status}.`, `The link may still work. Check later with: ${NPX} billing status`, { topup_id: id });
10226
10277
  await new Promise((r) => setTimeout(r, o.pollMs ?? 3000));
10227
10278
  t = await api(ctx, "GET", `/v1/billing/topups/${encodeURIComponent(id)}`);
10228
10279
  }
@@ -10233,7 +10284,7 @@ async function billingTopupAndWait(ctx, o) {
10233
10284
  var billingAutoReloadOff = (ctx) => api(ctx, "PATCH", "/v1/billing/auto-reload", { body: { enabled: false } });
10234
10285
  var billingTransactions = (ctx, o = {}) => api(ctx, "GET", `/v1/billing/transactions${o.cursor ? `?cursor=${encodeURIComponent(o.cursor)}` : ""}`);
10235
10286
  function billingUpgradeRemoved() {
10236
- throw new CliError("billing_upgrade_removed", "billing upgrade (monthly caps) was replaced by prepaid credits.", `Run \`${NPX2} billing topup --amount-usd 20\` and send your human the approval_url. They can turn on auto-reload on the same page.`);
10287
+ throw new CliError("billing_upgrade_removed", "billing upgrade (monthly caps) was replaced by prepaid credits.", `Run \`${NPX} billing topup --amount-usd 20\` and send your human the approval_url. They can turn on auto-reload on the same page.`);
10237
10288
  }
10238
10289
  var benchmarks = (ctx, id, region) => api(ctx, "GET", `/v1/models/${encodeURIComponent(id)}/benchmarks`, {
10239
10290
  auth: false,
@@ -10581,8 +10632,827 @@ async function decide2(ctx, body) {
10581
10632
  return { ...out, region: res.headers.get("x-st-region"), request_id: res.headers.get("x-st-request-id") };
10582
10633
  }
10583
10634
 
10635
+ // src/destinations/run.ts
10636
+ import { spawn as spawn2 } from "node:child_process";
10637
+ var TIMEOUT_MS2 = 120000;
10638
+ var spawnRunner = (cmd, args, opts) => new Promise((resolve, reject) => {
10639
+ const child = spawn2(cmd, args, {
10640
+ cwd: opts.cwd,
10641
+ env: opts.env ? { ...process.env, ...opts.env } : process.env,
10642
+ shell: false,
10643
+ stdio: ["pipe", "pipe", "pipe"],
10644
+ windowsHide: true
10645
+ });
10646
+ let stdout = "";
10647
+ let stderr = "";
10648
+ const timer = setTimeout(() => child.kill("SIGTERM"), TIMEOUT_MS2);
10649
+ child.stdout.on("data", (d) => {
10650
+ stdout += d.toString("utf8");
10651
+ });
10652
+ child.stderr.on("data", (d) => {
10653
+ stderr += d.toString("utf8");
10654
+ });
10655
+ child.on("error", (e) => {
10656
+ clearTimeout(timer);
10657
+ reject(e);
10658
+ });
10659
+ child.on("close", (code) => {
10660
+ clearTimeout(timer);
10661
+ resolve({ code: code ?? 1, stdout, stderr });
10662
+ });
10663
+ child.stdin.on("error", () => {});
10664
+ child.stdin.end(opts.stdin ?? "");
10665
+ });
10666
+ var isMissing = (e) => e?.code === "ENOENT";
10667
+ function redact(text, secrets) {
10668
+ let out = text;
10669
+ for (const s of secrets)
10670
+ if (s)
10671
+ out = out.split(s).join("[redacted]");
10672
+ return out.replace(/st_(ca|us)_(live|test)_[0-9A-Za-z]{8,}/g, "[redacted]");
10673
+ }
10674
+ async function probe(io, p, args, stdin) {
10675
+ try {
10676
+ return await io.run(p.cmd, args, { cwd: io.cwd, stdin });
10677
+ } catch (e) {
10678
+ if (isMissing(e))
10679
+ throw missing(p);
10680
+ throw new CliError("destination_failed", `Could not start ${p.cmd}.`, p.install);
10681
+ }
10682
+ }
10683
+ async function exec(io, p, args, o = {}) {
10684
+ const r = await probe(io, p, args, o.stdin);
10685
+ if (r.code !== 0) {
10686
+ const detail = redact(r.stderr || r.stdout, [...o.secrets ?? [], o.stdin ?? ""]).trim().slice(-300);
10687
+ throw new CliError("destination_failed", `\`${o.shown ?? `${p.cmd} ${args.slice(0, 3).join(" ")}`}\` failed (exit code ${r.code}).`, p.login, detail ? { detail } : {});
10688
+ }
10689
+ return r.stdout;
10690
+ }
10691
+ function missing(p) {
10692
+ return new CliError("destination_cli_missing", `\`${p.cmd}\` isn't installed or isn't on PATH.`, p.install);
10693
+ }
10694
+ var SAFE = /^[A-Za-z0-9_.@:+=][A-Za-z0-9_.@:+=-]*$/;
10695
+ var SAFE_SLASH = /^[A-Za-z0-9_.@:+=][A-Za-z0-9_.@:+=/-]*$/;
10696
+ var isSafeValue = (v, o = {}) => typeof v === "string" && v.length <= 120 && (o.slash ? SAFE_SLASH : SAFE).test(v);
10697
+ function safeValue(flag, v, o = {}) {
10698
+ if (!isSafeValue(v, o))
10699
+ throw new CliError("bad_argument", `--${flag} "${v.slice(0, 60)}" isn't a valid name${o.slash ? "" : " (no slashes)"}.`, "Use letters, digits and . _ - : @ (it must not start with -).");
10700
+ return v;
10701
+ }
10702
+
10703
+ // src/destinations/types.ts
10704
+ var PUT_FLAGS = [
10705
+ "repo",
10706
+ "env",
10707
+ "app",
10708
+ "project",
10709
+ "worker",
10710
+ "secret",
10711
+ "aws-region",
10712
+ "locations",
10713
+ "namespace",
10714
+ "context",
10715
+ "config"
10716
+ ];
10717
+ var keyName = (s) => s.length <= 80 ? s : `${s.slice(0, 79)}…`;
10718
+
10719
+ // src/destinations/aws.ts
10720
+ var AWS = {
10721
+ cmd: "aws",
10722
+ install: "Install the AWS CLI and configure it: https://aws.amazon.com/cli/, then `aws configure` or `aws sso login`.",
10723
+ login: "Check `aws sts get-caller-identity` and that you may manage Secrets Manager secrets in that region."
10724
+ };
10725
+ function target(region, secret) {
10726
+ return {
10727
+ livesIn: `aws:${region}/${secret}`,
10728
+ keyName: keyName(`aws: ${region} / ${secret}`),
10729
+ params: { region, secret }
10730
+ };
10731
+ }
10732
+ var FROM_STDIN = ["--secret-string", "file:///dev/stdin"];
10733
+ var aws = {
10734
+ id: "aws",
10735
+ label: "AWS Secrets Manager",
10736
+ flags: ["aws-region", "secret"],
10737
+ async resolve(f, io) {
10738
+ let region = f["aws-region"] ?? io.env.AWS_REGION ?? io.env.AWS_DEFAULT_REGION;
10739
+ if (!region)
10740
+ region = (await probe(io, AWS, ["configure", "get", "region"])).stdout.trim();
10741
+ if (!region)
10742
+ throw new CliError("bad_argument", "Which AWS region?", "Pass --aws-region, e.g. us-east-1.");
10743
+ const secret = safeValue("secret", f.secret ?? "scaledthought/api-key", { slash: true });
10744
+ return target(safeValue("aws-region", region), secret);
10745
+ },
10746
+ parse(rest) {
10747
+ const i = rest.indexOf("/");
10748
+ const region = rest.slice(0, i);
10749
+ const secret = rest.slice(i + 1);
10750
+ return i > 0 && isSafeValue(region) && isSafeValue(secret, { slash: true }) ? target(region, secret) : null;
10751
+ },
10752
+ async put(t, secret, io) {
10753
+ const { region, secret: name } = t.params;
10754
+ const exists = await probe(io, AWS, ["secretsmanager", "describe-secret", "--secret-id", name, "--region", region]);
10755
+ const args = exists.code === 0 ? ["secretsmanager", "put-secret-value", "--secret-id", name, ...FROM_STDIN, "--region", region] : ["secretsmanager", "create-secret", "--name", name, ...FROM_STDIN, "--region", region];
10756
+ const shown = `aws ${args.join(" ")}`;
10757
+ await exec(io, AWS, args, { stdin: secret, shown });
10758
+ return `${shown} (stdin)`;
10759
+ },
10760
+ next: (t) => `Read secret ${t.params.secret} in ${t.params.region} (AWSCURRENT); cached readers see it on refresh.`
10761
+ };
10762
+
10763
+ // src/destinations/cloudflare.ts
10764
+ import { existsSync as existsSync5, readFileSync as readFileSync7 } from "node:fs";
10765
+ import { join as join6 } from "node:path";
10766
+ var WRANGLER = {
10767
+ cmd: "wrangler",
10768
+ install: "Install Wrangler and log in: npm i -g wrangler && wrangler login",
10769
+ login: "Check `wrangler whoami` (log in with `wrangler login`) and the Worker name."
10770
+ };
10771
+ function target2(worker, env) {
10772
+ return {
10773
+ livesIn: `cloudflare:${worker}${env ? `/${env}` : ""}`,
10774
+ keyName: keyName(`cloudflare: ${worker}${env ? ` / ${env}` : ""}`),
10775
+ params: { worker, ...env ? { env } : {} }
10776
+ };
10777
+ }
10778
+ function workerName(cwd) {
10779
+ for (const f of ["wrangler.toml", "wrangler.json", "wrangler.jsonc"]) {
10780
+ const p = join6(cwd, f);
10781
+ if (!existsSync5(p))
10782
+ continue;
10783
+ const text = readFileSync7(p, "utf8");
10784
+ const m = f.endsWith(".toml") ? /^\s*name\s*=\s*["']([^"']+)["']/m.exec(text) : /"name"\s*:\s*"([^"]+)"/.exec(text);
10785
+ if (m)
10786
+ return m[1];
10787
+ }
10788
+ return;
10789
+ }
10790
+ var cloudflare = {
10791
+ id: "cloudflare",
10792
+ label: "Cloudflare Workers",
10793
+ flags: ["worker", "env"],
10794
+ async resolve(f, io) {
10795
+ const worker = f.worker ?? workerName(io.cwd);
10796
+ if (!worker)
10797
+ throw new CliError("bad_argument", "Which Worker?", "Pass --worker <name> (or run where wrangler.toml is).");
10798
+ return target2(safeValue("worker", worker), f.env ? safeValue("env", f.env) : undefined);
10799
+ },
10800
+ parse(rest) {
10801
+ const [worker, env, ...more] = rest.split("/");
10802
+ if (!isSafeValue(worker) || more.length || env && !isSafeValue(env))
10803
+ return null;
10804
+ return target2(worker, env || undefined);
10805
+ },
10806
+ async put(t, secret, io) {
10807
+ const args = ["secret", "put", "ST_API_KEY", "--name", t.params.worker];
10808
+ if (t.params.env)
10809
+ args.push("--env", t.params.env);
10810
+ const shown = `wrangler ${args.join(" ")}`;
10811
+ await exec(io, WRANGLER, args, { stdin: secret, shown });
10812
+ return `${shown} (stdin)`;
10813
+ },
10814
+ next: () => "The Worker reads env.ST_API_KEY; Cloudflare deploys the new secret at once."
10815
+ };
10816
+
10817
+ // src/destinations/doppler.ts
10818
+ var DOPPLER = {
10819
+ cmd: "doppler",
10820
+ install: "Install the Doppler CLI and log in: https://docs.doppler.com/docs/install-cli, then `doppler login`.",
10821
+ login: "Check `doppler me` and the project and config names (`doppler setup` links a directory)."
10822
+ };
10823
+ function target3(project, config) {
10824
+ return {
10825
+ livesIn: `doppler:${project}/${config}`,
10826
+ keyName: keyName(`doppler: ${project} / ${config}`),
10827
+ params: { project, config }
10828
+ };
10829
+ }
10830
+ var doppler = {
10831
+ id: "doppler",
10832
+ label: "Doppler",
10833
+ flags: ["project", "config"],
10834
+ async resolve(f, io) {
10835
+ const get = async (what) => (await probe(io, DOPPLER, ["configure", "get", what, "--plain"])).stdout.trim();
10836
+ const project = f.project ?? await get("project");
10837
+ const config = f.config ?? await get("config");
10838
+ if (!project || !config)
10839
+ throw new CliError("bad_argument", "Which Doppler project and config?", "Pass --project and --config (or run `doppler setup` here).");
10840
+ return target3(safeValue("project", project), safeValue("config", config));
10841
+ },
10842
+ parse(rest) {
10843
+ const [project, config, ...more] = rest.split("/");
10844
+ return isSafeValue(project) && isSafeValue(config) && !more.length ? target3(project, config) : null;
10845
+ },
10846
+ async put(t, secret, io) {
10847
+ const args = ["secrets", "set", "ST_API_KEY", "--project", t.params.project, "--config", t.params.config];
10848
+ const shown = `doppler ${args.join(" ")}`;
10849
+ await exec(io, DOPPLER, args, { stdin: secret, shown });
10850
+ return `${shown} (stdin)`;
10851
+ },
10852
+ next: () => "Apps started with `doppler run` get it on their next start."
10853
+ };
10854
+
10855
+ // src/destinations/fly.ts
10856
+ import { existsSync as existsSync6, readFileSync as readFileSync8 } from "node:fs";
10857
+ import { join as join7 } from "node:path";
10858
+ var FLY = {
10859
+ cmd: "fly",
10860
+ install: "Install flyctl and log in: https://fly.io/docs/flyctl/install/, then `fly auth login`.",
10861
+ login: "Check `fly auth whoami` (log in with `fly auth login`) and the app name."
10862
+ };
10863
+ var FLYCTL = { ...FLY, cmd: "flyctl" };
10864
+ var target4 = (app) => ({ livesIn: `fly:${app}`, keyName: keyName(`fly: ${app}`), params: { app } });
10865
+ function appFromToml(cwd) {
10866
+ const f = join7(cwd, "fly.toml");
10867
+ if (!existsSync6(f))
10868
+ return;
10869
+ return /^\s*app\s*=\s*["']([^"']+)["']/m.exec(readFileSync8(f, "utf8"))?.[1];
10870
+ }
10871
+ async function run(io, args, stdin, shown) {
10872
+ try {
10873
+ await exec(io, FLY, args, { stdin, shown });
10874
+ } catch (e) {
10875
+ if (e.code !== "destination_cli_missing")
10876
+ throw e;
10877
+ await exec(io, FLYCTL, args, { stdin, shown });
10878
+ }
10879
+ }
10880
+ var fly = {
10881
+ id: "fly",
10882
+ label: "Fly.io",
10883
+ flags: ["app"],
10884
+ async resolve(f, io) {
10885
+ const app = f.app ?? appFromToml(io.cwd);
10886
+ if (!app)
10887
+ throw new CliError("bad_argument", "Which Fly app?", "Pass --app <name> (or run where fly.toml is).");
10888
+ return target4(safeValue("app", app));
10889
+ },
10890
+ parse: (rest) => isSafeValue(rest) ? target4(rest) : null,
10891
+ async put(t, secret, io) {
10892
+ const args = ["secrets", "import", "-a", t.params.app];
10893
+ const shown = `fly ${args.join(" ")}`;
10894
+ await run(io, args, `ST_API_KEY=${secret}
10895
+ `, shown);
10896
+ return `${shown} (stdin)`;
10897
+ },
10898
+ next: () => "Fly restarts the app's machines with the new secret."
10899
+ };
10900
+
10901
+ // src/destinations/gcp.ts
10902
+ var GCLOUD = {
10903
+ cmd: "gcloud",
10904
+ install: "Install the Google Cloud CLI and log in: https://cloud.google.com/sdk/docs/install, then `gcloud auth login`.",
10905
+ login: "Check `gcloud auth list` and that you may manage Secret Manager secrets in the project."
10906
+ };
10907
+ var SECRET_RE = /^[A-Za-z0-9_][A-Za-z0-9_-]{0,254}$/;
10908
+ function target5(project, secret, locations) {
10909
+ return {
10910
+ livesIn: `gcp:${project}/${secret}`,
10911
+ keyName: keyName(`gcp: ${project} / ${secret}`),
10912
+ params: { project, secret, ...locations ? { locations } : {} }
10913
+ };
10914
+ }
10915
+ var gcp = {
10916
+ id: "gcp",
10917
+ label: "Google Cloud Secret Manager",
10918
+ flags: ["project", "secret", "locations"],
10919
+ async resolve(f, io) {
10920
+ let project = f.project;
10921
+ if (!project) {
10922
+ project = (await exec(io, GCLOUD, ["config", "get-value", "project"])).trim();
10923
+ if (!project || project === "(unset)")
10924
+ throw new CliError("bad_argument", "No Google Cloud project is set.", "Pass --project <id>.");
10925
+ }
10926
+ const secret = f.secret ?? "st-api-key";
10927
+ if (!SECRET_RE.test(secret))
10928
+ throw new CliError("bad_argument", "--secret may use letters, digits, _ and - only (Secret Manager ids).");
10929
+ return target5(safeValue("project", project), secret, f.locations ? safeValue("locations", f.locations.replace(/\s/g, "")) : undefined);
10930
+ },
10931
+ parse(rest) {
10932
+ const [project, secret, ...more] = rest.split("/");
10933
+ return isSafeValue(project) && secret && SECRET_RE.test(secret) && !more.length ? target5(project, secret) : null;
10934
+ },
10935
+ async put(t, secret, io) {
10936
+ const { project, secret: name } = t.params;
10937
+ const exists = await probe(io, GCLOUD, ["secrets", "describe", name, "--project", project, "--format=value(name)"]);
10938
+ const args = exists.code === 0 ? ["secrets", "versions", "add", name, "--project", project, "--data-file=-"] : [
10939
+ "secrets",
10940
+ "create",
10941
+ name,
10942
+ "--project",
10943
+ project,
10944
+ "--data-file=-",
10945
+ ...t.params.locations ? ["--replication-policy=user-managed", `--locations=${t.params.locations}`] : ["--replication-policy=automatic"]
10946
+ ];
10947
+ const shown = `gcloud ${args.join(" ")}`;
10948
+ await exec(io, GCLOUD, args, { stdin: secret, shown });
10949
+ return `${shown} (stdin)`;
10950
+ },
10951
+ next: (t) => `Read secret ${t.params.secret}, version latest (anything pinned to a version needs updating).`
10952
+ };
10953
+
10954
+ // src/destinations/github.ts
10955
+ var GH = {
10956
+ cmd: "gh",
10957
+ install: "Install the GitHub CLI and log in: https://cli.github.com, then `gh auth login`.",
10958
+ login: "Check `gh auth status` (log in with `gh auth login`) and that you can manage the repo's secrets."
10959
+ };
10960
+ var APPS = { actions: "Actions", codespaces: "Codespaces", dependabot: "Dependabot" };
10961
+ var REPO_RE = /^[A-Za-z0-9_.][A-Za-z0-9_.-]*\/[A-Za-z0-9_.-]+$/;
10962
+ var isApp = (v) => v !== undefined && Object.hasOwn(APPS, v);
10963
+ function target6(repo, app, env) {
10964
+ return {
10965
+ livesIn: `github:${repo}/${app}${env ? `/${env}` : ""}`,
10966
+ keyName: keyName(`github: ${repo} (${APPS[app]}${env ? `, ${env}` : ""})`),
10967
+ params: { repo, app, ...env ? { env } : {} }
10968
+ };
10969
+ }
10970
+ var github = {
10971
+ id: "github",
10972
+ label: "GitHub",
10973
+ flags: ["repo", "app", "env"],
10974
+ async resolve(f, io) {
10975
+ const app = f.app ?? "actions";
10976
+ if (!isApp(app))
10977
+ throw new CliError("bad_argument", "--app must be actions, codespaces or dependabot.");
10978
+ if (f.env && app !== "actions")
10979
+ throw new CliError("bad_argument", "--env (a deployment environment) works only with --app actions.");
10980
+ const repo = f.repo ?? (await exec(io, GH, ["repo", "view", "--json", "nameWithOwner", "--jq", ".nameWithOwner"])).trim();
10981
+ if (!REPO_RE.test(repo))
10982
+ throw new CliError("bad_argument", "--repo must look like owner/name.", "Pass --repo owner/name.");
10983
+ return target6(repo, app, f.env ? safeValue("env", f.env) : undefined);
10984
+ },
10985
+ parse(rest) {
10986
+ const [owner, name, app, env, ...more] = rest.split("/");
10987
+ if (!owner || !name || !isApp(app) || more.length || !REPO_RE.test(`${owner}/${name}`))
10988
+ return null;
10989
+ if (env && !isSafeValue(env))
10990
+ return null;
10991
+ return target6(`${owner}/${name}`, app, env || undefined);
10992
+ },
10993
+ async put(t, secret, io) {
10994
+ const args = ["secret", "set", "ST_API_KEY", "--repo", t.params.repo];
10995
+ if (t.params.app !== "actions")
10996
+ args.push("--app", t.params.app);
10997
+ if (t.params.env)
10998
+ args.push("--env", t.params.env);
10999
+ const shown = `gh ${args.join(" ")}`;
11000
+ await exec(io, GH, args, { stdin: secret, shown });
11001
+ return `${shown} (stdin)`;
11002
+ },
11003
+ next: () => "Workflows read it as secrets.ST_API_KEY from their next run."
11004
+ };
11005
+
11006
+ // src/destinations/k8s.ts
11007
+ var KUBECTL = {
11008
+ cmd: "kubectl",
11009
+ install: "Install kubectl and point it at your cluster: https://kubernetes.io/docs/tasks/tools/",
11010
+ login: "Check `kubectl config current-context` and that you may create Secrets in the namespace."
11011
+ };
11012
+ var SECRET_RE2 = /^[a-z0-9]([-a-z0-9.]{0,251}[a-z0-9])?$/;
11013
+ function target7(context, namespace, secret) {
11014
+ return {
11015
+ livesIn: `k8s:${context}/${namespace}/${secret}`,
11016
+ keyName: keyName(`k8s: ${namespace}/${secret} (${context})`),
11017
+ params: { context, namespace, secret }
11018
+ };
11019
+ }
11020
+ var k8s = {
11021
+ id: "k8s",
11022
+ label: "Kubernetes",
11023
+ flags: ["context", "namespace", "secret"],
11024
+ async resolve(f, io) {
11025
+ const context = f.context ?? (await exec(io, KUBECTL, ["config", "current-context"])).trim();
11026
+ if (!context)
11027
+ throw new CliError("bad_argument", "No kubectl context is set.", "Pass --context <name>.");
11028
+ let namespace = f.namespace;
11029
+ if (!namespace) {
11030
+ const r = await probe(io, KUBECTL, ["config", "view", "--minify", "-o", "jsonpath={..namespace}"]);
11031
+ namespace = r.code === 0 && r.stdout.trim() ? r.stdout.trim() : "default";
11032
+ }
11033
+ const secret = f.secret ?? "scaledthought";
11034
+ if (!SECRET_RE2.test(secret))
11035
+ throw new CliError("bad_argument", "--secret must be a lowercase DNS name, e.g. scaledthought.");
11036
+ return target7(safeValue("context", context, { slash: true }), safeValue("namespace", namespace), secret);
11037
+ },
11038
+ parse(rest) {
11039
+ const parts = rest.split("/");
11040
+ if (parts.length < 3)
11041
+ return null;
11042
+ const secret = parts.pop();
11043
+ const namespace = parts.pop();
11044
+ const context = parts.join("/");
11045
+ if (!isSafeValue(context, { slash: true }) || !isSafeValue(namespace) || !SECRET_RE2.test(secret))
11046
+ return null;
11047
+ return target7(context, namespace, secret);
11048
+ },
11049
+ async put(t, secret, io) {
11050
+ const where = ["--namespace", t.params.namespace, "--context", t.params.context];
11051
+ const create = ["create", "secret", "generic", t.params.secret, "--from-file=ST_API_KEY=/dev/stdin"];
11052
+ const manifest = await exec(io, KUBECTL, [...create, "--dry-run=client", "-o", "yaml", ...where], {
11053
+ stdin: secret,
11054
+ shown: `kubectl create secret generic ${t.params.secret}`
11055
+ });
11056
+ const apply = ["apply", "--server-side", "--force-conflicts", "--field-manager=scaledthought", "-f", "-", ...where];
11057
+ await exec(io, KUBECTL, apply, {
11058
+ stdin: manifest,
11059
+ secrets: [secret, Buffer.from(secret).toString("base64")],
11060
+ shown: "kubectl apply --server-side -f -"
11061
+ });
11062
+ return `kubectl ${create.join(" ")} --dry-run=client -o yaml | kubectl apply --server-side -f - (stdin)`;
11063
+ },
11064
+ next: (t) => `Pods read Secret ${t.params.secret} when they start: restart the ones that use it (kubectl rollout restart deployment/<name> -n ${t.params.namespace}).`
11065
+ };
11066
+
11067
+ // src/destinations/vercel.ts
11068
+ import { existsSync as existsSync7, readFileSync as readFileSync9 } from "node:fs";
11069
+ import { join as join8 } from "node:path";
11070
+ var VERCEL = {
11071
+ cmd: "vercel",
11072
+ install: "Install the Vercel CLI and log in: npm i -g vercel && vercel login",
11073
+ login: "Check `vercel whoami` (log in with `vercel login`) and that this directory is linked (`vercel link`)."
11074
+ };
11075
+ function target8(project, env) {
11076
+ return {
11077
+ livesIn: `vercel:${project}/${env}`,
11078
+ keyName: keyName(`vercel: ${project} / ${env}`),
11079
+ params: { project, env }
11080
+ };
11081
+ }
11082
+ function linkedProject(cwd) {
11083
+ const f = join8(cwd, ".vercel", "project.json");
11084
+ if (!existsSync7(f))
11085
+ return null;
11086
+ try {
11087
+ const j = JSON.parse(readFileSync9(f, "utf8"));
11088
+ return { name: j.projectName, id: j.projectId };
11089
+ } catch {
11090
+ return null;
11091
+ }
11092
+ }
11093
+ var NOT_LINKED = "Run this in the app's directory after `vercel link`.";
11094
+ var vercel = {
11095
+ id: "vercel",
11096
+ label: "Vercel",
11097
+ flags: ["project", "env"],
11098
+ async resolve(f, io) {
11099
+ const env = safeValue("env", f.env ?? "production");
11100
+ const linked = linkedProject(io.cwd);
11101
+ if (!linked)
11102
+ throw new CliError("not_linked", "This directory isn't linked to a Vercel project.", NOT_LINKED);
11103
+ const project = f.project ?? linked.name ?? linked.id;
11104
+ if (!project)
11105
+ throw new CliError("not_linked", "Can't tell which Vercel project this is.", "Pass --project.");
11106
+ if (f.project && linked.name && f.project !== linked.name)
11107
+ throw new CliError("not_linked", `This directory is linked to Vercel project "${linked.name}", not "${f.project}".`, NOT_LINKED);
11108
+ return target8(safeValue("project", project), env);
11109
+ },
11110
+ parse(rest) {
11111
+ const [project, env, ...more] = rest.split("/");
11112
+ return isSafeValue(project) && isSafeValue(env) && !more.length ? target8(project, env) : null;
11113
+ },
11114
+ async put(t, secret, io, mode) {
11115
+ const linked = linkedProject(io.cwd);
11116
+ if (!linked || linked.name !== t.params.project && linked.id !== t.params.project)
11117
+ throw new CliError("not_linked", `Vercel project "${t.params.project}" isn't the one linked in this directory.`, `Run \`keys rotate <id> --push\` in the directory linked to "${t.params.project}".`);
11118
+ if (mode === "replace")
11119
+ await probe(io, VERCEL, ["env", "rm", "ST_API_KEY", t.params.env, "--yes"]);
11120
+ const args = ["env", "add", "ST_API_KEY", t.params.env];
11121
+ const shown = `vercel ${args.join(" ")}`;
11122
+ await exec(io, VERCEL, args, { stdin: secret, shown });
11123
+ return `${shown} (stdin)`;
11124
+ },
11125
+ next: (t) => `Vercel reads the new value on the next deployment: ${t.params.env === "production" ? "vercel --prod" : "vercel"}`
11126
+ };
11127
+
11128
+ // src/destinations/index.ts
11129
+ var DESTINATIONS = Object.fromEntries([github, vercel, fly, cloudflare, gcp, aws, k8s, doppler].map((d) => [d.id, d]));
11130
+ function destination(id) {
11131
+ const d = Object.hasOwn(DESTINATIONS, id) ? DESTINATIONS[id] : undefined;
11132
+ if (!d)
11133
+ throw new CliError("unknown_destination", `Unknown destination "${id}".`, `Use one of: ${Object.keys(DESTINATIONS).join(", ")}.`);
11134
+ return d;
11135
+ }
11136
+ function fromLivesIn(livesIn) {
11137
+ if (!livesIn)
11138
+ return null;
11139
+ const i = livesIn.indexOf(":");
11140
+ if (i <= 0)
11141
+ return null;
11142
+ const id = livesIn.slice(0, i);
11143
+ const dest = Object.hasOwn(DESTINATIONS, id) ? DESTINATIONS[id] : undefined;
11144
+ const target = dest?.parse(livesIn.slice(i + 1));
11145
+ return dest && target ? { dest, target } : null;
11146
+ }
11147
+
11148
+ // src/everywhere.ts
11149
+ import { chmodSync as chmodSync4, existsSync as existsSync8, mkdirSync as mkdirSync3, readFileSync as readFileSync10, writeFileSync as writeFileSync4 } from "node:fs";
11150
+ import { homedir, hostname as hostname2 } from "node:os";
11151
+ import { dirname as dirname2, join as join9 } from "node:path";
11152
+ var io = (ctx) => ({ run: ctx.runner ?? spawnRunner, cwd: ctx.cwd, env: ctx.env });
11153
+ async function mintChild(ctx, o) {
11154
+ const k = await api(ctx, "POST", "/v1/keys", {
11155
+ body: {
11156
+ name: o.name,
11157
+ child: true,
11158
+ lives_in: o.livesIn,
11159
+ daily_budget_usd: o.budgetUsd,
11160
+ scopes: o.scopes,
11161
+ expires_in: o.expiresIn
11162
+ }
11163
+ });
11164
+ if (!k.api_key || !KEY_RE.test(k.api_key))
11165
+ throw new CliError("bad_response", "The server didn't return the new key.", "Retry; if it persists, report it.");
11166
+ return k;
11167
+ }
11168
+ async function revokeMinted(ctx, id) {
11169
+ return api(ctx, "DELETE", `/v1/keys/${encodeURIComponent(id)}`).then(() => true, () => false);
11170
+ }
11171
+ async function failAfterMint(ctx, keyId, e) {
11172
+ const revoked = await revokeMinted(ctx, keyId);
11173
+ const err = e instanceof CliError ? e : new CliError("destination_failed", "Storing the key failed.", "Retry; if it persists, report it.");
11174
+ throw new CliError(err.code, `${err.message} ${revoked ? "The new key was revoked; nothing else changed." : `Revoking the new key ${keyId} failed: run \`keys revoke ${keyId}\`.`}`, err.hint, { ...err.extra, key_id: keyId, key_revoked: revoked });
11175
+ }
11176
+ function checkFlags(dest, flags) {
11177
+ const extra = Object.keys(flags).filter((f) => flags[f] !== undefined && !dest.flags.includes(f));
11178
+ if (extra.length)
11179
+ throw new CliError("usage_error", `keys put ${dest.id} doesn't take --${extra.join(", --")}.`, `It takes: ${dest.flags.map((f) => `--${f}`).join(", ") || "no destination flags"}.`);
11180
+ }
11181
+ async function keysPut(ctx, destId, o) {
11182
+ const dest = destination(destId);
11183
+ checkFlags(dest, o.flags);
11184
+ const { region } = resolveKey(ctx);
11185
+ const target = await dest.resolve(o.flags, io(ctx));
11186
+ const k = await mintChild(ctx, {
11187
+ name: o.name ?? target.keyName,
11188
+ livesIn: target.livesIn,
11189
+ budgetUsd: o.budgetUsd,
11190
+ scopes: o.scopes,
11191
+ expiresIn: o.expiresIn
11192
+ });
11193
+ let storedWith;
11194
+ try {
11195
+ storedWith = await dest.put(target, k.api_key, io(ctx), "new");
11196
+ } catch (e) {
11197
+ return failAfterMint(ctx, k.id, e);
11198
+ }
11199
+ return {
11200
+ key_name: k.name,
11201
+ key_id: k.id,
11202
+ key_prefix: k.prefix,
11203
+ lives_in: target.livesIn,
11204
+ stored_with: storedWith,
11205
+ daily_budget_usd: k.daily_budget_usd,
11206
+ base_url: inferenceUrl(region, ctx.env),
11207
+ next: `${dest.next?.(target) ?? ""} The app reads ST_API_KEY; its base URL is ${inferenceUrl(region, ctx.env)} (not a secret: set ST_BASE_URL as a plain variable if your code uses it).`.trim()
11208
+ };
11209
+ }
11210
+ async function keysRotatePush(ctx, o) {
11211
+ const grace = o.grace ?? "24h";
11212
+ const { data } = await api(ctx, "GET", "/v1/keys");
11213
+ let keys;
11214
+ if (o.all)
11215
+ keys = data.filter((k) => k.status === "active");
11216
+ else {
11217
+ const k = data.find((x) => x.id === o.id);
11218
+ if (!k)
11219
+ throw new CliError("key_not_found", `No key ${o.id} on this account.`, "See `keys list`.");
11220
+ keys = [k];
11221
+ }
11222
+ const rotated = [];
11223
+ const skipped = [];
11224
+ const failed = [];
11225
+ const next = new Set;
11226
+ for (const k of keys) {
11227
+ const found = fromLivesIn(k.lives_in);
11228
+ if (!found) {
11229
+ const tool = /^tool:([a-z0-9-]+):/.exec(k.lives_in ?? "")?.[1];
11230
+ skipped.push({
11231
+ name: k.name,
11232
+ key_id: k.id,
11233
+ lives_in: k.lives_in ?? null,
11234
+ reason: !k.lives_in ? "no lives_in (not put anywhere by keys put)" : tool ? `a tool's config: run \`connect ${tool}\` again on that machine, then revoke this key` : k.lives_in.startsWith("env:") ? "a folder's ./.env (a project key from init, login or use): rotate it from that folder with `keys rotate`" : "lives_in isn't a destination keys put knows"
11235
+ });
11236
+ continue;
11237
+ }
11238
+ if (k.status !== "active") {
11239
+ skipped.push({ name: k.name, key_id: k.id, lives_in: k.lives_in ?? null, reason: `key is ${k.status}` });
11240
+ continue;
11241
+ }
11242
+ let r;
11243
+ try {
11244
+ r = await api(ctx, "POST", `/v1/keys/${encodeURIComponent(k.id)}/rotate`, { body: { grace } });
11245
+ } catch (e) {
11246
+ failed.push({ name: k.name, key_id: k.id, error: errorOf(e) });
11247
+ continue;
11248
+ }
11249
+ if (!r.api_key) {
11250
+ failed.push({ name: k.name, key_id: r.id, error: errorOf(null) });
11251
+ continue;
11252
+ }
11253
+ const stops = { old_key_stops: `in ${grace}`, old_key_expires_at: r.rotated_from?.expires_at ?? "" };
11254
+ try {
11255
+ const pushed = await found.dest.put(found.target, r.api_key, io(ctx), "replace");
11256
+ rotated.push({ name: r.name, key_id: r.id, pushed, ...stops });
11257
+ const n = found.dest.next?.(found.target);
11258
+ if (n)
11259
+ next.add(n);
11260
+ } catch (e) {
11261
+ const err = errorOf(e);
11262
+ failed.push({
11263
+ name: r.name,
11264
+ key_id: r.id,
11265
+ ...stops,
11266
+ error: {
11267
+ ...err,
11268
+ hint: `${err.hint ?? ""} The old key keeps working ${stops.old_key_stops}. Fix that, then run \`keys rotate ${r.id} --push --grace 0\`.`.trim()
11269
+ }
11270
+ });
11271
+ }
11272
+ }
11273
+ return {
11274
+ rotated,
11275
+ skipped,
11276
+ ...failed.length ? { failed } : {},
11277
+ ...next.size ? { next: [...next] } : {}
11278
+ };
11279
+ }
11280
+ function errorOf(e) {
11281
+ if (e instanceof CliError)
11282
+ return { code: e.code, message: e.message, hint: e.hint ?? null };
11283
+ return { code: "internal_error", message: "Unexpected error.", hint: "Retry; if it persists, report it." };
11284
+ }
11285
+ var CONNECT_TOOLS = ["opencode", "aider", "continue", "cursor"];
11286
+ function machineName(raw = hostname2()) {
11287
+ const n = raw.replace(/\.(local|lan|home)$/i, "").replace(/[^A-Za-z0-9.-]/g, "-").slice(0, 40);
11288
+ return n || "this-machine";
11289
+ }
11290
+ async function liveChatModels(ctx) {
11291
+ const { region } = resolveKey(ctx);
11292
+ const res = await api(ctx, "GET", "/v1/models?modality=chat", {
11293
+ auth: false,
11294
+ region
11295
+ }).catch(() => ({ data: [] }));
11296
+ return (res.data ?? []).filter((m) => typeof m.id === "string" && m.live_in_region !== false && (m.modality ?? "chat") === "chat").map((m) => ({ id: m.id, context: typeof m.context === "number" ? m.context : null }));
11297
+ }
11298
+ function writePrivate2(path, text) {
11299
+ mkdirSync3(dirname2(path), { recursive: true, mode: 448 });
11300
+ writeFileSync4(path, text, { mode: 384 });
11301
+ chmodSync4(path, 384);
11302
+ }
11303
+ function readJsonObject(path, what) {
11304
+ if (!existsSync8(path))
11305
+ return {};
11306
+ try {
11307
+ const v = JSON.parse(readFileSync10(path, "utf8"));
11308
+ if (v && typeof v === "object" && !Array.isArray(v))
11309
+ return v;
11310
+ } catch {}
11311
+ throw new CliError("config_unreadable", `${what} isn't plain JSON (comments or a syntax error). Nothing was changed.`, `Fix or move ${path}, then run connect again.`);
11312
+ }
11313
+ var PROVIDER_ID = "scaledthought";
11314
+ async function connect(ctx, tool, o = {}) {
11315
+ if (!CONNECT_TOOLS.includes(tool))
11316
+ throw new CliError("unknown_tool", `Unknown tool "${tool}".`, `Use one of: ${CONNECT_TOOLS.join(", ")}.`);
11317
+ const { region } = resolveKey(ctx);
11318
+ const baseUrl = inferenceUrl(region, ctx.env);
11319
+ const models = await liveChatModels(ctx);
11320
+ const model = o.model ?? models[0]?.id ?? "auto";
11321
+ if (!/^[A-Za-z0-9][A-Za-z0-9._:/-]{0,127}$/.test(model))
11322
+ throw new CliError("bad_argument", "--model isn't a model id.", "Pick one from `models --live`.");
11323
+ const host = machineName();
11324
+ const keyName = `${tool}: ${host}`;
11325
+ const livesIn = `tool:${tool}:${host}`;
11326
+ const t = tool;
11327
+ if (t === "cursor" || t === "continue")
11328
+ return instructions(t, baseUrl, model, models, keyName);
11329
+ if (t === "aider") {
11330
+ const existing = readDotEnv(ctx.cwd);
11331
+ if (existing.OPENAI_API_KEY && !KEY_RE.test(existing.OPENAI_API_KEY))
11332
+ throw new CliError("env_conflict", "./.env already has an OPENAI_API_KEY that isn't a ScaledThought key. Nothing was changed.", "Aider reads OPENAI_API_KEY from .env, so this would replace it. Run connect aider in another directory, or remove that line first.");
11333
+ const k = await mintChild(ctx, { name: keyName, livesIn, budgetUsd: o.budgetUsd });
11334
+ try {
11335
+ writeEnv(ctx.cwd, { OPENAI_API_BASE: baseUrl, OPENAI_API_KEY: k.api_key, AIDER_MODEL: `openai/${model}` });
11336
+ ensureGitignored(ctx.cwd);
11337
+ } catch (e) {
11338
+ return failAfterMint(ctx, k.id, e);
11339
+ }
11340
+ return {
11341
+ tool,
11342
+ key_name: k.name,
11343
+ key_prefix: k.prefix,
11344
+ lives_in: livesIn,
11345
+ daily_budget_usd: k.daily_budget_usd,
11346
+ configured: ".env (OPENAI_API_BASE, OPENAI_API_KEY, AIDER_MODEL), mode 0600, git-ignored",
11347
+ model: `openai/${model}`,
11348
+ models: ["auto", ...models.map((m) => m.id)],
11349
+ next: "Run `aider` in this directory. Aider may warn that it doesn't know the model's context window; that's harmless."
11350
+ };
11351
+ }
11352
+ const dataHome = ctx.env.XDG_DATA_HOME || join9(ctx.env.HOME || homedir(), ".local", "share");
11353
+ const authPath = join9(dataHome, "opencode", "auth.json");
11354
+ const configPath = join9(ctx.cwd, "opencode.json");
11355
+ const config = readJsonObject(configPath, "opencode.json");
11356
+ const auth = readJsonObject(authPath, authPath);
11357
+ const providers = config.provider && typeof config.provider === "object" ? config.provider : {};
11358
+ const modelEntries = { auto: { name: "auto (ScaledThought picks per request)" } };
11359
+ for (const m of models)
11360
+ modelEntries[m.id] = {
11361
+ name: m.id,
11362
+ ...m.context ? { limit: { context: m.context, output: Math.min(32768, Math.floor(m.context / 2)) } } : {}
11363
+ };
11364
+ if (!modelEntries[model])
11365
+ modelEntries[model] = { name: model };
11366
+ const k = await mintChild(ctx, { name: keyName, livesIn, budgetUsd: o.budgetUsd });
11367
+ try {
11368
+ const next = {
11369
+ ...existsSync8(configPath) ? {} : { $schema: "https://opencode.ai/config.json" },
11370
+ ...config,
11371
+ provider: {
11372
+ ...providers,
11373
+ [PROVIDER_ID]: {
11374
+ npm: "@ai-sdk/openai-compatible",
11375
+ name: "ScaledThought",
11376
+ options: { baseURL: baseUrl },
11377
+ models: modelEntries
11378
+ }
11379
+ },
11380
+ ...config.model ? {} : { model: `${PROVIDER_ID}/${model}` }
11381
+ };
11382
+ writePrivate2(configPath, `${JSON.stringify(next, null, 2)}
11383
+ `);
11384
+ writePrivate2(authPath, `${JSON.stringify({ ...auth, [PROVIDER_ID]: { type: "api", key: k.api_key } }, null, 2)}
11385
+ `);
11386
+ } catch (e) {
11387
+ return failAfterMint(ctx, k.id, e);
11388
+ }
11389
+ return {
11390
+ tool,
11391
+ key_name: k.name,
11392
+ key_prefix: k.prefix,
11393
+ lives_in: livesIn,
11394
+ daily_budget_usd: k.daily_budget_usd,
11395
+ configured: `opencode.json (provider ${PROVIDER_ID}, base URL ${baseUrl}) + ${authPath} (key, mode 0600)`,
11396
+ model: `${PROVIDER_ID}/${model}`,
11397
+ models: Object.keys(modelEntries),
11398
+ restart_needed: true,
11399
+ next: `Restart OpenCode in this directory and pick a ${PROVIDER_ID}/… model (or ${PROVIDER_ID}/auto).`
11400
+ };
11401
+ }
11402
+ function instructions(tool, baseUrl, model, models, name) {
11403
+ const ids = ["auto", ...models.map((m) => m.id)];
11404
+ if (tool === "cursor")
11405
+ return {
11406
+ tool,
11407
+ configured: false,
11408
+ key_minted: false,
11409
+ why: "Cursor keeps its OpenAI key in its own settings store, which other programs can't write safely. A human sets it once.",
11410
+ steps_for_human: [
11411
+ `Cursor Settings → Models → API Keys: turn on "Override OpenAI Base URL" and enter ${baseUrl}`,
11412
+ `In your own terminal (not through the agent) run: ${NPX} keys create --child --name "${name}" and paste the key it prints into "OpenAI API Key", then Verify.`,
11413
+ `Add model names under Models: ${ids.join(", ")}`
11414
+ ],
11415
+ base_url: baseUrl,
11416
+ models: ids,
11417
+ restart_needed: false
11418
+ };
11419
+ const block = [
11420
+ "models:",
11421
+ ` - name: ScaledThought ${model}`,
11422
+ " provider: openai",
11423
+ ` model: ${model}`,
11424
+ ` apiBase: ${baseUrl}`,
11425
+ ` apiKey: \${{ secrets.ST_API_KEY }}`,
11426
+ " defaultCompletionOptions:",
11427
+ " maxTokens: 32768",
11428
+ " roles: [chat, edit, apply]"
11429
+ ].join(`
11430
+ `);
11431
+ return {
11432
+ tool,
11433
+ configured: false,
11434
+ key_minted: false,
11435
+ why: "Continue's config.yaml is hand-edited YAML; this CLI won't rewrite it. The block below holds no secret: Continue reads ST_API_KEY from this workspace's .env.",
11436
+ steps_for_human: [
11437
+ "Open ~/.continue/config.yaml (Continue: Open configuration) and add this entry under models:",
11438
+ "Reload Continue and pick the ScaledThought model."
11439
+ ],
11440
+ config_yaml: block,
11441
+ base_url: baseUrl,
11442
+ models: ids,
11443
+ restart_needed: false
11444
+ };
11445
+ }
11446
+ function putFlagsFrom(args) {
11447
+ const out = {};
11448
+ for (const f of PUT_FLAGS)
11449
+ if (typeof args[f] === "string")
11450
+ out[f] = args[f];
11451
+ return out;
11452
+ }
11453
+
10584
11454
  // src/realtime.ts
10585
- import { readFileSync as readFileSync7, writeFileSync as writeFileSync4 } from "node:fs";
11455
+ import { readFileSync as readFileSync11, writeFileSync as writeFileSync5 } from "node:fs";
10586
11456
  import { resolve as resolve4 } from "node:path";
10587
11457
  var SAMPLE_RATE = 24000;
10588
11458
  var MAX_INPUT_SECONDS = 300;
@@ -10647,7 +11517,7 @@ async function realtime(ctx, o) {
10647
11517
  throw new CliError("unsupported_runtime", "This command needs a WebSocket client (Node.js 22 or newer).", "Upgrade Node.js to 22+.");
10648
11518
  let pcm;
10649
11519
  try {
10650
- pcm = readWav(readFileSync7(resolve4(ctx.cwd, o.input)));
11520
+ pcm = readWav(readFileSync11(resolve4(ctx.cwd, o.input)));
10651
11521
  } catch (e) {
10652
11522
  if (e instanceof CliError)
10653
11523
  throw e;
@@ -10739,7 +11609,7 @@ async function realtime(ctx, o) {
10739
11609
  });
10740
11610
  const audio = Buffer.concat(out);
10741
11611
  const path = resolve4(ctx.cwd, o.output);
10742
- writeFileSync4(path, wavOf(audio));
11612
+ writeFileSync5(path, wavOf(audio));
10743
11613
  return {
10744
11614
  model: o.model,
10745
11615
  region,
@@ -10770,7 +11640,7 @@ function out(data, args) {
10770
11640
  process.stdout.write(`${JSON.stringify(data, null, wantsJson(args) ? 0 : 2)}
10771
11641
  `);
10772
11642
  }
10773
- var run = async (fn, args) => out(await fn(), args);
11643
+ var run2 = async (fn, args) => out(await fn(), args);
10774
11644
  function region(v) {
10775
11645
  if (v === undefined)
10776
11646
  return;
@@ -10818,7 +11688,7 @@ var init2 = defineCommand({
10818
11688
  description: "Save the account's key in this machine's credential store so other folders reuse it (--no-save to opt out)"
10819
11689
  }
10820
11690
  },
10821
- run: ({ args }) => run(() => init(makeCtx(), {
11691
+ run: ({ args }) => run2(() => init(makeCtx(), {
10822
11692
  region: region(args.region),
10823
11693
  name: args.name,
10824
11694
  email: args.email,
@@ -10861,7 +11731,7 @@ var login2 = defineCommand({
10861
11731
  const t = args["timeout-s"] === undefined ? undefined : num("timeout-s", args["timeout-s"]);
10862
11732
  if (t !== undefined && t > 600)
10863
11733
  throw new CliError("bad_argument", `--timeout-s must be at most 600, got ${t}.`, "Run login --wait again.");
10864
- await run(async () => args.code ? loginWithCode(ctx, {
11734
+ await run2(async () => args.code ? loginWithCode(ctx, {
10865
11735
  code: args.code === "-" ? await readCodeFrom(process.stdin) : args.code,
10866
11736
  region: region(args.region),
10867
11737
  label: args.label,
@@ -10885,7 +11755,7 @@ var use = defineCommand({
10885
11755
  ...jsonFlag,
10886
11756
  account: { type: "positional", required: true, description: "The account's name or id" }
10887
11757
  },
10888
- run: ({ args }) => run(() => useAccount(makeCtx(), { target: args.account }), args)
11758
+ run: ({ args }) => run2(() => useAccount(makeCtx(), { target: args.account }), args)
10889
11759
  });
10890
11760
  var models = defineCommand({
10891
11761
  meta: { name: "models", description: "List models with prices and benchmarks, newest first; or show one" },
@@ -10905,7 +11775,7 @@ var models = defineCommand({
10905
11775
  },
10906
11776
  search: { type: "string", description: "Match id, name or lab" }
10907
11777
  },
10908
- run: ({ args }) => run(() => {
11778
+ run: ({ args }) => run2(() => {
10909
11779
  const r = region(args.region);
10910
11780
  return args.id ? showModel(makeCtx(), args.id, r) : listModels(makeCtx(), {
10911
11781
  live: args.live,
@@ -10923,7 +11793,7 @@ var account2 = defineCommand({
10923
11793
  run: ({ args, rawArgs }) => {
10924
11794
  if (rawArgs.some((a) => ACCOUNT_SUBCOMMANDS.has(a)))
10925
11795
  return;
10926
- return run(() => account(makeCtx()), args);
11796
+ return run2(() => account(makeCtx()), args);
10927
11797
  },
10928
11798
  subCommands: {
10929
11799
  delete: defineCommand({
@@ -10935,7 +11805,7 @@ var account2 = defineCommand({
10935
11805
  ...jsonFlag,
10936
11806
  confirm: { type: "string", required: true, description: "The account id (acct_...), to confirm" }
10937
11807
  },
10938
- run: ({ args }) => run(() => accountDelete(makeCtx(), { confirm: args.confirm }), args)
11808
+ run: ({ args }) => run2(() => accountDelete(makeCtx(), { confirm: args.confirm }), args)
10939
11809
  }),
10940
11810
  "ad-measurement": defineCommand({
10941
11811
  meta: {
@@ -10946,7 +11816,7 @@ var account2 = defineCommand({
10946
11816
  ...jsonFlag,
10947
11817
  state: { type: "positional", required: true, description: "off or on" }
10948
11818
  },
10949
- run: ({ args }) => run(() => accountAdMeasurement(makeCtx(), args.state), args)
11819
+ run: ({ args }) => run2(() => accountAdMeasurement(makeCtx(), args.state), args)
10950
11820
  })
10951
11821
  }
10952
11822
  });
@@ -10956,7 +11826,7 @@ var keys = defineCommand({
10956
11826
  list: defineCommand({
10957
11827
  meta: { name: "list", description: "Keys on this account (prefixes only)" },
10958
11828
  args: jsonFlag,
10959
- run: ({ args }) => run(() => keysList(makeCtx()), args)
11829
+ run: ({ args }) => run2(() => keysList(makeCtx()), args)
10960
11830
  }),
10961
11831
  create: defineCommand({
10962
11832
  meta: { name: "create", description: "Create a key; the full key is printed once" },
@@ -10974,7 +11844,7 @@ var keys = defineCommand({
10974
11844
  description: "Sub-agent key: budget, scopes and expiry within your key's; revoked when your key is"
10975
11845
  }
10976
11846
  },
10977
- run: ({ args }) => run(() => keysCreate(makeCtx(), {
11847
+ run: ({ args }) => run2(() => keysCreate(makeCtx(), {
10978
11848
  name: args.name,
10979
11849
  budgetUsd: num("budget-usd", args["budget-usd"]),
10980
11850
  expiresIn: args["expires-in"],
@@ -10982,23 +11852,89 @@ var keys = defineCommand({
10982
11852
  child: args.child
10983
11853
  }), args)
10984
11854
  }),
11855
+ put: defineCommand({
11856
+ meta: {
11857
+ name: "put",
11858
+ description: "Put a new child key straight into a platform's secret store as ST_API_KEY, through its own CLI on stdin (never printed). Records where it lives"
11859
+ },
11860
+ args: {
11861
+ ...jsonFlag,
11862
+ destination: {
11863
+ type: "positional",
11864
+ required: true,
11865
+ description: `Where: ${Object.keys(DESTINATIONS).join(", ")}`
11866
+ },
11867
+ name: { type: "string", description: "Key name (default: named after the destination)" },
11868
+ "budget-usd": { type: "string", description: "Hard daily budget in USD (default: none beyond your key's)" },
11869
+ "expires-in": { type: "string", description: "Key lifetime, e.g. 30d (max 365d)" },
11870
+ scopes: {
11871
+ type: "string",
11872
+ description: "Comma-separated scopes, a subset of your key's. Default inference,read"
11873
+ },
11874
+ repo: { type: "string", description: "github: owner/name (default: this directory's repo)" },
11875
+ app: { type: "string", description: "github: actions|codespaces|dependabot (default actions); fly: app name" },
11876
+ env: {
11877
+ type: "string",
11878
+ description: "github: deployment environment; vercel: production|preview|development (default production); cloudflare: Wrangler env"
11879
+ },
11880
+ project: { type: "string", description: "vercel (must match the linked project), gcp, doppler: project" },
11881
+ worker: { type: "string", description: "cloudflare: Worker name (default: wrangler.toml's name)" },
11882
+ secret: {
11883
+ type: "string",
11884
+ description: "gcp (default st-api-key), aws (default scaledthought/api-key), k8s (default scaledthought): secret name"
11885
+ },
11886
+ "aws-region": { type: "string", description: "aws: region (default: AWS_REGION or the CLI's)" },
11887
+ locations: {
11888
+ type: "string",
11889
+ description: "gcp: user-managed replication locations, e.g. northamerica-northeast1"
11890
+ },
11891
+ namespace: { type: "string", description: "k8s: namespace (default: the context's)" },
11892
+ context: { type: "string", description: "k8s: kubectl context (default: current)" },
11893
+ config: { type: "string", description: "doppler: config, e.g. prd (default: this directory's)" }
11894
+ },
11895
+ run: ({ args }) => run2(() => keysPut(makeCtx(), args.destination, {
11896
+ name: args.name,
11897
+ budgetUsd: num("budget-usd", args["budget-usd"]),
11898
+ expiresIn: args["expires-in"],
11899
+ scopes: args.scopes?.split(",").map((x) => x.trim()).filter(Boolean),
11900
+ flags: putFlagsFrom(args)
11901
+ }), args)
11902
+ }),
10985
11903
  rotate: defineCommand({
10986
11904
  meta: {
10987
11905
  name: "rotate",
10988
- description: "Replace a key: prints the new key once; the old key keeps working for --grace (default 24h, 0 to 7d)"
11906
+ description: "Replace a key: prints the new key once; the old key keeps working for --grace (default 24h, 0 to 7d). With --push, puts the new key where the old one lives instead of printing it"
10989
11907
  },
10990
11908
  args: {
10991
11909
  ...jsonFlag,
10992
- id: { type: "positional", required: true, description: "Key id (key_…)" },
11910
+ id: { type: "positional", required: false, description: "Key id (key_…); or --all with --push" },
10993
11911
  grace: { type: "string", description: "How long the old key keeps working: 0 to 7d (default 24h)" },
10994
- "expires-in": { type: "string", description: "New key's lifetime (default: the old key's)" }
11912
+ "expires-in": { type: "string", description: "New key's lifetime (default: the old key's)" },
11913
+ push: {
11914
+ type: "boolean",
11915
+ description: "Put each new key where the old one lives (its lives_in, from keys put); prints no keys"
11916
+ },
11917
+ all: { type: "boolean", description: "With --push: every active key that has a lives_in keys put can reach" }
10995
11918
  },
10996
- run: ({ args }) => run(() => keysRotate(makeCtx(), args.id, { grace: args.grace, expiresIn: args["expires-in"] }), args)
11919
+ run: ({ args }) => run2(() => {
11920
+ if (args.all && !args.push)
11921
+ throw new CliError("usage_error", "--all needs --push (rotating every key never prints them).");
11922
+ if (args.all && args.id)
11923
+ throw new CliError("usage_error", "Pass a key id or --all, not both.");
11924
+ if (!args.all && !args.id)
11925
+ throw new CliError("usage_error", "Pass a key id (or --all --push).");
11926
+ if (args.push) {
11927
+ if (args["expires-in"])
11928
+ throw new CliError("usage_error", "--expires-in can't be combined with --push.");
11929
+ return keysRotatePush(makeCtx(), { id: args.id, all: args.all, grace: args.grace });
11930
+ }
11931
+ return keysRotate(makeCtx(), args.id, { grace: args.grace, expiresIn: args["expires-in"] });
11932
+ }, args)
10997
11933
  }),
10998
11934
  revoke: defineCommand({
10999
11935
  meta: { name: "revoke", description: "Revoke a key by id (and its sub-agent keys)" },
11000
11936
  args: { ...jsonFlag, id: { type: "positional", required: true, description: "Key id (key_…)" } },
11001
- run: ({ args }) => run(() => keysRevoke(makeCtx(), args.id), args)
11937
+ run: ({ args }) => run2(() => keysRevoke(makeCtx(), args.id), args)
11002
11938
  }),
11003
11939
  "revoke-self": defineCommand({
11004
11940
  meta: {
@@ -11006,7 +11942,7 @@ var keys = defineCommand({
11006
11942
  description: "Revoke the key you are using now (e.g. if it may have leaked). Irreversible"
11007
11943
  },
11008
11944
  args: jsonFlag,
11009
- run: ({ args }) => run(() => keysRevokeSelf(makeCtx()), args)
11945
+ run: ({ args }) => run2(() => keysRevokeSelf(makeCtx()), args)
11010
11946
  })
11011
11947
  }
11012
11948
  });
@@ -11017,7 +11953,7 @@ var usage3 = defineCommand({
11017
11953
  days: { type: "string", default: "7", description: "Look-back window, 1-90" },
11018
11954
  by: { type: "string", default: "model", description: "model|day|key|modality" }
11019
11955
  },
11020
- run: ({ args }) => run(() => usage(makeCtx(), { days: num("days", args.days) ?? 7, by: args.by }), args)
11956
+ run: ({ args }) => run2(() => usage(makeCtx(), { days: num("days", args.days) ?? 7, by: args.by }), args)
11021
11957
  });
11022
11958
  var chat2 = defineCommand({
11023
11959
  meta: { name: "chat", description: "Send one message. Use -m auto to let the router pick" },
@@ -11028,7 +11964,7 @@ var chat2 = defineCommand({
11028
11964
  },
11029
11965
  run: async ({ args }) => {
11030
11966
  const human = !wantsJson(args);
11031
- await run(async () => {
11967
+ await run2(async () => {
11032
11968
  const r = await chat(makeCtx(), {
11033
11969
  model: args.model,
11034
11970
  prompt: args.prompt,
@@ -11091,7 +12027,7 @@ var speak2 = defineCommand({
11091
12027
  speed: { type: "string", description: "0.25 to 4 (default 1)" },
11092
12028
  instructions: { type: "string", description: "Delivery instructions for models that take them, optional" }
11093
12029
  },
11094
- run: ({ args }) => run(() => speak(makeCtx(), {
12030
+ run: ({ args }) => run2(() => speak(makeCtx(), {
11095
12031
  text: args.text,
11096
12032
  output: args.output,
11097
12033
  model: args.model,
@@ -11114,7 +12050,7 @@ var decideCmd = defineCommand({
11114
12050
  question: { type: "string", alias: "q", description: "id:type:instructions[:criteria], repeatable" },
11115
12051
  file: { type: "string", description: "A JSON request: {state, questions, model?}" }
11116
12052
  },
11117
- run: ({ args }) => run(() => {
12053
+ run: ({ args }) => run2(() => {
11118
12054
  const ctx = makeCtx();
11119
12055
  const raw = currentArgv;
11120
12056
  const questions = [];
@@ -11147,7 +12083,7 @@ var realtime2 = defineCommand({
11147
12083
  instructions: { type: "string", description: "System instructions for the session (optional)" },
11148
12084
  timeout: { type: "string", description: "Seconds to wait for the reply (default 120)" }
11149
12085
  },
11150
- run: ({ args }) => run(async () => {
12086
+ run: ({ args }) => run2(async () => {
11151
12087
  const t = num("timeout", args.timeout);
11152
12088
  return realtime(makeCtx(), {
11153
12089
  model: args.model,
@@ -11165,7 +12101,7 @@ function autoReloadArgs(args) {
11165
12101
  if (below === undefined && amount === undefined && max === undefined)
11166
12102
  return;
11167
12103
  if (below === undefined || amount === undefined)
11168
- throw new CliError("bad_argument", "Auto-reload needs both --auto-reload-below and --auto-reload-amount.", "e.g. --auto-reload-below 5 --auto-reload-amount 10");
12104
+ throw new CliError("bad_argument", "Auto-reload needs both --auto-reload-below and --auto-reload-amount.", "e.g. --auto-reload-below 5 --auto-reload-amount 20");
11169
12105
  return { threshold_usd: below, amount_usd: amount, ...max !== undefined ? { monthly_limit_usd: max } : {} };
11170
12106
  }
11171
12107
  var billing = defineCommand({
@@ -11177,7 +12113,7 @@ var billing = defineCommand({
11177
12113
  description: "Credit balance, auto-reload, pending top-ups (with their approval links), recent transactions"
11178
12114
  },
11179
12115
  args: jsonFlag,
11180
- run: ({ args }) => run(() => billingStatus(makeCtx()), args)
12116
+ run: ({ args }) => run2(() => billingStatus(makeCtx()), args)
11181
12117
  }),
11182
12118
  topup: defineCommand({
11183
12119
  meta: {
@@ -11214,7 +12150,7 @@ var billing = defineCommand({
11214
12150
  const autoReload = autoReloadArgs(args);
11215
12151
  checkTopupLimits(amountUsd, autoReload);
11216
12152
  const noOpen = args.open === false;
11217
- await run(() => args.wait ? billingTopupAndWait(makeCtx(), { amountUsd, autoReload, noOpen, onPending: (t) => out(t, args) }) : billingTopup(makeCtx(), { amountUsd, autoReload, noOpen }), args);
12153
+ await run2(() => args.wait ? billingTopupAndWait(makeCtx(), { amountUsd, autoReload, noOpen, onPending: (t) => out(t, args) }) : billingTopup(makeCtx(), { amountUsd, autoReload, noOpen }), args);
11218
12154
  }
11219
12155
  }),
11220
12156
  wait: defineCommand({
@@ -11234,7 +12170,7 @@ var billing = defineCommand({
11234
12170
  const t = args["timeout-s"] === undefined ? undefined : num("timeout-s", args["timeout-s"]);
11235
12171
  if (t !== undefined && t > 600)
11236
12172
  throw new CliError("bad_argument", `--timeout-s must be at most 600, got ${t}.`, "Run wait again instead.");
11237
- await run(() => billingWait(makeCtx(), { topupId: args.topup_id || undefined, timeoutS: t }), args);
12173
+ await run2(() => billingWait(makeCtx(), { topupId: args.topup_id || undefined, timeoutS: t }), args);
11238
12174
  }
11239
12175
  }),
11240
12176
  "auto-reload": defineCommand({
@@ -11261,7 +12197,7 @@ var billing = defineCommand({
11261
12197
  description: "Open the page in the browser (--no-open only prints approval_url)"
11262
12198
  }
11263
12199
  },
11264
- run: ({ args }) => run(() => billingAutoReloadSetup(makeCtx(), {
12200
+ run: ({ args }) => run2(() => billingAutoReloadSetup(makeCtx(), {
11265
12201
  thresholdUsd: num("below", args.below),
11266
12202
  amountUsd: num("amount", args.amount),
11267
12203
  noOpen: args.open === false
@@ -11270,14 +12206,14 @@ var billing = defineCommand({
11270
12206
  off: defineCommand({
11271
12207
  meta: { name: "off", description: "Disable auto-reload. No approval needed" },
11272
12208
  args: jsonFlag,
11273
- run: ({ args }) => run(() => billingAutoReloadOff(makeCtx()), args)
12209
+ run: ({ args }) => run2(() => billingAutoReloadOff(makeCtx()), args)
11274
12210
  })
11275
12211
  }
11276
12212
  }),
11277
12213
  transactions: defineCommand({
11278
12214
  meta: { name: "transactions", description: "Credit ledger: purchases, auto-reloads, usage, batches, refunds" },
11279
12215
  args: { ...jsonFlag, cursor: { type: "string", description: "next_cursor from the previous page" } },
11280
- run: ({ args }) => run(() => billingTransactions(makeCtx(), { cursor: args.cursor }), args)
12216
+ run: ({ args }) => run2(() => billingTransactions(makeCtx(), { cursor: args.cursor }), args)
11281
12217
  }),
11282
12218
  upgrade: defineCommand({
11283
12219
  meta: { name: "upgrade", description: "Removed: monthly caps became prepaid credits. Use billing topup" },
@@ -11296,34 +12232,34 @@ var batches = defineCommand({
11296
12232
  file: { type: "positional", required: true, description: "Path to requests.jsonl" },
11297
12233
  endpoint: { type: "string", default: "/v1/chat/completions", description: "Endpoint every line calls" }
11298
12234
  },
11299
- run: ({ args }) => run(() => batchCreate(makeCtx(), { path: args.file, endpoint: args.endpoint }), args)
12235
+ run: ({ args }) => run2(() => batchCreate(makeCtx(), { path: args.file, endpoint: args.endpoint }), args)
11300
12236
  }),
11301
12237
  list: defineCommand({
11302
12238
  meta: { name: "list", description: "Your batches" },
11303
12239
  args: jsonFlag,
11304
- run: ({ args }) => run(() => batchList(makeCtx()), args)
12240
+ run: ({ args }) => run2(() => batchList(makeCtx()), args)
11305
12241
  }),
11306
12242
  get: defineCommand({
11307
12243
  meta: { name: "get", description: "One batch" },
11308
12244
  args: { ...jsonFlag, id: { type: "positional", required: true, description: "Batch id" } },
11309
- run: ({ args }) => run(() => batchGet(makeCtx(), args.id), args)
12245
+ run: ({ args }) => run2(() => batchGet(makeCtx(), args.id), args)
11310
12246
  }),
11311
12247
  results: defineCommand({
11312
12248
  meta: { name: "results", description: "Print the output lines of a finished batch" },
11313
12249
  args: { ...jsonFlag, id: { type: "positional", required: true, description: "Batch id" } },
11314
- run: ({ args }) => run(() => batchResults(makeCtx(), args.id), args)
12250
+ run: ({ args }) => run2(() => batchResults(makeCtx(), args.id), args)
11315
12251
  }),
11316
12252
  cancel: defineCommand({
11317
12253
  meta: { name: "cancel", description: "Cancel a batch" },
11318
12254
  args: { ...jsonFlag, id: { type: "positional", required: true, description: "Batch id" } },
11319
- run: ({ args }) => run(() => batchCancel(makeCtx(), args.id), args)
12255
+ run: ({ args }) => run2(() => batchCancel(makeCtx(), args.id), args)
11320
12256
  })
11321
12257
  }
11322
12258
  });
11323
12259
  var benchmarks2 = defineCommand({
11324
12260
  meta: { name: "benchmarks", description: "Our own benchmark results for a model" },
11325
12261
  args: { ...jsonFlag, ...regionFlag, id: { type: "positional", required: true, description: "Model id" } },
11326
- run: ({ args }) => run(() => benchmarks(makeCtx(), args.id, region(args.region)), args)
12262
+ run: ({ args }) => run2(() => benchmarks(makeCtx(), args.id, region(args.region)), args)
11327
12263
  });
11328
12264
  var fineTune = defineCommand({
11329
12265
  meta: {
@@ -11340,7 +12276,7 @@ var fineTune = defineCommand({
11340
12276
  suffix: { type: "string", description: "Suffix for the fine-tuned model id" },
11341
12277
  epochs: { type: "string", description: "1-10, default 3" }
11342
12278
  },
11343
- run: ({ args }) => run(() => fineTuneCreate(makeCtx(), {
12279
+ run: ({ args }) => run2(() => fineTuneCreate(makeCtx(), {
11344
12280
  path: args.file,
11345
12281
  model: args.model,
11346
12282
  suffix: args.suffix,
@@ -11350,27 +12286,27 @@ var fineTune = defineCommand({
11350
12286
  list: defineCommand({
11351
12287
  meta: { name: "list", description: "Your jobs" },
11352
12288
  args: jsonFlag,
11353
- run: ({ args }) => run(() => fineTuneList(makeCtx()), args)
12289
+ run: ({ args }) => run2(() => fineTuneList(makeCtx()), args)
11354
12290
  }),
11355
12291
  get: defineCommand({
11356
12292
  meta: { name: "get", description: "One job" },
11357
12293
  args: { ...jsonFlag, id: { type: "positional", required: true, description: "Job id" } },
11358
- run: ({ args }) => run(() => fineTuneGet(makeCtx(), args.id), args)
12294
+ run: ({ args }) => run2(() => fineTuneGet(makeCtx(), args.id), args)
11359
12295
  }),
11360
12296
  events: defineCommand({
11361
12297
  meta: { name: "events", description: "A job's progress events" },
11362
12298
  args: { ...jsonFlag, id: { type: "positional", required: true, description: "Job id" } },
11363
- run: ({ args }) => run(() => fineTuneEvents(makeCtx(), args.id), args)
12299
+ run: ({ args }) => run2(() => fineTuneEvents(makeCtx(), args.id), args)
11364
12300
  }),
11365
12301
  cancel: defineCommand({
11366
12302
  meta: { name: "cancel", description: "Cancel a job" },
11367
12303
  args: { ...jsonFlag, id: { type: "positional", required: true, description: "Job id" } },
11368
- run: ({ args }) => run(() => fineTuneCancel(makeCtx(), args.id), args)
12304
+ run: ({ args }) => run2(() => fineTuneCancel(makeCtx(), args.id), args)
11369
12305
  }),
11370
12306
  models: defineCommand({
11371
12307
  meta: { name: "models", description: "Your fine-tuned models" },
11372
12308
  args: jsonFlag,
11373
- run: ({ args }) => run(() => fineTuneModels(makeCtx()), args)
12309
+ run: ({ args }) => run2(() => fineTuneModels(makeCtx()), args)
11374
12310
  })
11375
12311
  }
11376
12312
  });
@@ -11396,7 +12332,7 @@ var video = defineCommand({
11396
12332
  wait: { type: "boolean", description: "Wait until the video is ready" },
11397
12333
  output: { type: "string", alias: "o", description: "Save the MP4 here (waits for it)" }
11398
12334
  },
11399
- run: ({ args }) => run(() => videoCreate(makeCtx(), {
12335
+ run: ({ args }) => run2(() => videoCreate(makeCtx(), {
11400
12336
  prompt: args.prompt,
11401
12337
  model: args.model,
11402
12338
  seconds: num("seconds", args.seconds),
@@ -11410,7 +12346,7 @@ var video = defineCommand({
11410
12346
  get: defineCommand({
11411
12347
  meta: { name: "get", description: "One video job: status, progress, cost" },
11412
12348
  args: { ...jsonFlag, id: { type: "positional", required: true, description: "Video id" } },
11413
- run: ({ args }) => run(() => videoGet(makeCtx(), args.id), args)
12349
+ run: ({ args }) => run2(() => videoGet(makeCtx(), args.id), args)
11414
12350
  }),
11415
12351
  list: defineCommand({
11416
12352
  meta: { name: "list", description: "Your video jobs, newest first" },
@@ -11419,7 +12355,7 @@ var video = defineCommand({
11419
12355
  limit: { type: "string", description: "Page size, 1-100 (default 20)" },
11420
12356
  after: { type: "string", description: "Continue after this video id" }
11421
12357
  },
11422
- run: ({ args }) => run(() => videoList(makeCtx(), { limit: num("limit", args.limit), after: args.after }), args)
12358
+ run: ({ args }) => run2(() => videoList(makeCtx(), { limit: num("limit", args.limit), after: args.after }), args)
11423
12359
  }),
11424
12360
  download: defineCommand({
11425
12361
  meta: { name: "download", description: "Save a finished video (or --thumbnail) to a file" },
@@ -11429,12 +12365,12 @@ var video = defineCommand({
11429
12365
  output: { type: "string", alias: "o", required: true, description: "File to write" },
11430
12366
  thumbnail: { type: "boolean", description: "Download the JPEG thumbnail instead" }
11431
12367
  },
11432
- run: ({ args }) => run(() => videoDownload(makeCtx(), args.id, args.output, args.thumbnail ? "thumbnail" : "video"), args)
12368
+ run: ({ args }) => run2(() => videoDownload(makeCtx(), args.id, args.output, args.thumbnail ? "thumbnail" : "video"), args)
11433
12369
  }),
11434
12370
  delete: defineCommand({
11435
12371
  meta: { name: "delete", description: "Cancel (credits returned) or delete a video and its files" },
11436
12372
  args: { ...jsonFlag, id: { type: "positional", required: true, description: "Video id" } },
11437
- run: ({ args }) => run(() => videoDelete(makeCtx(), args.id), args)
12373
+ run: ({ args }) => run2(() => videoDelete(makeCtx(), args.id), args)
11438
12374
  })
11439
12375
  }
11440
12376
  });
@@ -11444,7 +12380,7 @@ var status2 = defineCommand({
11444
12380
  description: "Per-model health in the region (last hour), plus your account's notices when a key is set"
11445
12381
  },
11446
12382
  args: { ...jsonFlag, ...regionFlag },
11447
- run: ({ args }) => run(() => status(makeCtx(), region(args.region)), args)
12383
+ run: ({ args }) => run2(() => status(makeCtx(), region(args.region)), args)
11448
12384
  });
11449
12385
  var doctor2 = defineCommand({
11450
12386
  meta: {
@@ -11452,7 +12388,7 @@ var doctor2 = defineCommand({
11452
12388
  description: "Check this project's setup: key and region, account, credit, and notices to tell your human"
11453
12389
  },
11454
12390
  args: jsonFlag,
11455
- run: ({ args }) => run(() => doctor(makeCtx()), args)
12391
+ run: ({ args }) => run2(() => doctor(makeCtx()), args)
11456
12392
  });
11457
12393
  var webhooks = defineCommand({
11458
12394
  meta: {
@@ -11470,27 +12406,43 @@ var webhooks = defineCommand({
11470
12406
  description: "Comma-separated events (default: all four)"
11471
12407
  }
11472
12408
  },
11473
- run: ({ args }) => run(() => webhooksAdd(makeCtx(), { url: args.url, events: args.events }), args)
12409
+ run: ({ args }) => run2(() => webhooksAdd(makeCtx(), { url: args.url, events: args.events }), args)
11474
12410
  }),
11475
12411
  list: defineCommand({
11476
12412
  meta: { name: "list", description: "This account's webhook endpoints" },
11477
12413
  args: jsonFlag,
11478
- run: ({ args }) => run(() => webhooksList(makeCtx()), args)
12414
+ run: ({ args }) => run2(() => webhooksList(makeCtx()), args)
11479
12415
  }),
11480
12416
  remove: defineCommand({
11481
12417
  meta: { name: "remove", description: "Delete an endpoint by id (whk_…)" },
11482
12418
  args: { ...jsonFlag, id: { type: "positional", required: true, description: "Webhook id" } },
11483
- run: ({ args }) => run(() => webhooksRemove(makeCtx(), args.id), args)
12419
+ run: ({ args }) => run2(() => webhooksRemove(makeCtx(), args.id), args)
11484
12420
  })
11485
12421
  }
11486
12422
  });
12423
+ var connectTool = defineCommand({
12424
+ meta: {
12425
+ name: "connect",
12426
+ description: "Point an OpenAI-compatible tool at ScaledThought: writes its config with the base URL and a new child key (never printed), or prints the steps when the tool's key store can't be written safely"
12427
+ },
12428
+ args: {
12429
+ ...jsonFlag,
12430
+ tool: { type: "positional", required: true, description: CONNECT_TOOLS.join(", ") },
12431
+ model: { type: "string", description: "Default model (default: the newest live chat model)" },
12432
+ "budget-usd": { type: "string", description: "Hard daily budget for the tool's key, in USD" }
12433
+ },
12434
+ run: ({ args }) => run2(() => connect(makeCtx(), args.tool, {
12435
+ model: args.model,
12436
+ budgetUsd: num("budget-usd", args["budget-usd"])
12437
+ }), args)
12438
+ });
11487
12439
  var mcp = defineCommand({
11488
12440
  meta: {
11489
12441
  name: "mcp",
11490
12442
  description: "Print the `claude mcp add` command and JSON config for this account's MCP server"
11491
12443
  },
11492
12444
  args: jsonFlag,
11493
- run: ({ args }) => run(() => mcpSetup(makeCtx()), args)
12445
+ run: ({ args }) => run2(() => mcpSetup(makeCtx()), args)
11494
12446
  });
11495
12447
  var dashboard = defineCommand({
11496
12448
  meta: {
@@ -11506,7 +12458,7 @@ var dashboard = defineCommand({
11506
12458
  },
11507
12459
  open: { type: "boolean", default: true, description: "Open it in the browser (--no-open only prints the URL)" }
11508
12460
  },
11509
- run: ({ args }) => run(() => dashboardOpen(makeCtx(), {
12461
+ run: ({ args }) => run2(() => dashboardOpen(makeCtx(), {
11510
12462
  page: args.page,
11511
12463
  email: args.email,
11512
12464
  noOpen: args.open === false
@@ -11515,7 +12467,7 @@ var dashboard = defineCommand({
11515
12467
  var members2 = defineCommand({
11516
12468
  meta: { name: "members", description: "Who can sign in to this account's dashboard (email, role, status)" },
11517
12469
  args: jsonFlag,
11518
- run: ({ args }) => run(() => membersList(makeCtx()), args)
12470
+ run: ({ args }) => run2(() => membersList(makeCtx()), args)
11519
12471
  });
11520
12472
  var root = defineCommand({
11521
12473
  meta: {
@@ -11544,6 +12496,7 @@ var root = defineCommand({
11544
12496
  video,
11545
12497
  webhooks,
11546
12498
  doctor: doctor2,
12499
+ connect: connectTool,
11547
12500
  mcp,
11548
12501
  dashboard,
11549
12502
  members: members2