@vxil/cli 0.29.0 → 0.30.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.
@@ -105,6 +105,7 @@ export declare const NotificationsConfigSchema: import("@sinclair/typebox").TObj
105
105
  html: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
106
106
  text: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
107
107
  }>>>>;
108
+ retainSentRender: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TBoolean>;
108
109
  }>>;
109
110
  /** in-app inbox channel (send with channel: 'inbox' | 'both') */
110
111
  inboxEnabled: import("@sinclair/typebox").TBoolean;
@@ -616,6 +617,13 @@ export declare const DeclaredSearchCollectionSchema: import("@sinclair/typebox")
616
617
  orgScoped: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TBoolean>;
617
618
  }>;
618
619
  export type DeclaredSearchCollection = Static<typeof DeclaredSearchCollectionSchema>;
620
+ /** VECTOR-HYBRID-LANE-WEIGHTS: the two RRF lane weights (weighted RRF —
621
+ * each lane's 1/(k+rank) is scaled by its weight). 0..100 each; a request
622
+ * with both 0 is refused at query time. */
623
+ export declare const HybridLaneWeights: import("@sinclair/typebox").TObject<{
624
+ vector: import("@sinclair/typebox").TNumber;
625
+ keyword: import("@sinclair/typebox").TNumber;
626
+ }>;
619
627
  export declare const VectorSearchConfigSchema: import("@sinclair/typebox").TObject<{
620
628
  enabled: import("@sinclair/typebox").TBoolean;
621
629
  backend: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"auto">, import("@sinclair/typebox").TLiteral<"lakebase">, import("@sinclair/typebox").TLiteral<"pgvector">]>;
@@ -629,10 +637,14 @@ export declare const VectorSearchConfigSchema: import("@sinclair/typebox").TObje
629
637
  maxTokens: import("@sinclair/typebox").TInteger;
630
638
  overlap: import("@sinclair/typebox").TInteger;
631
639
  }>;
632
- hybrid: import("@sinclair/typebox").TObject<{
640
+ hybrid: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TObject<{
633
641
  defaultMode: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"hybrid">, import("@sinclair/typebox").TLiteral<"vector">, import("@sinclair/typebox").TLiteral<"keyword">]>;
634
642
  rrfK: import("@sinclair/typebox").TInteger;
635
- }>;
643
+ weights: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TObject<{
644
+ vector: import("@sinclair/typebox").TNumber;
645
+ keyword: import("@sinclair/typebox").TNumber;
646
+ }>>;
647
+ }>>;
636
648
  limits: import("@sinclair/typebox").TObject<{
637
649
  maxDocsPerCollection: import("@sinclair/typebox").TInteger;
638
650
  maxChunksPerDoc: import("@sinclair/typebox").TInteger;
@@ -692,6 +704,7 @@ export declare const AiConfigSchema: import("@sinclair/typebox").TObject<{
692
704
  maxTokens: import("@sinclair/typebox").TInteger;
693
705
  temperature: import("@sinclair/typebox").TNumber;
694
706
  thinkingLevel: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<import("@sinclair/typebox").TLiteral<"minimal" | "low" | "medium" | "high">[]>>;
707
+ mediaResolution: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"low">, import("@sinclair/typebox").TLiteral<"medium">, import("@sinclair/typebox").TLiteral<"high">]>>;
695
708
  }>>;
