@takeshape/schema 11.98.6 → 11.99.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.
Files changed (44) hide show
  1. package/dist/agents.d.ts +13 -7
  2. package/dist/agents.js +78 -65
  3. package/dist/builtin-schema.js +12 -0
  4. package/dist/index.d.ts +1 -0
  5. package/dist/index.js +1 -0
  6. package/dist/models/agent.d.ts +3 -0
  7. package/dist/models/agent.js +29 -0
  8. package/dist/models/project-schema.d.ts +17 -0
  9. package/dist/models/project-schema.js +112 -0
  10. package/dist/models/query.d.ts +2 -8
  11. package/dist/models/query.js +16 -4
  12. package/dist/models/runtime-schema.d.ts +3 -7
  13. package/dist/models/runtime-schema.js +9 -86
  14. package/dist/models/shape.d.ts +2 -10
  15. package/dist/models/shape.js +7 -4
  16. package/dist/models/types.d.ts +28 -4
  17. package/dist/models/user-schema.d.ts +7 -0
  18. package/dist/models/user-schema.js +9 -0
  19. package/dist/project-schema/latest.d.ts +33 -38
  20. package/dist/project-schema/v3.48.0.d.ts +33 -38
  21. package/dist/project-schema/v3.49.0.d.ts +33 -38
  22. package/dist/project-schema/v3.50.0.d.ts +33 -38
  23. package/dist/project-schema/v3.51.0.d.ts +33 -38
  24. package/dist/project-schema/v3.52.0.d.ts +33 -38
  25. package/dist/project-schema/v3.53.0.d.ts +33 -38
  26. package/dist/project-schema/v3.54.0.d.ts +33 -38
  27. package/dist/project-schema/v3.55.0.d.ts +33 -38
  28. package/dist/resolvers/takeshape/assets/asset-image-params.d.ts +1 -1
  29. package/dist/schema-util.d.ts +5 -4
  30. package/dist/schema-util.js +43 -3
  31. package/dist/schemas/project-schema/experimental.json +101 -131
  32. package/dist/util/mcp.d.ts +1 -0
  33. package/dist/util/mcp.js +1 -1
  34. package/dist/validate/ai.d.ts +6 -0
  35. package/dist/validate/ai.js +183 -0
  36. package/dist/validate/types.d.ts +1 -0
  37. package/dist/validate/types.js +1 -0
  38. package/dist/validate/util.d.ts +3 -0
  39. package/dist/validate/util.js +28 -0
  40. package/dist/validate/validate.d.ts +1 -0
  41. package/dist/validate/validate.js +14 -164
  42. package/examples/latest/agent-schema.json +24 -10
  43. package/examples/source/agent-schema.json +23 -9
  44. package/package.json +5 -5
@@ -193,58 +193,16 @@
193
193
  },
