@vxil/cli 0.11.0 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/vxil.js +198 -39
  2. package/package.json +3 -3
package/dist/vxil.js CHANGED
@@ -4462,8 +4462,8 @@ function lowerAllTriggerBindings(def, name) {
4462
4462
  }
4463
4463
  var CONFIG_FILENAMES = ["vxil.config.ts", "vxil.config.mjs", "vxil.config.js"];
4464
4464
  var VXIL_CONFIG_PKG_VERSION = "0.7.0";
4465
- var VXIL_SDK_PKG_VERSION = "0.11.0";
4466
- var VXIL_CLI_PKG_VERSION = "0.11.0";
4465
+ var VXIL_SDK_PKG_VERSION = "0.12.0";
4466
+ var VXIL_CLI_PKG_VERSION = "0.12.0";
4467
4467
  function ensureScaffoldPackageJson(cwd, opts = {}) {
4468
4468
  const file = resolve(cwd, "package.json");
4469
4469
  const wanted = {
@@ -4748,6 +4748,7 @@ async function serverApply({ api, bundle, resume, allowDestructive, onPlan }) {
4748
4748
  `apply execute (resume with: vxil push --server --resume ${plan.apply_id})`
4749
4749
  );
4750
4750
  }
4751
+ var PUSH_READ_CONCURRENCY = 5;
4751
4752
  async function planOrPush({ api, features, apply, allowDestructive }) {
4752
4753
  const results = [];
4753
4754
  const destructiveQs = allowDestructive ? "&allow_destructive=true" : "";
@@ -4755,8 +4756,20 @@ async function planOrPush({ api, features, apply, allowDestructive }) {
4755
4756
  const v = r.body.data?.api_state;
4756
4757
  return v && typeof v === "object" && typeof v.ok === "boolean" ? v : void 0;
4757
4758
  };
4758
- for (const [feature, manifest] of Object.entries(features)) {
4759
- const dry = await api("PUT", `/v1/config/${feature}?dry_run=true${destructiveQs}`, manifest);
4759
+ const entries = Object.entries(features);
4760
+ const reads = await mapPool(entries, PUSH_READ_CONCURRENCY, async ([feature, manifest]) => {
4761
+ try {
4762
+ const dry = await api("PUT", `/v1/config/${feature}?dry_run=true${destructiveQs}`, manifest);
4763
+ if (dry.status !== 200) return { dry };
4764
+ return { dry, cur: await api("GET", `/v1/config/${feature}`) };
4765
+ } catch (err) {
4766
+ return { err };
4767
+ }
4768
+ });
4769
+ for (const [i, [feature, manifest]] of entries.entries()) {
4770
+ const read = reads[i];
4771
+ if ("err" in read) throw read.err;
4772
+ const dry = read.dry;
4760
4773
  if (dry.status !== 200) {
4761
4774
  const e = dry.body.error ?? {};
4762
4775
  throw new Error(
@@ -4765,7 +4778,7 @@ async function planOrPush({ api, features, apply, allowDestructive }) {
4765
4778
  }
4766
4779
  const effective = dry.body.data?.manifest;
4767
4780
  const apiStatePlan = apiStateOf(dry);
4768
- const cur = await api("GET", `/v1/config/${feature}`);
4781
+ const cur = read.cur;
4769
4782
  const unavailable = readUnavailable(`GET /v1/config/${feature}`, cur);
4770
4783
  if (unavailable) {
4771
4784
  if (apply) {
@@ -7706,6 +7719,58 @@ function hookReconcileOf(data2) {
7706
7719
  function hookReconcileRemedy(fnName) {
7707
7720
  return fnName ? `re-run the reconcile with \`vxil functions deploy ${fnName} --force\` or \`vxil push --server\` (a plain re-push sends no deploy for an unchanged function, so it would not retry it)` : "re-run the reconcile with `vxil push --server` (a plain re-push sends no deploy, so it would not retry it)";
7708
7721
  }
7722
+ var WIRING_WARNING = /trigger subscription|cron schedule/i;
7723
+ function triggerWiringOf(data2) {
7724
+ if (!data2) return null;
7725
+ const counts = (v) => {
7726
+ if (!v || typeof v !== "object" || Array.isArray(v)) return void 0;
7727
+ const o = v;
7728
+ const n = (x) => typeof x === "number" && Number.isFinite(x) ? x : 0;
7729
+ const opt = (x) => typeof x === "number" && Number.isFinite(x) ? x : void 0;
7730
+ const updated = opt(o.updated);
7731
+ const unchanged = opt(o.unchanged);
7732
+ return {
7733
+ created: n(o.created),
7734
+ ...updated !== void 0 ? { updated } : {},
7735
+ ...unchanged !== void 0 ? { unchanged } : {},
7736
+ deleted: n(o.deleted),
7737
+ failed: n(o.failed)
7738
+ };
7739
+ };
7740
+ const cms = counts(data2.cms_hook_subscriptions);
7741
+ const webhook = counts(data2.webhook_subscriptions);
7742
+ const cron = counts(data2.cron_schedules);
7743
+ const total = counts(data2.hook_reconcile);
7744
+ if (!total && !cms && !webhook && !cron) return null;
7745
+ const warnings = Array.isArray(data2.warnings) ? data2.warnings.filter((w) => typeof w === "string" && WIRING_WARNING.test(w)) : [];
7746
+ return {
7747
+ total: total ?? { created: 0, deleted: 0, failed: (cms?.failed ?? 0) + (webhook?.failed ?? 0) + (cron?.failed ?? 0) },
7748
+ ...cms ? { cms_hook_subscriptions: cms } : {},
7749
+ ...webhook ? { webhook_subscriptions: webhook } : {},
7750
+ ...cron ? { cron_schedules: cron } : {},
7751
+ warnings
7752
+ };
7753
+ }
7754
+ function formatTriggerWiring(r) {
7755
+ const line = (c) => [
7756
+ `${c.created} created`,
7757
+ ...c.updated !== void 0 ? [`${c.updated} updated`] : [],
7758
+ ...c.unchanged !== void 0 ? [`${c.unchanged} unchanged`] : [],
7759
+ `${c.deleted} removed`,
7760
+ `${c.failed} failed`
7761
+ ].join(" \xB7 ");
7762
+ const lanes = [
7763
+ ["hook subscriptions (cms/auth)", r.cms_hook_subscriptions],
7764
+ ["webhook-trigger subscriptions", r.webhook_subscriptions],
7765
+ ["cron schedules", r.cron_schedules]
7766
+ ];
7767
+ const out = [r.total.failed > 0 ? `trigger wiring (reconciled by the server) \u2014 ${r.total.failed} FAILED:` : "trigger wiring (reconciled by the server):"];
7768
+ const shown = lanes.filter(([, c]) => c);
7769
+ if (shown.length) for (const [label, c] of shown) out.push(` ${label.padEnd(30)} ${line(c)}`);
7770
+ else out.push(` ${"all triggers".padEnd(30)} ${line(r.total)}`);
7771
+ for (const w of r.warnings) out.push(` ! ${w}`);
7772
+ return out;
7773
+ }
7709
7774
  function sourceSha12(source, runtime) {
7710
7775
  const suffix = runtime ? functionsRuntimeHashSuffix(runtime) : "";
7711
7776
  return createHash("sha256").update(source + suffix, "utf8").digest("hex").slice(0, 12);
@@ -12302,7 +12367,7 @@ var TOOLS = [
12302
12367
  {
12303
12368
  name: "search_query",
12304
12369
  feature: "vector-search",
12305
- description: "Retrieve the top-k most relevant chunks from a vector-search collection. mode 'hybrid' (default) fuses semantic + keyword via RRF; 'vector' is pure semantic; 'keyword' is lexical. filter is a JSON object of equality constraints over chunk metadata. Returns scored results with document/chunk attribution.",
12370
+ description: "Retrieve the top-k most relevant chunks from a vector-search collection. mode 'hybrid' (default) fuses semantic + keyword via RRF; 'vector' is pure semantic; 'keyword' is lexical. filter is a JSON object of equality constraints over chunk metadata. Returns ranked results with document/chunk attribution: score is the fused rank value (orders the hits, not a similarity); similarity is the cosine similarity to the query (-1..1, null in keyword mode) \u2014 threshold on similarity.",
12306
12371
  inputSchema: {
12307
12372
  type: "object",
12308
12373
  properties: {
@@ -12496,7 +12561,7 @@ var TOOLS = [
12496
12561
  filter: { type: "object", additionalProperties: true, description: "Metadata equality filter applied to retrieval." },
12497
12562
  rerank: { type: "boolean", description: "Forward rerank:true to vector-search's BYO rerank pass (inert until configured there)." },
12498
12563
  boosts: { type: "object", additionalProperties: true, description: "Per-metadata-field boost specs: { field: { kind:'recency', halfLifeDays?, weight? } | { kind:'value', weights:{\u2026} } }." },
12499
- min_score: { type: "number", description: "Drop hits below this EFFECTIVE (post-boost) score." }
12564
+ min_score: { type: "number", description: "Drop hits below this EFFECTIVE (post-boost) score. score is a rank value (about 0.016-0.033 at the top), so a floor above ~0.033 drops every hit; judge relevance by each hit's similarity instead." }
12500
12565
  },
12501
12566
  required: ["query"]
12502
12567
  },
@@ -13933,7 +13998,7 @@ var VERB_USAGE = {
13933
13998
  mcp: "usage: vxil mcp install [--client cursor|claude|vscode] [--project] [--print] [--key <api_key>] [--scopes a,b] [--name <server>]",
13934
13999
  plan: "usage: vxil plan [--dev|--target <name>] [--explain] [--skip-functions] \u2014 what `vxil push` would change: cms schema, feature config, declared API state, functions (a deployed function the config no longer declares shows as `-`); writes nothing",
13935
14000
  diff: "usage: vxil diff [--against <target>|--exit-code] [--explain] [--ignore <k,\u2026>] [--strict-secrets] [--strict-api-state] [--api-state] [--json] \u2014 the CI gate: exit 0 no drift \xB7 1 drift \xB7 2 error",
13936
- push: "usage: vxil push [--dev|--target <name>|--prod] [--allow-destructive] [--strict] [--server [--resume <apply_id>]] [--no-gen] [--skip-functions] [--yes] \u2014 apply the config; --allow-destructive also deletes deployed functions and stored AI templates the config no longer declares; --strict exits 1 when anything declared was refused, deferred or left unwired",
14001
+ push: "usage: vxil push [--dev|--target <name>|--prod] [--allow-destructive] [--strict] [--server [--resume <apply_id>]] [--no-gen] [--skip-functions] [--yes] \u2014 apply the config; --allow-destructive also deletes deployed functions and stored AI templates the config no longer declares; --strict exits 1 when anything declared was refused, deferred or left unwired; --server prints the trigger wiring the server reconciled (--json: one result document on stdout)",
13937
14002
  gen: "usage: vxil gen [--check] [--offline] [--out <f>] [--no-mcp] [--mcp-out <f>] \u2014 generate vxil.types.ts (+ vxil.mcp.json); --offline keeps an existing API_VERSIONS block; --check compares instead of writing",
13938
14003
  types: "usage: vxil types \u2014 alias of `vxil gen` (run `vxil gen --help`)",
13939
14004
  doctor: "usage: vxil doctor [--dev|--target <name>] \u2014 preflight: the binding's tenant vs the key's tenant, secrets referenced-vs-stored, per-function hashes, keys (read-only)",
@@ -14022,6 +14087,32 @@ function pushExitCode(p, strict) {
14022
14087
  if (p.strict.length) lines.push(`${p.strict.length} warning(s) \u2014 \`vxil push --strict\` turns them into exit 1 for CI`);
14023
14088
  return { code: 0, lines };
14024
14089
  }
14090
+ function serverApplyJson(input) {
14091
+ const { view, triggerWiring, problems, exitCode, error } = input;
14092
+ return {
14093
+ ok: exitCode === 0,
14094
+ exit_code: exitCode,
14095
+ apply_id: view.apply_id,
14096
+ status: view.status,
14097
+ steps: view.steps,
14098
+ ...view.failed_step ? { failed_step: view.failed_step } : {},
14099
+ trigger_wiring: triggerWiring ?? null,
14100
+ problems: { hard: problems.hard, strict: problems.strict },
14101
+ ...error ? { error } : {}
14102
+ };
14103
+ }
14104
+ function serverApplyErrorJson(input) {
14105
+ return {
14106
+ ok: false,
14107
+ exit_code: input.exitCode,
14108
+ apply_id: null,
14109
+ status: null,
14110
+ steps: [],
14111
+ trigger_wiring: null,
14112
+ problems: { hard: [], strict: [] },
14113
+ error: input.error
14114
+ };
14115
+ }
14025
14116
 
14026
14117
  // src/paymentsCmd.ts
14027
14118
  var SIMULATE_SCENARIOS = [
@@ -19669,12 +19760,19 @@ function hasFlag(name) {
19669
19760
  return rest.includes(`--${name}`);
19670
19761
  }
19671
19762
  var jsonOut = rest.includes("--json");
19763
+ var jsonFailDoc = null;
19672
19764
  function ttlFlag(fallback) {
19673
19765
  const parsed = parseTtlFlag(flag("ttl"), fallback);
19674
19766
  if ("error" in parsed) fail(parsed.error);
19675
19767
  return parsed.hours;
19676
19768
  }
19677
19769
  function fail(msg, code = 1) {
19770
+ if (jsonFailDoc) {
19771
+ const doc = jsonFailDoc;
19772
+ jsonFailDoc = null;
19773
+ process.stdout.write(`${doc(msg, code)}
19774
+ `);
19775
+ }
19678
19776
  console.error(`vxil: ${msg}`);
19679
19777
  process.exit(code);
19680
19778
  }
@@ -20566,22 +20664,79 @@ async function backendListsFunctions(api) {
20566
20664
  }
20567
20665
  }
20568
20666
  async function runServerApply(sel) {
20667
+ armServerApplyJsonFail();
20569
20668
  const { api, target } = requireApi(sel, { write: "push --server" });
20669
+ const say = (s) => {
20670
+ if (jsonOut) console.error(s);
20671
+ else console.log(s);
20672
+ };
20673
+ const strict = hasFlag("strict");
20674
+ const finish = async (done2, problems2, code, error) => {
20675
+ jsonFailDoc = null;
20676
+ if (jsonOut) {
20677
+ const doc = JSON.stringify(serverApplyJson({
20678
+ view: done2,
20679
+ triggerWiring: triggerWiringOf(done2),
20680
+ problems: problems2,
20681
+ exitCode: code,
20682
+ ...error ? { error } : {}
20683
+ }));
20684
+ await new Promise((r) => {
20685
+ process.stdout.write(`${doc}
20686
+ `, () => r());
20687
+ });
20688
+ }
20689
+ if (error) fail(error, code);
20690
+ process.exit(code);
20691
+ };
20692
+ const armWith = (done2, problems2) => {
20693
+ if (!jsonOut) return;
20694
+ jsonFailDoc = (error, exitCode) => JSON.stringify(serverApplyJson({
20695
+ view: done2,
20696
+ triggerWiring: triggerWiringOf(done2),
20697
+ problems: problems2,
20698
+ exitCode,
20699
+ error
20700
+ }));
20701
+ };
20702
+ const report = (done2, wiring) => {
20703
+ say(formatApplySteps(done2.steps));
20704
+ say(`
20705
+ apply ${done2.apply_id}: ${done2.status}`);
20706
+ if (!wiring) return;
20707
+ const w = triggerWiringOf(done2);
20708
+ if (w) say(`
20709
+ ${formatTriggerWiring(w).join("\n")}`);
20710
+ };
20711
+ const gen = async () => {
20712
+ if (hasFlag("no-gen")) return;
20713
+ if (!jsonOut) {
20714
+ await runGen(sel);
20715
+ return;
20716
+ }
20717
+ const log = console.log;
20718
+ console.log = (...a) => {
20719
+ console.error(...a);
20720
+ };
20721
+ try {
20722
+ await runGen(sel);
20723
+ } finally {
20724
+ console.log = log;
20725
+ }
20726
+ };
20570
20727
  const resume = flag("resume");
20571
20728
  if (resume) {
20572
20729
  const done2 = await serverApply({ api, resume });
20573
- console.log(formatApplySteps(done2.steps));
20574
- console.log(`
20575
- apply ${done2.apply_id}: ${done2.status}`);
20576
- if (done2.status === "running") console.log(`resume with: vxil push --server --resume ${done2.apply_id}`);
20577
- if (done2.status !== "succeeded" && done2.status !== "running") process.exit(1);
20578
- if (done2.status === "succeeded" && !hasFlag("no-gen")) await runGen(sel);
20730
+ report(done2, true);
20579
20731
  const resumed = { hard: [], strict: [] };
20732
+ armWith(done2, resumed);
20733
+ if (done2.status === "running") say(`resume with: vxil push --server --resume ${done2.apply_id}`);
20734
+ if (done2.status !== "succeeded" && done2.status !== "running") return finish(done2, resumed, 1);
20735
+ if (done2.status === "succeeded") await gen();
20580
20736
  applyHookProblems(done2, resumed);
20581
- const exitResumed = pushExitCode(resumed, hasFlag("strict"));
20737
+ const exitResumed = pushExitCode(resumed, strict);
20582
20738
  for (const line of exitResumed.lines) console.error(`vxil: ${line}`);
20583
- if (exitResumed.code !== 0) process.exit(exitResumed.code);
20584
- return;
20739
+ return finish(done2, resumed, exitResumed.code);
20585
20740
  }
20586
20741
  const loaded = await loadVxilConfig();
20587
20742
  const cwd = process.cwd();
@@ -20589,7 +20744,7 @@ apply ${done2.apply_id}: ${done2.status}`);
20589
20744
  const cfg = hasFlag("skip-functions") ? rest2 : loaded;
20590
20745
  const fnNames = Object.keys(cfg.functions ?? {});
20591
20746
  if (hasFlag("skip-functions") && declaredFns && Object.keys(declaredFns).length) {
20592
- console.log(`functions: skipped (--skip-functions) \u2014 ${Object.keys(declaredFns).length} declared function(s) not deployed`);
20747
+ say(`functions: skipped (--skip-functions) \u2014 ${Object.keys(declaredFns).length} declared function(s) not deployed`);
20593
20748
  }
20594
20749
  if (fnNames.length) {
20595
20750
  const ent = await probeFunctionsEntitlement(api, fnNames[0]);
@@ -20614,33 +20769,30 @@ apply ${done2.apply_id}: ${done2.status}`);
20614
20769
  bundle,
20615
20770
  allowDestructive: hasFlag("allow-destructive"),
20616
20771
  onPlan: (plan) => {
20617
- console.log(`plan (apply ${plan.apply_id}):`);
20618
- console.log(formatApplySteps(plan.steps));
20619
- for (const w of plan.warnings ?? []) console.log(` ! ${w}`);
20620
- console.log("\napplying server-side\u2026");
20772
+ say(`plan (apply ${plan.apply_id}):`);
20773
+ say(formatApplySteps(plan.steps));
20774
+ for (const w of plan.warnings ?? []) say(` ! ${w}`);
20775
+ say("\napplying server-side\u2026");
20621
20776
  }
20622
20777
  });
20623
- console.log(formatApplySteps(done.steps));
20624
- console.log(`
20625
- apply ${done.apply_id}: ${done.status}`);
20626
20778
  if (done.status === "running") {
20627
20779
  const errored = done.steps.filter((st) => st.status === "pending" && st.error);
20628
20780
  const onlyDeferredApiState = errored.length > 0 && errored.every((st) => st.kind === "api-state" && (st.error ?? "").startsWith("deferred:"));
20629
20781
  if (onlyDeferredApiState) {
20630
- console.log(" \u2026 declared API state deferred (the feature config is still propagating) \u2014 waiting 30 s, then resuming the same apply");
20782
+ report(done, false);
20783
+ say(" \u2026 declared API state deferred (the feature config is still propagating) \u2014 waiting 30 s, then resuming the same apply");
20631
20784
  await new Promise((r) => setTimeout(r, 3e4));
20632
20785
  done = await serverApply({ api, resume: done.apply_id });
20633
- console.log(formatApplySteps(done.steps));
20634
- console.log(`
20635
- apply ${done.apply_id}: ${done.status}`);
20636
20786
  }
20637
20787
  }
20788
+ report(done, true);
20789
+ const problems = { hard: [], strict: [] };
20790
+ armWith(done, problems);
20638
20791
  if (done.status === "running") {
20639
- fail(`a transient step failure interrupted the apply \u2014 resume with: vxil push --server --resume ${done.apply_id}`);
20792
+ return finish(done, problems, 1, `a transient step failure interrupted the apply \u2014 resume with: vxil push --server --resume ${done.apply_id}`);
20640
20793
  }
20641
20794
  const standing = done.steps.filter((st) => st.kind === "api-state" && st.status === "failed");
20642
20795
  const onlyApiStateFailed = done.steps.every((st) => st.status !== "failed" || st.kind === "api-state");
20643
- const problems = { hard: [], strict: [] };
20644
20796
  if (done.status === "partial" && standing.length && onlyApiStateFailed && done.failed_step?.kind === "api-state" && done.steps.every((st) => st.status !== "rolled_back")) {
20645
20797
  for (const st of standing) {
20646
20798
  console.error(`vxil: warning \u2014 ${st.target} not converged: ${st.error ?? ""} (the config stands; fix the cause and re-push)`);
@@ -20648,7 +20800,7 @@ apply ${done.apply_id}: ${done.status}`);
20648
20800
  }
20649
20801
  } else if (done.status !== "succeeded") {
20650
20802
  const f = done.failed_step;
20651
- fail(`apply ${done.status}${f ? ` \u2014 step ${f.seq} (${f.kind} ${f.target}): ${f.error}` : ""} (config/functions were rolled back to their pre-apply versions; cms schema additions were kept)`);
20803
+ return finish(done, problems, 1, `apply ${done.status}${f ? ` \u2014 step ${f.seq} (${f.kind} ${f.target}): ${f.error}` : ""} (config/functions were rolled back to their pre-apply versions; cms schema additions were kept)`);
20652
20804
  }
20653
20805
  applyHookProblems(done, problems);
20654
20806
  if (!hasFlag("skip-functions") && (fnNames.length || cfg.features.functions || await backendListsFunctions(api))) {
@@ -20662,24 +20814,26 @@ apply ${done.apply_id}: ${done.status}`);
20662
20814
  for (const name of deployed.filter((n) => !fnNames.includes(n)).sort()) {
20663
20815
  if (hasFlag("allow-destructive")) {
20664
20816
  const del = await deleteRemoteFunction(api, name);
20665
- console.log(` - ${name} [deployed, not in vxil.config] \u2014 ${del.gone ? "already gone" : "deleted (--allow-destructive)"}`);
20817
+ say(` - ${name} [deployed, not in vxil.config] \u2014 ${del.gone ? "already gone" : "deleted (--allow-destructive)"}`);
20666
20818
  if (del.hook && del.hook.failed > 0) problems.hard.push(`trigger wiring: ${del.hook.failed} subscription(s) failed to reconcile after deleting ${name} \u2014 ${hookReconcileRemedy(fnNames[0])}`);
20667
20819
  } else {
20668
- console.log(` - ${name} [deployed, not in vxil.config] \u2014 kept; \`vxil push --server --allow-destructive\` deletes it`);
20820
+ say(` - ${name} [deployed, not in vxil.config] \u2014 kept; \`vxil push --server --allow-destructive\` deletes it`);
20669
20821
  problems.strict.push(`deployed but not declared (kept): ${name}`);
20670
20822
  }
20671
20823
  }
20672
20824
  }
20673
20825
  }
20674
- if (!hasFlag("no-gen")) await runGen(sel);
20675
- const exitWith = pushExitCode(problems, hasFlag("strict"));
20826
+ await gen();
20827
+ const exitWith = pushExitCode(problems, strict);
20676
20828
  for (const line of exitWith.lines) console.error(`vxil: ${line}`);
20677
- if (exitWith.code !== 0) process.exit(exitWith.code);
20829
+ return finish(done, problems, exitWith.code);
20830
+ }
20831
+ function armServerApplyJsonFail() {
20832
+ if (jsonOut) jsonFailDoc = (error, exitCode) => JSON.stringify(serverApplyErrorJson({ error, exitCode }));
20678
20833
  }
20679
20834
  function applyHookProblems(done, problems) {
20680
20835
  const hook = hookReconcileOf(done);
20681
20836
  if (!hook || hook.failed === 0) return;
20682
- console.error(` ! trigger wiring: ${hook.warning ?? `${hook.failed} trigger subscription(s) could not be written`}`);
20683
20837
  problems.hard.push(`trigger wiring: ${hook.failed} subscription(s) failed to reconcile \u2014 a function may be wired to nothing; re-run \`vxil push --server\` (every executed apply re-runs the reconcile)`);
20684
20838
  }
20685
20839
  async function runSeed(sel, opts = {}) {
@@ -21877,6 +22031,7 @@ ${formatSummary(state)}`);
21877
22031
  break;
21878
22032
  }
21879
22033
  case "push": {
22034
+ if (hasFlag("server") || flag("resume") !== void 0) armServerApplyJsonFail();
21880
22035
  if (hasFlag("prod") && (hasFlag("dev") || flag("target") !== void 0)) fail("--prod cannot be combined with --dev / --target \u2014 pick one target");
21881
22036
  const sel = selector();
21882
22037
  const pushTarget = resolveTargetOrFail(sel);
@@ -22180,7 +22335,11 @@ export default defineConfig(${JSON.stringify({ features: featBlocks, cms: { coll
22180
22335
  console.log(`scaffolded functions/${name}.ts \u2014 declare it in vxil.config.ts \`functions\` and \`vxil push\``);
22181
22336
  } else if (sub === "list") {
22182
22337
  const { api } = requireApi(selector());
22183
- printEnvelope(await api("GET", "/v1/functions"));
22338
+ const listRes = await api("GET", "/v1/functions");
22339
+ printEnvelope(listRes);
22340
+ if (listRes.status === 200 && listRes.body?.data?.enabled === false) {
22341
+ console.error("vxil: these functions are PAUSED for the whole project (every invoke answers 404) \u2014 a Free project on the production workload, or a plan downgrade. `vxil projects workload <slug> staging` or an upgrade resumes them.");
22342
+ }
22184
22343
  } else if (sub === "delete") {
22185
22344
  if (!name) fail("usage: vxil functions delete <name>");
22186
22345
  const { api } = requireApi(selector(), { write: `functions delete ${name}` });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vxil/cli",
3
- "version": "0.11.0",
3
+ "version": "0.12.0",
4
4
  "private": false,
5
5
  "description": "The vxil CLI — init, quickstart, push, gen, secrets, keys, migrate, doctor, diff, functions, payments; installs the `vxil` command (npm i -g @vxil/cli).",
6
6
  "license": "MIT",
@@ -47,9 +47,9 @@
47
47
  "devDependencies": {
48
48
  "miniflare": "^4.20260611.0",
49
49
  "@vxil/config": "0.7.0",
50
- "@vxil/feature-configs": "0.7.0",
51
50
  "@vxil/runtime": "0.0.1",
52
- "@vxil/types": "0.0.1"
51
+ "@vxil/types": "0.0.1",
52
+ "@vxil/feature-configs": "0.7.0"
53
53
  },
54
54
  "scripts": {
55
55
  "build": "pnpm --filter @vxil/feature-configs run build && pnpm --filter @vxil/config run build && esbuild bin/vxil.ts --bundle --platform=node --format=esm --target=node24 --outfile=dist/vxil.js --banner:js='#!/usr/bin/env node' --external:esbuild --external:miniflare && esbuild src/config-entry.ts --bundle --platform=node --format=esm --target=node24 --outfile=dist/config.js && pnpm exec tsx scripts/build-config-dts.ts",