spawnfile 0.1.4 → 0.1.6
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/dist/cli/lifecycleCommands.d.ts +3 -0
- package/dist/cli/lifecycleCommands.js +80 -0
- package/dist/cli/runCli.d.ts +2 -1
- package/dist/cli/runCli.js +4 -48
- package/dist/compiler/buildCompilePlan.js +12 -202
- package/dist/compiler/buildCompilePlanRuntime.d.ts +6 -1
- package/dist/compiler/buildCompilePlanRuntime.js +9 -0
- package/dist/compiler/buildCompilePlanTeams.js +16 -10
- package/dist/compiler/buildCompilePlanTraversal.d.ts +16 -0
- package/dist/compiler/buildCompilePlanTraversal.js +214 -0
- package/dist/compiler/buildCompilePlanTraversalHelpers.d.ts +18 -0
- package/dist/compiler/buildCompilePlanTraversalHelpers.js +22 -0
- package/dist/compiler/compilePlanHelpers.d.ts +3 -1
- package/dist/compiler/compilePlanHelpers.js +37 -1
- package/dist/compiler/compileProject.js +14 -0
- package/dist/compiler/containerArtifacts.js +18 -3
- package/dist/compiler/containerArtifactsPlans.js +32 -0
- package/dist/compiler/containerArtifactsRender.js +86 -3
- package/dist/compiler/containerArtifactsTypes.d.ts +7 -3
- package/dist/compiler/containerEntrypointRender.d.ts +1 -1
- package/dist/compiler/containerEntrypointRender.js +34 -24
- package/dist/compiler/containerTargetResources.d.ts +4 -0
- package/dist/compiler/containerTargetResources.js +54 -0
- package/dist/compiler/containerWorkspaceResourceRender.d.ts +3 -0
- package/dist/compiler/containerWorkspaceResourceRender.js +128 -0
- package/dist/compiler/executionDefaults.js +0 -3
- package/dist/compiler/helpers.d.ts +1 -1
- package/dist/compiler/index.d.ts +1 -0
- package/dist/compiler/index.js +1 -0
- package/dist/compiler/moltnetArtifacts.d.ts +11 -5
- package/dist/compiler/moltnetArtifacts.js +133 -117
- package/dist/compiler/moltnetClientConfig.js +8 -2
- package/dist/compiler/moltnetConfigLowering.d.ts +36 -0
- package/dist/compiler/moltnetConfigLowering.js +125 -0
- package/dist/compiler/moltnetRuntimeConfig.d.ts +2 -0
- package/dist/compiler/moltnetRuntimeConfig.js +69 -0
- package/dist/compiler/surfaces.d.ts +3 -13
- package/dist/compiler/surfaces.js +1 -6
- package/dist/compiler/syncProjectAuth.js +14 -0
- package/dist/compiler/types.d.ts +16 -1
- package/dist/compiler/upProject.d.ts +19 -0
- package/dist/compiler/upProject.js +37 -0
- package/dist/compiler/view/buildOrganizationView.js +22 -2
- package/dist/compiler/view/renderNetworks.js +14 -3
- package/dist/compiler/view/renderTree.js +8 -2
- package/dist/compiler/view/types.d.ts +18 -3
- package/dist/compiler/workspaceResources.d.ts +34 -0
- package/dist/compiler/workspaceResources.js +120 -0
- package/dist/filesystem/paths.js +1 -10
- package/dist/manifest/executionSchemas.d.ts +106 -0
- package/dist/manifest/executionSchemas.js +140 -0
- package/dist/manifest/loadManifest.js +15 -27
- package/dist/manifest/renderSpawnfile.js +44 -52
- package/dist/manifest/renderSpawnfileNetworks.d.ts +2 -0
- package/dist/manifest/renderSpawnfileNetworks.js +63 -0
- package/dist/manifest/renderSpawnfileWorkspace.d.ts +2 -0
- package/dist/manifest/renderSpawnfileWorkspace.js +47 -0
- package/dist/manifest/scaffold.js +12 -6
- package/dist/manifest/scheduleSchemas.d.ts +15 -0
- package/dist/manifest/scheduleSchemas.js +26 -0
- package/dist/manifest/schemas.d.ts +626 -368
- package/dist/manifest/schemas.js +51 -191
- package/dist/manifest/teamNetworkSchemas.d.ts +228 -0
- package/dist/manifest/teamNetworkSchemas.js +295 -0
- package/dist/manifest/workspaceSchemas.d.ts +96 -0
- package/dist/manifest/workspaceSchemas.js +166 -0
- package/dist/report/types.d.ts +10 -0
- package/dist/runtime/common.d.ts +2 -1
- package/dist/runtime/common.js +3 -3
- package/dist/runtime/tinyclaw/adapter.js +9 -2
- package/dist/runtime/tinyclaw/schedules.d.ts +9 -0
- package/dist/runtime/tinyclaw/schedules.js +62 -0
- package/dist/runtime/types.d.ts +1 -0
- package/package.json +2 -1
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export { teamWorkspaceDocsSchema, teamWorkspaceSchema } from "./workspaceSchemas.js";
|
|
3
|
+
const moltnetScopeSchema = z.enum(["observe", "write", "admin", "attach", "pair"]);
|
|
4
|
+
const countTruthy = (value) => value.filter((entry) => Boolean(entry)).length;
|
|
5
|
+
const teamNetworkAuthTokenSchema = z
|
|
6
|
+
.object({
|
|
7
|
+
agents: z.array(z.string().trim().min(1)).optional(),
|
|
8
|
+
id: z.string().trim().min(1),
|
|
9
|
+
secret: z.string().trim().min(1),
|
|
10
|
+
scopes: z.array(moltnetScopeSchema).min(1)
|
|
11
|
+
})
|
|
12
|
+
.strict();
|
|
13
|
+
const teamNetworkAuthClientSchema = z
|
|
14
|
+
.object({
|
|
15
|
+
static_token: z.boolean().optional(),
|
|
16
|
+
token_env: z.string().trim().min(1).optional(),
|
|
17
|
+
token_id: z.string().trim().min(1).optional(),
|
|
18
|
+
token_path: z.string().trim().min(1).optional()
|
|
19
|
+
})
|
|
20
|
+
.strict()
|
|
21
|
+
.superRefine((value, context) => {
|
|
22
|
+
const tokenSourceCount = countTruthy([value.token_id, value.token_env, value.token_path]);
|
|
23
|
+
if (tokenSourceCount > 1) {
|
|
24
|
+
context.addIssue({
|
|
25
|
+
code: z.ZodIssueCode.custom,
|
|
26
|
+
message: "auth.client must declare exactly one of token_id, token_env, or token_path"
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
if (value.static_token === true && tokenSourceCount === 0) {
|
|
30
|
+
context.addIssue({
|
|
31
|
+
code: z.ZodIssueCode.custom,
|
|
32
|
+
message: "auth.client.static_token requires exactly one token source"
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
const teamNetworkAuthSchema = z
|
|
37
|
+
.object({
|
|
38
|
+
client: teamNetworkAuthClientSchema.optional(),
|
|
39
|
+
mode: z.enum(["none", "bearer", "open"]),
|
|
40
|
+
tokens: z.array(teamNetworkAuthTokenSchema).optional()
|
|
41
|
+
})
|
|
42
|
+
.strict()
|
|
43
|
+
.superRefine((value, context) => {
|
|
44
|
+
if (value.mode === "none") {
|
|
45
|
+
if (value.tokens && value.tokens.length > 0) {
|
|
46
|
+
context.addIssue({
|
|
47
|
+
code: z.ZodIssueCode.custom,
|
|
48
|
+
message: "auth.mode none must not declare tokens"
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
if (value.client) {
|
|
52
|
+
context.addIssue({
|
|
53
|
+
code: z.ZodIssueCode.custom,
|
|
54
|
+
message: "auth.mode none must not declare client"
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
if (value.mode === "bearer" && !value.client) {
|
|
60
|
+
context.addIssue({
|
|
61
|
+
code: z.ZodIssueCode.custom,
|
|
62
|
+
message: "auth.mode bearer requires auth.client"
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
if (value.mode === "open" && value.client) {
|
|
66
|
+
const tokenSourceCount = countTruthy([
|
|
67
|
+
value.client.token_id,
|
|
68
|
+
value.client.token_env,
|
|
69
|
+
value.client.token_path
|
|
70
|
+
]);
|
|
71
|
+
if (value.client.static_token !== true) {
|
|
72
|
+
context.addIssue({
|
|
73
|
+
code: z.ZodIssueCode.custom,
|
|
74
|
+
message: "open auth with auth.client requires static_token: true"
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
if (tokenSourceCount === 0) {
|
|
78
|
+
context.addIssue({
|
|
79
|
+
code: z.ZodIssueCode.custom,
|
|
80
|
+
message: "open auth with auth.client requires exactly one token source"
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
if (value.tokens) {
|
|
85
|
+
const tokenIds = value.tokens.map((token) => token.id);
|
|
86
|
+
if (new Set(tokenIds).size !== tokenIds.length) {
|
|
87
|
+
context.addIssue({
|
|
88
|
+
code: z.ZodIssueCode.custom,
|
|
89
|
+
message: "auth.tokens ids must be unique"
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
const teamNetworkStoreSqliteSchema = z
|
|
95
|
+
.object({
|
|
96
|
+
kind: z.literal("sqlite"),
|
|
97
|
+
path: z.string().trim().min(1)
|
|
98
|
+
})
|
|
99
|
+
.strict();
|
|
100
|
+
const teamNetworkStoreJsonSchema = z
|
|
101
|
+
.object({
|
|
102
|
+
kind: z.literal("json"),
|
|
103
|
+
path: z.string().trim().min(1)
|
|
104
|
+
})
|
|
105
|
+
.strict();
|
|
106
|
+
const teamNetworkStorePostgresSchema = z
|
|
107
|
+
.object({
|
|
108
|
+
kind: z.literal("postgres"),
|
|
109
|
+
dsn_secret: z.string().trim().min(1)
|
|
110
|
+
})
|
|
111
|
+
.strict();
|
|
112
|
+
const teamNetworkStoreMemorySchema = z.object({ kind: z.literal("memory") }).strict();
|
|
113
|
+
const teamNetworkStoreSchema = z.discriminatedUnion("kind", [
|
|
114
|
+
teamNetworkStoreSqliteSchema,
|
|
115
|
+
teamNetworkStoreJsonSchema,
|
|
116
|
+
teamNetworkStorePostgresSchema,
|
|
117
|
+
teamNetworkStoreMemorySchema
|
|
118
|
+
]);
|
|
119
|
+
const teamNetworkListenSchema = z
|
|
120
|
+
.object({
|
|
121
|
+
bind: z
|
|
122
|
+
.string()
|
|
123
|
+
.trim()
|
|
124
|
+
.min(1)
|
|
125
|
+
.superRefine((value, context) => {
|
|
126
|
+
if (value.startsWith("[") || value.endsWith("]") || /\[.*\]/.test(value)) {
|
|
127
|
+
context.addIssue({
|
|
128
|
+
code: z.ZodIssueCode.custom,
|
|
129
|
+
message: "listen.bind must be unbracketed"
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
}),
|
|
133
|
+
port: z.number().int().min(1).max(65535)
|
|
134
|
+
})
|
|
135
|
+
.strict();
|
|
136
|
+
const teamNetworkPairingSchema = z
|
|
137
|
+
.object({
|
|
138
|
+
id: z.string().trim().min(1),
|
|
139
|
+
remote_base_url: z.string().trim().min(1),
|
|
140
|
+
remote_network_id: z.string().trim().min(1),
|
|
141
|
+
remote_network_name: z.string().trim().min(1),
|
|
142
|
+
token_secret: z.string().trim().min(1)
|
|
143
|
+
})
|
|
144
|
+
.strict();
|
|
145
|
+
const teamNetworkManagedServerSchema = z
|
|
146
|
+
.object({
|
|
147
|
+
allowed_origins: z.array(z.string().trim().min(1)).optional(),
|
|
148
|
+
auth: teamNetworkAuthSchema,
|
|
149
|
+
direct_messages: z.boolean().optional(),
|
|
150
|
+
human_ingress: z.boolean().optional(),
|
|
151
|
+
listen: teamNetworkListenSchema,
|
|
152
|
+
mode: z.literal("managed"),
|
|
153
|
+
pairings: z.array(teamNetworkPairingSchema).optional(),
|
|
154
|
+
store: teamNetworkStoreSchema,
|
|
155
|
+
trust_forwarded_proto: z.boolean().optional(),
|
|
156
|
+
url: z.string().trim().optional()
|
|
157
|
+
})
|
|
158
|
+
.strict()
|
|
159
|
+
.superRefine((value, context) => {
|
|
160
|
+
if (value.auth.mode === "bearer") {
|
|
161
|
+
if (!value.auth.tokens || value.auth.tokens.length === 0) {
|
|
162
|
+
context.addIssue({
|
|
163
|
+
code: z.ZodIssueCode.custom,
|
|
164
|
+
message: "managed server with auth.mode bearer requires at least one auth token"
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
if (!value.auth.client?.token_id) {
|
|
168
|
+
context.addIssue({
|
|
169
|
+
code: z.ZodIssueCode.custom,
|
|
170
|
+
message: "managed bearer auth requires auth.client.token_id"
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
if (value.auth.client?.token_env || value.auth.client?.token_path) {
|
|
174
|
+
context.addIssue({
|
|
175
|
+
code: z.ZodIssueCode.custom,
|
|
176
|
+
message: "managed bearer auth requires auth.client.token_id"
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
if (value.auth.client?.token_id && value.auth.tokens) {
|
|
180
|
+
const tokenById = new Map(value.auth.tokens.map((token) => [token.id, token]));
|
|
181
|
+
const selected = tokenById.get(value.auth.client.token_id);
|
|
182
|
+
if (!selected) {
|
|
183
|
+
context.addIssue({
|
|
184
|
+
code: z.ZodIssueCode.custom,
|
|
185
|
+
message: `managed bearer auth references unknown token: ${value.auth.client.token_id}`
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
else if (!(selected.scopes.includes("attach") && selected.scopes.includes("write"))) {
|
|
189
|
+
context.addIssue({
|
|
190
|
+
code: z.ZodIssueCode.custom,
|
|
191
|
+
message: "managed bearer auth.client.token_id must reference a token with attach and write scopes"
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
if (value.auth.mode === "open" && value.auth.client) {
|
|
197
|
+
if (!value.auth.client.token_id) {
|
|
198
|
+
context.addIssue({
|
|
199
|
+
code: z.ZodIssueCode.custom,
|
|
200
|
+
message: "managed open auth requires auth.client.token_id"
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
if (value.auth.client.token_env || value.auth.client.token_path) {
|
|
204
|
+
context.addIssue({
|
|
205
|
+
code: z.ZodIssueCode.custom,
|
|
206
|
+
message: "managed open auth client token source must be token_id"
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
});
|
|
211
|
+
const teamNetworkExternalServerSchema = z
|
|
212
|
+
.object({
|
|
213
|
+
auth: teamNetworkAuthSchema,
|
|
214
|
+
mode: z.literal("external"),
|
|
215
|
+
url: z.string().trim().min(1)
|
|
216
|
+
})
|
|
217
|
+
.strict()
|
|
218
|
+
.superRefine((value, context) => {
|
|
219
|
+
if (value.auth.tokens && value.auth.tokens.length > 0) {
|
|
220
|
+
context.addIssue({
|
|
221
|
+
code: z.ZodIssueCode.custom,
|
|
222
|
+
message: "external server does not accept auth.tokens"
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
if (value.auth.mode === "none" && value.auth.client) {
|
|
226
|
+
context.addIssue({
|
|
227
|
+
code: z.ZodIssueCode.custom,
|
|
228
|
+
message: "auth.mode none must not declare client"
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
if (!value.auth.client) {
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
if (value.auth.client.token_id) {
|
|
235
|
+
context.addIssue({
|
|
236
|
+
code: z.ZodIssueCode.custom,
|
|
237
|
+
message: "auth.client.token_id is only valid for managed servers"
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
if (value.auth.mode === "open" && value.auth.client.static_token !== true) {
|
|
241
|
+
context.addIssue({
|
|
242
|
+
code: z.ZodIssueCode.custom,
|
|
243
|
+
message: "open auth with auth.client requires static_token: true"
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
if (value.auth.mode === "open" &&
|
|
247
|
+
countTruthy([value.auth.client.token_env, value.auth.client.token_path]) !== 1) {
|
|
248
|
+
context.addIssue({
|
|
249
|
+
code: z.ZodIssueCode.custom,
|
|
250
|
+
message: "external open auth requires token_env or token_path"
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
if (value.auth.mode === "bearer") {
|
|
254
|
+
const sourceCount = countTruthy([
|
|
255
|
+
value.auth.client.token_id,
|
|
256
|
+
value.auth.client.token_env,
|
|
257
|
+
value.auth.client.token_path
|
|
258
|
+
]);
|
|
259
|
+
if (sourceCount !== 1 || !value.auth.client.token_env && !value.auth.client.token_path) {
|
|
260
|
+
context.addIssue({
|
|
261
|
+
code: z.ZodIssueCode.custom,
|
|
262
|
+
message: "external bearer auth requires exactly one external token source"
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
});
|
|
267
|
+
const teamNetworkServerSchema = z.discriminatedUnion("mode", [
|
|
268
|
+
teamNetworkManagedServerSchema,
|
|
269
|
+
teamNetworkExternalServerSchema
|
|
270
|
+
]);
|
|
271
|
+
const teamNetworkRoomSchema = z
|
|
272
|
+
.object({
|
|
273
|
+
id: z.string().trim().min(1),
|
|
274
|
+
members: z.array(z.string().trim().min(1)).min(1),
|
|
275
|
+
name: z.string().trim().min(1).optional()
|
|
276
|
+
})
|
|
277
|
+
.strict();
|
|
278
|
+
export const teamNetworkSchema = z
|
|
279
|
+
.object({
|
|
280
|
+
id: z.string().trim().min(1),
|
|
281
|
+
name: z.string().trim().min(1).optional(),
|
|
282
|
+
provider: z.literal("moltnet"),
|
|
283
|
+
rooms: z.array(teamNetworkRoomSchema).min(1),
|
|
284
|
+
server: teamNetworkServerSchema
|
|
285
|
+
})
|
|
286
|
+
.strict()
|
|
287
|
+
.superRefine((value, context) => {
|
|
288
|
+
const roomIds = value.rooms.map((room) => room.id);
|
|
289
|
+
if (new Set(roomIds).size !== roomIds.length) {
|
|
290
|
+
context.addIssue({
|
|
291
|
+
code: z.ZodIssueCode.custom,
|
|
292
|
+
message: `network ${value.id} declares duplicate room ids`
|
|
293
|
+
});
|
|
294
|
+
}
|
|
295
|
+
});
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const teamWorkspaceDocsSchema: z.ZodObject<{
|
|
3
|
+
extras: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
4
|
+
heartbeat: z.ZodOptional<z.ZodString>;
|
|
5
|
+
identity: z.ZodOptional<z.ZodString>;
|
|
6
|
+
memory: z.ZodOptional<z.ZodString>;
|
|
7
|
+
soul: z.ZodOptional<z.ZodString>;
|
|
8
|
+
system: z.ZodOptional<z.ZodString>;
|
|
9
|
+
}, z.core.$strict>;
|
|
10
|
+
declare const teamWorkspaceResourceSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
11
|
+
branch: z.ZodOptional<z.ZodString>;
|
|
12
|
+
id: z.ZodString;
|
|
13
|
+
kind: z.ZodLiteral<"git">;
|
|
14
|
+
mount: z.ZodString;
|
|
15
|
+
mode: z.ZodEnum<{
|
|
16
|
+
readonly: "readonly";
|
|
17
|
+
mutable: "mutable";
|
|
18
|
+
}>;
|
|
19
|
+
ref: z.ZodOptional<z.ZodString>;
|
|
20
|
+
sharing: z.ZodOptional<z.ZodEnum<{
|
|
21
|
+
per_agent: "per_agent";
|
|
22
|
+
team: "team";
|
|
23
|
+
}>>;
|
|
24
|
+
tag: z.ZodOptional<z.ZodString>;
|
|
25
|
+
url: z.ZodString;
|
|
26
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
27
|
+
id: z.ZodString;
|
|
28
|
+
kind: z.ZodLiteral<"volume">;
|
|
29
|
+
mount: z.ZodString;
|
|
30
|
+
mode: z.ZodEnum<{
|
|
31
|
+
readonly: "readonly";
|
|
32
|
+
mutable: "mutable";
|
|
33
|
+
}>;
|
|
34
|
+
name: z.ZodOptional<z.ZodString>;
|
|
35
|
+
sharing: z.ZodOptional<z.ZodEnum<{
|
|
36
|
+
per_agent: "per_agent";
|
|
37
|
+
team: "team";
|
|
38
|
+
}>>;
|
|
39
|
+
}, z.core.$strict>], "kind">;
|
|
40
|
+
declare const workspaceSkillReferenceSchema: z.ZodObject<{
|
|
41
|
+
ref: z.ZodString;
|
|
42
|
+
requires: z.ZodOptional<z.ZodObject<{
|
|
43
|
+
mcp: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
44
|
+
}, z.core.$strict>>;
|
|
45
|
+
}, z.core.$strict>;
|
|
46
|
+
export declare const teamWorkspaceSchema: z.ZodObject<{
|
|
47
|
+
docs: z.ZodOptional<z.ZodObject<{
|
|
48
|
+
extras: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
49
|
+
heartbeat: z.ZodOptional<z.ZodString>;
|
|
50
|
+
identity: z.ZodOptional<z.ZodString>;
|
|
51
|
+
memory: z.ZodOptional<z.ZodString>;
|
|
52
|
+
soul: z.ZodOptional<z.ZodString>;
|
|
53
|
+
system: z.ZodOptional<z.ZodString>;
|
|
54
|
+
}, z.core.$strict>>;
|
|
55
|
+
resources: z.ZodOptional<z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
56
|
+
branch: z.ZodOptional<z.ZodString>;
|
|
57
|
+
id: z.ZodString;
|
|
58
|
+
kind: z.ZodLiteral<"git">;
|
|
59
|
+
mount: z.ZodString;
|
|
60
|
+
mode: z.ZodEnum<{
|
|
61
|
+
readonly: "readonly";
|
|
62
|
+
mutable: "mutable";
|
|
63
|
+
}>;
|
|
64
|
+
ref: z.ZodOptional<z.ZodString>;
|
|
65
|
+
sharing: z.ZodOptional<z.ZodEnum<{
|
|
66
|
+
per_agent: "per_agent";
|
|
67
|
+
team: "team";
|
|
68
|
+
}>>;
|
|
69
|
+
tag: z.ZodOptional<z.ZodString>;
|
|
70
|
+
url: z.ZodString;
|
|
71
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
72
|
+
id: z.ZodString;
|
|
73
|
+
kind: z.ZodLiteral<"volume">;
|
|
74
|
+
mount: z.ZodString;
|
|
75
|
+
mode: z.ZodEnum<{
|
|
76
|
+
readonly: "readonly";
|
|
77
|
+
mutable: "mutable";
|
|
78
|
+
}>;
|
|
79
|
+
name: z.ZodOptional<z.ZodString>;
|
|
80
|
+
sharing: z.ZodOptional<z.ZodEnum<{
|
|
81
|
+
per_agent: "per_agent";
|
|
82
|
+
team: "team";
|
|
83
|
+
}>>;
|
|
84
|
+
}, z.core.$strict>], "kind">>>;
|
|
85
|
+
skills: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
86
|
+
ref: z.ZodString;
|
|
87
|
+
requires: z.ZodOptional<z.ZodObject<{
|
|
88
|
+
mcp: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
89
|
+
}, z.core.$strict>>;
|
|
90
|
+
}, z.core.$strict>>>;
|
|
91
|
+
}, z.core.$strict>;
|
|
92
|
+
export type TeamWorkspace = z.infer<typeof teamWorkspaceSchema>;
|
|
93
|
+
export type TeamWorkspaceDocs = z.infer<typeof teamWorkspaceDocsSchema>;
|
|
94
|
+
export type TeamWorkspaceResource = z.infer<typeof teamWorkspaceResourceSchema>;
|
|
95
|
+
export type TeamWorkspaceSkill = z.infer<typeof workspaceSkillReferenceSchema>;
|
|
96
|
+
export {};
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
const workspaceResourceModeSchema = z.enum(["mutable", "readonly"]);
|
|
3
|
+
const workspaceResourceSharingSchema = z.enum(["per_agent", "team"]);
|
|
4
|
+
export const teamWorkspaceDocsSchema = z
|
|
5
|
+
.object({
|
|
6
|
+
extras: z.record(z.string(), z.string()).optional(),
|
|
7
|
+
heartbeat: z.string().min(1).optional(),
|
|
8
|
+
identity: z.string().min(1).optional(),
|
|
9
|
+
memory: z.string().min(1).optional(),
|
|
10
|
+
soul: z.string().min(1).optional(),
|
|
11
|
+
system: z.string().min(1).optional()
|
|
12
|
+
})
|
|
13
|
+
.strict();
|
|
14
|
+
const normalizeMount = (value) => {
|
|
15
|
+
const trimmed = value.trim();
|
|
16
|
+
const workspaceRelative = trimmed.startsWith("${workspace}/")
|
|
17
|
+
? `./${trimmed.slice("${workspace}/".length)}`
|
|
18
|
+
: trimmed;
|
|
19
|
+
const collapsed = workspaceRelative.replace(/\/+/g, "/");
|
|
20
|
+
if (collapsed.startsWith("./")) {
|
|
21
|
+
const relativePath = collapsed.slice(2).replace(/\/+$/u, "");
|
|
22
|
+
return `./${relativePath}`;
|
|
23
|
+
}
|
|
24
|
+
return collapsed.length > 1 ? collapsed.replace(/\/+$/u, "") : "/";
|
|
25
|
+
};
|
|
26
|
+
const mountHasParentSegment = (value) => value.split("/").some((segment) => segment === "..");
|
|
27
|
+
const resourceMountSchema = z
|
|
28
|
+
.string()
|
|
29
|
+
.trim()
|
|
30
|
+
.min(1)
|
|
31
|
+
.superRefine((value, context) => {
|
|
32
|
+
const normalized = normalizeMount(value);
|
|
33
|
+
if (mountHasParentSegment(normalized)) {
|
|
34
|
+
context.addIssue({
|
|
35
|
+
code: z.ZodIssueCode.custom,
|
|
36
|
+
message: "mount must not contain parent path segments"
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
if (normalized === "." || normalized === "./" || normalized === "${workspace}") {
|
|
40
|
+
context.addIssue({
|
|
41
|
+
code: z.ZodIssueCode.custom,
|
|
42
|
+
message: "mount must point inside the workspace, not at the workspace root"
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
if (!normalized.startsWith("/") &&
|
|
46
|
+
!normalized.startsWith("./") &&
|
|
47
|
+
!normalized.startsWith("${workspace}/")) {
|
|
48
|
+
context.addIssue({
|
|
49
|
+
code: z.ZodIssueCode.custom,
|
|
50
|
+
message: "mount must be an absolute POSIX path, ./ workspace path, or ${workspace}/ path"
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
const teamWorkspaceResourceGitSchema = z
|
|
55
|
+
.object({
|
|
56
|
+
branch: z.string().trim().optional(),
|
|
57
|
+
id: z.string().trim().min(1),
|
|
58
|
+
kind: z.literal("git"),
|
|
59
|
+
mount: resourceMountSchema,
|
|
60
|
+
mode: workspaceResourceModeSchema,
|
|
61
|
+
ref: z.string().trim().optional(),
|
|
62
|
+
sharing: workspaceResourceSharingSchema.optional(),
|
|
63
|
+
tag: z.string().trim().optional(),
|
|
64
|
+
url: z.string().trim().min(1)
|
|
65
|
+
})
|
|
66
|
+
.strict()
|
|
67
|
+
.superRefine((value, context) => {
|
|
68
|
+
const selectors = [value.branch, value.tag, value.ref].filter(Boolean).length;
|
|
69
|
+
if (selectors > 1) {
|
|
70
|
+
context.addIssue({
|
|
71
|
+
code: z.ZodIssueCode.custom,
|
|
72
|
+
message: "git resources may declare at most one of branch, tag, or ref"
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
if (value.sharing === "team") {
|
|
76
|
+
context.addIssue({
|
|
77
|
+
code: z.ZodIssueCode.custom,
|
|
78
|
+
message: "git resources do not support team sharing"
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
const teamWorkspaceResourceVolumeSchema = z
|
|
83
|
+
.object({
|
|
84
|
+
id: z.string().trim().min(1),
|
|
85
|
+
kind: z.literal("volume"),
|
|
86
|
+
mount: resourceMountSchema,
|
|
87
|
+
mode: workspaceResourceModeSchema,
|
|
88
|
+
name: z.string().trim().optional(),
|
|
89
|
+
sharing: workspaceResourceSharingSchema.optional()
|
|
90
|
+
})
|
|
91
|
+
.strict();
|
|
92
|
+
const teamWorkspaceResourceSchema = z.discriminatedUnion("kind", [
|
|
93
|
+
teamWorkspaceResourceGitSchema,
|
|
94
|
+
teamWorkspaceResourceVolumeSchema
|
|
95
|
+
]);
|
|
96
|
+
const workspaceSkillRequirementSchema = z
|
|
97
|
+
.object({
|
|
98
|
+
mcp: z.array(z.string()).optional()
|
|
99
|
+
})
|
|
100
|
+
.strict();
|
|
101
|
+
const workspaceSkillReferenceSchema = z
|
|
102
|
+
.object({
|
|
103
|
+
ref: z.string(),
|
|
104
|
+
requires: workspaceSkillRequirementSchema.optional()
|
|
105
|
+
})
|
|
106
|
+
.strict();
|
|
107
|
+
export const teamWorkspaceSchema = z
|
|
108
|
+
.object({
|
|
109
|
+
docs: teamWorkspaceDocsSchema.optional(),
|
|
110
|
+
resources: z.array(teamWorkspaceResourceSchema).optional(),
|
|
111
|
+
skills: z.array(workspaceSkillReferenceSchema).optional()
|
|
112
|
+
})
|
|
113
|
+
.strict()
|
|
114
|
+
.superRefine((value, context) => {
|
|
115
|
+
const resources = value.resources;
|
|
116
|
+
if (!resources || resources.length === 0) {
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
const normalizeResourceIdentity = (resource) => {
|
|
120
|
+
if (resource.kind === "git") {
|
|
121
|
+
return JSON.stringify({
|
|
122
|
+
branch: resource.branch?.trim() ?? "",
|
|
123
|
+
kind: "git",
|
|
124
|
+
mode: resource.mode,
|
|
125
|
+
mount: normalizeMount(resource.mount),
|
|
126
|
+
ref: resource.ref?.trim() ?? "",
|
|
127
|
+
sharing: resource.sharing ?? "per_agent",
|
|
128
|
+
tag: resource.tag?.trim() ?? "",
|
|
129
|
+
url: resource.url
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
return JSON.stringify({
|
|
133
|
+
kind: "volume",
|
|
134
|
+
mode: resource.mode,
|
|
135
|
+
mount: normalizeMount(resource.mount),
|
|
136
|
+
name: resource.name?.trim() ?? "",
|
|
137
|
+
sharing: resource.sharing ?? "per_agent"
|
|
138
|
+
});
|
|
139
|
+
};
|
|
140
|
+
for (let leftIndex = 0; leftIndex < resources.length; leftIndex += 1) {
|
|
141
|
+
const leftResource = resources[leftIndex];
|
|
142
|
+
const leftNormalizedIdentity = normalizeResourceIdentity(leftResource);
|
|
143
|
+
const leftMount = normalizeMount(leftResource.mount);
|
|
144
|
+
for (let rightIndex = leftIndex + 1; rightIndex < resources.length; rightIndex += 1) {
|
|
145
|
+
const rightResource = resources[rightIndex];
|
|
146
|
+
const rightNormalizedIdentity = normalizeResourceIdentity(rightResource);
|
|
147
|
+
const rightMount = normalizeMount(rightResource.mount);
|
|
148
|
+
if (leftResource.id === rightResource.id && leftNormalizedIdentity !== rightNormalizedIdentity) {
|
|
149
|
+
context.addIssue({
|
|
150
|
+
code: z.ZodIssueCode.custom,
|
|
151
|
+
message: `resource id ${leftResource.id} must use identical resource declarations`
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
if (leftMount === rightMount ||
|
|
155
|
+
leftMount.startsWith(`${rightMount}/`) ||
|
|
156
|
+
rightMount.startsWith(`${leftMount}/`)) {
|
|
157
|
+
if (leftResource.id !== rightResource.id) {
|
|
158
|
+
context.addIssue({
|
|
159
|
+
code: z.ZodIssueCode.custom,
|
|
160
|
+
message: `resources ${leftResource.id} and ${rightResource.id} use overlapping mounts`
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
});
|
package/dist/report/types.d.ts
CHANGED
|
@@ -18,6 +18,15 @@ export interface ContainerRuntimeInstanceReport {
|
|
|
18
18
|
model_secrets_required: string[];
|
|
19
19
|
runtime: string;
|
|
20
20
|
}
|
|
21
|
+
export interface ContainerWorkspaceResourceReport {
|
|
22
|
+
backing_path: string;
|
|
23
|
+
id: string;
|
|
24
|
+
kind: "git" | "volume";
|
|
25
|
+
link_path: string;
|
|
26
|
+
mode: "mutable" | "readonly";
|
|
27
|
+
mount: string;
|
|
28
|
+
sharing: "per_agent" | "team";
|
|
29
|
+
}
|
|
21
30
|
export interface NodeReport {
|
|
22
31
|
capabilities: CapabilityReport[];
|
|
23
32
|
diagnostics: DiagnosticReport[];
|
|
@@ -40,6 +49,7 @@ export interface ContainerReport {
|
|
|
40
49
|
runtime_secrets_required: string[];
|
|
41
50
|
runtimes_installed: string[];
|
|
42
51
|
secrets_required: string[];
|
|
52
|
+
workspace_resources?: ContainerWorkspaceResourceReport[];
|
|
43
53
|
}
|
|
44
54
|
export interface CompileReport {
|
|
45
55
|
container?: ContainerReport;
|
package/dist/runtime/common.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ export declare const createSkillFiles: (baseDirectory: string, skills: ResolvedS
|
|
|
8
8
|
export declare const createAgentCapabilities: (node: ResolvedAgentNode, options?: {
|
|
9
9
|
mcpOutcome?: CapabilityReport["outcome"];
|
|
10
10
|
sandboxOutcome?: CapabilityReport["outcome"];
|
|
11
|
+
scheduleMessage?: string;
|
|
12
|
+
scheduleOutcome?: CapabilityReport["outcome"];
|
|
11
13
|
subagentOutcome?: CapabilityReport["outcome"];
|
|
12
|
-
workspaceOutcome?: CapabilityReport["outcome"];
|
|
13
14
|
}) => CapabilityReport[];
|
package/dist/runtime/common.js
CHANGED
|
@@ -38,12 +38,12 @@ export const createAgentCapabilities = (node, options = {}) => {
|
|
|
38
38
|
if (node.execution?.model) {
|
|
39
39
|
capabilities.push(createCapability("execution.model", "supported"));
|
|
40
40
|
}
|
|
41
|
-
if (node.execution?.workspace) {
|
|
42
|
-
capabilities.push(createCapability("execution.workspace", options.workspaceOutcome ?? "supported"));
|
|
43
|
-
}
|
|
44
41
|
if (node.execution?.sandbox) {
|
|
45
42
|
capabilities.push(createCapability("execution.sandbox", options.sandboxOutcome ?? "supported"));
|
|
46
43
|
}
|
|
44
|
+
if (node.schedule) {
|
|
45
|
+
capabilities.push(createCapability("agent.schedule", options.scheduleOutcome ?? "degraded", options.scheduleMessage ?? "Schedule intent is validated but no runtime scheduler is emitted yet"));
|
|
46
|
+
}
|
|
47
47
|
if (node.surfaces?.discord) {
|
|
48
48
|
capabilities.push(createCapability("surfaces.discord", "supported"));
|
|
49
49
|
}
|
|
@@ -4,6 +4,7 @@ import { createCapability, createAgentCapabilities, createDocumentFiles, createS
|
|
|
4
4
|
import { prepareTinyClawRuntimeAuth } from "./runAuth.js";
|
|
5
5
|
import { createTinyClawAgentScaffold } from "./scaffold.js";
|
|
6
6
|
import { assertSupportedTinyClawSurfaces, buildTinyClawChannels, resolveTinyClawSurfaceTokenBindings } from "./surfaces.js";
|
|
7
|
+
import { createScheduleDiagnostics, createTinyClawSchedulesFile, scheduleOutcomeFor } from "./schedules.js";
|
|
7
8
|
const WORKSPACE_PLACEHOLDER = "<workspace-path>";
|
|
8
9
|
const SUPPORTED_TINYCLAW_OPENAI_MODEL_PREFIXES = ["gpt-5"];
|
|
9
10
|
const TINYCLAW_START_SCRIPT = `
|
|
@@ -106,6 +107,7 @@ const mergeTinyClawTargets = async (inputs) => {
|
|
|
106
107
|
let hasWhatsappChannel = false;
|
|
107
108
|
let hasTelegramChannel = false;
|
|
108
109
|
const workspaceFiles = agentInputs.flatMap((input) => input.emittedFiles.filter((file) => file.path !== "settings.json"));
|
|
110
|
+
const schedulesFile = createTinyClawSchedulesFile(agentInputs);
|
|
109
111
|
let mergedBase = null;
|
|
110
112
|
for (const input of agentInputs) {
|
|
111
113
|
const settings = parseJsonFile(input, "settings.json");
|
|
@@ -153,6 +155,7 @@ const mergeTinyClawTargets = async (inputs) => {
|
|
|
153
155
|
{
|
|
154
156
|
files: [
|
|
155
157
|
...workspaceFiles,
|
|
158
|
+
...(schedulesFile ? [schedulesFile] : []),
|
|
156
159
|
{
|
|
157
160
|
content: `${JSON.stringify(mergedSettings, null, 2)}\n`,
|
|
158
161
|
path: "settings.json"
|
|
@@ -207,6 +210,7 @@ export const tinyClawAdapter = {
|
|
|
207
210
|
instancePaths: {
|
|
208
211
|
configPathTemplate: "<instance-root>/tinyagi/<config-file>",
|
|
209
212
|
homePathTemplate: "<instance-root>/tinyagi",
|
|
213
|
+
sourceWorkspacePathTemplate: "<instance-root>/workspace/<agent-name>",
|
|
210
214
|
workspacePathTemplate: "<instance-root>/workspace"
|
|
211
215
|
},
|
|
212
216
|
port: 3777,
|
|
@@ -222,11 +226,14 @@ export const tinyClawAdapter = {
|
|
|
222
226
|
}
|
|
223
227
|
},
|
|
224
228
|
async compileAgent(node) {
|
|
229
|
+
const scheduleOutcome = scheduleOutcomeFor(node);
|
|
225
230
|
return {
|
|
226
231
|
capabilities: createAgentCapabilities(node, {
|
|
227
|
-
mcpOutcome: node.mcpServers.length > 0 ? "degraded" : "supported"
|
|
232
|
+
mcpOutcome: node.mcpServers.length > 0 ? "degraded" : "supported",
|
|
233
|
+
scheduleMessage: scheduleOutcome.message,
|
|
234
|
+
scheduleOutcome: scheduleOutcome.outcome
|
|
228
235
|
}),
|
|
229
|
-
diagnostics:
|
|
236
|
+
diagnostics: createScheduleDiagnostics(node),
|
|
230
237
|
files: [
|
|
231
238
|
...createDocumentFiles(`workspace/${node.name}`, node.docs),
|
|
232
239
|
...createSkillFiles(`workspace/${node.name}/.agents/skills`, node.skills),
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ResolvedAgentNode } from "../../compiler/types.js";
|
|
2
|
+
import type { CapabilityReport } from "../../report/index.js";
|
|
3
|
+
import type { ContainerTargetInput, EmittedFile } from "../types.js";
|
|
4
|
+
export declare const createTinyClawSchedulesFile: (inputs: ContainerTargetInput[]) => EmittedFile | null;
|
|
5
|
+
export declare const scheduleOutcomeFor: (node: ResolvedAgentNode) => {
|
|
6
|
+
message?: string;
|
|
7
|
+
outcome?: CapabilityReport["outcome"];
|
|
8
|
+
};
|
|
9
|
+
export declare const createScheduleDiagnostics: (node: ResolvedAgentNode) => import("../../report/types.js").DiagnosticReport[];
|