194
194
  "agentApi": {
195
195
  "title": "Agent API",
196
- "discriminator": {
197
- "propertyName": "type"
198
- },
199
- "oneOf": [
200
- {
201
- "$ref": "#/definitions/agentApiChat"
202
- },
203
- {
204
- "$ref": "#/definitions/agentApiGenerate"
205
- }
206
- ]
207
- },
208
- "agentApiChat": {
209
- "title": "Agent API Chat",
210
196
  "type": "object",
211
197
  "properties": {
212
- "type": {
213
- "enum": ["chat"]
214
- },
215
- "interactionTimeout": {
216
- "title": "Interaction Timeout (milliseconds)",
217
- "type": "integer"
218
- },
219
- "arguments": {
198
+ "inputs": {
220
199
  "type": "array",
221
200
  "items": {
222
- "$ref": "#/definitions/agentApiArgument"
201
+ "$ref": "#/definitions/agentApiInput"
223
202
  }
224
203
  }
225
204
  },
226
- "required": ["type"],
227
- "additionalProperties": false
228
- },
229
- "agentApiGenerate": {
230
- "title": "Agent API Generate",
231
- "type": "object",
232
- "properties": {
233
- "type": {
234
- "enum": ["generate"]
235
- },
236
- "interactionTimeout": {
237
- "title": "Interaction Timeout (milliseconds)",
238
- "type": "integer"
239
- },
240
- "arguments": {
241
- "type": "array",
242
- "items": {
243
- "$ref": "#/definitions/agentApiArgument"
244
- }
245
- }
246
- },
247
- "required": ["type"],
205
+ "required": ["inputs"],
248
206
  "additionalProperties": false
249
207
  },
250
208
  "agentMemory": {
@@ -309,7 +267,7 @@
309
267
  "transition": {
310
268
  "type": "array",
311
269
  "items": {
312
- "$ref": "#/definitions/agentTransitionStep"
270
+ "$ref": "#/definitions/agentTransitionSuspend"
313
271
  }
314
272
  }
315
273
  },
@@ -346,22 +304,10 @@
346
304
  "execution": {
347
305
  "$ref": "#/definitions/agentExecution"
348
306
  },
349
- "sessionMemory": {
350
- "title": "Agent State Session Memory",
351
- "type": "array",
352
- "items": {
353
- "default": {
354
- "condition": {
355
- "type": "none"
356
- }
357
- },
358
- "$ref": "#/definitions/agentStateSessionMemoryLocation"
359
- }
360
- },
361
307
  "transition": {
362
308
  "type": "array",
363
309
  "items": {
364
- "$ref": "#/definitions/agentTransitionStep"
310
+ "$ref": "#/definitions/agentTransition"
365
311
  }
366
312
  }
367
313
  },
@@ -385,110 +331,68 @@
385
331
  }
386
332
  ]
387
333
  },
