@gonvex/cli 0.5.2-staging.2 → 0.5.2-staging.20

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.
@@ -1,572 +0,0 @@
1
- //#region ../../packages/module-sdk/dist/index.js
2
- const freeze = (value) => Object.freeze(value);
3
- /** Constructors for the language-neutral schema subset. */
4
- const schema = {
5
- string(options = {}) {
6
- return freeze({
7
- kind: "string",
8
- ...options
9
- });
10
- },
11
- email() {
12
- return freeze({
13
- kind: "string",
14
- format: "email"
15
- });
16
- },
17
- uri() {
18
- return freeze({
19
- kind: "string",
20
- format: "uri"
21
- });
22
- },
23
- uuid() {
24
- return freeze({
25
- kind: "string",
26
- format: "uuid"
27
- });
28
- },
29
- datetime() {
30
- return freeze({
31
- kind: "string",
32
- format: "datetime"
33
- });
34
- },
35
- number(options = {}) {
36
- return freeze({
37
- kind: "number",
38
- ...options
39
- });
40
- },
41
- integer(options = {}) {
42
- return freeze({
43
- kind: "number",
44
- integer: true,
45
- ...options
46
- });
47
- },
48
- boolean() {
49
- return freeze({ kind: "boolean" });
50
- },
51
- null() {
52
- return freeze({ kind: "null" });
53
- },
54
- any() {
55
- return freeze({ kind: "any" });
56
- },
57
- id(entity) {
58
- if (!entity.trim()) throw new Error("schema.id requires an entity name");
59
- return freeze({
60
- kind: "id",
61
- entity
62
- });
63
- },
64
- literal(value) {
65
- return freeze({
66
- kind: "literal",
67
- value
68
- });
69
- },
70
- array(items) {
71
- return freeze({
72
- kind: "array",
73
- items
74
- });
75
- },
76
- object(fields, options = {}) {
77
- return freeze({
78
- kind: "object",
79
- fields: freeze({ ...fields }),
80
- ...options
81
- });
82
- },
83
- record(values) {
84
- return freeze({
85
- kind: "record",
86
- values
87
- });
88
- },
89
- optional(value) {
90
- return freeze({
91
- kind: "optional",
92
- value
93
- });
94
- }
95
- };
96
- const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
97
- const validateOfflinePolicy = (value, path) => {
98
- if (!isRecord(value) || value.mode !== "forbidden" && value.mode !== "allowed" && value.mode !== "onlineOnly") throw new Error(`reducer ${path} must declare a valid offline policy`);
99
- if (value.mode === "onlineOnly" && (typeof value.reason !== "string" || !value.reason.trim())) throw new Error(`reducer ${path} onlineOnly policy requires a reason`);
100
- if (value.mode === "allowed" && value.conflict !== void 0 && value.conflict !== "reject" && value.conflict !== "expectedVersion" && value.conflict !== "merge") throw new Error(`reducer ${path} has an invalid offline conflict policy`);
101
- };
102
- const validateOptimisticTransaction = (value, path) => {
103
- if (!isRecord(value) || !Array.isArray(value.effects) || value.effects.length === 0) throw new Error(`reducer ${path} optimistic metadata must contain a non-empty effects array`);
104
- if (value.expectedRevision !== void 0 && (typeof value.expectedRevision !== "number" || !Number.isSafeInteger(value.expectedRevision) || value.expectedRevision < 0)) throw new Error(`reducer ${path} optimistic expectedRevision must be a non-negative integer`);
105
- for (const effect of value.effects) {
106
- if (!isRecord(effect) || effect.operation !== "patch" && effect.operation !== "upsert" && effect.operation !== "delete") throw new Error(`reducer ${path} has an invalid optimistic effect`);
107
- if (typeof effect.entity !== "string" || !effect.entity.trim()) throw new Error(`reducer ${path} optimistic effects require an entity`);
108
- if (typeof effect.id === "string" && !effect.id.trim() || typeof effect.id !== "string" && (!Array.isArray(effect.id) || effect.id.length === 0 || effect.id.some((part) => typeof part !== "string" || !part.trim()))) throw new Error(`reducer ${path} optimistic effects require a string id or id references`);
109
- if ((effect.operation === "patch" || effect.operation === "upsert") && !isRecord(effect.operation === "patch" ? effect.fields : effect.value)) throw new Error(`reducer ${path} optimistic ${effect.operation} effects require an object value`);
110
- }
111
- };
112
- const validateReplicaCollection = (value, path) => {
113
- if (!isRecord(value) || typeof value.table !== "string" || !value.table.trim() || typeof value.key !== "string" || !value.key.trim() || !Array.isArray(value.columns) || value.columns.some((column) => typeof column !== "string" || !column.trim())) throw new Error(`replica collection ${path} requires a table, key, and columns`);
114
- for (const field of [
115
- "maxRows",
116
- "maxBytes",
117
- "retentionMs"
118
- ]) {
119
- const budget = value[field];
120
- if (budget !== void 0 && (typeof budget !== "number" || !Number.isSafeInteger(budget) || budget <= 0)) throw new Error(`replica collection ${path} ${field} must be a positive integer`);
121
- }
122
- if (value.mode !== void 0 && value.mode !== "eager" && value.mode !== "progressive") throw new Error(`replica collection ${path} has an invalid completeness mode`);
123
- if (value.orderDirection !== void 0 && value.orderDirection !== "asc" && value.orderDirection !== "desc") throw new Error(`replica collection ${path} has an invalid order direction`);
124
- };
125
- const validateActionCapabilities = (profile, value, path) => {
126
- if (value === void 0) return;
127
- if (!isRecord(value)) throw new Error(`action ${path} capabilities must be an object`);
128
- const allowed = /* @__PURE__ */ new Set([
129
- "networkOrigins",
130
- "secrets",
131
- "tools",
132
- "scheduler",
133
- "storage",
134
- "sandbox",
135
- "functions"
136
- ]);
137
- for (const field of Object.keys(value)) if (!allowed.has(field)) throw new Error(`action ${path} capabilities has unsupported field ${field}`);
138
- if (value.networkOrigins !== void 0) {
139
- if (!Array.isArray(value.networkOrigins) || value.networkOrigins.length === 0) throw new Error(`action ${path} networkOrigins must be a non-empty array`);
140
- const seen = /* @__PURE__ */ new Set();
141
- for (const origin of value.networkOrigins) {
142
- if (typeof origin !== "string") throw new Error(`action ${path} networkOrigins must contain strings`);
143
- let parsed;
144
- try {
145
- parsed = new URL(origin);
146
- } catch {
147
- throw new Error(`action ${path} network origin ${JSON.stringify(origin)} is invalid`);
148
- }
149
- if (parsed.protocol !== "https:" && parsed.protocol !== "http:" || parsed.origin !== origin || parsed.username || parsed.password) throw new Error(`action ${path} network origin ${JSON.stringify(origin)} must be an exact HTTP(S) origin`);
150
- if (seen.has(origin)) throw new Error(`action ${path} declares duplicate network origin ${origin}`);
151
- seen.add(origin);
152
- }
153
- }
154
- if (value.secrets !== void 0) {
155
- if (!Array.isArray(value.secrets) || value.secrets.some((name) => typeof name !== "string" || !/^[A-Z][A-Z0-9_]*$/.test(name))) throw new Error(`action ${path} secrets must be uppercase environment names`);
156
- }
157
- if (value.tools !== void 0) {
158
- if (profile !== "agent") throw new Error(`action ${path} tools require profile "agent"`);
159
- if (!isRecord(value.tools) || Object.keys(value.tools).length === 0) throw new Error(`agent action ${path} tools must be a non-empty object`);
160
- for (const [name, binding] of Object.entries(value.tools)) if (!/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(name) || !isRecord(binding) || binding.kind !== "query" && binding.kind !== "reducer" || typeof binding.function !== "string" || !binding.function.trim()) throw new Error(`agent action ${path} has an invalid tool binding ${JSON.stringify(name)}`);
161
- }
162
- if (value.scheduler !== void 0 && value.scheduler !== true) throw new Error(`action ${path} scheduler must be true when declared`);
163
- if (value.storage !== void 0 && value.storage !== true) throw new Error(`action ${path} storage must be true when declared`);
164
- if (value.functions !== void 0) {
165
- if (profile !== "agent") throw new Error(`action ${path} functions require profile "agent"`);
166
- if (value.functions !== true) throw new Error(`action ${path} functions must be true when declared`);
167
- }
168
- if (value.sandbox !== void 0) {
169
- if (profile !== "agent") throw new Error(`action ${path} sandbox requires profile "agent"`);
170
- if (!isRecord(value.sandbox)) throw new Error(`action ${path} sandbox must be an object`);
171
- for (const field of Object.keys(value.sandbox)) if (field !== "duckdb") throw new Error(`action ${path} sandbox has unsupported field ${field}`);
172
- if (value.sandbox.duckdb !== void 0 && value.sandbox.duckdb !== true) throw new Error(`action ${path} sandbox.duckdb must be true when declared`);
173
- }
174
- };
175
- const validateStructuredQueryPlan = (value, path) => {
176
- if (!isRecord(value) || typeof value.table !== "string" || !value.table.trim() || typeof value.key !== "string" || !value.key.trim() || !Array.isArray(value.columns) || value.columns.length === 0 || value.columns.some((column) => typeof column !== "string" || !column.trim())) throw new Error(`one-shot query ${path} requires a structured live query plan with a table, key, and columns`);
177
- if (!value.columns.includes(value.key)) throw new Error(`one-shot query ${path} live query plan columns must include its key`);
178
- if (value.filters !== void 0) {
179
- if (!isRecord(value.filters) || typeof value.filters.argument !== "string" || !value.filters.argument.trim() || !Array.isArray(value.filters.allowedColumns) || value.filters.allowedColumns.length === 0 || value.filters.allowedColumns.some((column) => typeof column !== "string" || !column.trim()) || !Array.isArray(value.filters.allowedOperators) || value.filters.allowedOperators.length === 0) throw new Error(`structured query plan ${path} filters must declare an argument, allowed columns, and allowed operators`);
180
- const operators = /* @__PURE__ */ new Set([
181
- "contains",
182
- "notContains",
183
- "equals",
184
- "notEquals",
185
- "startsWith",
186
- "endsWith",
187
- "empty",
188
- "notEmpty",
189
- "oneOf",
190
- "lessThan",
191
- "lessThanOrEqual",
192
- "greaterThan",
193
- "greaterThanOrEqual",
194
- "inRange"
195
- ]);
196
- if (value.filters.allowedOperators.some((operator) => typeof operator !== "string" || !operators.has(operator))) throw new Error(`structured query plan ${path} filters contains an unsupported operator`);
197
- }
198
- };
199
- const visibilityOperators = /* @__PURE__ */ new Set([
200
- "public",
201
- "permission",
202
- "role",
203
- "eqContext",
204
- "inSet",
205
- "and",
206
- "or",
207
- "not"
208
- ]);
209
- const visibilityContexts = /* @__PURE__ */ new Set([
210
- "account.id",
211
- "member.id",
212
- "tenant.id"
213
- ]);
214
- const validateExactObject = (value, path, fields) => {
215
- if (!isRecord(value)) throw new Error(`${path} must be an object`);
216
- const allowed = new Set(fields);
217
- const unexpected = Object.keys(value).find((field) => !allowed.has(field));
218
- if (unexpected !== void 0) throw new Error(`${path} has unsupported field ${unexpected}`);
219
- };
220
- const requireVisibilityString = (value, path) => {
221
- if (typeof value !== "string" || !value.trim()) throw new Error(`${path} must be a non-empty string`);
222
- return value;
223
- };
224
- const validateVisibilityContext = (value, path) => {
225
- if (typeof value !== "string" || !visibilityContexts.has(value)) throw new Error(`${path} must be account.id, member.id, or tenant.id`);
226
- return value;
227
- };
228
- const validateVisibilityExpression = (value, path, sets, ancestors = /* @__PURE__ */ new Set()) => {
229
- validateExactObject(value, path, [
230
- "operator",
231
- "column",
232
- "context",
233
- "set",
234
- "value",
235
- "children"
236
- ]);
237
- if (ancestors.has(value)) throw new Error(`${path} contains a cycle`);
238
- const operator = value.operator;
239
- if (typeof operator !== "string" || !visibilityOperators.has(operator)) throw new Error(`${path}.operator is unsupported`);
240
- const nested = new Set(ancestors);
241
- nested.add(value);
242
- switch (operator) {
243
- case "public":
244
- validateExactObject(value, path, ["operator"]);
245
- return;
246
- case "permission":
247
- case "role":
248
- validateExactObject(value, path, ["operator", "value"]);
249
- requireVisibilityString(value.value, `${path}.value`);
250
- return;
251
- case "eqContext":
252
- validateExactObject(value, path, [
253
- "operator",
254
- "column",
255
- "context"
256
- ]);
257
- requireVisibilityString(value.column, `${path}.column`);
258
- validateVisibilityContext(value.context, `${path}.context`);
259
- return;
260
- case "inSet": {
261
- validateExactObject(value, path, [
262
- "operator",
263
- "column",
264
- "set"
265
- ]);
266
- requireVisibilityString(value.column, `${path}.column`);
267
- const set = requireVisibilityString(value.set, `${path}.set`);
268
- if (!Object.prototype.hasOwnProperty.call(sets, set)) throw new Error(`${path}.set references unknown visibility set ${set}`);
269
- return;
270
- }
271
- case "and":
272
- case "or":
273
- validateExactObject(value, path, ["operator", "children"]);
274
- if (!Array.isArray(value.children) || value.children.length === 0) throw new Error(`${path}.${operator} requires children`);
275
- value.children.forEach((child, index) => validateVisibilityExpression(child, `${path}.children[${index}]`, sets, nested));
276
- return;
277
- case "not":
278
- validateExactObject(value, path, ["operator", "children"]);
279
- if (!Array.isArray(value.children) || value.children.length !== 1) throw new Error(`${path}.not requires exactly one child`);
280
- validateVisibilityExpression(value.children[0], `${path}.children[0]`, sets, nested);
281
- return;
282
- }
283
- };
284
- const validateVisibilityPlan = (value, path) => {
285
- validateExactObject(value, path, [
286
- "table",
287
- "key",
288
- "sets",
289
- "where"
290
- ]);
291
- requireVisibilityString(value.table, `${path}.table`);
292
- requireVisibilityString(value.key, `${path}.key`);
293
- if (!isRecord(value.sets)) throw new Error(`${path}.sets must be an object`);
294
- for (const [name, candidate] of Object.entries(value.sets)) {
295
- requireVisibilityString(name, `${path}.sets key`);
296
- const setPath = `${path}.sets.${name}`;
297
- validateExactObject(candidate, setPath, [
298
- "table",
299
- "alias",
300
- "select",
301
- "selectFrom",
302
- "joins",
303
- "where"
304
- ]);
305
- requireVisibilityString(candidate.table, `${setPath}.table`);
306
- if (candidate.alias !== void 0) requireVisibilityString(candidate.alias, `${setPath}.alias`);
307
- requireVisibilityString(candidate.select, `${setPath}.select`);
308
- if (candidate.selectFrom !== void 0) requireVisibilityString(candidate.selectFrom, `${setPath}.selectFrom`);
309
- if (!Array.isArray(candidate.joins)) throw new Error(`${setPath}.joins must be an array`);
310
- const joins = candidate.joins;
311
- joins.forEach((join, index) => {
312
- const joinPath = `${setPath}.joins[${index}]`;
313
- validateExactObject(join, joinPath, [
314
- "table",
315
- "alias",
316
- "leftAlias",
317
- "leftColumn",
318
- "rightColumn"
319
- ]);
320
- requireVisibilityString(join.table, `${joinPath}.table`);
321
- if (join.alias !== void 0) requireVisibilityString(join.alias, `${joinPath}.alias`);
322
- if (join.leftAlias !== void 0) requireVisibilityString(join.leftAlias, `${joinPath}.leftAlias`);
323
- requireVisibilityString(join.leftColumn, `${joinPath}.leftColumn`);
324
- requireVisibilityString(join.rightColumn, `${joinPath}.rightColumn`);
325
- });
326
- const occurrences = [{
327
- table: candidate.table,
328
- alias: candidate.alias ?? candidate.table,
329
- explicit: candidate.alias !== void 0
330
- }, ...joins.map((join) => ({
331
- table: join.table,
332
- alias: join.alias ?? join.table,
333
- explicit: join.alias !== void 0
334
- }))];
335
- const aliases = /* @__PURE__ */ new Set();
336
- const tableCounts = /* @__PURE__ */ new Map();
337
- for (const occurrence of occurrences) tableCounts.set(occurrence.table, (tableCounts.get(occurrence.table) ?? 0) + 1);
338
- occurrences.forEach((occurrence, index) => {
339
- if ((tableCounts.get(occurrence.table) ?? 0) > 1 && !occurrence.explicit) throw new Error(`${setPath} repeats table ${occurrence.table}; every occurrence requires an explicit alias`);
340
- if (aliases.has(occurrence.alias)) throw new Error(`${setPath} repeats logical alias ${occurrence.alias}`);
341
- if (index > 0) {
342
- const leftAlias = joins[index - 1].leftAlias;
343
- if (leftAlias !== void 0 && !aliases.has(leftAlias)) throw new Error(`${setPath}.joins[${index - 1}].leftAlias must reference an earlier occurrence`);
344
- }
345
- aliases.add(occurrence.alias);
346
- });
347
- const selectFrom = candidate.selectFrom ?? occurrences[0].alias;
348
- if (!aliases.has(selectFrom)) throw new Error(`${setPath}.selectFrom references unknown alias ${selectFrom}`);
349
- if (!Array.isArray(candidate.where)) throw new Error(`${setPath}.where must be an array`);
350
- candidate.where.forEach((constraint, index) => {
351
- const constraintPath = `${setPath}.where[${index}]`;
352
- validateExactObject(constraint, constraintPath, [
353
- "table",
354
- "column",
355
- "context"
356
- ]);
357
- requireVisibilityString(constraint.table, `${constraintPath}.table`);
358
- if (!aliases.has(constraint.table)) throw new Error(`${constraintPath}.table references unknown alias ${constraint.table}`);
359
- requireVisibilityString(constraint.column, `${constraintPath}.column`);
360
- validateVisibilityContext(constraint.context, `${constraintPath}.context`);
361
- });
362
- }
363
- validateVisibilityExpression(value.where, `${path}.where`, value.sets);
364
- };
365
- const freezeVisibilityExpression = (expression) => freeze({
366
- ...expression,
367
- children: expression.children === void 0 ? void 0 : freeze(expression.children.map(freezeVisibilityExpression))
368
- });
369
- const freezeVisibilityPlan = (plan) => {
370
- const sets = {};
371
- for (const name of Object.keys(plan.sets).sort()) {
372
- const set = plan.sets[name];
373
- sets[name] = freeze({
374
- ...set,
375
- joins: freeze(set.joins.map((join) => freeze({ ...join }))),
376
- where: freeze(set.where.map((constraint) => freeze({ ...constraint })))
377
- });
378
- }
379
- return freeze({
380
- ...plan,
381
- sets: freeze(sets),
382
- where: freezeVisibilityExpression(plan.where)
383
- });
384
- };
385
- /** Declare and validate one source table's language-neutral visibility plan. */
386
- function visibility(options) {
387
- validateVisibilityPlan(options, "visibility");
388
- return freezeVisibilityPlan(options);
389
- }
390
- const executableOptions = (options) => freeze({ ...options });
391
- const queryDefinition = (options, deliveryOverride) => {
392
- const liveQueryPlan = options.liveQueryPlan;
393
- const replica = options.replica;
394
- const delivery = deliveryOverride ?? options.delivery ?? "oneShot";
395
- if (delivery === "live" && !liveQueryPlan) throw new Error("live query requires a live query plan");
396
- if (delivery === "oneShot") {
397
- if (!liveQueryPlan) throw new Error("one-shot query requires a structured live query plan");
398
- validateStructuredQueryPlan(liveQueryPlan, "<export>");
399
- }
400
- if (delivery === "replica") {
401
- if (!replica) throw new Error("replica collection requires a replica definition");
402
- validateReplicaCollection(replica, "<export>");
403
- }
404
- return freeze({
405
- kind: "query",
406
- internal: options.internal,
407
- delivery,
408
- liveQueryPlan,
409
- replica,
410
- options: executableOptions(options),
411
- handler: options.run
412
- });
413
- };
414
- /** Declare an executable one-shot, live, or replica query export. */
415
- function query(options = {}) {
416
- return queryDefinition(options);
417
- }
418
- /** Declare an executable live query export with a structured live plan. */
419
- function liveQuery(options = {}) {
420
- return queryDefinition({
421
- ...options,
422
- delivery: "live"
423
- }, "live");
424
- }
425
- const reducerDefinition = (options, internal = false) => {
426
- validateOfflinePolicy(options.offline, "<export>");
427
- if (options.optimistic !== void 0) validateOptimisticTransaction(options.optimistic, "<export>");
428
- if (options.interactive === false && options.optimistic !== void 0) throw new Error("non-interactive reducer <export> cannot declare optimistic metadata");
429
- if (options.interactive !== false && options.optimistic === void 0 && !options.nonOptimisticReason?.trim()) throw new Error("interactive reducer <export> requires an optimistic transaction or nonOptimisticReason");
430
- return freeze({
431
- kind: "reducer",
432
- internal: internal || options.internal,
433
- options: executableOptions(options),
434
- handler: options.run
435
- });
436
- };
437
- /** Declare an executable public reducer export. */
438
- function reducer(options) {
439
- return reducerDefinition(options);
440
- }
441
- /** Declare an executable action export. */
442
- function action(options = {}) {
443
- validateActionCapabilities(options.profile ?? "standard", options.capabilities, options.name?.trim() || "<export>");
444
- return freeze({
445
- kind: "action",
446
- options: executableOptions(options),
447
- handler: options.run
448
- });
449
- }
450
- //#endregion
451
- //#region gonvex/messages.ts
452
- const messagesVisibility = visibility({
453
- table: "messages",
454
- key: "id",
455
- sets: {},
456
- where: { operator: "public" }
457
- });
458
- const list = liveQuery({
459
- args: schema.object({}),
460
- result: schema.array(schema.object({
461
- id: schema.id("messages"),
462
- body: schema.string(),
463
- author: schema.string(),
464
- created_at: schema.datetime()
465
- })),
466
- liveQueryPlan: {
467
- table: "messages",
468
- key: "id",
469
- columns: [
470
- "id",
471
- "body",
472
- "author",
473
- "created_at"
474
- ],
475
- sort: {
476
- defaultColumn: "created_at",
477
- defaultDirection: "asc",
478
- allowedColumns: ["created_at"]
479
- }
480
- },
481
- run: async () => []
482
- });
483
- const get = query({
484
- interactive: true,
485
- description: "Read one visible message by ID.",
486
- agent: {
487
- tags: ["messages"],
488
- confirmation: "none"
489
- },
490
- args: schema.object({ id: schema.id("messages") }),
491
- result: schema.array(schema.object({
492
- id: schema.id("messages"),
493
- body: schema.string(),
494
- author: schema.string(),
495
- created_at: schema.datetime()
496
- })),
497
- liveQueryPlan: {
498
- table: "messages",
499
- key: "id",
500
- columns: [
501
- "id",
502
- "body",
503
- "author",
504
- "created_at"
505
- ],
506
- where: {
507
- operator: "eq",
508
- column: "id",
509
- value: { argument: "id" }
510
- }
511
- },
512
- run: async () => []
513
- });
514
- const send = reducer({
515
- interactive: true,
516
- description: "Send a message as the acting tenant member.",
517
- agent: {
518
- tags: ["messages"],
519
- confirmation: "none"
520
- },
521
- args: schema.object({ body: schema.string() }),
522
- result: schema.object({
523
- id: schema.id("messages"),
524
- body: schema.string(),
525
- author: schema.string(),
526
- created_at: schema.datetime()
527
- }),
528
- offline: {
529
- mode: "onlineOnly",
530
- reason: "server assigns the message id"
531
- },
532
- nonOptimisticReason: "server assigns the message id",
533
- run: async ({ db, member }, args) => {
534
- if (!member || member.status !== "active") throw new Error("active tenant membership required");
535
- return db.insert("messages", {
536
- id: crypto.randomUUID(),
537
- body: args.body,
538
- author: member.displayName ?? member.id
539
- });
540
- }
541
- });
542
- const echo = action({
543
- interactive: true,
544
- description: "Return the supplied message without changing durable state.",
545
- agent: {
546
- tags: ["messages"],
547
- confirmation: "none"
548
- },
549
- args: schema.object({ message: schema.string() }),
550
- result: schema.object({ message: schema.string() }),
551
- run: async (_ctx, args) => args
552
- });
553
- /** Minimal reference for testing permission-equivalent delegated invocation. */
554
- const agentInvoke = action({
555
- profile: "agent",
556
- interactive: false,
557
- description: "Invoke one function from the active interactive catalog.",
558
- capabilities: { functions: true },
559
- args: schema.object({
560
- path: schema.string(),
561
- args: schema.any(),
562
- artifactHash: schema.string()
563
- }),
564
- result: schema.any(),
565
- run: (ctx, args) => ctx.functions.invoke({
566
- path: args.path,
567
- args: args.args,
568
- artifactHash: args.artifactHash
569
- })
570
- });
571
- //#endregion
572
- export { agentInvoke, echo, get, list, messagesVisibility, send };