@anchrd/intel-contract 0.1.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.
@@ -0,0 +1,462 @@
1
+ import { z } from "zod";
2
+ export const IntelId = z.string().min(1).max(128);
3
+ export const IsoDateTime = z.iso.datetime({ offset: true });
4
+ export const ProblemDetails = z.strictObject({
5
+ type: z.string(),
6
+ status: z.number().int().min(400).max(599),
7
+ title: z.string(),
8
+ detail: z.string().optional(),
9
+ instance: z.string().optional(),
10
+ code: z.string().optional(),
11
+ });
12
+ export const KnowledgeNodeKind = z.enum(["folder", "document", "attachment"]);
13
+ export const ContextPolicy = z.enum(["pinned", "relevant", "explicit"]);
14
+ export const ResourceRole = z.enum(["viewer", "commenter", "editor", "manager"]);
15
+ export const SharePrincipal = z.discriminatedUnion("type", [
16
+ z.strictObject({ type: z.literal("user"), id: IntelId }),
17
+ z.strictObject({ type: z.literal("email"), email: z.email() }),
18
+ z.strictObject({ type: z.literal("organization") }),
19
+ ]);
20
+ export const KnowledgeNode = z.strictObject({
21
+ id: IntelId,
22
+ parentId: IntelId.nullable(),
23
+ kind: KnowledgeNodeKind,
24
+ title: z.string().min(1).max(240),
25
+ description: z.string().max(2_000).nullable(),
26
+ contextPolicy: ContextPolicy,
27
+ ownerId: IntelId,
28
+ currentVersionId: IntelId.nullable(),
29
+ createdAt: IsoDateTime,
30
+ updatedAt: IsoDateTime,
31
+ archivedAt: IsoDateTime.nullable(),
32
+ });
33
+ export const KnowledgeVersion = z.strictObject({
34
+ id: IntelId,
35
+ nodeId: IntelId,
36
+ sequence: z.number().int().positive(),
37
+ contentKey: z.string().min(1),
38
+ mediaType: z.string().min(1).max(160),
39
+ contentHash: z.string().regex(/^[a-f0-9]{64}$/),
40
+ size: z.number().int().nonnegative(),
41
+ createdBy: IntelId,
42
+ createdAt: IsoDateTime,
43
+ });
44
+ export const ListKnowledgeNodesInput = z.strictObject({
45
+ parentId: IntelId.nullable().default(null),
46
+ includeArchived: z.boolean().default(false),
47
+ });
48
+ export const GetKnowledgeNodeInput = z.strictObject({ nodeId: IntelId });
49
+ export const ListKnowledgeGrantsInput = z.strictObject({ resourceId: IntelId });
50
+ export const CreateKnowledgeNodeInput = z.strictObject({
51
+ parentId: IntelId.nullable().default(null),
52
+ kind: KnowledgeNodeKind,
53
+ title: z.string().trim().min(1).max(240),
54
+ description: z.string().trim().max(2_000).nullable().default(null),
55
+ contextPolicy: ContextPolicy.default("relevant"),
56
+ idempotencyKey: z.string().min(8).max(200),
57
+ });
58
+ export const SaveKnowledgeVersionInput = z.strictObject({
59
+ nodeId: IntelId,
60
+ baseVersionId: IntelId.nullable(),
61
+ content: z.string().max(10_000_000),
62
+ mediaType: z.string().min(1).max(160).default("text/markdown"),
63
+ idempotencyKey: z.string().min(8).max(200),
64
+ });
65
+ export const SaveKnowledgeAttachmentInput = z.strictObject({
66
+ nodeId: IntelId,
67
+ baseVersionId: IntelId.nullable(),
68
+ contentBase64: z.string().min(1).max(20_000_000),
69
+ mediaType: z.string().min(1).max(160),
70
+ idempotencyKey: z.string().min(8).max(200),
71
+ });
72
+ export const UpdateKnowledgeNodeInput = z
73
+ .strictObject({
74
+ nodeId: IntelId,
75
+ baseUpdatedAt: IsoDateTime,
76
+ title: z.string().trim().min(1).max(240).optional(),
77
+ description: z.string().trim().max(2_000).nullable().optional(),
78
+ contextPolicy: ContextPolicy.optional(),
79
+ parentId: IntelId.nullable().optional(),
80
+ idempotencyKey: z.string().min(8).max(200),
81
+ })
82
+ .refine((input) => input.title !== undefined ||
83
+ input.description !== undefined ||
84
+ input.contextPolicy !== undefined ||
85
+ input.parentId !== undefined, { message: "At least one change is required" });
86
+ export const ArchiveKnowledgeNodeInput = z.strictObject({
87
+ nodeId: IntelId,
88
+ baseUpdatedAt: IsoDateTime,
89
+ archived: z.boolean(),
90
+ idempotencyKey: z.string().min(8).max(200),
91
+ });
92
+ export const KnowledgeNodeList = z.strictObject({ items: z.array(KnowledgeNode) });
93
+ export const KnowledgeVersionList = z.strictObject({ items: z.array(KnowledgeVersion) });
94
+ export const KnowledgeDocument = z.strictObject({
95
+ node: KnowledgeNode,
96
+ version: KnowledgeVersion.nullable(),
97
+ content: z.string().nullable(),
98
+ });
99
+ export const KnowledgeAttachment = z.strictObject({
100
+ node: KnowledgeNode,
101
+ version: KnowledgeVersion,
102
+ resourceUri: z.string().regex(/^intel:\/\/knowledge\/[^/]+\/attachment$/),
103
+ });
104
+ export const KnowledgeLinkRelation = z.enum(["references", "related", "depends_on", "implements"]);
105
+ export const KnowledgeLink = z.strictObject({
106
+ id: IntelId,
107
+ sourceNodeId: IntelId,
108
+ targetNodeId: IntelId,
109
+ relation: KnowledgeLinkRelation,
110
+ label: z.string().trim().min(1).max(120).nullable(),
111
+ createdBy: IntelId,
112
+ createdAt: IsoDateTime,
113
+ });
114
+ export const KnowledgeLinkList = z.strictObject({ items: z.array(KnowledgeLink) });
115
+ export const CreateKnowledgeLinkInput = z
116
+ .strictObject({
117
+ sourceNodeId: IntelId,
118
+ targetNodeId: IntelId,
119
+ relation: KnowledgeLinkRelation,
120
+ label: z.string().trim().min(1).max(120).nullable().default(null),
121
+ idempotencyKey: z.string().min(8).max(200),
122
+ })
123
+ .refine((input) => input.sourceNodeId !== input.targetNodeId, {
124
+ message: "Knowledge cannot link to itself",
125
+ });
126
+ export const DeleteKnowledgeLinkInput = z.strictObject({
127
+ sourceNodeId: IntelId,
128
+ linkId: IntelId,
129
+ idempotencyKey: z.string().min(8).max(200),
130
+ });
131
+ export const KnowledgeGraphInput = z.strictObject({
132
+ limit: z.number().int().min(1).max(500).default(250),
133
+ });
134
+ export const KnowledgeGraph = z.strictObject({
135
+ nodes: z.array(KnowledgeNode),
136
+ links: z.array(KnowledgeLink),
137
+ });
138
+ export const BlockNoteMediaType = "application/vnd.anchrd.intel.blocknote+json";
139
+ export const BlockNoteDocument = z.strictObject({
140
+ format: z.literal("blocknote"),
141
+ schemaVersion: z.literal(1),
142
+ blocks: z.array(z.record(z.string(), z.unknown())),
143
+ markdown: z.string(),
144
+ });
145
+ export const ResourceGrant = z.strictObject({
146
+ id: IntelId,
147
+ resourceId: IntelId,
148
+ principal: SharePrincipal,
149
+ role: ResourceRole,
150
+ expiresAt: IsoDateTime.nullable(),
151
+ createdBy: IntelId,
152
+ createdAt: IsoDateTime,
153
+ });
154
+ export const ShareKnowledgeInput = z.strictObject({
155
+ resourceId: IntelId,
156
+ principal: SharePrincipal,
157
+ role: ResourceRole,
158
+ expiresAt: IsoDateTime.nullable().default(null),
159
+ idempotencyKey: z.string().min(8).max(200),
160
+ });
161
+ export const RevokeKnowledgeGrantInput = z.strictObject({
162
+ resourceId: IntelId,
163
+ grantId: IntelId,
164
+ idempotencyKey: z.string().min(8).max(200),
165
+ });
166
+ export const ResourceGrantList = z.strictObject({ items: z.array(ResourceGrant) });
167
+ export const SearchKnowledgeInput = z.strictObject({
168
+ query: z.string().trim().min(1).max(500),
169
+ limit: z.number().int().min(1).max(50).default(10),
170
+ });
171
+ export const KnowledgeCitation = z.strictObject({
172
+ nodeId: IntelId,
173
+ versionId: IntelId,
174
+ title: z.string(),
175
+ passage: z.string(),
176
+ source: z.string(),
177
+ freshness: IsoDateTime,
178
+ score: z.number().min(0).max(1),
179
+ match: z.enum(["lexical", "semantic", "hybrid"]),
180
+ });
181
+ export const SearchKnowledgeResult = z.strictObject({
182
+ items: z.array(KnowledgeCitation),
183
+ });
184
+ export const ReindexKnowledgeResult = z.strictObject({ queued: z.number().int().nonnegative() });
185
+ export const RevokeGrantResult = z.strictObject({ revoked: z.boolean() });
186
+ export const DeleteKnowledgeLinkResult = z.strictObject({ deleted: z.boolean() });
187
+ function isPrivateIpv4(hostname) {
188
+ const parts = hostname.split(".").map(Number);
189
+ if (parts.length !== 4 ||
190
+ parts.some((part) => !Number.isInteger(part) || part < 0 || part > 255)) {
191
+ return false;
192
+ }
193
+ const [first = 0, second = 0] = parts;
194
+ return (first === 0 ||
195
+ first === 10 ||
196
+ first === 127 ||
197
+ (first === 100 && second >= 64 && second <= 127) ||
198
+ (first === 169 && second === 254) ||
199
+ (first === 172 && second >= 16 && second <= 31) ||
200
+ (first === 192 && second === 168) ||
201
+ (first === 198 && (second === 18 || second === 19)) ||
202
+ first >= 224);
203
+ }
204
+ function normalizedHostname(url) {
205
+ return url.hostname.toLowerCase().replace(/^\[|\]$/g, "");
206
+ }
207
+ function isPublicToolHost(url) {
208
+ const hostname = normalizedHostname(url);
209
+ if (hostname === "localhost" || hostname === "127.0.0.1" || hostname === "::1") {
210
+ return url.protocol === "http:";
211
+ }
212
+ if (!hostname.includes(".") ||
213
+ hostname.endsWith(".local") ||
214
+ hostname.endsWith(".localhost") ||
215
+ hostname.endsWith(".internal") ||
216
+ isPrivateIpv4(hostname) ||
217
+ hostname.includes(":")) {
218
+ return false;
219
+ }
220
+ return url.protocol === "https:";
221
+ }
222
+ export const ToolSourceUrl = z.url().refine((value) => {
223
+ try {
224
+ const url = new URL(value);
225
+ return !url.username && !url.password && isPublicToolHost(url);
226
+ }
227
+ catch {
228
+ return false;
229
+ }
230
+ }, "Tool source must use an approved public HTTPS host without embedded credentials");
231
+ export const ToolSource = z.strictObject({
232
+ id: IntelId,
233
+ name: z.string().min(1).max(120),
234
+ url: ToolSourceUrl,
235
+ connectionHandle: z.string().regex(/^[a-z0-9][a-z0-9-]{1,62}$/),
236
+ enabled: z.boolean(),
237
+ createdBy: IntelId,
238
+ createdAt: IsoDateTime,
239
+ updatedAt: IsoDateTime,
240
+ lastDiscoveredAt: IsoDateTime.nullable(),
241
+ });
242
+ export const ToolAnnotations = z.strictObject({
243
+ title: z.string().max(240).optional(),
244
+ readOnlyHint: z.boolean().optional(),
245
+ destructiveHint: z.boolean().optional(),
246
+ idempotentHint: z.boolean().optional(),
247
+ openWorldHint: z.boolean().optional(),
248
+ });
249
+ export const ToolCapability = z.strictObject({
250
+ sourceId: IntelId,
251
+ name: z.string().min(1).max(240),
252
+ title: z.string().max(240).nullable(),
253
+ description: z.string().max(10_000).nullable(),
254
+ inputSchema: z.record(z.string(), z.unknown()),
255
+ outputSchema: z.record(z.string(), z.unknown()).nullable(),
256
+ annotations: ToolAnnotations,
257
+ fingerprint: z.string().regex(/^[a-f0-9]{64}$/),
258
+ discoveredAt: IsoDateTime,
259
+ });
260
+ export const ToolConnectionStatus = z.enum(["connected", "missing", "forbidden", "invalid"]);
261
+ export const ToolCatalogEntry = z.strictObject({
262
+ source: ToolSource,
263
+ capability: ToolCapability,
264
+ connectionStatus: ToolConnectionStatus,
265
+ });
266
+ export const ToolSourceList = z.strictObject({ items: z.array(ToolSource) });
267
+ export const ToolCatalog = z.strictObject({ items: z.array(ToolCatalogEntry) });
268
+ export const CreateToolSourceInput = z.strictObject({
269
+ name: z.string().trim().min(1).max(120),
270
+ url: ToolSourceUrl,
271
+ connectionHandle: z
272
+ .string()
273
+ .regex(/^[a-z0-9][a-z0-9-]{1,62}$/)
274
+ .default("intel-tools"),
275
+ idempotencyKey: z.string().min(8).max(200),
276
+ });
277
+ export const DiscoverToolSourceInput = z.strictObject({
278
+ sourceId: IntelId,
279
+ idempotencyKey: z.string().min(8).max(200),
280
+ });
281
+ export const TestToolInput = z.strictObject({
282
+ sourceId: IntelId,
283
+ name: z.string().min(1).max(240),
284
+ arguments: z.record(z.string(), z.unknown()).default({}),
285
+ });
286
+ export const ExecuteToolInput = TestToolInput;
287
+ export const ToolTestResult = z.strictObject({
288
+ isError: z.boolean(),
289
+ content: z.array(z.unknown()),
290
+ structuredContent: z.unknown().optional(),
291
+ });
292
+ export const FlowNodeId = z.string().regex(/^[A-Za-z0-9][A-Za-z0-9_-]{0,99}$/);
293
+ export const FlowPosition = z.strictObject({ x: z.number().finite(), y: z.number().finite() });
294
+ const FlowNodeBase = {
295
+ id: FlowNodeId,
296
+ position: FlowPosition,
297
+ label: z.string().trim().min(1).max(160),
298
+ description: z.string().trim().max(2_000).nullable().default(null),
299
+ };
300
+ export const FlowNode = z.discriminatedUnion("kind", [
301
+ z.strictObject({
302
+ ...FlowNodeBase,
303
+ kind: z.literal("trigger"),
304
+ configuration: z.discriminatedUnion("mode", [
305
+ z.strictObject({ mode: z.literal("manual") }),
306
+ z.strictObject({ mode: z.literal("webhook"), event: z.string().min(1).max(120) }),
307
+ z.strictObject({ mode: z.literal("schedule"), cron: z.string().min(5).max(120) }),
308
+ ]),
309
+ }),
310
+ z.strictObject({
311
+ ...FlowNodeBase,
312
+ kind: z.literal("instruction"),
313
+ configuration: z.strictObject({ prompt: z.string().min(1).max(50_000) }),
314
+ }),
315
+ z.strictObject({
316
+ ...FlowNodeBase,
317
+ kind: z.literal("knowledge"),
318
+ configuration: z.strictObject({
319
+ resourceIds: z.array(IntelId).min(1).max(100),
320
+ mode: z.enum(["full", "relevant"]),
321
+ query: z.string().max(1_000).nullable().default(null),
322
+ }),
323
+ }),
324
+ z.strictObject({
325
+ ...FlowNodeBase,
326
+ kind: z.literal("tool"),
327
+ configuration: z.strictObject({
328
+ sourceId: IntelId,
329
+ toolName: z.string().min(1).max(240),
330
+ fingerprint: z
331
+ .string()
332
+ .regex(/^[a-f0-9]{64}$/)
333
+ .nullable()
334
+ .default(null),
335
+ arguments: z.record(z.string(), z.unknown()).default({}),
336
+ }),
337
+ }),
338
+ z.strictObject({
339
+ ...FlowNodeBase,
340
+ kind: z.literal("condition"),
341
+ configuration: z.strictObject({
342
+ mode: z.literal("semantic"),
343
+ instruction: z.string().min(1).max(10_000),
344
+ }),
345
+ }),
346
+ z.strictObject({
347
+ ...FlowNodeBase,
348
+ kind: z.literal("approval"),
349
+ configuration: z.strictObject({
350
+ prompt: z.string().min(1).max(10_000),
351
+ timeout: z.string().regex(/^\d+\s+(minute|minutes|hour|hours|day|days)$/),
352
+ }),
353
+ }),
354
+ z.strictObject({
355
+ ...FlowNodeBase,
356
+ kind: z.literal("output"),
357
+ configuration: z.strictObject({ template: z.string().max(50_000).default("") }),
358
+ }),
359
+ ]);
360
+ export const FlowEdge = z.strictObject({
361
+ id: FlowNodeId,
362
+ source: FlowNodeId,
363
+ target: FlowNodeId,
364
+ label: z.string().trim().min(1).max(120).nullable().default(null),
365
+ sourceHandle: z.string().trim().min(1).max(120).nullable().default(null),
366
+ });
367
+ export const FlowGraph = z.strictObject({
368
+ nodes: z.array(FlowNode).min(2).max(200),
369
+ edges: z.array(FlowEdge).min(1).max(500),
370
+ });
371
+ export const Flow = z.strictObject({
372
+ id: IntelId,
373
+ title: z.string().min(1).max(240),
374
+ description: z.string().max(2_000).nullable(),
375
+ ownerId: IntelId,
376
+ currentVersionId: IntelId.nullable(),
377
+ publishedVersionId: IntelId.nullable(),
378
+ createdAt: IsoDateTime,
379
+ updatedAt: IsoDateTime,
380
+ archivedAt: IsoDateTime.nullable(),
381
+ });
382
+ export const FlowVersion = z.strictObject({
383
+ id: IntelId,
384
+ flowId: IntelId,
385
+ sequence: z.number().int().positive(),
386
+ graph: FlowGraph,
387
+ createdBy: IntelId,
388
+ createdAt: IsoDateTime,
389
+ });
390
+ export const FlowDocument = z.strictObject({
391
+ flow: Flow,
392
+ version: FlowVersion.nullable(),
393
+ });
394
+ export const FlowList = z.strictObject({ items: z.array(Flow) });
395
+ export const CreateFlowInput = z.strictObject({
396
+ title: z.string().trim().min(1).max(240),
397
+ description: z.string().trim().max(2_000).nullable().default(null),
398
+ idempotencyKey: z.string().min(8).max(200),
399
+ });
400
+ export const GetFlowInput = z.strictObject({ flowId: IntelId });
401
+ export const SaveFlowVersionInput = z.strictObject({
402
+ flowId: IntelId,
403
+ baseVersionId: IntelId.nullable(),
404
+ graph: FlowGraph,
405
+ idempotencyKey: z.string().min(8).max(200),
406
+ });
407
+ export const PublishFlowInput = z.strictObject({
408
+ flowId: IntelId,
409
+ versionId: IntelId,
410
+ idempotencyKey: z.string().min(8).max(200),
411
+ });
412
+ export const ListFlowGrantsInput = z.strictObject({ resourceId: IntelId });
413
+ export const ShareFlowInput = z.strictObject({
414
+ resourceId: IntelId,
415
+ principal: SharePrincipal,
416
+ role: ResourceRole,
417
+ expiresAt: IsoDateTime.nullable().default(null),
418
+ idempotencyKey: z.string().min(8).max(200),
419
+ });
420
+ export const RevokeFlowGrantInput = z.strictObject({
421
+ resourceId: IntelId,
422
+ grantId: IntelId,
423
+ idempotencyKey: z.string().min(8).max(200),
424
+ });
425
+ export const FlowRunStatus = z.enum([
426
+ "queued",
427
+ "running",
428
+ "waiting",
429
+ "completed",
430
+ "failed",
431
+ "cancelled",
432
+ ]);
433
+ export const FlowRun = z.strictObject({
434
+ id: IntelId,
435
+ flowId: IntelId,
436
+ versionId: IntelId,
437
+ status: FlowRunStatus,
438
+ currentNodeId: FlowNodeId.nullable(),
439
+ input: z.record(z.string(), z.unknown()),
440
+ output: z.unknown().nullable(),
441
+ error: z.string().max(2_000).nullable(),
442
+ initiatedBy: IntelId,
443
+ createdAt: IsoDateTime,
444
+ updatedAt: IsoDateTime,
445
+ completedAt: IsoDateTime.nullable(),
446
+ });
447
+ export const FlowRunStep = z.strictObject({ run: FlowRun, node: FlowNode.nullable() });
448
+ export const StartFlowRunInput = z.strictObject({
449
+ flowId: IntelId,
450
+ input: z.record(z.string(), z.unknown()).default({}),
451
+ idempotencyKey: z.string().min(8).max(200),
452
+ });
453
+ export const GetFlowRunInput = z.strictObject({ runId: IntelId });
454
+ export const CompleteFlowRunStepInput = z.strictObject({
455
+ runId: IntelId,
456
+ nodeId: FlowNodeId,
457
+ outcome: z.enum(["completed", "failed"]),
458
+ branch: z.string().min(1).max(120).nullable().default(null),
459
+ output: z.unknown().nullable().default(null),
460
+ error: z.string().max(2_000).nullable().default(null),
461
+ idempotencyKey: z.string().min(8).max(200),
462
+ });
package/package.json ADDED
@@ -0,0 +1,39 @@
1
+ {
2
+ "name": "@anchrd/intel-contract",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "license": "UNLICENSED",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/anchrd/intel.git",
9
+ "directory": "packages/contract"
10
+ },
11
+ "publishConfig": {
12
+ "access": "public"
13
+ },
14
+ "exports": {
15
+ ".": {
16
+ "types": "./dist/contract/contract.d.ts",
17
+ "default": "./dist/contract/contract.js"
18
+ }
19
+ },
20
+ "files": [
21
+ "dist"
22
+ ],
23
+ "scripts": {
24
+ "build": "tsc -p tsconfig.build.json && node ../../scripts/pack/fix-dts.mjs",
25
+ "prepack": "bun run build && node ../../scripts/pack/to-dist-manifest.mjs",
26
+ "postpack": "node ../../scripts/pack/restore-manifest.mjs",
27
+ "test": "vitest run",
28
+ "typecheck": "tsc --noEmit"
29
+ },
30
+ "dependencies": {
31
+ "zod": "^4.4.3"
32
+ },
33
+ "devDependencies": {
34
+ "vitest": "^4.1.10"
35
+ },
36
+ "main": "./dist/contract/contract.js",
37
+ "module": "./dist/contract/contract.js",
38
+ "types": "./dist/contract/contract.d.ts"
39
+ }