@artemiskit/core 0.5.3 → 0.6.1

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 (92) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/README.md +12 -0
  3. package/dist/adapters/factory.d.ts +1 -1
  4. package/dist/adapters/index.d.ts +3 -3
  5. package/dist/adapters/registry.d.ts +1 -1
  6. package/dist/adapters/types.d.ts +7 -0
  7. package/dist/adapters/types.d.ts.map +1 -1
  8. package/dist/agent-evaluation/index.d.ts +2 -2
  9. package/dist/agent-evaluation/scorer.d.ts +1 -1
  10. package/dist/agent-workflow/catalog.d.ts +28 -0
  11. package/dist/agent-workflow/catalog.d.ts.map +1 -0
  12. package/dist/agent-workflow/environment.d.ts +47 -0
  13. package/dist/agent-workflow/environment.d.ts.map +1 -0
  14. package/dist/agent-workflow/index.d.ts +10 -0
  15. package/dist/agent-workflow/index.d.ts.map +1 -0
  16. package/dist/agent-workflow/parser.d.ts +7 -0
  17. package/dist/agent-workflow/parser.d.ts.map +1 -0
  18. package/dist/agent-workflow/sandbox-fixtures/qualify.d.ts +2 -0
  19. package/dist/agent-workflow/sandbox-fixtures/qualify.d.ts.map +1 -0
  20. package/dist/agent-workflow/sandbox.d.ts +12 -0
  21. package/dist/agent-workflow/sandbox.d.ts.map +1 -0
  22. package/dist/agent-workflow/schema.d.ts +774 -0
  23. package/dist/agent-workflow/schema.d.ts.map +1 -0
  24. package/dist/agent-workflow/session.d.ts +113 -0
  25. package/dist/agent-workflow/session.d.ts.map +1 -0
  26. package/dist/agent-workflow/simulated-tools.d.ts +35 -0
  27. package/dist/agent-workflow/simulated-tools.d.ts.map +1 -0
  28. package/dist/agent-workflow/target.d.ts +243 -0
  29. package/dist/agent-workflow/target.d.ts.map +1 -0
  30. package/dist/artifacts/index.d.ts +2 -2
  31. package/dist/artifacts/manifest.d.ts +1 -1
  32. package/dist/artifacts/types.d.ts +2 -2
  33. package/dist/comparison/eligibility.d.ts +1 -1
  34. package/dist/comparison/index.d.ts +1 -1
  35. package/dist/evaluators/combined.d.ts +2 -2
  36. package/dist/evaluators/contains.d.ts +2 -2
  37. package/dist/evaluators/exact.d.ts +2 -2
  38. package/dist/evaluators/fuzzy.d.ts +2 -2
  39. package/dist/evaluators/index.d.ts +13 -13
  40. package/dist/evaluators/inline.d.ts +2 -2
  41. package/dist/evaluators/json-schema.d.ts +2 -2
  42. package/dist/evaluators/llm-grader.d.ts +2 -2
  43. package/dist/evaluators/not-contains.d.ts +2 -2
  44. package/dist/evaluators/regex.d.ts +2 -2
  45. package/dist/evaluators/similarity.d.ts +2 -2
  46. package/dist/evaluators/tool-trace.d.ts +2 -2
  47. package/dist/evaluators/types.d.ts +3 -3
  48. package/dist/index.d.ts +15 -14
  49. package/dist/index.d.ts.map +1 -1
  50. package/dist/index.js +17827 -15174
  51. package/dist/provenance/execution-provenance.d.ts +1 -1
  52. package/dist/provenance/git.d.ts +1 -1
  53. package/dist/provenance/index.d.ts +4 -4
  54. package/dist/provenance/workload-identity.d.ts +2 -2
  55. package/dist/redaction/index.d.ts +2 -2
  56. package/dist/redaction/redactor.d.ts +1 -1
  57. package/dist/runner/executor.d.ts +3 -3
  58. package/dist/runner/index.d.ts +3 -3
  59. package/dist/runner/runner.d.ts +1 -1
  60. package/dist/runner/types.d.ts +5 -5
  61. package/dist/scenario/index.d.ts +4 -4
  62. package/dist/scenario/parser.d.ts +1 -1
  63. package/dist/scenario/variables.d.ts +1 -1
  64. package/dist/storage/factory.d.ts +1 -1
  65. package/dist/storage/index.d.ts +4 -4
  66. package/dist/storage/local.d.ts +2 -2
  67. package/dist/storage/supabase.d.ts +2 -2
  68. package/dist/storage/types.d.ts +2 -2
  69. package/dist/tools/fixture-executor.d.ts +2 -2
  70. package/dist/tools/index.d.ts +3 -3
  71. package/dist/tools/types.d.ts +1 -1
  72. package/dist/utils/index.d.ts +2 -2
  73. package/dist/validator/index.d.ts +2 -2
  74. package/dist/validator/validator.d.ts +1 -1
  75. package/package.json +4 -4
  76. package/src/adapters/types.ts +7 -0
  77. package/src/agent-workflow/catalog.ts +220 -0
  78. package/src/agent-workflow/environment.ts +207 -0
  79. package/src/agent-workflow/index.ts +10 -0
  80. package/src/agent-workflow/parser.ts +43 -0
  81. package/src/agent-workflow/sandbox-fixtures/qualify.ts +305 -0
  82. package/src/agent-workflow/sandbox.test.ts +117 -0
  83. package/src/agent-workflow/sandbox.ts +438 -0
  84. package/src/agent-workflow/schema.test.ts +218 -0
  85. package/src/agent-workflow/schema.ts +270 -0
  86. package/src/agent-workflow/session.test.ts +629 -0
  87. package/src/agent-workflow/session.ts +1119 -0
  88. package/src/agent-workflow/simulated-tools.test.ts +177 -0
  89. package/src/agent-workflow/simulated-tools.ts +230 -0
  90. package/src/agent-workflow/target.test.ts +280 -0
  91. package/src/agent-workflow/target.ts +357 -0
  92. package/src/index.ts +3 -0
