@sequenceholdings/agent-spec 0.1.1 → 0.1.3
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.
- package/README.md +93 -0
- package/dist/agent-definition.d.ts +616 -0
- package/dist/agent-definition.js +240 -0
- package/dist/canonical-json.d.ts +2 -0
- package/dist/canonical-json.js +13 -0
- package/dist/index.d.ts +2 -117
- package/dist/index.js +2 -248
- package/dist/input-schema.d.ts +19 -0
- package/dist/input-schema.js +57 -0
- package/dist/voice-access.d.ts +40 -0
- package/dist/voice-access.js +34 -0
- package/dist/voice-actions-contracts.d.ts +423 -0
- package/dist/voice-actions-contracts.js +95 -0
- package/dist/voice-actions-transitions.d.ts +52 -0
- package/dist/voice-actions-transitions.js +170 -0
- package/dist/voice-actions.d.ts +2 -0
- package/dist/voice-actions.js +2 -0
- package/dist/voice-api.d.ts +1102 -0
- package/dist/voice-api.js +164 -0
- package/dist/voice-authoring.d.ts +463 -0
- package/dist/voice-authoring.js +132 -0
- package/dist/voice-authority-contracts.d.ts +247 -0
- package/dist/voice-authority-contracts.js +177 -0
- package/dist/voice-authority-evaluation.d.ts +29 -0
- package/dist/voice-authority-evaluation.js +80 -0
- package/dist/voice-authority-verification.d.ts +47 -0
- package/dist/voice-authority-verification.js +184 -0
- package/dist/voice-authority.d.ts +3 -0
- package/dist/voice-authority.js +3 -0
- package/dist/voice-common.d.ts +21 -0
- package/dist/voice-common.js +23 -0
- package/dist/voice-drafts.d.ts +441 -0
- package/dist/voice-drafts.js +75 -0
- package/dist/voice-grant.d.ts +19 -0
- package/dist/voice-grant.js +21 -0
- package/dist/voice-lifecycle-control.d.ts +130 -0
- package/dist/voice-lifecycle-control.js +138 -0
- package/dist/voice-lifecycle-session.d.ts +168 -0
- package/dist/voice-lifecycle-session.js +114 -0
- package/dist/voice-lifecycle-states.d.ts +96 -0
- package/dist/voice-lifecycle-states.js +139 -0
- package/dist/voice-lifecycle.d.ts +3 -0
- package/dist/voice-lifecycle.js +3 -0
- package/dist/voice-policy-duration.d.ts +46 -0
- package/dist/voice-policy-duration.js +166 -0
- package/dist/voice-policy-limits.d.ts +174 -0
- package/dist/voice-policy-limits.js +188 -0
- package/dist/voice-policy.d.ts +2 -0
- package/dist/voice-policy.js +2 -0
- package/dist/voice-provider-evidence.d.ts +80 -0
- package/dist/voice-provider-evidence.js +115 -0
- package/dist/voice-provider-publication.d.ts +319 -0
- package/dist/voice-provider-publication.js +117 -0
- package/dist/voice-provider-release.d.ts +386 -0
- package/dist/voice-provider-release.js +154 -0
- package/dist/voice-provider.d.ts +3 -0
- package/dist/voice-provider.js +3 -0
- package/dist/voice-release.d.ts +808 -0
- package/dist/voice-release.js +110 -0
- package/dist/voice-runs-audio.d.ts +157 -0
- package/dist/voice-runs-audio.js +85 -0
- package/dist/voice-runs-evidence.d.ts +183 -0
- package/dist/voice-runs-evidence.js +154 -0
- package/dist/voice-runs-model.d.ts +967 -0
- package/dist/voice-runs-model.js +199 -0
- package/dist/voice-runs-tooling.d.ts +88 -0
- package/dist/voice-runs-tooling.js +100 -0
- package/dist/voice-runs.d.ts +4 -0
- package/dist/voice-runs.js +4 -0
- package/dist/voice.d.ts +13 -0
- package/dist/voice.js +13 -0
- package/package.json +8 -3
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { inputSchemaSchema } from './input-schema.js';
|
|
4
|
+
import { canonicalJson, sortJson } from './canonical-json.js';
|
|
5
|
+
import { voiceDeclarationSchema } from './voice-authoring.js';
|
|
6
|
+
export { canonicalJson } from './canonical-json.js';
|
|
7
|
+
export { voiceDeclarationSchema } from './voice-authoring.js';
|
|
8
|
+
const OBJECT_ID_PATTERN = /^[0-9a-f]{24}$/;
|
|
9
|
+
const IDENTIFIER_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
10
|
+
const DEFAULT_MODEL = {
|
|
11
|
+
provider: 'anthropic',
|
|
12
|
+
name: 'claude-sonnet-4-5-20250929',
|
|
13
|
+
};
|
|
14
|
+
const jsonObjectSchema = z.record(z.string(), z.unknown());
|
|
15
|
+
const unsupportedConstraints = {
|
|
16
|
+
integer: ['minimum', 'maximum', 'exclusiveMinimum', 'exclusiveMaximum'],
|
|
17
|
+
number: ['minimum', 'maximum', 'exclusiveMinimum', 'exclusiveMaximum'],
|
|
18
|
+
array: ['minItems', 'maxItems', 'uniqueItems'],
|
|
19
|
+
string: ['minLength', 'maxLength', 'format', 'pattern'],
|
|
20
|
+
};
|
|
21
|
+
export function collectUnsupportedConstraints({ schema, path = '', }) {
|
|
22
|
+
if (schema === null || typeof schema !== 'object')
|
|
23
|
+
return [];
|
|
24
|
+
const object = schema;
|
|
25
|
+
const type = typeof object.type === 'string' ? object.type : undefined;
|
|
26
|
+
const violations = [];
|
|
27
|
+
if (type !== undefined) {
|
|
28
|
+
for (const keyword of unsupportedConstraints[type] ?? []) {
|
|
29
|
+
if (keyword in object) {
|
|
30
|
+
violations.push({ path: path || '(root)', type, keyword });
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
if (type === 'object' &&
|
|
35
|
+
object.properties !== null &&
|
|
36
|
+
typeof object.properties === 'object') {
|
|
37
|
+
for (const [key, value] of Object.entries(object.properties)) {
|
|
38
|
+
violations.push(...collectUnsupportedConstraints({
|
|
39
|
+
schema: value,
|
|
40
|
+
path: `${path}.properties.${key}`,
|
|
41
|
+
}));
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
if (type === 'array' && object.items !== undefined) {
|
|
45
|
+
violations.push(...collectUnsupportedConstraints({
|
|
46
|
+
schema: object.items,
|
|
47
|
+
path: `${path}.items`,
|
|
48
|
+
}));
|
|
49
|
+
}
|
|
50
|
+
for (const combinator of ['anyOf', 'oneOf', 'allOf', 'prefixItems']) {
|
|
51
|
+
const entries = object[combinator];
|
|
52
|
+
if (!Array.isArray(entries))
|
|
53
|
+
continue;
|
|
54
|
+
entries.forEach((entry, index) => {
|
|
55
|
+
violations.push(...collectUnsupportedConstraints({
|
|
56
|
+
schema: entry,
|
|
57
|
+
path: `${path}.${combinator}[${index}]`,
|
|
58
|
+
}));
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
return violations;
|
|
62
|
+
}
|
|
63
|
+
const modelSchema = z.object({
|
|
64
|
+
provider: z.string().min(1),
|
|
65
|
+
name: z.string().min(1),
|
|
66
|
+
});
|
|
67
|
+
export const AGENT_PERMISSION_ROLES = [
|
|
68
|
+
'owner',
|
|
69
|
+
'editor',
|
|
70
|
+
'invoker',
|
|
71
|
+
'outputs_viewer',
|
|
72
|
+
];
|
|
73
|
+
const permissionGrantSchema = z.object({
|
|
74
|
+
type: z.enum(['user', 'group']),
|
|
75
|
+
id: z.string().min(1),
|
|
76
|
+
role: z.enum(AGENT_PERMISSION_ROLES),
|
|
77
|
+
});
|
|
78
|
+
const subagentSchema = z.union([
|
|
79
|
+
z.string().min(1),
|
|
80
|
+
z.object({
|
|
81
|
+
id: z.string().min(1),
|
|
82
|
+
forkContext: z.boolean().optional(),
|
|
83
|
+
}),
|
|
84
|
+
]);
|
|
85
|
+
export const AGENT_REFERENCE_KINDS = ['mcp_server', 'skill', 'subagent', 'managed_function'];
|
|
86
|
+
export const agentReferenceSchema = z.strictObject({
|
|
87
|
+
kind: z.enum(AGENT_REFERENCE_KINDS),
|
|
88
|
+
id: z.string().min(1),
|
|
89
|
+
});
|
|
90
|
+
const openaiCodeInterpreterSchema = z.preprocess((value) => {
|
|
91
|
+
if (value === true)
|
|
92
|
+
return { enabled: true };
|
|
93
|
+
if (value === false)
|
|
94
|
+
return { enabled: false };
|
|
95
|
+
return value;
|
|
96
|
+
}, z.object({
|
|
97
|
+
enabled: z.boolean(),
|
|
98
|
+
containerId: z.string().min(1).optional(),
|
|
99
|
+
fileIds: z.array(z.string().min(1)).optional(),
|
|
100
|
+
}));
|
|
101
|
+
const textDefinitionBaseSchema = z
|
|
102
|
+
.strictObject({
|
|
103
|
+
id: z
|
|
104
|
+
.string()
|
|
105
|
+
.regex(OBJECT_ID_PATTERN, 'id must be a 24-character lowercase hex ObjectId'),
|
|
106
|
+
name: z.string().min(1),
|
|
107
|
+
description: z.string().optional(),
|
|
108
|
+
framework: z.enum(['vercel', 'claude-agent']).optional(),
|
|
109
|
+
vmBackend: z.enum(['gce', 'e2b']).optional(),
|
|
110
|
+
idleTimeoutSeconds: z.number().int().min(60).max(86_400).optional(),
|
|
111
|
+
agentCapabilities: jsonObjectSchema.nullish(),
|
|
112
|
+
claudeToolSearch: z.enum(['enabled', 'disabled', 'auto']).optional(),
|
|
113
|
+
claudeBuiltInTools: z.array(z.string()).default([]),
|
|
114
|
+
openaiCodeInterpreter: openaiCodeInterpreterSchema.nullish(),
|
|
115
|
+
model: modelSchema.default(DEFAULT_MODEL),
|
|
116
|
+
thinking: jsonObjectSchema.nullish(),
|
|
117
|
+
reasoningEffort: z.string().nullish(),
|
|
118
|
+
temperature: z.number().min(0).max(1).nullish(),
|
|
119
|
+
systemPrompt: z.string().optional(),
|
|
120
|
+
tools: z.array(z.string()).default([]),
|
|
121
|
+
mcpServers: z.array(z.string()).default([]),
|
|
122
|
+
requiredMcpServers: z.array(z.string()).default([]),
|
|
123
|
+
requiredReferences: z.array(agentReferenceSchema).optional(),
|
|
124
|
+
managedFunctions: z.array(z.string().min(1)).optional(),
|
|
125
|
+
excludedMcpTools: z.array(z.string()).default([]),
|
|
126
|
+
hideIntermediateText: z.boolean().optional(),
|
|
127
|
+
middleware: z.array(z.string()).default([]),
|
|
128
|
+
subagents: z.array(subagentSchema).default([]),
|
|
129
|
+
skills: z.array(z.string()).default([]),
|
|
130
|
+
contextFileIds: z.array(z.string()).default([]),
|
|
131
|
+
structuredOutput: jsonObjectSchema.optional(),
|
|
132
|
+
inputSchema: inputSchemaSchema.nullish(),
|
|
133
|
+
promptTemplate: z.string().optional(),
|
|
134
|
+
webhooks: jsonObjectSchema.optional(),
|
|
135
|
+
mcpServerConfigs: jsonObjectSchema.optional(),
|
|
136
|
+
stubConfig: jsonObjectSchema.nullish(),
|
|
137
|
+
maxTtlSeconds: z.number().int().positive().optional(),
|
|
138
|
+
agentPermissions: z.array(jsonObjectSchema).optional(),
|
|
139
|
+
apiPermissions: z.array(z.string()).optional(),
|
|
140
|
+
managedBy: z.literal('automation').nullish(),
|
|
141
|
+
isPublic: z.boolean().optional(),
|
|
142
|
+
publicOutputs: z.boolean().optional(),
|
|
143
|
+
permissions: z.array(permissionGrantSchema).optional(),
|
|
144
|
+
});
|
|
145
|
+
export const textAgentDefinitionSchema = textDefinitionBaseSchema.safeExtend({
|
|
146
|
+
mode: z.literal('text').optional(),
|
|
147
|
+
voice: z.never().optional(),
|
|
148
|
+
}).superRefine((definition, context) => {
|
|
149
|
+
for (const [index, serverId] of definition.requiredMcpServers.entries()) {
|
|
150
|
+
if (definition.mcpServers.includes(serverId))
|
|
151
|
+
continue;
|
|
152
|
+
context.addIssue({
|
|
153
|
+
code: 'custom',
|
|
154
|
+
path: ['requiredMcpServers', index],
|
|
155
|
+
message: `requiredMcpServers entry "${serverId}" must also appear in mcpServers`,
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
const declaredByKind = {
|
|
159
|
+
managed_function: new Set(definition.managedFunctions ?? []),
|
|
160
|
+
mcp_server: new Set(definition.mcpServers),
|
|
161
|
+
skill: new Set(definition.skills),
|
|
162
|
+
subagent: new Set(definition.subagents.map((entry) => typeof entry === 'string' ? entry : entry.id)),
|
|
163
|
+
};
|
|
164
|
+
for (const [index, reference] of (definition.requiredReferences ?? []).entries()) {
|
|
165
|
+
if (declaredByKind[reference.kind].has(reference.id))
|
|
166
|
+
continue;
|
|
167
|
+
context.addIssue({
|
|
168
|
+
code: 'custom',
|
|
169
|
+
path: ['requiredReferences', index],
|
|
170
|
+
message: `requiredReferences entry ${reference.kind} "${reference.id}" must also be declared on the agent`,
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
if (definition.structuredOutput?.enabled === true) {
|
|
174
|
+
const schema = definition.structuredOutput.schema;
|
|
175
|
+
for (const violation of collectUnsupportedConstraints({ schema })) {
|
|
176
|
+
context.addIssue({
|
|
177
|
+
code: 'custom',
|
|
178
|
+
path: ['structuredOutput', 'schema'],
|
|
179
|
+
message: `${violation.path}: "${violation.keyword}" on ${violation.type} is not supported`,
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
export const voiceAgentDefinitionSchema = textDefinitionBaseSchema.pick({
|
|
185
|
+
id: true, name: true, description: true, permissions: true,
|
|
186
|
+
}).extend({
|
|
187
|
+
mode: z.literal('voice'),
|
|
188
|
+
model: z.strictObject({ provider: z.string().trim().min(1).max(200), name: z.string().trim().min(1).max(200) }),
|
|
189
|
+
systemPrompt: z.string().min(1).max(100_000).refine((text) => text.trim().length > 0, 'Prompt must contain text'),
|
|
190
|
+
skills: z.array(z.string().trim().min(1).max(200)).max(32).default([])
|
|
191
|
+
.refine((ids) => new Set(ids).size === ids.length, 'Duplicate native Skill reference')
|
|
192
|
+
.transform((ids) => [...ids].sort()),
|
|
193
|
+
voice: voiceDeclarationSchema,
|
|
194
|
+
isPublic: z.literal(false).optional(),
|
|
195
|
+
publicOutputs: z.literal(false).optional(),
|
|
196
|
+
}).superRefine((definition, context) => {
|
|
197
|
+
const captured = new Set(definition.voice.procedures.map((item) => item.source.skillId));
|
|
198
|
+
if (definition.skills.length !== captured.size || definition.skills.some((id) => !captured.has(id))) {
|
|
199
|
+
context.addIssue({ code: 'custom', path: ['skills'], message: 'Native Skill references must match captured Voice procedures' });
|
|
200
|
+
}
|
|
201
|
+
});
|
|
202
|
+
export const agentDefinitionSchema = z.discriminatedUnion('mode', [
|
|
203
|
+
textAgentDefinitionSchema, voiceAgentDefinitionSchema,
|
|
204
|
+
]);
|
|
205
|
+
export function defineAgent(input) {
|
|
206
|
+
return agentDefinitionSchema.parse(input);
|
|
207
|
+
}
|
|
208
|
+
export function getAgentMode({ definition }) {
|
|
209
|
+
return definition.mode ?? 'text';
|
|
210
|
+
}
|
|
211
|
+
export function validateAgentModeUpdate({ existing, incoming }) {
|
|
212
|
+
const parsed = agentDefinitionSchema.parse(incoming);
|
|
213
|
+
if (existing.id !== parsed.id)
|
|
214
|
+
throw new Error('Agent identity cannot change across versions');
|
|
215
|
+
if (getAgentMode({ definition: existing }) !== getAgentMode({ definition: parsed })) {
|
|
216
|
+
throw new Error('Agent mode cannot change across versions');
|
|
217
|
+
}
|
|
218
|
+
return parsed;
|
|
219
|
+
}
|
|
220
|
+
export function canonicalAgentJson(definition) {
|
|
221
|
+
return canonicalJson(definition);
|
|
222
|
+
}
|
|
223
|
+
export function hashAgentBundle({ definitions, }) {
|
|
224
|
+
const canonical = [...definitions]
|
|
225
|
+
.sort((a, b) => a.id.localeCompare(b.id))
|
|
226
|
+
.map(canonicalAgentJson)
|
|
227
|
+
.join('\n');
|
|
228
|
+
return createHash('sha256').update('sequence-agent-bundle-v1\0').update(canonical).digest('hex');
|
|
229
|
+
}
|
|
230
|
+
export function formatAgentSource({ definition, exportName = 'agent', }) {
|
|
231
|
+
if (!IDENTIFIER_PATTERN.test(exportName)) {
|
|
232
|
+
throw new Error('exportName must be a valid TypeScript identifier');
|
|
233
|
+
}
|
|
234
|
+
const object = JSON.stringify(sortJson(definition), null, 2);
|
|
235
|
+
return ("import { defineAgent } from '@sequenceholdings/agent-spec'\n\n" +
|
|
236
|
+
`export const ${exportName} = defineAgent(${object})\n`);
|
|
237
|
+
}
|
|
238
|
+
export function generateAgentSource({ definition, exportName = 'agent', }) {
|
|
239
|
+
return formatAgentSource({ definition: defineAgent(definition), exportName });
|
|
240
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export function sortJson(value) {
|
|
2
|
+
if (Array.isArray(value))
|
|
3
|
+
return value.map(sortJson);
|
|
4
|
+
if (value === null || typeof value !== 'object')
|
|
5
|
+
return value;
|
|
6
|
+
return Object.fromEntries(Object.entries(value)
|
|
7
|
+
.sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0)
|
|
8
|
+
.filter(([, nested]) => nested !== undefined)
|
|
9
|
+
.map(([key, nested]) => [key, sortJson(nested)]));
|
|
10
|
+
}
|
|
11
|
+
export function canonicalJson(value) {
|
|
12
|
+
return JSON.stringify(sortJson(value));
|
|
13
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,117 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
export
|
|
3
|
-
path: string;
|
|
4
|
-
type: string;
|
|
5
|
-
keyword: string;
|
|
6
|
-
};
|
|
7
|
-
export declare function collectUnsupportedConstraints({ schema, path, }: {
|
|
8
|
-
schema: unknown;
|
|
9
|
-
path?: string;
|
|
10
|
-
}): UnsupportedConstraint[];
|
|
11
|
-
export declare const AGENT_PERMISSION_ROLES: readonly ["owner", "editor", "invoker", "outputs_viewer"];
|
|
12
|
-
export type AgentPermissionRole = (typeof AGENT_PERMISSION_ROLES)[number];
|
|
13
|
-
export declare const agentDefinitionSchema: z.ZodObject<{
|
|
14
|
-
id: z.ZodString;
|
|
15
|
-
name: z.ZodString;
|
|
16
|
-
description: z.ZodOptional<z.ZodString>;
|
|
17
|
-
framework: z.ZodOptional<z.ZodEnum<{
|
|
18
|
-
vercel: "vercel";
|
|
19
|
-
"claude-agent": "claude-agent";
|
|
20
|
-
}>>;
|
|
21
|
-
vmBackend: z.ZodOptional<z.ZodEnum<{
|
|
22
|
-
gce: "gce";
|
|
23
|
-
e2b: "e2b";
|
|
24
|
-
}>>;
|
|
25
|
-
idleTimeoutSeconds: z.ZodOptional<z.ZodNumber>;
|
|
26
|
-
agentCapabilities: z.ZodOptional<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
|
|
27
|
-
claudeToolSearch: z.ZodOptional<z.ZodEnum<{
|
|
28
|
-
enabled: "enabled";
|
|
29
|
-
disabled: "disabled";
|
|
30
|
-
auto: "auto";
|
|
31
|
-
}>>;
|
|
32
|
-
claudeBuiltInTools: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
33
|
-
openaiCodeInterpreter: z.ZodOptional<z.ZodNullable<z.ZodPreprocess<z.ZodObject<{
|
|
34
|
-
enabled: z.ZodBoolean;
|
|
35
|
-
containerId: z.ZodOptional<z.ZodString>;
|
|
36
|
-
fileIds: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
37
|
-
}, z.core.$strip>>>>;
|
|
38
|
-
model: z.ZodDefault<z.ZodObject<{
|
|
39
|
-
provider: z.ZodString;
|
|
40
|
-
name: z.ZodString;
|
|
41
|
-
}, z.core.$strip>>;
|
|
42
|
-
thinking: z.ZodOptional<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
|
|
43
|
-
reasoningEffort: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
44
|
-
temperature: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
45
|
-
systemPrompt: z.ZodOptional<z.ZodString>;
|
|
46
|
-
tools: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
47
|
-
mcpServers: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
48
|
-
requiredMcpServers: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
49
|
-
excludedMcpTools: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
50
|
-
hideIntermediateText: z.ZodOptional<z.ZodBoolean>;
|
|
51
|
-
middleware: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
52
|
-
subagents: z.ZodDefault<z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
|
|
53
|
-
id: z.ZodString;
|
|
54
|
-
forkContext: z.ZodOptional<z.ZodBoolean>;
|
|
55
|
-
}, z.core.$strip>]>>>;
|
|
56
|
-
skills: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
57
|
-
contextFileIds: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
58
|
-
structuredOutput: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
59
|
-
inputSchema: z.ZodOptional<z.ZodNullable<z.ZodObject<{
|
|
60
|
-
fields: z.ZodArray<z.ZodObject<{
|
|
61
|
-
name: z.ZodString;
|
|
62
|
-
label: z.ZodOptional<z.ZodString>;
|
|
63
|
-
description: z.ZodOptional<z.ZodString>;
|
|
64
|
-
type: z.ZodEnum<{
|
|
65
|
-
string: "string";
|
|
66
|
-
number: "number";
|
|
67
|
-
boolean: "boolean";
|
|
68
|
-
enum: "enum";
|
|
69
|
-
text: "text";
|
|
70
|
-
}>;
|
|
71
|
-
required: z.ZodOptional<z.ZodBoolean>;
|
|
72
|
-
default: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>;
|
|
73
|
-
enum: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
74
|
-
placeholder: z.ZodOptional<z.ZodString>;
|
|
75
|
-
}, z.core.$strip>>;
|
|
76
|
-
}, z.core.$strip>>>;
|
|
77
|
-
promptTemplate: z.ZodOptional<z.ZodString>;
|
|
78
|
-
webhooks: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
79
|
-
mcpServerConfigs: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
80
|
-
aiCheckerConfig: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
81
|
-
stubConfig: z.ZodOptional<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
|
|
82
|
-
maxTtlSeconds: z.ZodOptional<z.ZodNumber>;
|
|
83
|
-
agentPermissions: z.ZodOptional<z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
|
|
84
|
-
apiPermissions: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
85
|
-
managedBy: z.ZodOptional<z.ZodNullable<z.ZodLiteral<"automation">>>;
|
|
86
|
-
isPublic: z.ZodOptional<z.ZodBoolean>;
|
|
87
|
-
publicOutputs: z.ZodOptional<z.ZodBoolean>;
|
|
88
|
-
permissions: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
89
|
-
type: z.ZodEnum<{
|
|
90
|
-
user: "user";
|
|
91
|
-
group: "group";
|
|
92
|
-
}>;
|
|
93
|
-
id: z.ZodString;
|
|
94
|
-
role: z.ZodEnum<{
|
|
95
|
-
owner: "owner";
|
|
96
|
-
editor: "editor";
|
|
97
|
-
invoker: "invoker";
|
|
98
|
-
outputs_viewer: "outputs_viewer";
|
|
99
|
-
}>;
|
|
100
|
-
}, z.core.$strip>>>;
|
|
101
|
-
}, z.core.$strict>;
|
|
102
|
-
export type AgentDefinition = z.infer<typeof agentDefinitionSchema>;
|
|
103
|
-
export type AgentDefinitionInput = z.input<typeof agentDefinitionSchema>;
|
|
104
|
-
export declare function defineAgent(input: AgentDefinitionInput): AgentDefinition;
|
|
105
|
-
export declare function canonicalJson(value: unknown): string;
|
|
106
|
-
export declare function canonicalAgentJson(definition: AgentDefinition): string;
|
|
107
|
-
export declare function hashAgentBundle({ definitions, }: {
|
|
108
|
-
definitions: AgentDefinition[];
|
|
109
|
-
}): string;
|
|
110
|
-
export declare function formatAgentSource({ definition, exportName, }: {
|
|
111
|
-
definition: unknown;
|
|
112
|
-
exportName?: string;
|
|
113
|
-
}): string;
|
|
114
|
-
export declare function generateAgentSource({ definition, exportName, }: {
|
|
115
|
-
definition: AgentDefinition;
|
|
116
|
-
exportName?: string;
|
|
117
|
-
}): string;
|
|
1
|
+
export * from './agent-definition.js';
|
|
2
|
+
export * from './voice.js';
|
package/dist/index.js
CHANGED
|
@@ -1,248 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const OBJECT_ID_PATTERN = /^[0-9a-f]{24}$/;
|
|
4
|
-
const IDENTIFIER_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
5
|
-
const DEFAULT_MODEL = {
|
|
6
|
-
provider: 'anthropic',
|
|
7
|
-
name: 'claude-sonnet-4-5-20250929',
|
|
8
|
-
};
|
|
9
|
-
const jsonObjectSchema = z.record(z.string(), z.unknown());
|
|
10
|
-
const unsupportedConstraints = {
|
|
11
|
-
integer: ['minimum', 'maximum', 'exclusiveMinimum', 'exclusiveMaximum'],
|
|
12
|
-
number: ['minimum', 'maximum', 'exclusiveMinimum', 'exclusiveMaximum'],
|
|
13
|
-
array: ['minItems', 'maxItems', 'uniqueItems'],
|
|
14
|
-
string: ['minLength', 'maxLength', 'format', 'pattern'],
|
|
15
|
-
};
|
|
16
|
-
export function collectUnsupportedConstraints({ schema, path = '', }) {
|
|
17
|
-
if (schema === null || typeof schema !== 'object')
|
|
18
|
-
return [];
|
|
19
|
-
const object = schema;
|
|
20
|
-
const type = typeof object.type === 'string' ? object.type : undefined;
|
|
21
|
-
const violations = [];
|
|
22
|
-
if (type !== undefined) {
|
|
23
|
-
for (const keyword of unsupportedConstraints[type] ?? []) {
|
|
24
|
-
if (keyword in object) {
|
|
25
|
-
violations.push({ path: path || '(root)', type, keyword });
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
if (type === 'object' &&
|
|
30
|
-
object.properties !== null &&
|
|
31
|
-
typeof object.properties === 'object') {
|
|
32
|
-
for (const [key, value] of Object.entries(object.properties)) {
|
|
33
|
-
violations.push(...collectUnsupportedConstraints({
|
|
34
|
-
schema: value,
|
|
35
|
-
path: `${path}.properties.${key}`,
|
|
36
|
-
}));
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
if (type === 'array' && object.items !== undefined) {
|
|
40
|
-
violations.push(...collectUnsupportedConstraints({
|
|
41
|
-
schema: object.items,
|
|
42
|
-
path: `${path}.items`,
|
|
43
|
-
}));
|
|
44
|
-
}
|
|
45
|
-
for (const combinator of ['anyOf', 'oneOf', 'allOf', 'prefixItems']) {
|
|
46
|
-
const entries = object[combinator];
|
|
47
|
-
if (!Array.isArray(entries))
|
|
48
|
-
continue;
|
|
49
|
-
entries.forEach((entry, index) => {
|
|
50
|
-
violations.push(...collectUnsupportedConstraints({
|
|
51
|
-
schema: entry,
|
|
52
|
-
path: `${path}.${combinator}[${index}]`,
|
|
53
|
-
}));
|
|
54
|
-
});
|
|
55
|
-
}
|
|
56
|
-
return violations;
|
|
57
|
-
}
|
|
58
|
-
const modelSchema = z.object({
|
|
59
|
-
provider: z.string().min(1),
|
|
60
|
-
name: z.string().min(1),
|
|
61
|
-
});
|
|
62
|
-
export const AGENT_PERMISSION_ROLES = [
|
|
63
|
-
'owner',
|
|
64
|
-
'editor',
|
|
65
|
-
'invoker',
|
|
66
|
-
'outputs_viewer',
|
|
67
|
-
];
|
|
68
|
-
const permissionGrantSchema = z.object({
|
|
69
|
-
type: z.enum(['user', 'group']),
|
|
70
|
-
id: z.string().min(1),
|
|
71
|
-
role: z.enum(AGENT_PERMISSION_ROLES),
|
|
72
|
-
});
|
|
73
|
-
const subagentSchema = z.union([
|
|
74
|
-
z.string().min(1),
|
|
75
|
-
z.object({
|
|
76
|
-
id: z.string().min(1),
|
|
77
|
-
forkContext: z.boolean().optional(),
|
|
78
|
-
}),
|
|
79
|
-
]);
|
|
80
|
-
const inputFieldSchema = z
|
|
81
|
-
.object({
|
|
82
|
-
name: z
|
|
83
|
-
.string()
|
|
84
|
-
.min(1)
|
|
85
|
-
.regex(/^[A-Za-z_][A-Za-z0-9_]*$/, 'name must be a valid identifier'),
|
|
86
|
-
label: z.string().optional(),
|
|
87
|
-
description: z.string().optional(),
|
|
88
|
-
type: z.enum(['string', 'text', 'number', 'boolean', 'enum']),
|
|
89
|
-
required: z.boolean().optional(),
|
|
90
|
-
default: z.union([z.string(), z.number(), z.boolean()]).optional(),
|
|
91
|
-
enum: z.array(z.string()).optional(),
|
|
92
|
-
placeholder: z.string().optional(),
|
|
93
|
-
})
|
|
94
|
-
.superRefine((field, context) => {
|
|
95
|
-
if (field.type === 'enum') {
|
|
96
|
-
if (field.enum === undefined || field.enum.length === 0) {
|
|
97
|
-
context.addIssue({
|
|
98
|
-
code: 'custom',
|
|
99
|
-
path: ['enum'],
|
|
100
|
-
message: 'enum fields require at least one option',
|
|
101
|
-
});
|
|
102
|
-
}
|
|
103
|
-
if (field.default !== undefined &&
|
|
104
|
-
(typeof field.default !== 'string' ||
|
|
105
|
-
!field.enum?.includes(field.default))) {
|
|
106
|
-
context.addIssue({
|
|
107
|
-
code: 'custom',
|
|
108
|
-
path: ['default'],
|
|
109
|
-
message: 'default must be one of the declared enum options',
|
|
110
|
-
});
|
|
111
|
-
}
|
|
112
|
-
return;
|
|
113
|
-
}
|
|
114
|
-
if (field.default === undefined)
|
|
115
|
-
return;
|
|
116
|
-
const expected = field.type === 'number'
|
|
117
|
-
? 'number'
|
|
118
|
-
: field.type === 'boolean'
|
|
119
|
-
? 'boolean'
|
|
120
|
-
: 'string';
|
|
121
|
-
if (typeof field.default !== expected) {
|
|
122
|
-
context.addIssue({
|
|
123
|
-
code: 'custom',
|
|
124
|
-
path: ['default'],
|
|
125
|
-
message: `default for ${field.type} fields must be a ${expected}`,
|
|
126
|
-
});
|
|
127
|
-
}
|
|
128
|
-
});
|
|
129
|
-
const inputSchemaSchema = z
|
|
130
|
-
.object({ fields: z.array(inputFieldSchema) })
|
|
131
|
-
.refine((schema) => new Set(schema.fields.map((field) => field.name)).size ===
|
|
132
|
-
schema.fields.length, {
|
|
133
|
-
path: ['fields'],
|
|
134
|
-
message: 'fields[].name must be unique within an inputSchema',
|
|
135
|
-
});
|
|
136
|
-
const openaiCodeInterpreterSchema = z.preprocess((value) => {
|
|
137
|
-
if (value === true)
|
|
138
|
-
return { enabled: true };
|
|
139
|
-
if (value === false)
|
|
140
|
-
return { enabled: false };
|
|
141
|
-
return value;
|
|
142
|
-
}, z.object({
|
|
143
|
-
enabled: z.boolean(),
|
|
144
|
-
containerId: z.string().min(1).optional(),
|
|
145
|
-
fileIds: z.array(z.string().min(1)).optional(),
|
|
146
|
-
}));
|
|
147
|
-
export const agentDefinitionSchema = z
|
|
148
|
-
.strictObject({
|
|
149
|
-
id: z
|
|
150
|
-
.string()
|
|
151
|
-
.regex(OBJECT_ID_PATTERN, 'id must be a 24-character lowercase hex ObjectId'),
|
|
152
|
-
name: z.string().min(1),
|
|
153
|
-
description: z.string().optional(),
|
|
154
|
-
framework: z.enum(['vercel', 'claude-agent']).optional(),
|
|
155
|
-
vmBackend: z.enum(['gce', 'e2b']).optional(),
|
|
156
|
-
idleTimeoutSeconds: z.number().int().min(60).max(86_400).optional(),
|
|
157
|
-
agentCapabilities: jsonObjectSchema.nullish(),
|
|
158
|
-
claudeToolSearch: z.enum(['enabled', 'disabled', 'auto']).optional(),
|
|
159
|
-
claudeBuiltInTools: z.array(z.string()).default([]),
|
|
160
|
-
openaiCodeInterpreter: openaiCodeInterpreterSchema.nullish(),
|
|
161
|
-
model: modelSchema.default(DEFAULT_MODEL),
|
|
162
|
-
thinking: jsonObjectSchema.nullish(),
|
|
163
|
-
reasoningEffort: z.string().nullish(),
|
|
164
|
-
temperature: z.number().min(0).max(1).nullish(),
|
|
165
|
-
systemPrompt: z.string().optional(),
|
|
166
|
-
tools: z.array(z.string()).default([]),
|
|
167
|
-
mcpServers: z.array(z.string()).default([]),
|
|
168
|
-
requiredMcpServers: z.array(z.string()).default([]),
|
|
169
|
-
excludedMcpTools: z.array(z.string()).default([]),
|
|
170
|
-
hideIntermediateText: z.boolean().optional(),
|
|
171
|
-
middleware: z.array(z.string()).default([]),
|
|
172
|
-
subagents: z.array(subagentSchema).default([]),
|
|
173
|
-
skills: z.array(z.string()).default([]),
|
|
174
|
-
contextFileIds: z.array(z.string()).default([]),
|
|
175
|
-
structuredOutput: jsonObjectSchema.optional(),
|
|
176
|
-
inputSchema: inputSchemaSchema.nullish(),
|
|
177
|
-
promptTemplate: z.string().optional(),
|
|
178
|
-
webhooks: jsonObjectSchema.optional(),
|
|
179
|
-
mcpServerConfigs: jsonObjectSchema.optional(),
|
|
180
|
-
aiCheckerConfig: jsonObjectSchema.optional(),
|
|
181
|
-
stubConfig: jsonObjectSchema.nullish(),
|
|
182
|
-
maxTtlSeconds: z.number().int().positive().optional(),
|
|
183
|
-
agentPermissions: z.array(jsonObjectSchema).optional(),
|
|
184
|
-
apiPermissions: z.array(z.string()).optional(),
|
|
185
|
-
managedBy: z.literal('automation').nullish(),
|
|
186
|
-
isPublic: z.boolean().optional(),
|
|
187
|
-
publicOutputs: z.boolean().optional(),
|
|
188
|
-
permissions: z.array(permissionGrantSchema).optional(),
|
|
189
|
-
})
|
|
190
|
-
.superRefine((definition, context) => {
|
|
191
|
-
for (const [index, serverId] of definition.requiredMcpServers.entries()) {
|
|
192
|
-
if (definition.mcpServers.includes(serverId))
|
|
193
|
-
continue;
|
|
194
|
-
context.addIssue({
|
|
195
|
-
code: 'custom',
|
|
196
|
-
path: ['requiredMcpServers', index],
|
|
197
|
-
message: `requiredMcpServers entry "${serverId}" must also appear in mcpServers`,
|
|
198
|
-
});
|
|
199
|
-
}
|
|
200
|
-
if (definition.structuredOutput?.enabled === true) {
|
|
201
|
-
const schema = definition.structuredOutput.schema;
|
|
202
|
-
for (const violation of collectUnsupportedConstraints({ schema })) {
|
|
203
|
-
context.addIssue({
|
|
204
|
-
code: 'custom',
|
|
205
|
-
path: ['structuredOutput', 'schema'],
|
|
206
|
-
message: `${violation.path}: "${violation.keyword}" on ${violation.type} is not supported`,
|
|
207
|
-
});
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
});
|
|
211
|
-
export function defineAgent(input) {
|
|
212
|
-
return agentDefinitionSchema.parse(input);
|
|
213
|
-
}
|
|
214
|
-
function sortJson(value) {
|
|
215
|
-
if (Array.isArray(value))
|
|
216
|
-
return value.map(sortJson);
|
|
217
|
-
if (value === null || typeof value !== 'object')
|
|
218
|
-
return value;
|
|
219
|
-
const object = value;
|
|
220
|
-
return Object.fromEntries(Object.keys(object)
|
|
221
|
-
.sort()
|
|
222
|
-
.filter((key) => object[key] !== undefined)
|
|
223
|
-
.map((key) => [key, sortJson(object[key])]));
|
|
224
|
-
}
|
|
225
|
-
export function canonicalJson(value) {
|
|
226
|
-
return JSON.stringify(sortJson(value));
|
|
227
|
-
}
|
|
228
|
-
export function canonicalAgentJson(definition) {
|
|
229
|
-
return canonicalJson(definition);
|
|
230
|
-
}
|
|
231
|
-
export function hashAgentBundle({ definitions, }) {
|
|
232
|
-
const canonical = [...definitions]
|
|
233
|
-
.sort((a, b) => a.id.localeCompare(b.id))
|
|
234
|
-
.map(canonicalAgentJson)
|
|
235
|
-
.join('\n');
|
|
236
|
-
return createHash('sha256').update('sequence-agent-bundle-v1\0').update(canonical).digest('hex');
|
|
237
|
-
}
|
|
238
|
-
export function formatAgentSource({ definition, exportName = 'agent', }) {
|
|
239
|
-
if (!IDENTIFIER_PATTERN.test(exportName)) {
|
|
240
|
-
throw new Error('exportName must be a valid TypeScript identifier');
|
|
241
|
-
}
|
|
242
|
-
const object = JSON.stringify(sortJson(definition), null, 2);
|
|
243
|
-
return ("import { defineAgent } from '@sequenceholdings/agent-spec'\n\n" +
|
|
244
|
-
`export const ${exportName} = defineAgent(${object})\n`);
|
|
245
|
-
}
|
|
246
|
-
export function generateAgentSource({ definition, exportName = 'agent', }) {
|
|
247
|
-
return formatAgentSource({ definition: defineAgent(definition), exportName });
|
|
248
|
-
}
|
|
1
|
+
export * from './agent-definition.js';
|
|
2
|
+
export * from './voice.js';
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const inputSchemaSchema: z.ZodObject<{
|
|
3
|
+
fields: z.ZodArray<z.ZodObject<{
|
|
4
|
+
name: z.ZodString;
|
|
5
|
+
label: z.ZodOptional<z.ZodString>;
|
|
6
|
+
description: z.ZodOptional<z.ZodString>;
|
|
7
|
+
type: z.ZodEnum<{
|
|
8
|
+
string: "string";
|
|
9
|
+
number: "number";
|
|
10
|
+
boolean: "boolean";
|
|
11
|
+
text: "text";
|
|
12
|
+
enum: "enum";
|
|
13
|
+
}>;
|
|
14
|
+
required: z.ZodOptional<z.ZodBoolean>;
|
|
15
|
+
default: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>;
|
|
16
|
+
enum: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
17
|
+
placeholder: z.ZodOptional<z.ZodString>;
|
|
18
|
+
}, z.core.$strip>>;
|
|
19
|
+
}, z.core.$strip>;
|