696
709
  cache: import("@sinclair/typebox").TObject<{
697
710
  ttlSeconds: import("@sinclair/typebox").TInteger;
@@ -1025,7 +1038,14 @@ export declare function isDeclaredRetainDays(v: unknown): v is number | null | u
1025
1038
  export declare function retainDaysShortens(declared: number | null, remote: number | null): boolean;
1026
1039
  /** = cms-v1 core.ts DELETED_RETAIN_DAYS_MAX (a parity test pins the two). */
1027
1040
  export declare const CMS_DELETED_RETAIN_DAYS_MAX = 29;
1041
+ /** = cms-v1 core.ts DELETED_RETAIN_DAYS_DEFAULT: the platform window. Writing
1042
+ * it explicitly is accepted and stored as null (MX-1023-SMALL — the
1043
+ * documented default must never be a 422). */
1044
+ export declare const CMS_DELETED_RETAIN_DAYS_DEFAULT = 30;
1028
1045
  export declare function isDeclaredDeletedRetainDays(v: unknown): v is number | null | undefined;
1046
+ /** The stored form of a declared window: the explicit default (30) is null,
1047
+ * so a push declaring 30 against a null remote plans nothing. */
1048
+ export declare function normalizeDeletedRetainDays<T extends number | null | undefined>(v: T): T | null;
1029
1049
  export declare function isDeclaredOnOwnerErase(v: unknown): v is 'delete' | 'keep' | undefined;
1030
1050
  /** Does moving from `remote` to `declared` make an erase delete MORE (turning
1031
1051
  * 'delete' on)? On an existing collection that applies only under
package/dist/config.d.ts CHANGED
@@ -143,7 +143,7 @@ export interface CollectionDef {
143
143
  /** Recovery window for DELETED items, in days (guide ch. 4): a soft-deleted
144
144
  * item stays restorable this long before the nightly cleanup purges it for
145
145
  * good. An integer 0..29 (0 = purged at the next nightly run, ≤ 24 h), or
146
- * `null` for the platform default of 30 days. ABSENT = not managed by
146
+ * `null` (or `30`, stored as null) for the platform default of 30 days. ABSENT = not managed by
147
147
  * config. Shortening it on an existing collection needs
148
148
  * `vxil push --allow-destructive`. Carried by BOTH push paths. */
149
149
  deletedRetainDays?: number | null;
package/dist/vxil-main.js CHANGED
@@ -3699,7 +3699,14 @@ var NotificationsConfigSchema = Type.Object({
3699
3699
  html: Type.Optional(Type.String({ maxLength: NOTIF_OVERRIDE_BODY_MAX })),
3700
3700
  text: Type.Optional(Type.String({ maxLength: NOTIF_OVERRIDE_BODY_MAX }))
3701
3701
  }))
3702
- ))
3702
+ )),
3703
+ // CVS-1022-1 (2026-10-23): keep the render of a REAL send on its delivery
3704
+ // row for 7 days (GET /v1/notifications/deliveries/{id}, rendered_from
3705
+ // send | send_redacted). Opt-in, no default (absent = off, manifests stay
3706
+ // byte-identical); auth-class mail is kept WITHOUT its data; a render
3707
+ // over 64 KiB is dropped (row kept). Inside the ONE optional templates
3708
+ // leaf — the schema is at the 15-leaf cap.
3709
+ retainSentRender: Type.Optional(Type.Boolean())
3703
3710
  },
3704
3711
  { default: {} }
3705
3712
  )),
@@ -4598,6 +4605,10 @@ var DeclaredSearchCollectionSchema = Type.Object({
4598
4605
  // filtered to the active org; immutable after create (inside the array leaf).
4599
4606
  orgScoped: Type.Optional(Type.Boolean())
4600
4607
  });
