spawnfile 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.
- package/LICENSE +21 -0
- package/README.md +464 -0
- package/dist/.env.example +5 -0
- package/dist/Dockerfile +21 -0
- package/dist/auth/importers.d.ts +8 -0
- package/dist/auth/importers.js +93 -0
- package/dist/auth/index.d.ts +5 -0
- package/dist/auth/index.js +5 -0
- package/dist/auth/paths.d.ts +6 -0
- package/dist/auth/paths.js +18 -0
- package/dist/auth/profileStore.d.ts +10 -0
- package/dist/auth/profileStore.js +125 -0
- package/dist/auth/runtimeCredentials.d.ts +14 -0
- package/dist/auth/runtimeCredentials.js +76 -0
- package/dist/auth/types.d.ts +22 -0
- package/dist/auth/types.js +1 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.js +4 -0
- package/dist/cli/runCli.d.ts +27 -0
- package/dist/cli/runCli.js +314 -0
- package/dist/compiler/addProjectNode.d.ts +21 -0
- package/dist/compiler/addProjectNode.js +126 -0
- package/dist/compiler/agentSurfaces.d.ts +4 -0
- package/dist/compiler/agentSurfaces.js +70 -0
- package/dist/compiler/buildCompilePlan.d.ts +2 -0
- package/dist/compiler/buildCompilePlan.js +258 -0
- package/dist/compiler/buildProject.d.ts +20 -0
- package/dist/compiler/buildProject.js +52 -0
- package/dist/compiler/compilePlanHelpers.d.ts +7 -0
- package/dist/compiler/compilePlanHelpers.js +39 -0
- package/dist/compiler/compileProject.d.ts +11 -0
- package/dist/compiler/compileProject.js +182 -0
- package/dist/compiler/containerArtifacts.d.ts +4 -0
- package/dist/compiler/containerArtifacts.js +64 -0
- package/dist/compiler/containerArtifactsPlans.d.ts +4 -0
- package/dist/compiler/containerArtifactsPlans.js +154 -0
- package/dist/compiler/containerArtifactsRender.d.ts +6 -0
- package/dist/compiler/containerArtifactsRender.js +237 -0
- package/dist/compiler/containerArtifactsTypes.d.ts +42 -0
- package/dist/compiler/containerArtifactsTypes.js +1 -0
- package/dist/compiler/discordSurface.d.ts +4 -0
- package/dist/compiler/discordSurface.js +28 -0
- package/dist/compiler/executionDefaults.d.ts +2 -0
- package/dist/compiler/executionDefaults.js +9 -0
- package/dist/compiler/helpers.d.ts +7 -0
- package/dist/compiler/helpers.js +35 -0
- package/dist/compiler/index.d.ts +9 -0
- package/dist/compiler/index.js +9 -0
- package/dist/compiler/initProject.d.ts +9 -0
- package/dist/compiler/initProject.js +46 -0
- package/dist/compiler/modelAuth.d.ts +2 -0
- package/dist/compiler/modelAuth.js +17 -0
- package/dist/compiler/modelEnv.d.ts +10 -0
- package/dist/compiler/modelEnv.js +97 -0
- package/dist/compiler/runProject.d.ts +34 -0
- package/dist/compiler/runProject.js +197 -0
- package/dist/compiler/runProjectAuth.d.ts +9 -0
- package/dist/compiler/runProjectAuth.js +59 -0
- package/dist/compiler/surfaceSupport.d.ts +2 -0
- package/dist/compiler/surfaceSupport.js +13 -0
- package/dist/compiler/surfaces.d.ts +21 -0
- package/dist/compiler/surfaces.js +59 -0
- package/dist/compiler/syncProjectAuth.d.ts +7 -0
- package/dist/compiler/syncProjectAuth.js +65 -0
- package/dist/compiler/types.d.ts +134 -0
- package/dist/compiler/types.js +1 -0
- package/dist/compiler/updateProjectModels.d.ts +20 -0
- package/dist/compiler/updateProjectModels.js +181 -0
- package/dist/container/rootfs/var/lib/spawnfile/instances/picoclaw/agent-assistant/picoclaw/config.json +16 -0
- package/dist/container/rootfs/var/lib/spawnfile/instances/picoclaw/agent-assistant/picoclaw/workspace/AGENTS.md +1 -0
- package/dist/e2e/cli.d.ts +1 -0
- package/dist/e2e/cli.js +40 -0
- package/dist/e2e/dockerAuth.d.ts +18 -0
- package/dist/e2e/dockerAuth.js +212 -0
- package/dist/e2e/fixtures.d.ts +2 -0
- package/dist/e2e/fixtures.js +49 -0
- package/dist/e2e/index.d.ts +4 -0
- package/dist/e2e/index.js +4 -0
- package/dist/e2e/runtimePrompts.d.ts +13 -0
- package/dist/e2e/runtimePrompts.js +132 -0
- package/dist/e2e/scenarios.d.ts +3 -0
- package/dist/e2e/scenarios.js +84 -0
- package/dist/e2e/types.d.ts +35 -0
- package/dist/e2e/types.js +1 -0
- package/dist/entrypoint.sh +71 -0
- package/dist/filesystem/index.d.ts +2 -0
- package/dist/filesystem/index.js +2 -0
- package/dist/filesystem/io.d.ts +11 -0
- package/dist/filesystem/io.js +57 -0
- package/dist/filesystem/paths.d.ts +6 -0
- package/dist/filesystem/paths.js +30 -0
- package/dist/manifest/index.d.ts +5 -0
- package/dist/manifest/index.js +5 -0
- package/dist/manifest/loadManifest.d.ts +12 -0
- package/dist/manifest/loadManifest.js +208 -0
- package/dist/manifest/renderSpawnfile.d.ts +2 -0
- package/dist/manifest/renderSpawnfile.js +211 -0
- package/dist/manifest/scaffold.d.ts +16 -0
- package/dist/manifest/scaffold.js +41 -0
- package/dist/manifest/schemas.d.ts +989 -0
- package/dist/manifest/schemas.js +314 -0
- package/dist/manifest/skillFrontmatter.d.ts +5 -0
- package/dist/manifest/skillFrontmatter.js +32 -0
- package/dist/manifest/surfaceSchemas.d.ts +148 -0
- package/dist/manifest/surfaceSchemas.js +162 -0
- package/dist/report/createDiagnostic.d.ts +2 -0
- package/dist/report/createDiagnostic.js +4 -0
- package/dist/report/createReport.d.ts +2 -0
- package/dist/report/createReport.js +7 -0
- package/dist/report/index.d.ts +4 -0
- package/dist/report/index.js +4 -0
- package/dist/report/types.d.ts +50 -0
- package/dist/report/types.js +1 -0
- package/dist/report/writeReport.d.ts +2 -0
- package/dist/report/writeReport.js +9 -0
- package/dist/runtime/common.d.ts +13 -0
- package/dist/runtime/common.js +63 -0
- package/dist/runtime/container.d.ts +8 -0
- package/dist/runtime/container.js +67 -0
- package/dist/runtime/index.d.ts +4 -0
- package/dist/runtime/index.js +4 -0
- package/dist/runtime/install.d.ts +51 -0
- package/dist/runtime/install.js +167 -0
- package/dist/runtime/openclaw/adapter.d.ts +2 -0
- package/dist/runtime/openclaw/adapter.js +194 -0
- package/dist/runtime/openclaw/runAuth.d.ts +2 -0
- package/dist/runtime/openclaw/runAuth.js +125 -0
- package/dist/runtime/openclaw/scaffold-assets/AGENTS.md +120 -0
- package/dist/runtime/openclaw/scaffold-assets/CLAUDE.md +5 -0
- package/dist/runtime/openclaw/scaffold-assets/IDENTITY.md +23 -0
- package/dist/runtime/openclaw/scaffold-assets/SOUL.md +36 -0
- package/dist/runtime/openclaw/scaffold.d.ts +2 -0
- package/dist/runtime/openclaw/scaffold.js +28 -0
- package/dist/runtime/openclaw/surfaces.d.ts +5 -0
- package/dist/runtime/openclaw/surfaces.js +253 -0
- package/dist/runtime/picoclaw/adapter.d.ts +2 -0
- package/dist/runtime/picoclaw/adapter.js +204 -0
- package/dist/runtime/picoclaw/runAuth.d.ts +2 -0
- package/dist/runtime/picoclaw/runAuth.js +117 -0
- package/dist/runtime/picoclaw/scaffold-assets/AGENTS.md +3 -0
- package/dist/runtime/picoclaw/scaffold-assets/CLAUDE.md +5 -0
- package/dist/runtime/picoclaw/scaffold-assets/IDENTITY.md +3 -0
- package/dist/runtime/picoclaw/scaffold-assets/SOUL.md +3 -0
- package/dist/runtime/picoclaw/scaffold.d.ts +2 -0
- package/dist/runtime/picoclaw/scaffold.js +28 -0
- package/dist/runtime/picoclaw/surfaces.d.ts +5 -0
- package/dist/runtime/picoclaw/surfaces.js +111 -0
- package/dist/runtime/registry.d.ts +41 -0
- package/dist/runtime/registry.js +134 -0
- package/dist/runtime/scaffoldAssets.d.ts +1 -0
- package/dist/runtime/scaffoldAssets.js +2 -0
- package/dist/runtime/tinyclaw/adapter.d.ts +2 -0
- package/dist/runtime/tinyclaw/adapter.js +263 -0
- package/dist/runtime/tinyclaw/runAuth.d.ts +2 -0
- package/dist/runtime/tinyclaw/runAuth.js +22 -0
- package/dist/runtime/tinyclaw/scaffold-assets/AGENTS.md +160 -0
- package/dist/runtime/tinyclaw/scaffold-assets/CLAUDE.md +5 -0
- package/dist/runtime/tinyclaw/scaffold-assets/SOUL.md +177 -0
- package/dist/runtime/tinyclaw/scaffold.d.ts +2 -0
- package/dist/runtime/tinyclaw/scaffold.js +24 -0
- package/dist/runtime/tinyclaw/surfaces.d.ts +8 -0
- package/dist/runtime/tinyclaw/surfaces.js +86 -0
- package/dist/runtime/types.d.ts +87 -0
- package/dist/runtime/types.js +1 -0
- package/dist/runtimes/picoclaw/agents/assistant/config.json +16 -0
- package/dist/runtimes/picoclaw/agents/assistant/workspace/AGENTS.md +1 -0
- package/dist/shared/constants.d.ts +7 -0
- package/dist/shared/constants.js +7 -0
- package/dist/shared/errors.d.ts +6 -0
- package/dist/shared/errors.js +9 -0
- package/dist/shared/index.d.ts +3 -0
- package/dist/shared/index.js +3 -0
- package/dist/shared/types.d.ts +9 -0
- package/dist/shared/types.js +1 -0
- package/dist/spawnfile-report.json +71 -0
- package/package.json +41 -0
- package/runtimes.yaml +62 -0
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { surfacesSchema } from "./surfaceSchemas.js";
|
|
3
|
+
const modelAuthMethodSchema = z.enum(["api_key", "claude-code", "codex", "none"]);
|
|
4
|
+
const modelEndpointCompatibilitySchema = z.enum(["anthropic", "openai"]);
|
|
5
|
+
const modelAuthSchema = z
|
|
6
|
+
.object({
|
|
7
|
+
method: modelAuthMethodSchema.optional(),
|
|
8
|
+
methods: z.record(z.string(), modelAuthMethodSchema).optional()
|
|
9
|
+
})
|
|
10
|
+
.strict()
|
|
11
|
+
.superRefine((value, context) => {
|
|
12
|
+
if (!value.method && !value.methods) {
|
|
13
|
+
context.addIssue({
|
|
14
|
+
code: z.ZodIssueCode.custom,
|
|
15
|
+
message: "model auth must declare method or methods"
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
if (value.method && value.methods) {
|
|
19
|
+
context.addIssue({
|
|
20
|
+
code: z.ZodIssueCode.custom,
|
|
21
|
+
message: "model auth must not declare both method and methods"
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
if (value.methods && Object.keys(value.methods).length === 0) {
|
|
25
|
+
context.addIssue({
|
|
26
|
+
code: z.ZodIssueCode.custom,
|
|
27
|
+
message: "model auth methods must not be empty"
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
const modelEntryAuthMethodSchema = z.enum(["api_key", "claude-code", "codex", "none"]);
|
|
32
|
+
const modelEntryAuthSchema = z
|
|
33
|
+
.object({
|
|
34
|
+
key: z.string().optional(),
|
|
35
|
+
method: modelEntryAuthMethodSchema.optional()
|
|
36
|
+
})
|
|
37
|
+
.strict()
|
|
38
|
+
.superRefine((value, context) => {
|
|
39
|
+
if (!value.method) {
|
|
40
|
+
context.addIssue({
|
|
41
|
+
code: z.ZodIssueCode.custom,
|
|
42
|
+
message: "model auth must declare method"
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
if (value.key && value.method !== "api_key") {
|
|
46
|
+
context.addIssue({
|
|
47
|
+
code: z.ZodIssueCode.custom,
|
|
48
|
+
message: "model auth key is only valid for api_key auth"
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
const modelEndpointSchema = z
|
|
53
|
+
.object({
|
|
54
|
+
base_url: z.string().min(1),
|
|
55
|
+
compatibility: modelEndpointCompatibilitySchema
|
|
56
|
+
})
|
|
57
|
+
.strict();
|
|
58
|
+
const modelTargetSchema = z
|
|
59
|
+
.object({
|
|
60
|
+
auth: modelEntryAuthSchema.optional(),
|
|
61
|
+
endpoint: modelEndpointSchema.optional(),
|
|
62
|
+
name: z.string(),
|
|
63
|
+
provider: z.string()
|
|
64
|
+
})
|
|
65
|
+
.strict()
|
|
66
|
+
.superRefine((value, context) => {
|
|
67
|
+
const usesCustomEndpoint = value.provider === "custom" || value.provider === "local";
|
|
68
|
+
if (usesCustomEndpoint && !value.endpoint) {
|
|
69
|
+
context.addIssue({
|
|
70
|
+
code: z.ZodIssueCode.custom,
|
|
71
|
+
message: `${value.provider} models must declare endpoint`
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
if (!usesCustomEndpoint && value.endpoint) {
|
|
75
|
+
context.addIssue({
|
|
76
|
+
code: z.ZodIssueCode.custom,
|
|
77
|
+
message: "endpoint is only valid for custom or local models"
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
const docsSchema = z
|
|
82
|
+
.object({
|
|
83
|
+
extras: z.record(z.string(), z.string()).optional(),
|
|
84
|
+
heartbeat: z.string().optional(),
|
|
85
|
+
identity: z.string().optional(),
|
|
86
|
+
memory: z.string().optional(),
|
|
87
|
+
soul: z.string().optional(),
|
|
88
|
+
system: z.string().optional()
|
|
89
|
+
})
|
|
90
|
+
.strict();
|
|
91
|
+
const skillRequirementSchema = z
|
|
92
|
+
.object({
|
|
93
|
+
mcp: z.array(z.string()).optional()
|
|
94
|
+
})
|
|
95
|
+
.strict();
|
|
96
|
+
const skillReferenceSchema = z
|
|
97
|
+
.object({
|
|
98
|
+
ref: z.string(),
|
|
99
|
+
requires: skillRequirementSchema.optional()
|
|
100
|
+
})
|
|
101
|
+
.strict();
|
|
102
|
+
const mcpAuthSchema = z
|
|
103
|
+
.object({
|
|
104
|
+
secret: z.string()
|
|
105
|
+
})
|
|
106
|
+
.strict();
|
|
107
|
+
const mcpServerSchema = z
|
|
108
|
+
.object({
|
|
109
|
+
args: z.array(z.string()).optional(),
|
|
110
|
+
auth: mcpAuthSchema.optional(),
|
|
111
|
+
command: z.string().optional(),
|
|
112
|
+
env: z.record(z.string(), z.string()).optional(),
|
|
113
|
+
name: z.string(),
|
|
114
|
+
transport: z.enum(["sse", "stdio", "streamable_http"]),
|
|
115
|
+
url: z.string().optional()
|
|
116
|
+
})
|
|
117
|
+
.strict()
|
|
118
|
+
.superRefine((value, context) => {
|
|
119
|
+
if (value.transport === "stdio" && !value.command) {
|
|
120
|
+
context.addIssue({
|
|
121
|
+
code: z.ZodIssueCode.custom,
|
|
122
|
+
message: "stdio MCP servers must declare command"
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
if (value.transport !== "stdio" && !value.url) {
|
|
126
|
+
context.addIssue({
|
|
127
|
+
code: z.ZodIssueCode.custom,
|
|
128
|
+
message: `${value.transport} MCP servers must declare url`
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
const executionSchema = z
|
|
133
|
+
.object({
|
|
134
|
+
model: z
|
|
135
|
+
.object({
|
|
136
|
+
auth: modelAuthSchema.optional(),
|
|
137
|
+
fallback: z.array(modelTargetSchema).optional(),
|
|
138
|
+
primary: modelTargetSchema
|
|
139
|
+
})
|
|
140
|
+
.superRefine((value, context) => {
|
|
141
|
+
const declaredProviders = new Set([
|
|
142
|
+
value.primary.provider,
|
|
143
|
+
...(value.fallback ?? []).map((model) => model.provider)
|
|
144
|
+
]);
|
|
145
|
+
if (value.auth?.methods) {
|
|
146
|
+
for (const provider of declaredProviders) {
|
|
147
|
+
if (!(provider in value.auth.methods)) {
|
|
148
|
+
context.addIssue({
|
|
149
|
+
code: z.ZodIssueCode.custom,
|
|
150
|
+
message: `model auth methods must declare provider ${provider}`
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
for (const provider of Object.keys(value.auth.methods)) {
|
|
155
|
+
if (!declaredProviders.has(provider)) {
|
|
156
|
+
context.addIssue({
|
|
157
|
+
code: z.ZodIssueCode.custom,
|
|
158
|
+
message: `model auth methods declared unknown provider ${provider}`
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
for (const target of [value.primary, ...(value.fallback ?? [])]) {
|
|
164
|
+
const method = target.auth?.method ??
|
|
165
|
+
value.auth?.methods?.[target.provider] ??
|
|
166
|
+
value.auth?.method ??
|
|
167
|
+
(target.provider === "local" ? "none" : undefined);
|
|
168
|
+
if (target.provider === "custom" && !method) {
|
|
169
|
+
context.addIssue({
|
|
170
|
+
code: z.ZodIssueCode.custom,
|
|
171
|
+
message: "custom models must declare auth.method or inherit legacy model auth"
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
if ((target.provider === "custom" || target.provider === "local") &&
|
|
175
|
+
method === "api_key" &&
|
|
176
|
+
!target.auth?.key) {
|
|
177
|
+
context.addIssue({
|
|
178
|
+
code: z.ZodIssueCode.custom,
|
|
179
|
+
message: `${target.provider} api_key auth must declare auth.key`
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
})
|
|
184
|
+
.strict()
|
|
185
|
+
.optional(),
|
|
186
|
+
sandbox: z
|
|
187
|
+
.object({
|
|
188
|
+
mode: z.enum(["sandboxed", "unrestricted", "workspace"])
|
|
189
|
+
})
|
|
190
|
+
.strict()
|
|
191
|
+
.optional(),
|
|
192
|
+
workspace: z
|
|
193
|
+
.object({
|
|
194
|
+
isolation: z.enum(["isolated", "shared"])
|
|
195
|
+
})
|
|
196
|
+
.strict()
|
|
197
|
+
.optional()
|
|
198
|
+
})
|
|
199
|
+
.strict();
|
|
200
|
+
const runtimeBindingSchema = z.union([
|
|
201
|
+
z.string().min(1),
|
|
202
|
+
z
|
|
203
|
+
.object({
|
|
204
|
+
name: z.string().min(1),
|
|
205
|
+
options: z.record(z.string(), z.unknown()).optional()
|
|
206
|
+
})
|
|
207
|
+
.strict()
|
|
208
|
+
]);
|
|
209
|
+
const secretSchema = z
|
|
210
|
+
.object({
|
|
211
|
+
name: z.string(),
|
|
212
|
+
required: z.boolean()
|
|
213
|
+
})
|
|
214
|
+
.strict();
|
|
215
|
+
const policySchema = z
|
|
216
|
+
.object({
|
|
217
|
+
mode: z.enum(["permissive", "strict", "warn"]),
|
|
218
|
+
on_degrade: z.enum(["allow", "error", "warn"])
|
|
219
|
+
})
|
|
220
|
+
.strict();
|
|
221
|
+
const commonManifestSchema = z
|
|
222
|
+
.object({
|
|
223
|
+
docs: docsSchema.optional(),
|
|
224
|
+
env: z.record(z.string(), z.string()).optional(),
|
|
225
|
+
execution: executionSchema.optional(),
|
|
226
|
+
kind: z.enum(["agent", "team"]),
|
|
227
|
+
mcp_servers: z.array(mcpServerSchema).optional(),
|
|
228
|
+
name: z
|
|
229
|
+
.string()
|
|
230
|
+
.min(1)
|
|
231
|
+
.refine((value) => !/\s/.test(value), { message: "name must not contain whitespace" }),
|
|
232
|
+
policy: policySchema.optional(),
|
|
233
|
+
runtime: runtimeBindingSchema.optional(),
|
|
234
|
+
secrets: z.array(secretSchema).optional(),
|
|
235
|
+
skills: z.array(skillReferenceSchema).optional(),
|
|
236
|
+
surfaces: surfacesSchema.optional(),
|
|
237
|
+
spawnfile_version: z.literal("0.1")
|
|
238
|
+
})
|
|
239
|
+
.strict();
|
|
240
|
+
const subagentSchema = z
|
|
241
|
+
.object({
|
|
242
|
+
id: z.string().min(1),
|
|
243
|
+
ref: z.string()
|
|
244
|
+
})
|
|
245
|
+
.strict();
|
|
246
|
+
const sharedSurfaceSchema = z
|
|
247
|
+
.object({
|
|
248
|
+
env: z.record(z.string(), z.string()).optional(),
|
|
249
|
+
mcp_servers: z.array(mcpServerSchema).optional(),
|
|
250
|
+
secrets: z.array(secretSchema).optional(),
|
|
251
|
+
skills: z.array(skillReferenceSchema).optional()
|
|
252
|
+
})
|
|
253
|
+
.strict();
|
|
254
|
+
const structureSchema = z
|
|
255
|
+
.object({
|
|
256
|
+
external: z.array(z.string().min(1)).optional(),
|
|
257
|
+
leader: z.string().min(1).optional(),
|
|
258
|
+
mode: z.enum(["hierarchical", "swarm"])
|
|
259
|
+
})
|
|
260
|
+
.strict()
|
|
261
|
+
.superRefine((value, context) => {
|
|
262
|
+
if (value.mode === "hierarchical" && !value.leader) {
|
|
263
|
+
context.addIssue({
|
|
264
|
+
code: z.ZodIssueCode.custom,
|
|
265
|
+
message: "hierarchical teams must declare a leader"
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
if (value.mode === "swarm" && value.leader) {
|
|
269
|
+
context.addIssue({
|
|
270
|
+
code: z.ZodIssueCode.custom,
|
|
271
|
+
message: "swarm teams must not declare a leader"
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
});
|
|
275
|
+
const memberSchema = z
|
|
276
|
+
.object({
|
|
277
|
+
id: z.string().min(1),
|
|
278
|
+
ref: z.string()
|
|
279
|
+
})
|
|
280
|
+
.strict();
|
|
281
|
+
const agentManifestSchema = commonManifestSchema
|
|
282
|
+
.extend({
|
|
283
|
+
kind: z.literal("agent"),
|
|
284
|
+
subagents: z.array(subagentSchema).optional()
|
|
285
|
+
})
|
|
286
|
+
.strict();
|
|
287
|
+
const teamManifestSchema = commonManifestSchema
|
|
288
|
+
.extend({
|
|
289
|
+
kind: z.literal("team"),
|
|
290
|
+
members: z.array(memberSchema),
|
|
291
|
+
shared: sharedSurfaceSchema.optional(),
|
|
292
|
+
structure: structureSchema
|
|
293
|
+
})
|
|
294
|
+
.superRefine((value, context) => {
|
|
295
|
+
if (value.execution !== undefined) {
|
|
296
|
+
context.addIssue({
|
|
297
|
+
code: z.ZodIssueCode.custom,
|
|
298
|
+
message: "team manifests must not declare execution"
|
|
299
|
+
});
|
|
300
|
+
}
|
|
301
|
+
if (value.surfaces !== undefined) {
|
|
302
|
+
context.addIssue({
|
|
303
|
+
code: z.ZodIssueCode.custom,
|
|
304
|
+
message: "team manifests must not declare surfaces"
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
})
|
|
308
|
+
.strict();
|
|
309
|
+
export const manifestSchema = z.discriminatedUnion("kind", [
|
|
310
|
+
agentManifestSchema,
|
|
311
|
+
teamManifestSchema
|
|
312
|
+
]);
|
|
313
|
+
export const isAgentManifest = (manifest) => manifest.kind === "agent";
|
|
314
|
+
export const isTeamManifest = (manifest) => manifest.kind === "team";
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { parse as parseYaml } from "yaml";
|
|
2
|
+
import { SpawnfileError } from "../shared/index.js";
|
|
3
|
+
const readFrontmatterBlock = (source) => {
|
|
4
|
+
const lines = source.split(/\r?\n/);
|
|
5
|
+
if (lines[0]?.trim() !== "---") {
|
|
6
|
+
throw new SpawnfileError("validation_error", "SKILL.md must begin with YAML frontmatter");
|
|
7
|
+
}
|
|
8
|
+
const closingIndex = lines.findIndex((line, index) => index > 0 && line.trim() === "---");
|
|
9
|
+
if (closingIndex === -1) {
|
|
10
|
+
throw new SpawnfileError("validation_error", "SKILL.md must begin with YAML frontmatter");
|
|
11
|
+
}
|
|
12
|
+
return lines.slice(1, closingIndex).join("\n");
|
|
13
|
+
};
|
|
14
|
+
export const parseSkillFrontmatter = (source) => {
|
|
15
|
+
let parsed;
|
|
16
|
+
try {
|
|
17
|
+
parsed = parseYaml(readFrontmatterBlock(source));
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
throw new SpawnfileError("validation_error", "SKILL.md frontmatter must be valid YAML");
|
|
21
|
+
}
|
|
22
|
+
if (!parsed ||
|
|
23
|
+
typeof parsed !== "object" ||
|
|
24
|
+
typeof parsed.name !== "string" ||
|
|
25
|
+
typeof parsed.description !== "string") {
|
|
26
|
+
throw new SpawnfileError("validation_error", "Skill frontmatter must declare name and description");
|
|
27
|
+
}
|
|
28
|
+
return {
|
|
29
|
+
description: parsed.description,
|
|
30
|
+
name: parsed.name
|
|
31
|
+
};
|
|
32
|
+
};
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
declare const discordSurfaceAccessSchema: z.ZodObject<{
|
|
3
|
+
channels: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
4
|
+
guilds: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
5
|
+
mode: z.ZodOptional<z.ZodEnum<{
|
|
6
|
+
allowlist: "allowlist";
|
|
7
|
+
open: "open";
|
|
8
|
+
pairing: "pairing";
|
|
9
|
+
}>>;
|
|
10
|
+
users: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
11
|
+
}, z.core.$strict>;
|
|
12
|
+
declare const telegramSurfaceAccessSchema: z.ZodObject<{
|
|
13
|
+
chats: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
14
|
+
mode: z.ZodOptional<z.ZodEnum<{
|
|
15
|
+
allowlist: "allowlist";
|
|
16
|
+
open: "open";
|
|
17
|
+
pairing: "pairing";
|
|
18
|
+
}>>;
|
|
19
|
+
users: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
20
|
+
}, z.core.$strict>;
|
|
21
|
+
declare const whatsappSurfaceAccessSchema: z.ZodObject<{
|
|
22
|
+
groups: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
23
|
+
mode: z.ZodOptional<z.ZodEnum<{
|
|
24
|
+
allowlist: "allowlist";
|
|
25
|
+
open: "open";
|
|
26
|
+
pairing: "pairing";
|
|
27
|
+
}>>;
|
|
28
|
+
users: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
29
|
+
}, z.core.$strict>;
|
|
30
|
+
declare const slackSurfaceAccessSchema: z.ZodObject<{
|
|
31
|
+
channels: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
32
|
+
mode: z.ZodOptional<z.ZodEnum<{
|
|
33
|
+
allowlist: "allowlist";
|
|
34
|
+
open: "open";
|
|
35
|
+
pairing: "pairing";
|
|
36
|
+
}>>;
|
|
37
|
+
users: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
38
|
+
}, z.core.$strict>;
|
|
39
|
+
declare const discordSurfaceSchema: z.ZodObject<{
|
|
40
|
+
access: z.ZodOptional<z.ZodObject<{
|
|
41
|
+
channels: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
42
|
+
guilds: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
43
|
+
mode: z.ZodOptional<z.ZodEnum<{
|
|
44
|
+
allowlist: "allowlist";
|
|
45
|
+
open: "open";
|
|
46
|
+
pairing: "pairing";
|
|
47
|
+
}>>;
|
|
48
|
+
users: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
49
|
+
}, z.core.$strict>>;
|
|
50
|
+
bot_token_secret: z.ZodOptional<z.ZodString>;
|
|
51
|
+
}, z.core.$strict>;
|
|
52
|
+
declare const telegramSurfaceSchema: z.ZodObject<{
|
|
53
|
+
access: z.ZodOptional<z.ZodObject<{
|
|
54
|
+
chats: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
55
|
+
mode: z.ZodOptional<z.ZodEnum<{
|
|
56
|
+
allowlist: "allowlist";
|
|
57
|
+
open: "open";
|
|
58
|
+
pairing: "pairing";
|
|
59
|
+
}>>;
|
|
60
|
+
users: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
61
|
+
}, z.core.$strict>>;
|
|
62
|
+
bot_token_secret: z.ZodOptional<z.ZodString>;
|
|
63
|
+
}, z.core.$strict>;
|
|
64
|
+
declare const whatsappSurfaceSchema: z.ZodObject<{
|
|
65
|
+
access: z.ZodOptional<z.ZodObject<{
|
|
66
|
+
groups: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
67
|
+
mode: z.ZodOptional<z.ZodEnum<{
|
|
68
|
+
allowlist: "allowlist";
|
|
69
|
+
open: "open";
|
|
70
|
+
pairing: "pairing";
|
|
71
|
+
}>>;
|
|
72
|
+
users: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
73
|
+
}, z.core.$strict>>;
|
|
74
|
+
}, z.core.$strict>;
|
|
75
|
+
declare const slackSurfaceSchema: z.ZodObject<{
|
|
76
|
+
access: z.ZodOptional<z.ZodObject<{
|
|
77
|
+
channels: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
78
|
+
mode: z.ZodOptional<z.ZodEnum<{
|
|
79
|
+
allowlist: "allowlist";
|
|
80
|
+
open: "open";
|
|
81
|
+
pairing: "pairing";
|
|
82
|
+
}>>;
|
|
83
|
+
users: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
84
|
+
}, z.core.$strict>>;
|
|
85
|
+
app_token_secret: z.ZodOptional<z.ZodString>;
|
|
86
|
+
bot_token_secret: z.ZodOptional<z.ZodString>;
|
|
87
|
+
}, z.core.$strict>;
|
|
88
|
+
export declare const surfacesSchema: z.ZodObject<{
|
|
89
|
+
discord: z.ZodOptional<z.ZodObject<{
|
|
90
|
+
access: z.ZodOptional<z.ZodObject<{
|
|
91
|
+
channels: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
92
|
+
guilds: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
93
|
+
mode: z.ZodOptional<z.ZodEnum<{
|
|
94
|
+
allowlist: "allowlist";
|
|
95
|
+
open: "open";
|
|
96
|
+
pairing: "pairing";
|
|
97
|
+
}>>;
|
|
98
|
+
users: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
99
|
+
}, z.core.$strict>>;
|
|
100
|
+
bot_token_secret: z.ZodOptional<z.ZodString>;
|
|
101
|
+
}, z.core.$strict>>;
|
|
102
|
+
slack: z.ZodOptional<z.ZodObject<{
|
|
103
|
+
access: z.ZodOptional<z.ZodObject<{
|
|
104
|
+
channels: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
105
|
+
mode: z.ZodOptional<z.ZodEnum<{
|
|
106
|
+
allowlist: "allowlist";
|
|
107
|
+
open: "open";
|
|
108
|
+
pairing: "pairing";
|
|
109
|
+
}>>;
|
|
110
|
+
users: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
111
|
+
}, z.core.$strict>>;
|
|
112
|
+
app_token_secret: z.ZodOptional<z.ZodString>;
|
|
113
|
+
bot_token_secret: z.ZodOptional<z.ZodString>;
|
|
114
|
+
}, z.core.$strict>>;
|
|
115
|
+
telegram: z.ZodOptional<z.ZodObject<{
|
|
116
|
+
access: z.ZodOptional<z.ZodObject<{
|
|
117
|
+
chats: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
118
|
+
mode: z.ZodOptional<z.ZodEnum<{
|
|
119
|
+
allowlist: "allowlist";
|
|
120
|
+
open: "open";
|
|
121
|
+
pairing: "pairing";
|
|
122
|
+
}>>;
|
|
123
|
+
users: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
124
|
+
}, z.core.$strict>>;
|
|
125
|
+
bot_token_secret: z.ZodOptional<z.ZodString>;
|
|
126
|
+
}, z.core.$strict>>;
|
|
127
|
+
whatsapp: z.ZodOptional<z.ZodObject<{
|
|
128
|
+
access: z.ZodOptional<z.ZodObject<{
|
|
129
|
+
groups: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
130
|
+
mode: z.ZodOptional<z.ZodEnum<{
|
|
131
|
+
allowlist: "allowlist";
|
|
132
|
+
open: "open";
|
|
133
|
+
pairing: "pairing";
|
|
134
|
+
}>>;
|
|
135
|
+
users: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
136
|
+
}, z.core.$strict>>;
|
|
137
|
+
}, z.core.$strict>>;
|
|
138
|
+
}, z.core.$strict>;
|
|
139
|
+
export type DiscordSurfaceAccess = z.infer<typeof discordSurfaceAccessSchema>;
|
|
140
|
+
export type DiscordSurface = z.infer<typeof discordSurfaceSchema>;
|
|
141
|
+
export type SlackSurfaceAccess = z.infer<typeof slackSurfaceAccessSchema>;
|
|
142
|
+
export type SlackSurface = z.infer<typeof slackSurfaceSchema>;
|
|
143
|
+
export type TelegramSurfaceAccess = z.infer<typeof telegramSurfaceAccessSchema>;
|
|
144
|
+
export type TelegramSurface = z.infer<typeof telegramSurfaceSchema>;
|
|
145
|
+
export type WhatsAppSurfaceAccess = z.infer<typeof whatsappSurfaceAccessSchema>;
|
|
146
|
+
export type WhatsAppSurface = z.infer<typeof whatsappSurfaceSchema>;
|
|
147
|
+
export type SurfacesBlock = z.infer<typeof surfacesSchema>;
|
|
148
|
+
export {};
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
const surfaceAccessModeSchema = z.enum(["allowlist", "open", "pairing"]);
|
|
3
|
+
const discordSurfaceAccessSchema = z
|
|
4
|
+
.object({
|
|
5
|
+
channels: z.array(z.string().min(1)).optional(),
|
|
6
|
+
guilds: z.array(z.string().min(1)).optional(),
|
|
7
|
+
mode: surfaceAccessModeSchema.optional(),
|
|
8
|
+
users: z.array(z.string().min(1)).optional()
|
|
9
|
+
})
|
|
10
|
+
.strict()
|
|
11
|
+
.superRefine((value, context) => {
|
|
12
|
+
const hasAllowlistEntries = (value.users?.length ?? 0) +
|
|
13
|
+
(value.guilds?.length ?? 0) +
|
|
14
|
+
(value.channels?.length ?? 0) >
|
|
15
|
+
0;
|
|
16
|
+
const mode = value.mode ?? (hasAllowlistEntries ? "allowlist" : undefined);
|
|
17
|
+
if (!mode) {
|
|
18
|
+
context.addIssue({
|
|
19
|
+
code: z.ZodIssueCode.custom,
|
|
20
|
+
message: "discord access must declare mode or allowlist entries"
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
if (mode !== "allowlist" && hasAllowlistEntries) {
|
|
24
|
+
context.addIssue({
|
|
25
|
+
code: z.ZodIssueCode.custom,
|
|
26
|
+
message: "discord access users, guilds, and channels are only valid for allowlist mode"
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
if (mode === "allowlist" && !hasAllowlistEntries) {
|
|
30
|
+
context.addIssue({
|
|
31
|
+
code: z.ZodIssueCode.custom,
|
|
32
|
+
message: "discord allowlist access must declare users, guilds, or channels"
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
const telegramSurfaceAccessSchema = z
|
|
37
|
+
.object({
|
|
38
|
+
chats: z.array(z.string().min(1)).optional(),
|
|
39
|
+
mode: surfaceAccessModeSchema.optional(),
|
|
40
|
+
users: z.array(z.string().min(1)).optional()
|
|
41
|
+
})
|
|
42
|
+
.strict()
|
|
43
|
+
.superRefine((value, context) => {
|
|
44
|
+
const hasAllowlistEntries = (value.users?.length ?? 0) + (value.chats?.length ?? 0) > 0;
|
|
45
|
+
const mode = value.mode ?? (hasAllowlistEntries ? "allowlist" : undefined);
|
|
46
|
+
if (!mode) {
|
|
47
|
+
context.addIssue({
|
|
48
|
+
code: z.ZodIssueCode.custom,
|
|
49
|
+
message: "telegram access must declare mode or allowlist entries"
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
if (mode !== "allowlist" && hasAllowlistEntries) {
|
|
53
|
+
context.addIssue({
|
|
54
|
+
code: z.ZodIssueCode.custom,
|
|
55
|
+
message: "telegram access users and chats are only valid for allowlist mode"
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
if (mode === "allowlist" && !hasAllowlistEntries) {
|
|
59
|
+
context.addIssue({
|
|
60
|
+
code: z.ZodIssueCode.custom,
|
|
61
|
+
message: "telegram allowlist access must declare users or chats"
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
const whatsappSurfaceAccessSchema = z
|
|
66
|
+
.object({
|
|
67
|
+
groups: z.array(z.string().min(1)).optional(),
|
|
68
|
+
mode: surfaceAccessModeSchema.optional(),
|
|
69
|
+
users: z.array(z.string().min(1)).optional()
|
|
70
|
+
})
|
|
71
|
+
.strict()
|
|
72
|
+
.superRefine((value, context) => {
|
|
73
|
+
const hasAllowlistEntries = (value.users?.length ?? 0) + (value.groups?.length ?? 0) > 0;
|
|
74
|
+
const mode = value.mode ?? (hasAllowlistEntries ? "allowlist" : undefined);
|
|
75
|
+
if (!mode) {
|
|
76
|
+
context.addIssue({
|
|
77
|
+
code: z.ZodIssueCode.custom,
|
|
78
|
+
message: "whatsapp access must declare mode or allowlist entries"
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
if (mode !== "allowlist" && hasAllowlistEntries) {
|
|
82
|
+
context.addIssue({
|
|
83
|
+
code: z.ZodIssueCode.custom,
|
|
84
|
+
message: "whatsapp access users and groups are only valid for allowlist mode"
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
if (mode === "allowlist" && !hasAllowlistEntries) {
|
|
88
|
+
context.addIssue({
|
|
89
|
+
code: z.ZodIssueCode.custom,
|
|
90
|
+
message: "whatsapp allowlist access must declare users or groups"
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
const slackSurfaceAccessSchema = z
|
|
95
|
+
.object({
|
|
96
|
+
channels: z.array(z.string().min(1)).optional(),
|
|
97
|
+
mode: surfaceAccessModeSchema.optional(),
|
|
98
|
+
users: z.array(z.string().min(1)).optional()
|
|
99
|
+
})
|
|
100
|
+
.strict()
|
|
101
|
+
.superRefine((value, context) => {
|
|
102
|
+
const hasAllowlistEntries = (value.users?.length ?? 0) + (value.channels?.length ?? 0) > 0;
|
|
103
|
+
const mode = value.mode ?? (hasAllowlistEntries ? "allowlist" : undefined);
|
|
104
|
+
if (!mode) {
|
|
105
|
+
context.addIssue({
|
|
106
|
+
code: z.ZodIssueCode.custom,
|
|
107
|
+
message: "slack access must declare mode or allowlist entries"
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
if (mode !== "allowlist" && hasAllowlistEntries) {
|
|
111
|
+
context.addIssue({
|
|
112
|
+
code: z.ZodIssueCode.custom,
|
|
113
|
+
message: "slack access users and channels are only valid for allowlist mode"
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
if (mode === "allowlist" && !hasAllowlistEntries) {
|
|
117
|
+
context.addIssue({
|
|
118
|
+
code: z.ZodIssueCode.custom,
|
|
119
|
+
message: "slack allowlist access must declare users or channels"
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
const discordSurfaceSchema = z
|
|
124
|
+
.object({
|
|
125
|
+
access: discordSurfaceAccessSchema.optional(),
|
|
126
|
+
bot_token_secret: z.string().min(1).optional()
|
|
127
|
+
})
|
|
128
|
+
.strict();
|
|
129
|
+
const telegramSurfaceSchema = z
|
|
130
|
+
.object({
|
|
131
|
+
access: telegramSurfaceAccessSchema.optional(),
|
|
132
|
+
bot_token_secret: z.string().min(1).optional()
|
|
133
|
+
})
|
|
134
|
+
.strict();
|
|
135
|
+
const whatsappSurfaceSchema = z
|
|
136
|
+
.object({
|
|
137
|
+
access: whatsappSurfaceAccessSchema.optional()
|
|
138
|
+
})
|
|
139
|
+
.strict();
|
|
140
|
+
const slackSurfaceSchema = z
|
|
141
|
+
.object({
|
|
142
|
+
access: slackSurfaceAccessSchema.optional(),
|
|
143
|
+
app_token_secret: z.string().min(1).optional(),
|
|
144
|
+
bot_token_secret: z.string().min(1).optional()
|
|
145
|
+
})
|
|
146
|
+
.strict();
|
|
147
|
+
export const surfacesSchema = z
|
|
148
|
+
.object({
|
|
149
|
+
discord: discordSurfaceSchema.optional(),
|
|
150
|
+
slack: slackSurfaceSchema.optional(),
|
|
151
|
+
telegram: telegramSurfaceSchema.optional(),
|
|
152
|
+
whatsapp: whatsappSurfaceSchema.optional()
|
|
153
|
+
})
|
|
154
|
+
.strict()
|
|
155
|
+
.superRefine((value, context) => {
|
|
156
|
+
if (!value.discord && !value.telegram && !value.whatsapp && !value.slack) {
|
|
157
|
+
context.addIssue({
|
|
158
|
+
code: z.ZodIssueCode.custom,
|
|
159
|
+
message: "surfaces must declare at least one surface"
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
});
|