388
- "agentApiArgument": {
389
- "title": "Agent API Argument",
390
- "type": "object",
391
- "properties": {
392
- "argName": {
393
- "type": "string",
394
- "pattern": "^[0-9A-Za-z_]+$"
395
- },
396
- "argDescription": {
397
- "type": "string"
398
- },
399
- "argType": {
400
- "enum": ["boolean", "integer", "number", "string", "sessionId"]
401
- },
402
- "required": {
403
- "type": "boolean"
404
- }
405
- },
406
- "required": ["argName", "argType"],
407
- "additionalProperties": false
408
- },
409
- "agentExecutionGraphql": {
410
- "title": "Agent Execution GraphQL",
411
- "type": "object",
412
- "properties": {
413
- "type": {
414
- "enum": ["graphql"]
415
- },
416
- "query": {
417
- "type": "string"
418
- },
419
- "path": {
420
- "type": "string"
421
- }
422
- },
423
- "required": ["type", "query"],
424
- "additionalProperties": false
425
- },
426
- "agentStateSessionMemoryLocation": {
427
- "title": "Agent State Session Memory Location",
334
+ "agentApiInput": {
335
+ "title": "Agent API Input",
428
336
  "discriminator": {
429
337
  "propertyName": "type"
430
338
  },
431
339
  "oneOf": [
432
340
  {
433
- "$ref": "#/definitions/agentStateSessionMemoryLocationContent"
434
- },
435
- {
436
- "$ref": "#/definitions/agentStateSessionMemoryLocationArtifact"
437
- },
438
- {
439
- "$ref": "#/definitions/agentStateSessionMemoryLocationStaticValue"
341
+ "$ref": "#/definitions/agentApiMutationInput"
440
342
  }
441
343
  ]
442
344
  },
443
- "agentStateSessionMemoryLocationStaticValue": {
444
- "title": "Agent State Session Memory Location Static Value",
345
+ "agentApiMutationInput": {
346
+ "title": "Agent API Mutation Input",
445
347
  "type": "object",
446
348
  "properties": {
447
349
  "type": {
448
- "enum": ["staticValue"]
350
+ "enum": ["mutation"]
449
351
  },
450
- "memoryPath": {
451
- "type": "string"
352
+ "name": {
353
+ "type": "string",
354
+ "pattern": "^[0-9A-Za-z_]+$"
452
355
  },
453
- "value": {
356
+ "args": {
454
357
  "type": "string"
358
+ },
359
+ "interactionTimeout": {
360
+ "title": "Interaction Timeout (milliseconds)",
361
+ "type": "integer"
455
362
  }
456
363
  },
457
- "required": ["type"],
364
+ "required": ["type", "name", "args"],
458
365
  "additionalProperties": false
459
366
  },
460
- "agentStateSessionMemoryLocationArtifact": {
461
- "title": "Agent State Session Memory Location Artifact",
367
+ "agentExecutionGraphql": {
368
+ "title": "Agent Execution GraphQL",
462
369
  "type": "object",
463
370
  "properties": {
464
371
  "type": {
465
- "enum": ["artifactValue"]
372
+ "enum": ["graphql"]
466
373
  },
467
- "memoryPath": {
374
+ "query": {
468
375
  "type": "string"
469
376
  },
470
- "artifactPath": {
377
+ "path": {
471
378
  "type": "string"
472
379
  }
473
380
  },
474
- "required": ["type"],
381
+ "required": ["type", "query"],
475
382
  "additionalProperties": false
476
383
  },
477
- "agentStateSessionMemoryLocationContent": {
478
- "title": "Agent State Session Memory Location Content",
384
+ "agentStateSessionMemoryAssignment": {
385
+ "title": "Agent State Session Memory Assignment",
479
386
  "type": "object",
480
387
  "properties": {
481
- "type": {
482
- "enum": ["content"]
483
- },
484
388
  "memoryPath": {
485
389
  "type": "string"
486
390
  },
487
- "path": {
391
+ "expression": {
488
392
  "type": "string"
489
393
  }
490
394
  },
491
- "required": ["type"],
395
+ "required": ["expression"],
492
396
  "additionalProperties": false
493
397
  },
494
398
  "agentAiStateInputArg": {
@@ -792,17 +696,35 @@
792
696
  "required": ["type", "service", "model", "input"],
793
697
  "additionalProperties": false
794
698
  },
795
- "agentTransitionStep": {
796
- "title": "Agent Transition Step",
699
+
700
+ "agentTransition": {
701
+ "title": "Agent Transition",
797
702
  "description": "These steps are evaluated in order until a destination is found.",
703
+ "discriminator": {
704
+ "propertyName": "type"
705
+ },
706
+ "oneOf": [
707
+ {
708
+ "$ref": "#/definitions/agentTransitionImmediate"
709
+ },
710
+ {
711
+ "$ref": "#/definitions/agentTransitionSuspend"
712
+ }
713
+ ]
714
+ },
715
+ "agentTransitionSuspend": {
716
+ "title": "Agent Transition Suspend",
798
717
  "type": "object",
799
718
  "properties": {
719
+ "type": {
720
+ "enum": ["suspend"]
721
+ },
800
722
  "destination": {
801
723
  "type": "string",
802
724
  "pattern": "^[0-9A-Za-z_]+$"
803
725
  },
804
- "suspend": {
805
- "type": "boolean"
726
+ "input": {
727
+ "type": "string"
806
728
  },
807
729
  "condition": {
808
730
  "type": "string"
@@ -810,12 +732,60 @@
810
732
  "limit": {
811
733
  "type": "integer"
812
734
  },
735
+ "sessionMemory": {
736
+ "title": "Agent State Session Memory",
737
+ "type": "array",
738
+ "items": {
739
+ "default": {
740
+ "condition": {
741
+ "type": "none"
742
+ }
743
+ },
744
+ "$ref": "#/definitions/agentStateSessionMemoryAssignment"
745
+ }
746
+ },
747
+ "historyStrategy": {
748
+ "type": "string"
749
+ }
750
+ },
751
+ "additionalProperties": false,
752
+ "required": ["type", "destination", "input"]
753
+ },
754
+ "agentTransitionImmediate": {
755
+ "title": "Agent Transition Immediate",
756
+ "type": "object",
757
+ "properties": {
758
+ "type": {
759
+ "enum": ["immediate"]
760
+ },
761
+ "destination": {
762
+ "type": "string",
763
+ "pattern": "^[0-9A-Za-z_]+$"
764
+ },
765
+ "condition": {
766
+ "type": "string"
767
+ },
768
+ "limit": {
769
+ "type": "integer"
770
+ },
771
+ "sessionMemory": {
772
+ "title": "Agent State Session Memory",
773
+ "type": "array",
774
+ "items": {
775
+ "default": {
776
+ "condition": {
777
+ "type": "none"
778
+ }
779
+ },
780
+ "$ref": "#/definitions/agentStateSessionMemoryAssignment"
781
+ }
782
+ },
813
783
  "historyStrategy": {
814
784
  "type": "string"
815
785
  }
816
786
  },
817
787
  "additionalProperties": false,
818
- "required": ["destination"]
788
+ "required": ["type", "destination"]
819
789
  },
820
790
  "agentMap": {
821
791
  "title": "Agent Map",
@@ -1,4 +1,5 @@
1
1
  import type { ProjectSchemaJSON, ToolJSON, ToolMap } from '../project-schema/latest.ts';
2
+ export declare const TOOL_SCHEMA_PATH: readonly ["ai-experimental", "mcp", "tools"];
2
3
  export declare function getMcpToolMap(projectSchema: ProjectSchemaJSON): ToolMap | undefined;
3
4
  export declare function getMcpTools(projectSchema: ProjectSchemaJSON): ToolJSON[] | undefined;
4
5
  export declare function getMcpToolNames(projectSchema: ProjectSchemaJSON): string[];
package/dist/util/mcp.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import set from 'lodash/fp/set.js';
2
- const TOOL_SCHEMA_PATH = ['ai-experimental', 'mcp', 'tools'];
2
+ export const TOOL_SCHEMA_PATH = ['ai-experimental', 'mcp', 'tools'];
3
3
  export function getMcpToolMap(projectSchema) {
4
4
  return projectSchema['ai-experimental']?.mcp?.tools;
5
5
  }
@@ -0,0 +1,6 @@
1
+ import type { SchemaValidationErrorItem } from '@takeshape/errors';
2
+ import type { AIToolConfig, ProjectSchemaJSON } from '../project-schema/latest.ts';
3
+ import { type GetNamespace } from '../refs.ts';
4
+ import type { Path } from './types.ts';
5
+ export declare function validateAIToolConfig(projectSchema: ProjectSchemaJSON, getNamespace: GetNamespace, tool: AIToolConfig | string, basePath: Path): SchemaValidationErrorItem | undefined;
6
+ export declare function validateAgents(projectSchema: ProjectSchemaJSON): SchemaValidationErrorItem[];
@@ -0,0 +1,183 @@
1
+ import get from 'lodash/get.js';
2
+ import { AGENTS_SCHEMA_PATH, getAgentMap, getGuardConfig, isValidAgentMutation } from '../agents.js';
3
+ import { createGetNamespace, getToolRef, parsePropertyRef, propertyRefItemToPath } from "../refs.js";
4
+ import { isBuiltinMutation, isBuiltinQuery } from "../schema-util.js";
5
+ import { validateExpression } from "../util/expressions.js";
6
+ import { findDuplicateIndices, pushErrors } from "./util.js";
7
+ export function validateAIToolConfig(projectSchema, getNamespace, tool, basePath) {
8
+ const toolRef = getToolRef(tool);
9
+ const path = typeof tool === 'string' ? basePath : basePath.concat('ref');
10
+ const parsed = parsePropertyRef(toolRef);
11
+ if (!parsed) {
12
+ return {
13
+ type: 'conflict',
14
+ path,
15
+ message: `Unable to parse property ref "${toolRef}"`
16
+ };
17
+ }
18
+ if (parsed.layerId !== 'local') {
19
+ return;
20
+ }
21
+ if ((parsed.shapeName === 'Query' && isBuiltinQuery(parsed.propertyName)) ||
22
+ (parsed.shapeName === 'Mutation' && isBuiltinMutation(parsed.propertyName))) {
23
+ return;
24
+ }
25
+ const propertyPath = propertyRefItemToPath(getNamespace, parsed);
26
+ if (propertyPath[0] !== 'queries' && propertyPath[0] !== 'mutations') {
27
+ return {
28
+ type: 'conflict',
29
+ path,
30
+ message: 'Tools must be a query or mutation'
31
+ };
32
+ }
33
+ const property = get(projectSchema, propertyPath);
34
+ if (propertyPath[0] === 'mutations' && isValidAgentMutation(projectSchema, propertyPath[1])) {
35
+ return;
36
+ }
37
+ if (!property) {
38
+ return {
39
+ type: 'notFound',
40
+ path,
41
+ message: `Missing tool ${propertyPath[0] === 'queries' ? 'query' : 'mutation'} "${toolRef}"`
42
+ };
43
+ }
44
+ }
45
+ function validateAgentTransitions(parentPath, inputNames, transitions) {
46
+ const errors = [];
47
+ transitions.forEach((transition, transitionIndex) => {
48
+ if (transition.type === 'suspend') {
49
+ if (!inputNames.has(transition.input)) {
50
+ errors.push({
51
+ path: [...parentPath, transitionIndex, 'input'],
52
+ type: 'notFound',
53
+ message: `Invalid input "${transition.input}"`
54
+ });
55
+ }
56
+ }
57
+ if (transition.condition) {
58
+ const conditionValidation = validateExpression(transition.condition);
59
+ if (!conditionValidation.valid) {
60
+ const common = {
61
+ path: [...parentPath, transitionIndex, 'expression'],
62
+ type: 'conflict'
63
+ };
64
+ errors.push(...conditionValidation.errors.map((message) => ({ ...common, message })));
65
+ }
66
+ }
67
+ });
68
+ return errors;
69
+ }
70
+ export function validateAgents(projectSchema) {
71
+ const getNamespace = createGetNamespace(projectSchema);
72
+ const errors = [];
73
+ const agents = getAgentMap(projectSchema);
74
+ if (!agents) {
75
+ return errors;
76
+ }
77
+ for (const [agentName, agent] of Object.entries(agents)) {
78
+ const stateNames = new Set();
79
+ const agentPath = [...AGENTS_SCHEMA_PATH, agentName];
80
+ const inputNames = new Set(agent.api.inputs.map((input) => input.name));
81
+ for (const [name, indices] of findDuplicateIndices(agent.api.inputs, 'name')) {
82
+ for (const index of indices) {
83
+ errors.push({
84
+ path: [...agentPath, 'api', 'inputs', index, 'name'],
85
+ type: 'conflict',
86
+ message: `Duplicate input name "${name}"`
87
+ });
88
+ }
89
+ }
90
+ pushErrors(errors, validateAgentTransitions([...agentPath, 'start', 'transition'], inputNames, agent.start.transition));
91
+ for (const [stateId, state] of Object.entries(agent.states)) {
92
+ const statePath = [...agentPath, 'states', stateId];
93
+ if (stateNames.has(state.name)) {
94
+ errors.push({
95
+ path: [...statePath, 'name'],
96
+ type: 'conflict',
97
+ message: `Duplicate state name "${state.name}"`
98
+ });
99
+ }
100
+ else {
101
+ stateNames.add(state.name);
102
+ }
103
+ if (state.variables) {
104
+ state.variables.forEach((variable, variableIndex) => {
105
+ variable.steps.forEach((step, stepIndex) => {
106
+ const stepPath = [...statePath, 'variables', variableIndex, 'steps', stepIndex];
107
+ if (step.condition) {
108
+ const conditionValidation = validateExpression(step.condition);
109
+ if (!conditionValidation.valid) {
110
+ const common = {
111
+ path: [...stepPath, 'condition'],
112
+ type: 'conflict'
113
+ };
114
+ errors.push(...conditionValidation.errors.map((message) => ({ ...common, message })));
115
+ }
116
+ }
117
+ const exprValidation = validateExpression(step.expression);
118
+ if (!exprValidation.valid) {
119
+ const common = {
120
+ path: [...stepPath, 'expression'],
121
+ type: 'conflict'
122
+ };
123
+ errors.push(...exprValidation.errors.map((message) => ({ ...common, message })));
124
+ }
125
+ });
126
+ });
127
+ }
128
+ if (state.transition) {
129
+ errors.push(...validateAgentTransitions([...statePath, 'transition'], inputNames, state.transition));
130
+ }
131
+ if (state.execution.type === 'generate' || state.execution.type === 'chat') {
132
+ if (!state.execution.tools) {
133
+ continue;
134
+ }
135
+ for (const [name, indices] of findDuplicateIndices(state.execution.tools, 'name')) {
136
+ for (const index of indices) {
137
+ errors.push({
138
+ path: [...statePath, 'execution', 'tools', index, 'name'],
139
+ type: 'conflict',
140
+ message: `Duplicate tool name "${name}"`
141
+ });
142
+ }
143
+ }
144
+ state.execution.tools.forEach((tool, toolIndex) => {
145
+ pushErrors(errors, validateAIToolConfig(projectSchema, getNamespace, tool, [
146
+ ...statePath,
147
+ 'execution',
148
+ 'tools',
149
+ toolIndex,
150
+ 'ref'
151
+ ]));
152
+ });
153
+ }
154
+ }
155
+ if (agent.guards) {
156
+ agent.guards.forEach(({ guardId }, index) => {
157
+ if (!getGuardConfig(projectSchema, guardId)) {
158
+ errors.push({
159
+ path: [...agentPath, 'guards', index, 'guardId'],
160
+ type: 'notFound',
161
+ message: `Invalid guardId "${guardId}"`
162
+ });
163
+ }
164
+ });
165
+ }
166
+ if (agent.historyStrategies) {
167
+ const seenStrategyNames = new Set();
168
+ for (const [historyStrategyId, historyStrategy] of Object.entries(agent.historyStrategies)) {
169
+ if (seenStrategyNames.has(historyStrategy.name)) {
170
+ errors.push({
171
+ path: [...agentPath, 'historyStrategies', historyStrategyId, 'name'],
172
+ type: 'conflict',
173
+ message: `Duplicate history strategy name "${historyStrategy.name}"`
174
+ });
175
+ }
176
+ else {
177
+ seenStrategyNames.add(historyStrategy.name);
178
+ }
179
+ }
180
+ }
181
+ }
182
+ return errors;
183
+ }
@@ -0,0 +1 @@
1
+ export type Path = Array<string | number>;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,3 @@
1
+ import type { SchemaValidationErrorItem } from '@takeshape/errors';
2
+ export declare function findDuplicateIndices<Obj extends object, Key extends keyof Obj>(array: Obj[], key: Key): [Obj[Key], number[]][];
3
+ export declare function pushErrors(errors: SchemaValidationErrorItem[], error: SchemaValidationErrorItem | SchemaValidationErrorItem[] | undefined): void;
@@ -0,0 +1,28 @@
1
+ export function findDuplicateIndices(array, key) {
2
+ const indicesByValue = new Map();
3
+ for (let i = 0; i < array.length; i++) {
4
+ const value = array[i][key];
5
+ const indices = indicesByValue.get(value) ?? [];
6
+ indices.push(i);
7
+ indicesByValue.set(value, indices);
8
+ }
9
+ const result = [];
10
+ for (const [value, indices] of indicesByValue) {
11
+ if (indices.length > 1) {
12
+ result.push([value, indices]);
13
+ }
14
+ }
15
+ return result;
16
+ }
17
+ export function pushErrors(errors, error) {
18
+ if (error) {
19
+ if (Array.isArray(error)) {
20
+ if (error.length) {
21
+ errors.push(...error);
22
+ }
23
+ }
24
+ else {
25
+ errors.push(error);
26
+ }
27
+ }
28
+ }
@@ -34,6 +34,7 @@ export type EntitlementsOptions = {
34
34
  };
35
35
  export type ValidateContext = {
36
36
  allowDisconnectedLayers?: boolean;
37
+ generatedApi?: Pick<ProjectSchemaJSON, 'queries' | 'mutations'>;
37
38
  } & EntitlementsOptions & ValidateSyntaxOptions;
38
39
  export type ValidateReferencesContext = SetRequired<ValidateContext, 'resolveLayer'>;
39
40
  export declare function validateSchemaSyntax(obj: unknown, options?: ValidateSyntaxOptions): SchemaValidationResult;