@anchrd/colab-sdk 0.1.29 → 0.1.31

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.
@@ -0,0 +1,442 @@
1
+ import { z } from "zod";
2
+ import { GadgetFile, GadgetFilePath, GadgetLevel, GadgetTestRun } from "../gadgets/gadgets.js";
3
+ import { idSchema } from "../ids/ids.js";
4
+ import { Flag, Limit } from "../list-input.js";
5
+ import { NodeId, NodePath, NodePerson } from "../nodes/nodes.js";
6
+ import { IdempotencyKey, Rev } from "../primitives/primitives.js";
7
+ import { RunId } from "../runs/runs.js";
8
+ import { UserId } from "../users/users.js";
9
+ // Sources (#900, E151, Nodes › Quelle): a node that fetches data from outside on a schedule and keeps
10
+ // what came as items. Its files (`source.json`, `source.js`, `tests/**`) with a draft and published
11
+ // versions like a gadget, its queries, its runs and its items. The inputs of
12
+ // `intelligence_source_*` and their answers.
13
+ const SourceId = NodeId.describe("The source's id, a `node_…` of kind source.");
14
+ export const QueryId = idSchema("query").describe("A query of the source, `query_…`.");
15
+ export const ItemId = idSchema("item").describe("An item of the source, `item_…`.");
16
+ // ---- The manifest `source.json`, schema `colab:source/1` ----
17
+ export const sourceSchema = "colab:source/1";
18
+ // The column types of a table (Nodes › Tabelle): a source's fields take exactly these.
19
+ export const sourceFieldTypes = ["text", "number", "date", "email", "chip"];
20
+ export const SourceFieldType = z.enum(sourceFieldTypes);
21
+ // Cleaning beyond the type (Nodes › Quelle › Bereinigung): a company's name in its usual spelling,
22
+ // an amount of money as a number.
23
+ export const sourceCleans = ["company", "money"];
24
+ // A path into one entry: `$`, then `.name`, `[0]`, `["name"]`, and `[*]` for every element.
25
+ export const SourcePath = z
26
+ .string()
27
+ .min(1)
28
+ .max(300)
29
+ .regex(/^\$(\.[A-Za-z_$][A-Za-z0-9_$-]*|\[\d+\]|\[\*\]|\["[^"\]]+"\])*$/, 'A path is $ followed by .name, [0], ["name"] or [*], like $.data[*] or $.company.name.');
30
+ const Word = z.string().regex(/^[a-z][A-Za-z0-9]{0,39}$/, "A key is a word like company or since.");
31
+ const SecretName = z
32
+ .string()
33
+ .regex(/^[A-Z][A-Z0-9_]{0,63}$/)
34
+ .describe("A secret's name in capitals, such as PORTAL_KEY.");
35
+ export const SourceField = z.strictObject({
36
+ label: z.string().min(1).max(100),
37
+ type: SourceFieldType,
38
+ path: SourcePath,
39
+ clean: z.array(z.enum(sourceCleans)).max(2).optional(),
40
+ });
41
+ export const SourceParam = z.strictObject({
42
+ label: z.string().min(1).max(100).optional(),
43
+ type: z.enum(["text", "number", "date"]).optional(),
44
+ // A query picks one of these.
45
+ enum: z.array(z.string().min(1).max(200)).min(1).max(200).optional(),
46
+ required: z.boolean().optional(),
47
+ // Set by the run itself: the moment the last successful run of the query started.
48
+ from: z.literal("lastRun").optional(),
49
+ default: z.union([z.string().max(200), z.number()]).optional(),
50
+ });
51
+ // How the bridge sets the key on every request; the code never sees it.
52
+ export const SourceAccess = z.discriminatedUnion("kind", [
53
+ z.strictObject({ kind: z.literal("bearer"), secret: SecretName }),
54
+ z.strictObject({
55
+ kind: z.literal("header"),
56
+ name: z.string().regex(/^[A-Za-z0-9-]{1,64}$/),
57
+ prefix: z.string().max(40).optional(),
58
+ secret: SecretName,
59
+ }),
60
+ z.strictObject({ kind: z.literal("basic"), username: SecretName, password: SecretName }),
61
+ z.strictObject({
62
+ kind: z.literal("query"),
63
+ name: z.string().regex(/^[A-Za-z0-9_.-]{1,64}$/),
64
+ secret: SecretName,
65
+ }),
66
+ z.strictObject({ kind: z.literal("none") }),
67
+ ]);
68
+ export const SourcePaging = z.discriminatedUnion("type", [
69
+ // `?<param>=1`, 2, … until a page has no entries or `max` pages were read.
70
+ z.strictObject({
71
+ type: z.literal("page"),
72
+ param: z.string().regex(/^[A-Za-z0-9_.-]{1,64}$/),
73
+ start: z.number().int().min(0).max(1).optional(),
74
+ max: z.number().int().min(1).max(5),
75
+ }),
76
+ // The answer names the next page's address under `path`, until it names none.
77
+ z.strictObject({
78
+ type: z.literal("next"),
79
+ path: SourcePath,
80
+ max: z.number().int().min(1).max(5),
81
+ }),
82
+ ]);
83
+ export const SourceManifest = z.strictObject({
84
+ $schema: z.literal(sourceSchema),
85
+ name: z.string().min(1).max(200),
86
+ description: z.string().max(2000).optional(),
87
+ // json and rss run through Colab's own interpreter, code through `source.js`.
88
+ kind: z.enum(["json", "rss", "code"]),
89
+ // Every request's address starts here, an `https` address on one of the hosts.
90
+ base: z.string().min(1).max(500),
91
+ // The only hosts a request reaches: host names, never an address.
92
+ hosts: z.array(z.string().min(1).max(253)).min(1).max(10),
93
+ access: SourceAccess.optional(),
94
+ secrets: z
95
+ .record(SecretName, z.strictObject({ label: z.string().min(1).max(100), help: z.string().max(500).optional() }))
96
+ .optional(),
97
+ params: z.record(Word, SourceParam).optional(),
98
+ // Below `base`; `{{params.name}}` puts in a query's parameter.
99
+ request: z
100
+ .strictObject({
101
+ path: z.string().min(1).max(2000),
102
+ query: z.record(z.string().min(1).max(64), z.string().max(500)).optional(),
103
+ })
104
+ .optional(),
105
+ paging: SourcePaging.optional(),
106
+ // Where the entries stand in an answer; an rss source reads its items itself.
107
+ items: SourcePath.optional(),
108
+ // The one required field: what an entry is recognised by again.
109
+ ref: SourcePath,
110
+ fields: z.record(Word, SourceField).optional(),
111
+ });
112
+ export const sourceManifestPath = "source.json";
113
+ export const sourceCodePath = "source.js";
114
+ // A run's limits (Nodes › Quelle › Grenzen).
115
+ export const sourceLimits = {
116
+ timeoutMs: 10_000,
117
+ bytes: 2 * 1024 * 1024,
118
+ pages: 5,
119
+ // A `source.js` sends at most this many requests per run (a list, then a detail per entry).
120
+ requests: 50,
121
+ items: 1000,
122
+ };
123
+ export const sourceKeepDays = [30, 90, 180];
124
+ const KeepDays = z
125
+ .union([z.literal(30), z.literal(90), z.literal(180)])
126
+ .describe("How many days the items stay: 30, 90 or 180.");
127
+ const LogDays = z
128
+ .union([z.literal(7), z.literal(14), z.literal(30)])
129
+ .describe("How many days the runs stay: 7, 14 or 30.");
130
+ // ---- Queries ----
131
+ export const sourceEvery = ["hour", "day", "week"];
132
+ const TimeOfDay = z
133
+ .string()
134
+ .regex(/^([01]\d|2[0-3]):00$/, "A time is a full hour, HH:00, like 07:00.");
135
+ export const SourceSchedule = z
136
+ .strictObject({
137
+ every: z.enum(sourceEvery).describe("hour, day or week."),
138
+ time: TimeOfDay.optional().describe("The hour of a daily or weekly run, like 07:00."),
139
+ day: z
140
+ .enum(["monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday"])
141
+ .optional()
142
+ .describe("The weekday of a weekly run."),
143
+ zone: z
144
+ .string()
145
+ .max(64)
146
+ .optional()
147
+ .describe("The time zone of time, Europe/Berlin if left out."),
148
+ })
149
+ .refine((value) => value.every === "hour" || value.time !== undefined, {
150
+ message: "A daily or weekly run needs its time.",
151
+ path: ["time"],
152
+ })
153
+ .refine((value) => value.every === "week" || value.day === undefined, {
154
+ message: "Only a weekly run takes a day.",
155
+ path: ["day"],
156
+ })
157
+ .refine((value) => value.every !== "week" || value.day !== undefined, {
158
+ message: "A weekly run needs its day.",
159
+ path: ["day"],
160
+ });
161
+ export const SourceWhere = z.strictObject({
162
+ field: Word,
163
+ op: z.enum(["eq", "ne", "gte", "lte", "contains"]),
164
+ value: z.union([z.string().max(200), z.number()]),
165
+ });
166
+ const ParamValues = z
167
+ .record(Word, z.union([z.string().max(200), z.number()]))
168
+ .describe("The values of the source's params by name; a param with an enum takes one of it.");
169
+ // ---- Tool inputs ----
170
+ const FileContent = z.string().describe("The file's whole text.");
171
+ export const SourceCreateInput = z.strictObject({
172
+ parentId: NodeId.nullable().describe("The folder to create the source in, one you can write to; null creates it on the top level of Shared."),
173
+ name: z.string().max(200).describe("The name as people read it."),
174
+ files: z
175
+ .record(GadgetFilePath, FileContent)
176
+ .optional()
177
+ .describe("The first files by path: source.json, source.js (only for kind code), tests/*.test.js, tests/fixtures/*, icon.svg. They become the draft. Leaving it out creates an empty source."),
178
+ idempotencyKey: IdempotencyKey,
179
+ });
180
+ export const SourceVersionRef = z.preprocess((value) => (typeof value === "string" && /^[1-9][0-9]{0,8}$/.test(value) ? Number(value) : value), z.union([z.enum(["live", "draft"]), z.number().int().min(1)]));
181
+ export const SourceGetInput = z.strictObject({
182
+ sourceId: SourceId,
183
+ version: SourceVersionRef.optional().describe("Which state to read: live (the default), draft or a published version's number; both only with the right to change the source."),
184
+ include: z
185
+ .preprocess((value) => (typeof value === "string" ? value.split(",") : value), z
186
+ .array(z.enum(["files"]))
187
+ .min(1)
188
+ .max(1))
189
+ .optional()
190
+ .describe("files: answer the text of every file of that state."),
191
+ });
192
+ export const SourceUpdateInput = z.strictObject({
193
+ sourceId: SourceId,
194
+ files: z
195
+ .record(GadgetFilePath, FileContent.nullable())
196
+ .optional()
197
+ .describe("Files to write into the draft by path, each with its whole new text; null removes one. Files you leave out stay. Without a draft, it starts from the live version."),
198
+ fromVersion: z
199
+ .number()
200
+ .int()
201
+ .min(1)
202
+ .optional()
203
+ .describe("Restore a published version into the draft."),
204
+ discard: z.literal(true).optional().describe("Throw the draft away."),
205
+ settings: z
206
+ .strictObject({
207
+ responsibleId: UserId.nullable().optional(),
208
+ level: GadgetLevel.optional(),
209
+ keepDays: KeepDays.optional(),
210
+ logDays: LogDays.optional(),
211
+ })
212
+ .optional()
213
+ .describe("The settings; they apply at once, not through the draft."),
214
+ rev: Rev,
215
+ });
216
+ export const SourceTestInput = z.strictObject({
217
+ sourceId: SourceId,
218
+ version: z
219
+ .enum(["live", "draft"])
220
+ .optional()
221
+ .describe("draft (the default when there is one) or live."),
222
+ probe: z
223
+ .strictObject({
224
+ queryId: QueryId.optional().describe("Fetch with this query's params."),
225
+ params: ParamValues.optional(),
226
+ })
227
+ .optional()
228
+ .describe("A probe instead of the tests: fetch from the provider for real with that state and answer the items, without storing anything."),
229
+ });
230
+ export const SourcePublishInput = z.strictObject({
231
+ sourceId: SourceId,
232
+ force: z.literal(true).optional().describe("Publish although tests fail. Never for a machine."),
233
+ rev: Rev,
234
+ });
235
+ export const SourceQueryListInput = z.strictObject({
236
+ sourceId: SourceId,
237
+ archived: Flag.optional().describe("true lists the archived queries instead."),
238
+ });
239
+ export const SourceQueryCreateInput = z.strictObject({
240
+ sourceId: SourceId,
241
+ name: z.string().trim().min(1).max(200),
242
+ schedule: SourceSchedule,
243
+ params: ParamValues.optional(),
244
+ where: z
245
+ .array(SourceWhere)
246
+ .max(10)
247
+ .optional()
248
+ .describe("Only if: keep an item only when every condition holds."),
249
+ enabled: z.boolean().optional().describe("Whether it runs on its schedule; true if left out."),
250
+ idempotencyKey: IdempotencyKey,
251
+ });
252
+ export const SourceQueryUpdateInput = z.strictObject({
253
+ sourceId: SourceId,
254
+ queryId: QueryId,
255
+ name: z.string().trim().min(1).max(200).optional(),
256
+ schedule: SourceSchedule.optional(),
257
+ params: ParamValues.optional(),
258
+ where: z.array(SourceWhere).max(10).optional(),
259
+ enabled: z.boolean().optional(),
260
+ rev: z.number().int().min(1).describe("The query's rev as the last read returned it."),
261
+ });
262
+ export const SourceQueryArchiveInput = z.strictObject({ sourceId: SourceId, queryId: QueryId });
263
+ export const SourceQueryRestoreInput = z.strictObject({ sourceId: SourceId, queryId: QueryId });
264
+ export const SourceRunListInput = z.strictObject({
265
+ sourceId: SourceId,
266
+ queryId: QueryId.optional(),
267
+ status: z.enum(["running", "succeeded", "failed"]).optional(),
268
+ cursor: z.string().max(200).optional(),
269
+ limit: Limit.optional(),
270
+ });
271
+ export const SourceRunGetInput = z.strictObject({ sourceId: SourceId, runId: RunId });
272
+ export const SourceRunCreateInput = z.strictObject({
273
+ sourceId: SourceId,
274
+ queryId: QueryId.describe("The query to fetch now (Play)."),
275
+ });
276
+ // Over REST the filter arrives as JSON text in the query string.
277
+ const WhereList = z.preprocess((value) => {
278
+ if (typeof value !== "string")
279
+ return value;
280
+ try {
281
+ return JSON.parse(value);
282
+ }
283
+ catch {
284
+ // Not JSON: a list of one, so the refusal names the condition, not the list.
285
+ return [value];
286
+ }
287
+ }, z.array(SourceWhere).max(10));
288
+ export const SourceItemListInput = z.strictObject({
289
+ sourceId: SourceId,
290
+ queryId: QueryId.optional().describe("Only the items of this query."),
291
+ since: z.iso
292
+ .datetime({ offset: true })
293
+ .optional()
294
+ .describe("Only items fetched at or after this moment. Colab remembers no reader: you say from when."),
295
+ cursor: z
296
+ .string()
297
+ .max(200)
298
+ .optional()
299
+ .describe("The nextCursor of an earlier page; it also works after the last page, for what came since."),
300
+ where: WhereList.optional().describe("Only items whose fields match every condition."),
301
+ limit: Limit.optional(),
302
+ });
303
+ // ---- Answers ----
304
+ export const SourceStep = z.object({
305
+ name: z.string(),
306
+ status: z.enum(["succeeded", "failed"]),
307
+ durationMs: z.number().int(),
308
+ detail: z.string().nullable(),
309
+ });
310
+ export const SourceRunCounts = z.object({
311
+ fetched: z.number().int(),
312
+ new: z.number().int(),
313
+ withoutRef: z.number().int(),
314
+ duplicates: z.number().int(),
315
+ filtered: z.number().int(),
316
+ expired: z.number().int(),
317
+ });
318
+ // Why a run failed: `host` a request to a host the source does not name (sent nowhere), `access`
319
+ // the provider refused the key (401, 403), `provider` it failed otherwise, `code` the source's code
320
+ // or manifest broke.
321
+ export const SourceRunFailure = z.enum(["host", "access", "provider", "code"]);
322
+ export const SourceRun = z.object({
323
+ runId: RunId,
324
+ sourceId: SourceId,
325
+ queryId: QueryId,
326
+ // The workflow instance, `src-<source>-<query>-<time>`: one run per query and moment.
327
+ instance: z.string(),
328
+ // schedule, a person or machine by hand, or a probe against the draft.
329
+ trigger: z.enum(["schedule", "play"]),
330
+ by: NodePerson.nullable(),
331
+ version: z.number().int().nullable(),
332
+ status: z.enum(["running", "succeeded", "failed"]),
333
+ failure: SourceRunFailure.nullable(),
334
+ message: z.string().nullable(),
335
+ counts: SourceRunCounts,
336
+ steps: z.array(SourceStep),
337
+ startedAt: z.iso.datetime(),
338
+ endedAt: z.iso.datetime().nullable(),
339
+ durationMs: z.number().int().nullable(),
340
+ });
341
+ export const SourceRunList = z.object({
342
+ items: z.array(SourceRun),
343
+ nextCursor: z.string().nullable(),
344
+ });
345
+ export const SourceQuery = z.object({
346
+ queryId: QueryId,
347
+ sourceId: SourceId,
348
+ name: z.string(),
349
+ schedule: SourceSchedule,
350
+ params: z.record(z.string(), z.union([z.string(), z.number()])),
351
+ where: z.array(SourceWhere),
352
+ enabled: z.boolean(),
353
+ // Paused after the provider refused the key (401, 403), until a person sets it anew.
354
+ pausedAt: z.iso.datetime().nullable(),
355
+ archivedAt: z.iso.datetime().nullable(),
356
+ lastRun: z
357
+ .object({
358
+ runId: RunId,
359
+ status: z.enum(["running", "succeeded", "failed"]),
360
+ startedAt: z.iso.datetime(),
361
+ new: z.number().int(),
362
+ })
363
+ .nullable(),
364
+ nextRunAt: z.iso.datetime().nullable(),
365
+ rev: z.number().int(),
366
+ });
367
+ export const SourceQueryList = z.object({ items: z.array(SourceQuery) });
368
+ export const SourceItem = z.object({
369
+ itemId: ItemId,
370
+ sourceId: SourceId,
371
+ queryId: QueryId,
372
+ ref: z.string(),
373
+ version: z.number().int().nullable(),
374
+ fetchedAt: z.iso.datetime(),
375
+ // New in the last run of its query.
376
+ fresh: z.boolean(),
377
+ fields: z.record(z.string(), z.union([z.string(), z.number(), z.array(z.string()), z.null()])),
378
+ });
379
+ export const SourceItemList = z.object({
380
+ items: z.array(SourceItem),
381
+ // ⚠️ Never null: the cursor after the last page is the one to ask again with for what comes next.
382
+ nextCursor: z.string(),
383
+ // Whether more pages stand already now.
384
+ more: z.boolean(),
385
+ });
386
+ // The items of a probe or a test, never stored.
387
+ export const SourceProbe = z.object({
388
+ status: z.enum(["succeeded", "failed"]),
389
+ failure: SourceRunFailure.nullable(),
390
+ message: z.string().nullable(),
391
+ counts: SourceRunCounts,
392
+ items: z.array(z.object({ ref: z.string(), fields: SourceItem.shape.fields })),
393
+ });
394
+ export const SourceDetail = z.object({
395
+ sourceId: SourceId,
396
+ name: z.string(),
397
+ hidden: z.boolean(),
398
+ parentId: NodeId.nullable(),
399
+ path: NodePath,
400
+ version: z.union([z.number().int(), z.literal("draft")]).nullable(),
401
+ // Only for whoever may change the source; null for a reader and without a readable source.json.
402
+ manifest: SourceManifest.nullable(),
403
+ // The live fields as the items show them, for every reader: the columns of the view Treffer.
404
+ fields: z.array(z.object({ name: z.string(), label: z.string(), type: SourceFieldType })),
405
+ // A reader gets the fields and the queries' names, never the files.
406
+ files: z.array(GadgetFile),
407
+ queries: z.array(z.object({ queryId: QueryId, name: z.string() })),
408
+ live: z
409
+ .object({ version: z.number().int(), publishedAt: z.iso.datetime(), publishedBy: NodePerson })
410
+ .nullable(),
411
+ draft: z
412
+ .object({
413
+ updatedAt: z.iso.datetime(),
414
+ updatedBy: NodePerson,
415
+ changes: z.array(z.object({ path: z.string(), change: z.enum(["added", "changed", "removed"]) })),
416
+ // Hosts the draft reaches that live does not; the publish shows them.
417
+ newHosts: z.array(z.string()),
418
+ newFields: z.array(z.string()),
419
+ })
420
+ .nullable(),
421
+ test: GadgetTestRun.nullable(),
422
+ settings: z
423
+ .object({
424
+ responsible: NodePerson.nullable(),
425
+ level: GadgetLevel,
426
+ keepDays: z.number().int(),
427
+ logDays: z.number().int(),
428
+ // Names only, never values: which key is set and when. ⚠️ Not `secrets`: `/mcp` strikes every
429
+ // value under such a name.
430
+ credentials: z.array(z.object({ name: z.string(), label: z.string(), setAt: z.iso.datetime().nullable() })),
431
+ })
432
+ .nullable(),
433
+ pausedAt: z.iso.datetime().nullable(),
434
+ rights: z.object({ write: z.boolean() }),
435
+ rev: z.number().int(),
436
+ archivedAt: z.iso.datetime().nullable(),
437
+ });
438
+ // The door of a secret (`PUT /api/intelligence/sources/:sourceId/secrets`, no tool): a person in the
439
+ // browser sets the key, never an AI (Nodes › Quelle › Einstellungen).
440
+ export const SourceSecretsInput = z.strictObject({
441
+ values: z.record(SecretName, z.string().min(1).max(4000).nullable()),
442
+ });
@@ -1,4 +1,4 @@
1
1
  import type { NodeKind } from "../nodes/nodes.js";
2
- export declare const treeKindOrder: readonly ["folder", "document", "table", "board", "gadget", "file", "skill", "goal"];
2
+ export declare const treeKindOrder: readonly ["folder", "document", "table", "board", "gadget", "source", "file", "skill", "goal"];
3
3
  export declare function treeKindRank(kind: NodeKind): number;
4
4
  export declare function compareTreeNames(a: string, b: string): number;
@@ -7,6 +7,7 @@ export const treeKindOrder = [
7
7
  "table",
8
8
  "board",
9
9
  "gadget",
10
+ "source",
10
11
  "file",
11
12
  "skill",
12
13
  "goal",
@@ -15,6 +15,7 @@ export declare const TicketSubject: z.ZodObject<{
15
15
  gadget: "gadget";
16
16
  goal: "goal";
17
17
  skill: "skill";
18
+ source: "source";
18
19
  }>;
19
20
  name: z.ZodString;
20
21
  path: z.ZodObject<{
@@ -42,6 +43,7 @@ export declare const TicketSubjectRef: z.ZodObject<{
42
43
  gadget: "gadget";
43
44
  goal: "goal";
44
45
  skill: "skill";
46
+ source: "source";
45
47
  }>;
46
48
  path: z.ZodObject<{
47
49
  section: z.ZodEnum<{
@@ -48,9 +48,9 @@ export declare const VersionMove: z.ZodObject<{
48
48
  export type VersionMove = z.infer<typeof VersionMove>;
49
49
  export declare const taskVersionChanges: readonly ["title", "text", "assignee", "dates", "labels", "parent", "dependencies", "waiting", "fields"];
50
50
  export declare const TaskVersionChange: z.ZodEnum<{
51
- fields: "fields";
52
51
  title: "title";
53
52
  text: "text";
53
+ fields: "fields";
54
54
  dates: "dates";
55
55
  waiting: "waiting";
56
56
  assignee: "assignee";
@@ -164,9 +164,9 @@ export declare const NodeVersion: z.ZodObject<{
164
164
  comment: z.ZodNullable<z.ZodString>;
165
165
  }, z.core.$strip>>;
166
166
  changes: z.ZodNullable<z.ZodArray<z.ZodEnum<{
167
- fields: "fields";
168
167
  title: "title";
169
168
  text: "text";
169
+ fields: "fields";
170
170
  dates: "dates";
171
171
  waiting: "waiting";
172
172
  assignee: "assignee";
@@ -225,9 +225,9 @@ export declare const NodeVersionList: z.ZodObject<{
225
225
  comment: z.ZodNullable<z.ZodString>;
226
226
  }, z.core.$strip>>;
227
227
  changes: z.ZodNullable<z.ZodArray<z.ZodEnum<{
228
- fields: "fields";
229
228
  title: "title";
230
229
  text: "text";
230
+ fields: "fields";
231
231
  dates: "dates";
232
232
  waiting: "waiting";
233
233
  assignee: "assignee";
@@ -288,9 +288,9 @@ export declare const NodeVersionDetail: z.ZodObject<{
288
288
  comment: z.ZodNullable<z.ZodString>;
289
289
  }, z.core.$strip>>;
290
290
  changes: z.ZodNullable<z.ZodArray<z.ZodEnum<{
291
- fields: "fields";
292
291
  title: "title";
293
292
  text: "text";
293
+ fields: "fields";
294
294
  dates: "dates";
295
295
  waiting: "waiting";
296
296
  assignee: "assignee";
@@ -439,9 +439,9 @@ export declare const NodeVersionExcerpt: z.ZodObject<{
439
439
  comment: z.ZodNullable<z.ZodString>;
440
440
  }, z.core.$strip>>;
441
441
  changes: z.ZodNullable<z.ZodArray<z.ZodEnum<{
442
- fields: "fields";
443
442
  title: "title";
444
443
  text: "text";
444
+ fields: "fields";
445
445
  dates: "dates";
446
446
  waiting: "waiting";
447
447
  assignee: "assignee";
@@ -9,6 +9,8 @@ export declare const Changed: z.ZodObject<{
9
9
  gadgetId: z.ZodOptional<z.ZodTemplateLiteral<`node_${string}`>>;
10
10
  goalId: z.ZodOptional<z.ZodTemplateLiteral<`node_${string}`>>;
11
11
  skillId: z.ZodOptional<z.ZodTemplateLiteral<`node_${string}`>>;
12
+ sourceId: z.ZodOptional<z.ZodTemplateLiteral<`node_${string}`>>;
13
+ queryId: z.ZodOptional<z.ZodTemplateLiteral<`query_${string}`>>;
12
14
  runId: z.ZodOptional<z.ZodTemplateLiteral<`run_${string}`>>;
13
15
  messageId: z.ZodOptional<z.ZodTemplateLiteral<`message_${string}`>>;
14
16
  chatId: z.ZodOptional<z.ZodTemplateLiteral<`node_${string}`>>;
@@ -100,6 +102,8 @@ export declare const Written: z.ZodObject<{
100
102
  gadgetId: z.ZodOptional<z.ZodTemplateLiteral<`node_${string}`>>;
101
103
  goalId: z.ZodOptional<z.ZodTemplateLiteral<`node_${string}`>>;
102
104
  skillId: z.ZodOptional<z.ZodTemplateLiteral<`node_${string}`>>;
105
+ sourceId: z.ZodOptional<z.ZodTemplateLiteral<`node_${string}`>>;
106
+ queryId: z.ZodOptional<z.ZodTemplateLiteral<`query_${string}`>>;
103
107
  runId: z.ZodOptional<z.ZodTemplateLiteral<`run_${string}`>>;
104
108
  messageId: z.ZodOptional<z.ZodTemplateLiteral<`message_${string}`>>;
105
109
  chatId: z.ZodOptional<z.ZodTemplateLiteral<`node_${string}`>>;
@@ -15,6 +15,7 @@ import { CredentialId } from "../operators/operators.js";
15
15
  import { RoleId } from "../roles/roles.js";
16
16
  import { RunId } from "../runs/runs.js";
17
17
  import { FunctionId, InterfaceId, ServiceId } from "../services/services.js";
18
+ import { QueryId } from "../sources/sources.js";
18
19
  import { SsoId } from "../sso/sso.js";
19
20
  import { UserId } from "../users/users.js";
20
21
  // What a write answers over `/mcp` (E126, #672): what it changed and what that caused, never the
@@ -33,6 +34,8 @@ export const Changed = z.object({
33
34
  gadgetId: NodeId.optional(),
34
35
  goalId: NodeId.optional(),
35
36
  skillId: NodeId.optional(),
37
+ sourceId: NodeId.optional(),
38
+ queryId: QueryId.optional(),
36
39
  runId: RunId.optional(),
37
40
  messageId: MessageId.optional(),
38
41
  // A chat is its node's (#45).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@anchrd/colab-sdk",
3
- "version": "0.1.29",
3
+ "version": "0.1.31",
4
4
  "description": "Types, Zod schemas and the service client of Colab, the contract between its UI, backends and outside services.",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",