4608
+ var HybridLaneWeights = Type.Object({
4609
+ vector: Type.Number({ minimum: 0, maximum: 100 }),
4610
+ keyword: Type.Number({ minimum: 0, maximum: 100 })
4611
+ }, { additionalProperties: false });
4601
4612
  var VectorSearchConfigSchema = Type.Object({
4602
4613
  enabled: Type.Boolean({ default: true }),
4603
4614
  // 'auto' resolves to the default managed vector backend for the tier.
@@ -4633,16 +4644,22 @@ var VectorSearchConfigSchema = Type.Object({
4633
4644
  },
4634
4645
  { default: {} }
4635
4646
  ),
4636
- hybrid: Type.Object(
4647
+ // The hybrid-fusion knobs — ONE optional bag (VECTOR-HYBRID-LANE-WEIGHTS
4648
+ // folded it from 2 leaves to 1, so `weights` rides it at no leaf cost);
4649
+ // `{ default: {} }` keeps defaultMode / rrfK filled exactly as before.
4650
+ hybrid: Type.Optional(Type.Object(
4637
4651
  {
4638
4652
  defaultMode: Type.Union(
4639
4653
  [Type.Literal("hybrid"), Type.Literal("vector"), Type.Literal("keyword")],
4640
4654
  { default: "hybrid" }
4641
4655
  ),
4642
- rrfK: Type.Integer({ default: 60, minimum: 1, maximum: 1e3 })
4656
+ rrfK: Type.Integer({ default: 60, minimum: 1, maximum: 1e3 }),
4657
+ // Per-lane RRF weights for hybrid queries (absent = 1 / 1, today's
4658
+ // fusion); a request's `weights` overrides. At least one must be > 0.
4659
+ weights: Type.Optional(HybridLaneWeights)
4643
4660
  },
4644
4661
  { default: {} }
4645
- ),
4662
+ )),
4646
4663
  limits: Type.Object(
4647
4664
  {
4648
4665
  maxDocsPerCollection: Type.Integer({ default: 1e5, minimum: 1 }),
@@ -4750,7 +4767,11 @@ var AiConfigSchema = Type.Object({
4750
4767
  model: Type.String({ default: "mock-1" }),
4751
4768
  maxTokens: Type.Integer({ default: 1024, minimum: 1, maximum: 2e5 }),
4752
4769
  temperature: Type.Number({ default: 0.7, minimum: 0, maximum: 2 }),
4753
- thinkingLevel: Type.Optional(Type.Union(AI_THINKING_LEVELS.map((l) => Type.Literal(l))))
4770
+ thinkingLevel: Type.Optional(Type.Union(AI_THINKING_LEVELS.map((l) => Type.Literal(l)))),
4771
+ // MX-1023-MEDIA-RESOLUTION (2026-10-23): Gemini's per-image / per-page
4772
+ // token budget, sent to Gemini only (ignored elsewhere). No default, so an
4773
+ // existing manifest stays byte-identical; inside the bag, so no new leaf.
4774
+ mediaResolution: Type.Optional(Type.Union([Type.Literal("low"), Type.Literal("medium"), Type.Literal("high")]))
4754
4775
  }, { default: {} })),
4755
4776
  cache: Type.Object({ ttlSeconds: Type.Integer({ default: 0, minimum: 0 }) }, { default: {} }),
4756
4777
  // 0 = off
@@ -5412,8 +5433,12 @@ function retainDaysShortens(declared, remote) {
5412
5433
  return remote === null || declared < remote;
5413
5434
  }
5414
5435
  var CMS_DELETED_RETAIN_DAYS_MAX = 29;
5436
+ var CMS_DELETED_RETAIN_DAYS_DEFAULT = 30;
5415
5437
  function isDeclaredDeletedRetainDays(v) {
5416
- return v === void 0 || v === null || typeof v === "number" && Number.isInteger(v) && v >= 0 && v <= CMS_DELETED_RETAIN_DAYS_MAX;
5438
+ return v === void 0 || v === null || typeof v === "number" && Number.isInteger(v) && v >= 0 && (v <= CMS_DELETED_RETAIN_DAYS_MAX || v === CMS_DELETED_RETAIN_DAYS_DEFAULT);
5439
+ }
5440
+ function normalizeDeletedRetainDays(v) {
5441
+ return v === CMS_DELETED_RETAIN_DAYS_DEFAULT ? null : v;
5417
5442
  }
5418
5443
  function isDeclaredOnOwnerErase(v) {
5419
5444
  return v === void 0 || v === "delete" || v === "keep";
@@ -5641,9 +5666,9 @@ function lowerAllTriggerBindings(def, name) {
5641
5666
  return bindings;
5642
5667
  }
5643
5668
  var CONFIG_FILENAMES = ["vxil.config.ts", "vxil.config.mjs", "vxil.config.js"];
5644
- var VXIL_CONFIG_PKG_VERSION = "0.21.0";
5645
- var VXIL_SDK_PKG_VERSION = "0.28.0";
5646
- var VXIL_CLI_PKG_VERSION = "0.29.0";
5669
+ var VXIL_CONFIG_PKG_VERSION = "0.22.0";
5670
+ var VXIL_SDK_PKG_VERSION = "0.29.0";
5671
+ var VXIL_CLI_PKG_VERSION = "0.30.0";
5647
5672
  function ensureScaffoldPackageJson(cwd, opts = {}) {
5648
5673
  const file = resolve(cwd, "package.json");
5649
5674
  const wanted = {
@@ -9846,7 +9871,7 @@ async function planCmsSchema({ api, collections, apply, allowDestructive = false
9846
9871
  }
9847
9872
  const drd = def.deletedRetainDays;
9848
9873
  if (!isDeclaredDeletedRetainDays(drd)) {
9849
- throw new Error(`cms.collections.${name}.deletedRetainDays must be an integer 0..29 (days) or null (got ${JSON.stringify(drd)})`);
9874
+ throw new Error(`cms.collections.${name}.deletedRetainDays must be an integer 0..29 (days), or 30 / null for the default (got ${JSON.stringify(drd)})`);
9850
9875
  }
9851
9876
  const ooe = def.onOwnerErase;
9852
9877
  if (!isDeclaredOnOwnerErase(ooe)) {
@@ -10089,7 +10114,7 @@ async function planCmsSchema({ api, collections, apply, allowDestructive = false
10089
10114
  });
10090
10115
  }
10091
10116
  }
10092
- const declaredWindow = def.deletedRetainDays;
10117
+ const declaredWindow = normalizeDeletedRetainDays(def.deletedRetainDays);
10093
10118
  if (declaredWindow !== void 0 && declaredWindow !== rc.deletedRetainDays) {
10094
10119
  const fmtWin = (d) => d === null ? "30 days (default)" : `${d} days`;
10095
10120
  const shortens = retainDaysShortens(declaredWindow, rc.deletedRetainDays);
@@ -10195,7 +10220,8 @@ async function planCmsSchema({ api, collections, apply, allowDestructive = false
10195
10220
  const orgRoles = writeRolesOf(def.orgReadRoles);
10196
10221
  if (orgRoles.length > 0) body.org_read_roles = orgRoles;
10197
10222
  if (typeof def.retainDays === "number") body.retain_days = def.retainDays;
10198
- if (typeof def.deletedRetainDays === "number") body.deleted_retain_days = def.deletedRetainDays;
10223
+ const createWindow = normalizeDeletedRetainDays(def.deletedRetainDays);
10224
+ if (typeof createWindow === "number") body.deleted_retain_days = createWindow;
10199
10225
  if (def.onOwnerErase === "delete") body.on_owner_erase = "delete";
10200
10226
  if (def.actions && def.actions.length > 0) body.actions = normalizeActions(def.actions);
10201
10227
  const res = await api("POST", "/v1/cms/collections", body);
@@ -10280,7 +10306,7 @@ async function planCmsSchema({ api, collections, apply, allowDestructive = false
10280
10306
  applied++;
10281
10307
  } else if (c.kind === "set-deleted-retain-days" || c.kind === "set-on-owner-erase") {
10282
10308
  const def = collections[c.collection];
10283
- const body = c.kind === "set-deleted-retain-days" ? { deleted_retain_days: def.deletedRetainDays ?? null } : { on_owner_erase: def.onOwnerErase ?? "keep" };
10309
+ const body = c.kind === "set-deleted-retain-days" ? { deleted_retain_days: normalizeDeletedRetainDays(def.deletedRetainDays) ?? null } : { on_owner_erase: def.onOwnerErase ?? "keep" };
10284
10310
  const res = await api("POST", `/v1/cms/collections/${encodeURIComponent(c.collection)}/fields`, body);
10285
10311
  if (res.status !== 200 && res.status !== 201) {
10286
10312
  const e = res.body.error ?? {};
@@ -14852,6 +14878,13 @@ var TOOLS = [
14852
14878
  mode: { type: "string", enum: ["hybrid", "vector", "keyword"], default: "hybrid" },
14853
14879
  filter: { type: "object", additionalProperties: true, description: 'Metadata filter, keys ANDed: equality {"user_id":"u_42"} or any-of {"folder":{"$in":["a","b"]}} (1\u201350 values, \u22644 $in keys). null / arrays / other operators are refused 422.' },
14854
14880
  rerank: { type: "boolean", description: "Apply the configured BYO reranker (config rerank block) to the fused results before top-k. Fail-open: a provider fault returns the RRF order with reranked:false." },
14881
+ weights: {
14882
+ type: "object",
14883
+ additionalProperties: false,
14884
+ required: ["vector", "keyword"],
14885
+ properties: { vector: { type: "number", minimum: 0, maximum: 100 }, keyword: { type: "number", minimum: 0, maximum: 100 } },
14886
+ description: `Hybrid mode only: per-lane RRF weights, e.g. {"vector":0.8,"keyword":0.2} to favour meaning over exact words. Not both 0. Default: the config's hybrid.weights, else equal.`
14887
+ },
14855
14888
  org_id: { type: "string", description: "Workspace-scoped (org_scoped) collections only: the org to search. Required with a server key (422 org_id_required without); an end-user session always searches its active workspace. Refused 422 on a collection that is not org-scoped." }
14856
14889
  },
14857
14890
  required: ["collection", "query"]
@@ -14862,7 +14895,7 @@ var TOOLS = [
14862
14895
  {
14863
14896
  name: "ai_generate",
14864
14897
  feature: "ai",
14865
- description: "Generate a completion from a prompt or a named tenant template. Pass either prompt (raw text) or template + input (vars for a stored template). Defaults to the tenant-configured provider/model; override with provider/model. response_schema makes the output schema-guaranteed JSON (parsed into data.output). Returns the synchronous completion (set stream only via the REST API).",
14898
+ description: "Generate a completion from a prompt or a named tenant template. Pass either prompt (raw text) or template + input (vars for a stored template). Defaults to the tenant-configured provider/model; override with provider/model. response_schema makes the output schema-guaranteed JSON (parsed into data.output). Returns the synchronous completion by default (set stream only via the REST API); mode:'job' instead returns a 202 handle (generation_id, run_id) \u2014 read the answer with ai_generation_get and wait:25.",
14866
14899
  inputSchema: {
14867
14900
  type: "object",
14868
14901
  properties: {
@@ -14878,6 +14911,22 @@ var TOOLS = [
14878
14911
  enum: ["minimal", "low", "medium", "high"],
14879
14912
  description: "Gemini thinking depth (ignored by other providers). Omitted: the tenant's defaults.thinkingLevel, then the model default. 'minimal' on a model that rejects it is a 422 thinking_level_unsupported. Thinking tokens bill as output."
14880
14913
  },
14914
+ media_resolution: {
14915
+ type: "string",
14916
+ enum: ["low", "medium", "high"],
14917
+ description: "Gemini token budget per image or PDF page (ignored by other providers): lower is faster and bills fewer input tokens. Omitted: the tenant's defaults.mediaResolution, then the model default."
14918
+ },
14919
+ mode: {
14920
+ type: "string",
14921
+ enum: ["sync", "job"],
14922
+ description: "'sync' (default) answers with the completion. 'job' routes the generation through a jobs run and answers 202 with generation_id + run_id; read it with ai_generation_get (wait:25)."
14923
+ },
14924
+ deadline_ms: {
14925
+ type: "integer",
14926
+ minimum: 1e3,
14927
+ maximum: 17e3,
14928
+ description: "mode:'job' only (422 otherwise): bound the run's first provider call at this many ms so it can start without the queue hop. A first call that passes it is retried on the queue with the normal job-lane bound."
14929
+ },
14881
14930
  json_mode: { type: "boolean", description: "Constrain the output to JSON (no schema \u2014 use response_schema for a guaranteed shape)." },
14882
14931
  response_schema: {
14883
14932
  type: "object",
@@ -15168,14 +15217,15 @@ var TOOLS = [
15168
15217
  properties: {
15169
15218
  since: { type: "string", description: "ISO-8601 lower bound on created_at (inclusive; no zone = UTC). Tail with an overlap (last stored created_at minus a minute) and dedupe on ledger_entry_id." },
15170
15219
  cursor: { type: "string", description: "Opaque keyset cursor from a prior page (next_cursor)." },
15171
- user_id: { type: "string", maxLength: 512, description: "Only this end user's rows." },
15220
+ user_id: { type: "string", maxLength: 512, description: "Only this end user's rows. Give this OR org_id." },
15221
+ org_id: { type: "string", maxLength: 64, description: "WORKSPACE BILLING: only this workspace's rows (an orgs id; the same as user_id 'org:<id>'). Give this OR user_id." },
15172
15222
  credit_type: { type: "string", maxLength: 200, description: "Only rows of this credit type, e.g. 'scans'." },
15173
15223
  limit: { type: "number", default: 100, description: "Page size, clamped 1..500." }
15174
15224
  }
15175
15225
  },
15176
15226
  method: "GET",
15177
15227
  path: "/v1/payments/credits/ledger",
15178
- queryArgs: ["since", "cursor", "user_id", "credit_type", "limit"]
15228
+ queryArgs: ["since", "cursor", "user_id", "org_id", "credit_type", "limit"]
15179
15229
  },
15180
15230
  {
15181
15231
  name: "payments_list_refunds",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vxil/cli",
3
- "version": "0.29.0",
3
+ "version": "0.30.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",
@@ -45,8 +45,8 @@
45
45
  }
46
46
  },
47
47
  "devDependencies": {
48
- "@vxil/config": "0.21.0",
49
- "@vxil/feature-configs": "0.19.0",
48
+ "@vxil/config": "0.22.0",
49
+ "@vxil/feature-configs": "0.20.0",
50
50
  "@vxil/runtime": "0.0.1",
51
51
  "@vxil/types": "0.0.1",
52
52
  "miniflare": "^4.20260730.0"