@query-farm/vgi 0.7.0 → 0.9.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.
- package/dist/arguments/argument-spec.d.ts +49 -0
- package/dist/catalog/descriptors.d.ts +6 -0
- package/dist/catalog/interface.d.ts +34 -0
- package/dist/functions/scalar.d.ts +14 -0
- package/dist/generated/vgi-client.d.ts +1 -0
- package/dist/generated/vgi-protocol-schemas.d.ts +1 -0
- package/dist/index.core.d.ts +1 -1
- package/dist/index.js +218 -107
- package/dist/index.js.map +13 -13
- package/dist/types.d.ts +4 -0
- package/dist/worker-cf-entry.js +169 -70
- package/dist/worker-cf-entry.js.map +11 -11
- package/package.json +1 -1
- package/src/arguments/argument-spec.ts +148 -0
- package/src/catalog/descriptors.ts +6 -0
- package/src/catalog/interface.ts +55 -1
- package/src/catalog/read-only.ts +6 -0
- package/src/client/client.ts +3 -0
- package/src/functions/scalar.ts +18 -1
- package/src/generated/vgi-client.ts +2 -1
- package/src/generated/vgi-protocol-schemas.ts +16 -1
- package/src/index.core.ts +1 -1
- package/src/protocol/handlers/catalog/admin.ts +1 -0
- package/src/types.ts +14 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@query-farm/vgi",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"description": "TypeScript framework for extending DuckDB with user-defined functions via the Vector Gateway Interface (VGI) over Arrow IPC.",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE",
|
|
6
6
|
"author": "Query Farm LLC (https://query.farm)",
|
|
@@ -14,6 +14,10 @@ import {
|
|
|
14
14
|
VGI_CONST_KEY,
|
|
15
15
|
VGI_CONST_TRUE,
|
|
16
16
|
VGI_DOC_KEY,
|
|
17
|
+
VGI_DEFAULT_KEY,
|
|
18
|
+
VGI_CHOICES_KEY,
|
|
19
|
+
VGI_RANGE_KEY,
|
|
20
|
+
VGI_PATTERN_KEY,
|
|
17
21
|
} from "../types.js";
|
|
18
22
|
|
|
19
23
|
export interface ArgumentSpec {
|
|
@@ -25,6 +29,126 @@ export interface ArgumentSpec {
|
|
|
25
29
|
isVarargs?: boolean;
|
|
26
30
|
isConst?: boolean;
|
|
27
31
|
doc?: string;
|
|
32
|
+
/**
|
|
33
|
+
* Discovery-facing constraint metadata, pre-encoded to their surfaced UTF-8
|
|
34
|
+
* forms (presence-only — `undefined` means the constraint is absent and the
|
|
35
|
+
* corresponding field-metadata key is omitted entirely). Mirrors Python's
|
|
36
|
+
* `ArgumentSpec.default_json` / `choices_json` / `range_notation` / `pattern`
|
|
37
|
+
* so `argumentSpecsToSchema`/`schemaToArgumentSpecs` round-trip symmetrically.
|
|
38
|
+
*/
|
|
39
|
+
defaultJson?: string;
|
|
40
|
+
choicesJson?: string;
|
|
41
|
+
rangeNotation?: string;
|
|
42
|
+
pattern?: string;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Raw per-argument constraint declarations, as authored on a function's
|
|
47
|
+
* argument descriptor. Encoded into the pre-computed {@link ArgumentSpec}
|
|
48
|
+
* constraint fields via {@link constraintSpecFields}.
|
|
49
|
+
*/
|
|
50
|
+
export interface ArgumentConstraints {
|
|
51
|
+
/** Closed set of allowed values (JSON-encoded into `vgi_choices`). */
|
|
52
|
+
choices?: readonly unknown[];
|
|
53
|
+
/** Inclusive lower bound (`>=`). */
|
|
54
|
+
ge?: number;
|
|
55
|
+
/** Inclusive upper bound (`<=`). */
|
|
56
|
+
le?: number;
|
|
57
|
+
/** Exclusive lower bound (`>`). */
|
|
58
|
+
gt?: number;
|
|
59
|
+
/** Exclusive upper bound (`<`). */
|
|
60
|
+
lt?: number;
|
|
61
|
+
/** Regex the value must match (surfaced as `vgi_pattern`, as-is). */
|
|
62
|
+
pattern?: string;
|
|
63
|
+
/** Default value (JSON-encoded into `vgi_default`); optional args only. */
|
|
64
|
+
default?: unknown;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** `JSON.stringify`, falling back to the value's string form when unserializable. */
|
|
68
|
+
function safeJson(value: unknown): string {
|
|
69
|
+
try {
|
|
70
|
+
const encoded = JSON.stringify(value);
|
|
71
|
+
// JSON.stringify returns undefined for functions/symbols/undefined.
|
|
72
|
+
if (encoded === undefined) {
|
|
73
|
+
return JSON.stringify(String(value));
|
|
74
|
+
}
|
|
75
|
+
return encoded;
|
|
76
|
+
} catch {
|
|
77
|
+
return JSON.stringify(String(value));
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Build interval notation from an argument's numeric bounds.
|
|
83
|
+
*
|
|
84
|
+
* Inclusive bounds (`ge`/`le`) render as square brackets, exclusive bounds
|
|
85
|
+
* (`gt`/`lt`) as parentheses, and an open side as `-inf`/`+inf`. Returns
|
|
86
|
+
* `undefined` when the argument has no numeric bound at all.
|
|
87
|
+
*
|
|
88
|
+
* Examples: `ge=0,le=10` -> `"[0, 10]"`; `gt=0` -> `"(0, +inf)"`;
|
|
89
|
+
* `ge=1,lt=10` -> `"[1, 10)"`.
|
|
90
|
+
*/
|
|
91
|
+
export function formatRange(
|
|
92
|
+
ge?: number,
|
|
93
|
+
le?: number,
|
|
94
|
+
gt?: number,
|
|
95
|
+
lt?: number,
|
|
96
|
+
): string | undefined {
|
|
97
|
+
if (ge === undefined && le === undefined && gt === undefined && lt === undefined) {
|
|
98
|
+
return undefined;
|
|
99
|
+
}
|
|
100
|
+
let low: string;
|
|
101
|
+
if (gt !== undefined) {
|
|
102
|
+
low = `(${gt}`;
|
|
103
|
+
} else if (ge !== undefined) {
|
|
104
|
+
low = `[${ge}`;
|
|
105
|
+
} else {
|
|
106
|
+
low = "(-inf";
|
|
107
|
+
}
|
|
108
|
+
let high: string;
|
|
109
|
+
if (lt !== undefined) {
|
|
110
|
+
high = `${lt})`;
|
|
111
|
+
} else if (le !== undefined) {
|
|
112
|
+
high = `${le}]`;
|
|
113
|
+
} else {
|
|
114
|
+
high = "+inf)";
|
|
115
|
+
}
|
|
116
|
+
return `${low}, ${high}`;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Encode raw {@link ArgumentConstraints} into the pre-computed constraint
|
|
121
|
+
* fields of an {@link ArgumentSpec} (presence-only — absent constraints yield
|
|
122
|
+
* no field). Mirrors Python's `_constraint_kwargs`.
|
|
123
|
+
*/
|
|
124
|
+
export function constraintSpecFields(
|
|
125
|
+
constraints: ArgumentConstraints | undefined,
|
|
126
|
+
): Pick<ArgumentSpec, "defaultJson" | "choicesJson" | "rangeNotation" | "pattern"> {
|
|
127
|
+
const fields: Pick<
|
|
128
|
+
ArgumentSpec,
|
|
129
|
+
"defaultJson" | "choicesJson" | "rangeNotation" | "pattern"
|
|
130
|
+
> = {};
|
|
131
|
+
if (constraints === undefined) return fields;
|
|
132
|
+
|
|
133
|
+
if ("default" in constraints && constraints.default !== undefined) {
|
|
134
|
+
fields.defaultJson = safeJson(constraints.default);
|
|
135
|
+
}
|
|
136
|
+
if (constraints.choices !== undefined) {
|
|
137
|
+
fields.choicesJson = safeJson([...constraints.choices]);
|
|
138
|
+
}
|
|
139
|
+
const range = formatRange(
|
|
140
|
+
constraints.ge,
|
|
141
|
+
constraints.le,
|
|
142
|
+
constraints.gt,
|
|
143
|
+
constraints.lt,
|
|
144
|
+
);
|
|
145
|
+
if (range !== undefined) {
|
|
146
|
+
fields.rangeNotation = range;
|
|
147
|
+
}
|
|
148
|
+
if (constraints.pattern !== undefined) {
|
|
149
|
+
fields.pattern = constraints.pattern;
|
|
150
|
+
}
|
|
151
|
+
return fields;
|
|
28
152
|
}
|
|
29
153
|
|
|
30
154
|
function argumentSpecSortKey(spec: ArgumentSpec): [number, number | string] {
|
|
@@ -76,6 +200,20 @@ export function argumentSpecsToSchema(specs: ArgumentSpec[]): VgiSchema {
|
|
|
76
200
|
metadata.set(VGI_DOC_KEY, spec.doc);
|
|
77
201
|
}
|
|
78
202
|
|
|
203
|
+
// Per-argument constraint metadata (presence-only; already value-encoded).
|
|
204
|
+
if (spec.defaultJson !== undefined) {
|
|
205
|
+
metadata.set(VGI_DEFAULT_KEY, spec.defaultJson);
|
|
206
|
+
}
|
|
207
|
+
if (spec.choicesJson !== undefined) {
|
|
208
|
+
metadata.set(VGI_CHOICES_KEY, spec.choicesJson);
|
|
209
|
+
}
|
|
210
|
+
if (spec.rangeNotation !== undefined) {
|
|
211
|
+
metadata.set(VGI_RANGE_KEY, spec.rangeNotation);
|
|
212
|
+
}
|
|
213
|
+
if (spec.pattern !== undefined) {
|
|
214
|
+
metadata.set(VGI_PATTERN_KEY, spec.pattern);
|
|
215
|
+
}
|
|
216
|
+
|
|
79
217
|
const field = field_(
|
|
80
218
|
spec.name,
|
|
81
219
|
spec.arrowType,
|
|
@@ -184,6 +322,12 @@ export function schemaToArgumentSpecs(schema: VgiSchema): ArgumentSpec[] {
|
|
|
184
322
|
const isConst = metadata.get(VGI_CONST_KEY) === VGI_CONST_TRUE;
|
|
185
323
|
const doc = metadata.get(VGI_DOC_KEY) ?? "";
|
|
186
324
|
|
|
325
|
+
// Per-argument constraint metadata (absent key -> undefined).
|
|
326
|
+
const defaultJson = metadata.get(VGI_DEFAULT_KEY);
|
|
327
|
+
const choicesJson = metadata.get(VGI_CHOICES_KEY);
|
|
328
|
+
const rangeNotation = metadata.get(VGI_RANGE_KEY);
|
|
329
|
+
const pattern = metadata.get(VGI_PATTERN_KEY);
|
|
330
|
+
|
|
187
331
|
specs.push({
|
|
188
332
|
name: field.name,
|
|
189
333
|
position,
|
|
@@ -193,6 +337,10 @@ export function schemaToArgumentSpecs(schema: VgiSchema): ArgumentSpec[] {
|
|
|
193
337
|
isVarargs,
|
|
194
338
|
isConst,
|
|
195
339
|
doc,
|
|
340
|
+
defaultJson,
|
|
341
|
+
choicesJson,
|
|
342
|
+
rangeNotation,
|
|
343
|
+
pattern,
|
|
196
344
|
});
|
|
197
345
|
}
|
|
198
346
|
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
// Declarative catalog descriptor types.
|
|
3
3
|
|
|
4
4
|
import type { VgiSchema, VgiDataType } from "../arrow/index.js";
|
|
5
|
+
import type { AttachCatalogInfo } from "./interface.js";
|
|
5
6
|
import type { VgiFunction } from "../functions/types.js";
|
|
6
7
|
import type { Arguments } from "../arguments/arguments.js";
|
|
7
8
|
import type { ColumnStatistics } from "../util/statistics.js";
|
|
@@ -152,6 +153,11 @@ export interface CatalogDescriptor {
|
|
|
152
153
|
schemas: SchemaDescriptor[];
|
|
153
154
|
settings?: SettingDescriptor[];
|
|
154
155
|
secretTypes?: SecretTypeDescriptor[];
|
|
156
|
+
/**
|
|
157
|
+
* Companion catalogs (lakehouse federation) the client should ATTACH when this
|
|
158
|
+
* VGI catalog attaches. Surfaced via `catalog_attach.attach_catalogs`.
|
|
159
|
+
*/
|
|
160
|
+
attachCatalogs?: AttachCatalogInfo[];
|
|
155
161
|
comment?: string;
|
|
156
162
|
tags?: Record<string, string>;
|
|
157
163
|
/**
|
package/src/catalog/interface.ts
CHANGED
|
@@ -74,7 +74,10 @@ export { encodeIndexInfo, decodeIndexInfo } from "../generated/vgi-client.js";
|
|
|
74
74
|
// generic ASD codec with the generated schema. Mirrors vgi-python's
|
|
75
75
|
// catalog_interface.CopyFromFormatInfo.
|
|
76
76
|
import { encodeASD } from "../codec/asd.js";
|
|
77
|
-
import {
|
|
77
|
+
import {
|
|
78
|
+
AttachCatalogInfoSchema,
|
|
79
|
+
CopyFromFormatInfoSchema,
|
|
80
|
+
} from "../generated/vgi-protocol-schemas.js";
|
|
78
81
|
|
|
79
82
|
export interface CopyFromFormatInfo {
|
|
80
83
|
/** Free-text comment (CopyFromFunction's `copyFromComment`). */
|
|
@@ -117,6 +120,42 @@ export const encodeCopyFromFormatInfo = (v: CopyFromFormatInfo): Uint8Array =>
|
|
|
117
120
|
ordered: v.ordered ?? false,
|
|
118
121
|
});
|
|
119
122
|
|
|
123
|
+
/**
|
|
124
|
+
* A companion catalog the client should ATTACH when this VGI catalog attaches
|
|
125
|
+
* (lakehouse federation). Serialized into `CatalogAttachResult.attach_catalogs`;
|
|
126
|
+
* the C++ VGI extension attaches each at VGI-attach time so multi-branch
|
|
127
|
+
* catalog-table branches can resolve tables in a companion DuckLake / Iceberg /
|
|
128
|
+
* Postgres / DuckDB.
|
|
129
|
+
*/
|
|
130
|
+
export interface AttachCatalogInfo {
|
|
131
|
+
/** ATTACH alias; also a catalog-table ScanBranch's `sourceCatalog`. */
|
|
132
|
+
alias: string;
|
|
133
|
+
/** ATTACH target — a path or DSN (e.g. `ducklake:sqlite:/data/meta.sqlite`). */
|
|
134
|
+
target: string;
|
|
135
|
+
/** DuckDB db type; empty => inferred from the target scheme prefix. */
|
|
136
|
+
db_type?: string;
|
|
137
|
+
/** Extra ATTACH options forwarded verbatim (e.g. DuckLake DATA_PATH). */
|
|
138
|
+
options?: Record<string, string>;
|
|
139
|
+
/** Attach hidden (excluded from duckdb_databases()); still resolvable. */
|
|
140
|
+
hidden?: boolean;
|
|
141
|
+
/** When true, attach failure fails the whole VGI ATTACH. */
|
|
142
|
+
required?: boolean;
|
|
143
|
+
/** Optional named secret to inject into the companion's ATTACH options. */
|
|
144
|
+
secret_ref?: string;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/** Encode an AttachCatalogInfo to Arrow IPC bytes (single-row batch). */
|
|
148
|
+
export const encodeAttachCatalogInfo = (v: AttachCatalogInfo): Uint8Array =>
|
|
149
|
+
encodeASD(AttachCatalogInfoSchema, {
|
|
150
|
+
alias: v.alias,
|
|
151
|
+
target: v.target,
|
|
152
|
+
db_type: v.db_type ?? "",
|
|
153
|
+
options: v.options ?? {},
|
|
154
|
+
hidden: v.hidden ?? false,
|
|
155
|
+
required: v.required ?? false,
|
|
156
|
+
secret_ref: v.secret_ref ?? "",
|
|
157
|
+
});
|
|
158
|
+
|
|
120
159
|
// ============================================================================
|
|
121
160
|
// ScanFunctionResult — typed result for catalog_table_scan_function_get.
|
|
122
161
|
// Mirrors vgi-python's ScanFunctionResult (catalog_interface.py:380).
|
|
@@ -204,6 +243,9 @@ export function singleBranchResult(
|
|
|
204
243
|
arguments: [toUint8Array(legacy.arguments)],
|
|
205
244
|
branch_filter: [null],
|
|
206
245
|
writable: [false],
|
|
246
|
+
source_catalog: [null],
|
|
247
|
+
source_schema: [null],
|
|
248
|
+
source_table: [null],
|
|
207
249
|
},
|
|
208
250
|
ScanBranchSchema as any,
|
|
209
251
|
);
|
|
@@ -233,6 +275,15 @@ export interface ScanBranchInput {
|
|
|
233
275
|
branchFilter?: string | null;
|
|
234
276
|
/** Declares this branch as the INSERT target (at most one per table). */
|
|
235
277
|
writable?: boolean;
|
|
278
|
+
/**
|
|
279
|
+
* Catalog-table branch (lakehouse federation): leave `functionName` empty and
|
|
280
|
+
* set these to scan the base table
|
|
281
|
+
* `sourceCatalog.sourceSchema.sourceTable` in a companion catalog instead of
|
|
282
|
+
* calling a table function.
|
|
283
|
+
*/
|
|
284
|
+
sourceCatalog?: string | null;
|
|
285
|
+
sourceSchema?: string | null;
|
|
286
|
+
sourceTable?: string | null;
|
|
236
287
|
}
|
|
237
288
|
|
|
238
289
|
/**
|
|
@@ -284,6 +335,9 @@ export function buildScanBranchesResult(
|
|
|
284
335
|
arguments: [serializeBranchArguments(branch)],
|
|
285
336
|
branch_filter: [branch.branchFilter ?? null],
|
|
286
337
|
writable: [branch.writable ?? false],
|
|
338
|
+
source_catalog: [branch.sourceCatalog ?? null],
|
|
339
|
+
source_schema: [branch.sourceSchema ?? null],
|
|
340
|
+
source_table: [branch.sourceTable ?? null],
|
|
287
341
|
},
|
|
288
342
|
ScanBranchSchema as any,
|
|
289
343
|
);
|
package/src/catalog/read-only.ts
CHANGED
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
type IndexInfo,
|
|
17
17
|
type IndexConstraintType,
|
|
18
18
|
type CopyFromFormatInfo,
|
|
19
|
+
encodeAttachCatalogInfo,
|
|
19
20
|
} from "./interface.js";
|
|
20
21
|
import type { CatalogDescriptor, SchemaDescriptor, TableDescriptor, ViewDescriptor, MacroDescriptor, SettingDescriptor, SecretTypeDescriptor, ForeignKeyDef, DefaultValue } from "./descriptors.js";
|
|
21
22
|
import { serializeColumnStatistics } from "../util/statistics.js";
|
|
@@ -80,6 +81,10 @@ export class ReadOnlyCatalogInterface extends CatalogInterface {
|
|
|
80
81
|
serializeSecretType(s)
|
|
81
82
|
);
|
|
82
83
|
|
|
84
|
+
const attachCatalogs = (this._descriptor.attachCatalogs ?? []).map((c) =>
|
|
85
|
+
encodeAttachCatalogInfo(c)
|
|
86
|
+
);
|
|
87
|
+
|
|
83
88
|
// Auto-derive supportsTimeTravel from table descriptors
|
|
84
89
|
const hasTimeTravel = this._descriptor.schemas.some(
|
|
85
90
|
(s) => s.tables?.some((t) => t.supportsTimeTravel) ?? false
|
|
@@ -95,6 +100,7 @@ export class ReadOnlyCatalogInterface extends CatalogInterface {
|
|
|
95
100
|
default_schema: this._descriptor.defaultSchema ?? "main",
|
|
96
101
|
settings,
|
|
97
102
|
secret_types: secretTypes,
|
|
103
|
+
attach_catalogs: attachCatalogs,
|
|
98
104
|
comment: this._descriptor.comment ?? null,
|
|
99
105
|
tags: this._descriptor.tags ?? {},
|
|
100
106
|
// Advertise true so DuckDB routes catalog_table_column_statistics_get
|
package/src/client/client.ts
CHANGED
|
@@ -621,6 +621,9 @@ export class VgiClient {
|
|
|
621
621
|
secret_types: inner.secret_types
|
|
622
622
|
? (Array.isArray(inner.secret_types) ? inner.secret_types : [...inner.secret_types]).map(toUint8Array)
|
|
623
623
|
: [],
|
|
624
|
+
attach_catalogs: inner.attach_catalogs
|
|
625
|
+
? (Array.isArray(inner.attach_catalogs) ? inner.attach_catalogs : [...inner.attach_catalogs]).map(toUint8Array)
|
|
626
|
+
: [],
|
|
624
627
|
comment: inner.comment ?? null,
|
|
625
628
|
tags: deserializeTags(inner.tags),
|
|
626
629
|
supports_column_statistics: inner.supports_column_statistics ?? false,
|
package/src/functions/scalar.ts
CHANGED
|
@@ -37,7 +37,7 @@ import type {
|
|
|
37
37
|
FunctionExample,
|
|
38
38
|
} from "./types.js";
|
|
39
39
|
import type { ArgumentSpec } from "../arguments/argument-spec.js";
|
|
40
|
-
import { argumentSpecsToSchema } from "../arguments/argument-spec.js";
|
|
40
|
+
import { argumentSpecsToSchema, constraintSpecFields } from "../arguments/argument-spec.js";
|
|
41
41
|
import { batchToScalarDict, batchToSecretDict, batchFromColumns, projectBatch, safeNumber } from "../util/arrow/index.js";
|
|
42
42
|
|
|
43
43
|
// ============================================================================
|
|
@@ -71,6 +71,22 @@ export interface ScalarParameterDef {
|
|
|
71
71
|
varargs?: boolean;
|
|
72
72
|
/** Human-readable per-argument description (surfaced as `vgi_doc`). */
|
|
73
73
|
doc?: string;
|
|
74
|
+
// Discovery-facing validation constraints (surfaced via
|
|
75
|
+
// `vgi_function_arguments()`). All optional; see `ArgumentConstraints`.
|
|
76
|
+
/** Closed set of allowed values (surfaced as `vgi_choices`). */
|
|
77
|
+
choices?: readonly unknown[];
|
|
78
|
+
/** Inclusive lower bound, `>=` (folded into `vgi_range`). */
|
|
79
|
+
ge?: number;
|
|
80
|
+
/** Inclusive upper bound, `<=` (folded into `vgi_range`). */
|
|
81
|
+
le?: number;
|
|
82
|
+
/** Exclusive lower bound, `>` (folded into `vgi_range`). */
|
|
83
|
+
gt?: number;
|
|
84
|
+
/** Exclusive upper bound, `<` (folded into `vgi_range`). */
|
|
85
|
+
lt?: number;
|
|
86
|
+
/** Regex the value must match (surfaced as `vgi_pattern`). */
|
|
87
|
+
pattern?: string;
|
|
88
|
+
/** Default value (surfaced as `vgi_default`, JSON-encoded). */
|
|
89
|
+
default?: unknown;
|
|
74
90
|
}
|
|
75
91
|
|
|
76
92
|
/**
|
|
@@ -183,6 +199,7 @@ export function defineScalarFunction<
|
|
|
183
199
|
isConst: p.const,
|
|
184
200
|
isVarargs: p.varargs,
|
|
185
201
|
doc: p.doc,
|
|
202
|
+
...constraintSpecFields(p),
|
|
186
203
|
});
|
|
187
204
|
}
|
|
188
205
|
} else {
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// GENERATED by vgi.codegen.ts_client. DO NOT EDIT BY HAND.
|
|
3
3
|
//
|
|
4
4
|
// Generator: vgi-gen-ts-client v1
|
|
5
|
-
// Content hash:
|
|
5
|
+
// Content hash: 5ddab596625f
|
|
6
6
|
//
|
|
7
7
|
// To regenerate:
|
|
8
8
|
// uv run --project ~/Development/vgi-python vgi-gen-ts-client \
|
|
@@ -366,6 +366,7 @@ export interface CatalogAttachResult {
|
|
|
366
366
|
default_schema: string;
|
|
367
367
|
settings: Uint8Array[];
|
|
368
368
|
secret_types: Uint8Array[];
|
|
369
|
+
attach_catalogs: Uint8Array[];
|
|
369
370
|
comment?: string | null;
|
|
370
371
|
tags: Record<string, string>;
|
|
371
372
|
supports_column_statistics: boolean;
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// GENERATED by vgi.codegen.ts_schemas. DO NOT EDIT BY HAND.
|
|
3
3
|
//
|
|
4
4
|
// Generator: vgi-gen-ts-schemas v2
|
|
5
|
-
// Content hash:
|
|
5
|
+
// Content hash: 673bfdc9573a
|
|
6
6
|
//
|
|
7
7
|
// To regenerate:
|
|
8
8
|
// uv run --project ~/Development/vgi-python vgi-gen-ts-schemas \
|
|
@@ -175,6 +175,20 @@ export const ScanBranchSchema = schema([
|
|
|
175
175
|
field("arguments", binary(), false),
|
|
176
176
|
field("branch_filter", utf8(), true),
|
|
177
177
|
field("writable", bool(), false),
|
|
178
|
+
field("source_catalog", utf8(), true),
|
|
179
|
+
field("source_schema", utf8(), true),
|
|
180
|
+
field("source_table", utf8(), true),
|
|
181
|
+
]);
|
|
182
|
+
|
|
183
|
+
// Origin: AttachCatalogInfo
|
|
184
|
+
export const AttachCatalogInfoSchema = schema([
|
|
185
|
+
field("alias", utf8(), false),
|
|
186
|
+
field("target", utf8(), false),
|
|
187
|
+
field("db_type", utf8(), false),
|
|
188
|
+
field("options", map(field("key", utf8(), false), field("value", utf8(), true), false), false),
|
|
189
|
+
field("hidden", bool(), false),
|
|
190
|
+
field("required", bool(), false),
|
|
191
|
+
field("secret_ref", utf8(), false),
|
|
178
192
|
]);
|
|
179
193
|
|
|
180
194
|
// Origin: method 'aggregate_bind' result
|
|
@@ -246,6 +260,7 @@ export const CatalogAttachResultSchema = schema([
|
|
|
246
260
|
field("default_schema", utf8(), false),
|
|
247
261
|
field("settings", list(field("item", binary(), true)), false),
|
|
248
262
|
field("secret_types", list(field("item", binary(), true)), false),
|
|
263
|
+
field("attach_catalogs", list(field("item", binary(), true)), false),
|
|
249
264
|
field("comment", utf8(), true),
|
|
250
265
|
field("tags", map(field("key", utf8(), false), field("value", utf8(), true), false), false),
|
|
251
266
|
field("supports_column_statistics", bool(), false),
|
package/src/index.core.ts
CHANGED
|
@@ -75,7 +75,7 @@ export type {
|
|
|
75
75
|
|
|
76
76
|
// Arguments
|
|
77
77
|
export { Arguments } from "./arguments/arguments.js";
|
|
78
|
-
export { type ArgumentSpec, argumentSpecsToSchema, schemaToArgumentSpecs, macroArgumentsSchema, macroParameterDocsFromSchema } from "./arguments/argument-spec.js";
|
|
78
|
+
export { type ArgumentSpec, type ArgumentConstraints, argumentSpecsToSchema, schemaToArgumentSpecs, macroArgumentsSchema, macroParameterDocsFromSchema, formatRange, constraintSpecFields } from "./arguments/argument-spec.js";
|
|
79
79
|
|
|
80
80
|
// Errors
|
|
81
81
|
export {
|
|
@@ -100,6 +100,7 @@ export function registerCatalogAdminMethods(protocol: Protocol, getCatalog: GetC
|
|
|
100
100
|
default_schema: result.default_schema ?? "main",
|
|
101
101
|
settings: result.settings ?? [],
|
|
102
102
|
secret_types: result.secret_types ?? [],
|
|
103
|
+
attach_catalogs: result.attach_catalogs ?? [],
|
|
103
104
|
comment: result.comment ?? null,
|
|
104
105
|
tags: result.tags ?? {},
|
|
105
106
|
// True so DuckDB will route catalog_table_column_statistics_get RPCs
|
package/src/types.ts
CHANGED
|
@@ -62,6 +62,20 @@ export const VGI_CONST_TRUE = "true";
|
|
|
62
62
|
// Per-argument description (UTF-8; presence-only). `vgi_doc_*` prefix reserved.
|
|
63
63
|
export const VGI_DOC_KEY = "vgi_doc";
|
|
64
64
|
|
|
65
|
+
// Per-argument constraint metadata for agent discovery. All presence-only
|
|
66
|
+
// (omitted when absent) and value-encoded as UTF-8 so the surfaced column type
|
|
67
|
+
// stays uniform regardless of the arg's value type:
|
|
68
|
+
// vgi_default — JSON scalar (the arg's default value; optional args only)
|
|
69
|
+
// vgi_choices — JSON array (the closed set of allowed values)
|
|
70
|
+
// vgi_range — interval notation built from ge/le/gt/lt (e.g. "[0, 100]",
|
|
71
|
+
// "(0, +inf)", "[1, 10)"); a discovery surface, not raw bounds
|
|
72
|
+
// vgi_pattern — raw regex the value must match (open set)
|
|
73
|
+
// Kept byte-for-byte in sync with the C++ reader and the Python/other SDKs.
|
|
74
|
+
export const VGI_DEFAULT_KEY = "vgi_default";
|
|
75
|
+
export const VGI_CHOICES_KEY = "vgi_choices";
|
|
76
|
+
export const VGI_RANGE_KEY = "vgi_range";
|
|
77
|
+
export const VGI_PATTERN_KEY = "vgi_pattern";
|
|
78
|
+
|
|
65
79
|
export interface TableCardinality {
|
|
66
80
|
estimate: number | null;
|
|
67
81
|
max: number | null;
|