@@ -0,0 +1,270 @@
1
+ import { z } from 'zod';
2
+ import { WORKFLOW_TOOL_IDS, getWorkflowTool } from './catalog';
3
+
4
+ export type WorkflowJson =
5
+ | null
6
+ | boolean
7
+ | number
8
+ | string
9
+ | WorkflowJson[]
10
+ | { [key: string]: WorkflowJson };
11
+ const forbiddenKeys = new Set(['__proto__', 'prototype', 'constructor']);
12
+
13
+ /** Limit both recursive work and retained fixture size before schema parsing/cloning. */
14
+ export function isWorkflowJson(value: unknown): value is WorkflowJson {
15
+ let nodes = 0;
16
+ let textBytes = 0;
17
+ const ancestors = new Set<object>();
18
+ function visit(item: unknown, depth: number): boolean {
19
+ if (++nodes > 10_000 || depth > 16) return false;
20
+ if (item === null || typeof item === 'boolean') return true;
21
+ if (typeof item === 'number') return Number.isFinite(item);
22
+ if (typeof item === 'string') {
23
+ textBytes += Buffer.byteLength(item);
24
+ return textBytes <= 1_048_576;
25
+ }
26
+ if (typeof item !== 'object' || ancestors.has(item)) return false;
27
+ if (
28
+ !Array.isArray(item) &&
29
+ Object.getPrototypeOf(item) !== Object.prototype &&
30
+ Object.getPrototypeOf(item) !== null
31
+ )
32
+ return false;
33
+ if (Object.getOwnPropertySymbols(item).length) return false;
34
+ if (
35
+ Array.isArray(item) &&
36
+ (item.length > 10_000 ||
37
+ Object.keys(item).length !== item.length ||
38
+ Object.keys(item).some((key, index) => key !== String(index)))
39
+ )
40
+ return false;
41
+ ancestors.add(item);
42
+ for (const key of Object.getOwnPropertyNames(item)) {
43
+ if (Array.isArray(item) && key === 'length') continue;
44
+ textBytes += Buffer.byteLength(key);
45
+ const entry = Object.getOwnPropertyDescriptor(item, key);
46
+ if (
47
+ textBytes > 1_048_576 ||
48
+ forbiddenKeys.has(key) ||
49
+ !entry ||
50
+ !('value' in entry) ||
51
+ !entry.enumerable ||
52
+ !visit(entry.value, depth + 1)
53
+ )
54
+ return false;
55
+ }
56
+ ancestors.delete(item);
57
+ return true;
58
+ }
59
+ return visit(value, 0);
60
+ }
61
+
62
+ export function isWorkflowRelativePath(value: string): boolean {
63
+ return (
64
+ value.length <= 512 &&
65
+ /^[A-Za-z0-9_-][A-Za-z0-9_./-]*$/.test(value) &&
66
+ value
67
+ .split('/')
68
+ .every((part) => part.length > 0 && part !== '.' && part !== '..' && !forbiddenKeys.has(part))
69
+ );
70
+ }
71
+
72
+ const json = z.custom<WorkflowJson>(
73
+ isWorkflowJson,
74
+ 'Expected bounded plain JSON without unsafe keys'
75
+ );
76
+ const jsonObject = json.refine(
77
+ (value) => value !== null && typeof value === 'object' && !Array.isArray(value),
78
+ 'Expected JSON object'
79
+ );
80
+ const relativePath = z.string().refine(isWorkflowRelativePath, 'Expected safe relative path');
81
+ const statePath = z
82
+ .string()
83
+ .max(512)
84
+ .refine(
85
+ (value) =>
86
+ value.split('.').every((part) => /^[A-Za-z0-9_-]+$/.test(part) && !forbiddenKeys.has(part)),
87
+ 'Expected safe dotted state path'
88
+ );
89
+ const permission = z.enum(['read', 'write']);
90
+
91
+ export const WorkflowPolicySchema = z
92
+ .object({
93
+ network: z.literal('denied'),
94
+ side_effects: z.enum(['denied', 'approval_required']),
95
+ permissions: z
96
+ .object({
97
+ documents: permission.optional(),
98
+ records: permission.optional(),
99
+ files: permission.optional(),
100
+ workflow_state: permission.optional(),
101
+ communication: permission.optional(),
102
+ coordination: permission.optional(),
103
+ })
104
+ .strict(),
105
+ paths: z
106
+ .object({ read: z.array(relativePath).max(1000), write: z.array(relativePath).max(1000) })
107
+ .strict()
108
+ .optional(),
109
+ budgets: z
110
+ .object({
111
+ max_actions: z.number().int().min(1).max(1000),
112
+ max_model_requests: z.number().int().min(1).max(1000).optional(),
113
+ max_tool_calls: z.number().int().min(1).max(1000).optional(),
114
+ timeout_ms: z.number().int().min(1).max(3_600_000),
115
+ max_tokens: z.number().int().min(1).max(1_000_000).optional(),
116
+ })
117
+ .strict(),
118
+ })
119
+ .strict();
120
+ export type WorkflowPolicy = z.infer<typeof WorkflowPolicySchema>;
121
+
122
+ const deterministic = z.discriminatedUnion('type', [
123
+ z.object({ type: z.literal('workflow_state'), path: statePath, equals: json }).strict(),
124
+ z
125
+ .object({
126
+ type: z.literal('tool_trace'),
127
+ tool: z.enum(WORKFLOW_TOOL_IDS),
128
+ minimum_calls: z.number().int().min(0).max(1000),
129
+ maximum_calls: z.number().int().min(0).max(1000).optional(),
130
+ })
131
+ .strict(),
132
+ z
133
+ .object({
134
+ type: z.literal('policy'),
135
+ rule: z.enum([
136
+ 'no_undeclared_tool',
137
+ 'permissions_respected',
138
+ 'network_denied',
139
+ 'budgets_respected',
140
+ 'no_external_side_effects',
141
+ ]),
142
+ expected: z.literal('passed'),
143
+ })
144
+ .strict(),
145
+ z
146
+ .object({
147
+ type: z.literal('file'),
148
+ path: relativePath,
149
+ exists: z.boolean(),
150
+ equals: z.string().max(16_384).optional(),
151
+ })
152
+ .strict(),
153
+ ]);
154
+
155
+ const definition = z
156
+ .object({
157
+ version: z.literal('1'),
158
+ kind: z.literal('agent_workflow'),
159
+ name: z
160
+ .string()
161
+ .min(1)
162
+ .max(128)
163
+ .refine((value) => value.trim().length > 0, 'Expected nonblank workflow name'),
164
+ description: z.string().max(4096).optional(),
165
+ target: z
166
+ .object({
167
+ provider: z
168
+ .string()
169
+ .min(1)
170
+ .max(64)
171
+ .regex(/^[a-z0-9_-]+$/),
172
+ model: z.string().min(1).max(256),
173
+ generation: z
174
+ .object({
175
+ max_tokens: z.number().int().min(1).max(1_000_000).optional(),
176
+ temperature: z.number().min(0).max(2).optional(),
177
+ })
178
+ .strict()
179
+ .optional(),
180
+ })
181
+ .strict(),
182
+ environment: z
183
+ .object({ type: z.enum(['simulated', 'sandbox']), policy: WorkflowPolicySchema })
184
+ .strict(),
185
+ tools: z.array(z.enum(WORKFLOW_TOOL_IDS)).min(1).max(WORKFLOW_TOOL_IDS.length),
186
+ workflow: z
187
+ .object({
188
+ system_instructions: z.string().min(1).max(32_768),
189
+ initial_state: z.union([relativePath, jsonObject]),
190
+ turns: z
191
+ .array(
192
+ z.object({ role: z.literal('user'), content: z.string().min(1).max(32_768) }).strict()
193
+ )
194
+ .min(1)
195
+ .max(100),
196
+ })
197
+ .strict(),
198
+ outcomes: z
199
+ .object({
200
+ deterministic: z.array(deterministic).min(1).max(100),
201
+ semantic: z
202
+ .array(
203
+ z
204
+ .object({
205
+ type: z.literal('llm_judge'),
206
+ rubric: z.string().min(1).max(16_384),
207
+ mode: z.literal('strict_assurance'),
208
+ })
209
+ .strict()
210
+ )
211
+ .max(20)
212
+ .optional(),
213
+ })
214
+ .strict(),
215
+ evidence: z
216
+ .object({
217
+ trace: z.literal('summary'),
218
+ artifacts: z.literal('checksums'),
219
+ redact: z.literal(true),
220
+ })
221
+ .strict(),
222
+ })
223
+ .strict()
224
+ .superRefine((workflow, ctx) => {
225
+ if (new Set(workflow.tools).size !== workflow.tools.length)
226
+ ctx.addIssue({ code: 'custom', path: ['tools'], message: 'Duplicate tool declaration' });
227
+ for (const [index, id] of workflow.tools.entries()) {
228
+ const tool = getWorkflowTool(id);
229
+ if (!tool || tool.authority.access === 'none') continue;
230
+ const resource = tool.authority.resource as keyof WorkflowPolicy['permissions'];
231
+ const grant = workflow.environment.policy.permissions[resource];
232
+ if (!grant || (tool.authority.access === 'write' && grant !== 'write'))
233
+ ctx.addIssue({
234
+ code: 'custom',
235
+ path: ['tools', index],
236
+ message: `Missing ${tool.authority.access} permission for ${resource}`,
237
+ });
238
+ }
239
+ workflow.outcomes.deterministic.forEach((outcome, index) => {
240
+ if (
241
+ outcome.type === 'tool_trace' &&
242
+ (!workflow.tools.includes(outcome.tool) ||
243
+ (outcome.maximum_calls !== undefined && outcome.maximum_calls < outcome.minimum_calls))
244
+ )
245
+ ctx.addIssue({
246
+ code: 'custom',
247
+ path: ['outcomes', 'deterministic', index],
248
+ message: 'Tool trace references an undeclared tool or inconsistent call bounds',
249
+ });
250
+ if (outcome.type === 'file' && !outcome.exists && outcome.equals !== undefined)
251
+ ctx.addIssue({
252
+ code: 'custom',
253
+ path: ['outcomes', 'deterministic', index],
254
+ message: 'An absent file cannot have expected content',
255
+ });
256
+ });
257
+ });
258
+
259
+ /** V1 rejects unavailable authority/environment features rather than silently accepting them. */
260
+ export const AgentWorkflowSchema = z
261
+ .unknown()
262
+ .superRefine((value, ctx) => {
263
+ if (!isWorkflowJson(value))
264
+ ctx.addIssue({
265
+ code: 'custom',
266
+ message: 'Workflow must be bounded plain JSON without unsafe keys',
267
+ });
268
+ })
269
+ .pipe(definition);
270
+ export type AgentWorkflow = z.infer<typeof AgentWorkflowSchema>;