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.
Files changed (74) hide show
  1. package/dist/cli/lifecycleCommands.d.ts +3 -0
  2. package/dist/cli/lifecycleCommands.js +80 -0
  3. package/dist/cli/runCli.d.ts +2 -1
  4. package/dist/cli/runCli.js +4 -48
  5. package/dist/compiler/buildCompilePlan.js +12 -202
  6. package/dist/compiler/buildCompilePlanRuntime.d.ts +6 -1
  7. package/dist/compiler/buildCompilePlanRuntime.js +9 -0
  8. package/dist/compiler/buildCompilePlanTeams.js +16 -10
  9. package/dist/compiler/buildCompilePlanTraversal.d.ts +16 -0
  10. package/dist/compiler/buildCompilePlanTraversal.js +214 -0
  11. package/dist/compiler/buildCompilePlanTraversalHelpers.d.ts +18 -0
  12. package/dist/compiler/buildCompilePlanTraversalHelpers.js +22 -0
  13. package/dist/compiler/compilePlanHelpers.d.ts +3 -1
  14. package/dist/compiler/compilePlanHelpers.js +37 -1
  15. package/dist/compiler/compileProject.js +14 -0
  16. package/dist/compiler/containerArtifacts.js +18 -3
  17. package/dist/compiler/containerArtifactsPlans.js +32 -0
  18. package/dist/compiler/containerArtifactsRender.js +86 -3
  19. package/dist/compiler/containerArtifactsTypes.d.ts +7 -3
  20. package/dist/compiler/containerEntrypointRender.d.ts +1 -1
  21. package/dist/compiler/containerEntrypointRender.js +34 -24
  22. package/dist/compiler/containerTargetResources.d.ts +4 -0
  23. package/dist/compiler/containerTargetResources.js +54 -0
  24. package/dist/compiler/containerWorkspaceResourceRender.d.ts +3 -0
  25. package/dist/compiler/containerWorkspaceResourceRender.js +128 -0
  26. package/dist/compiler/executionDefaults.js +0 -3
  27. package/dist/compiler/helpers.d.ts +1 -1
  28. package/dist/compiler/index.d.ts +1 -0
  29. package/dist/compiler/index.js +1 -0
  30. package/dist/compiler/moltnetArtifacts.d.ts +11 -5
  31. package/dist/compiler/moltnetArtifacts.js +133 -117
  32. package/dist/compiler/moltnetClientConfig.js +8 -2
  33. package/dist/compiler/moltnetConfigLowering.d.ts +36 -0
  34. package/dist/compiler/moltnetConfigLowering.js +125 -0
  35. package/dist/compiler/moltnetRuntimeConfig.d.ts +2 -0
  36. package/dist/compiler/moltnetRuntimeConfig.js +69 -0
  37. package/dist/compiler/surfaces.d.ts +3 -13
  38. package/dist/compiler/surfaces.js +1 -6
  39. package/dist/compiler/syncProjectAuth.js +14 -0
  40. package/dist/compiler/types.d.ts +16 -1
  41. package/dist/compiler/upProject.d.ts +19 -0
  42. package/dist/compiler/upProject.js +37 -0
  43. package/dist/compiler/view/buildOrganizationView.js +22 -2
  44. package/dist/compiler/view/renderNetworks.js +14 -3
  45. package/dist/compiler/view/renderTree.js +8 -2
  46. package/dist/compiler/view/types.d.ts +18 -3
  47. package/dist/compiler/workspaceResources.d.ts +34 -0
  48. package/dist/compiler/workspaceResources.js +120 -0
  49. package/dist/filesystem/paths.js +1 -10
  50. package/dist/manifest/executionSchemas.d.ts +106 -0
  51. package/dist/manifest/executionSchemas.js +140 -0
  52. package/dist/manifest/loadManifest.js +15 -27
  53. package/dist/manifest/renderSpawnfile.js +44 -52
  54. package/dist/manifest/renderSpawnfileNetworks.d.ts +2 -0
  55. package/dist/manifest/renderSpawnfileNetworks.js +63 -0
  56. package/dist/manifest/renderSpawnfileWorkspace.d.ts +2 -0
  57. package/dist/manifest/renderSpawnfileWorkspace.js +47 -0
  58. package/dist/manifest/scaffold.js +12 -6
  59. package/dist/manifest/scheduleSchemas.d.ts +15 -0
  60. package/dist/manifest/scheduleSchemas.js +26 -0
  61. package/dist/manifest/schemas.d.ts +626 -368
  62. package/dist/manifest/schemas.js +51 -191
  63. package/dist/manifest/teamNetworkSchemas.d.ts +228 -0
  64. package/dist/manifest/teamNetworkSchemas.js +295 -0
  65. package/dist/manifest/workspaceSchemas.d.ts +96 -0
  66. package/dist/manifest/workspaceSchemas.js +166 -0
  67. package/dist/report/types.d.ts +10 -0
  68. package/dist/runtime/common.d.ts +2 -1
  69. package/dist/runtime/common.js +3 -3
  70. package/dist/runtime/tinyclaw/adapter.js +9 -2
  71. package/dist/runtime/tinyclaw/schedules.d.ts +9 -0
  72. package/dist/runtime/tinyclaw/schedules.js +62 -0
  73. package/dist/runtime/types.d.ts +1 -0
  74. package/package.json +2 -1
@@ -0,0 +1,140 @@
1
+ import { z } from "zod";
2
+ const modelAuthMethodSchema = z.enum(["api_key", "claude-code", "codex", "none"]);
3
+ const modelEndpointCompatibilitySchema = z.enum(["anthropic", "openai"]);
4
+ const modelAuthSchema = z
5
+ .object({
6
+ method: modelAuthMethodSchema.optional(),
7
+ methods: z.record(z.string(), modelAuthMethodSchema).optional()
8
+ })
9
+ .strict()
10
+ .superRefine((value, context) => {
11
+ if (!value.method && !value.methods) {
12
+ context.addIssue({
13
+ code: z.ZodIssueCode.custom,
14
+ message: "model auth must declare method or methods"
15
+ });
16
+ }
17
+ if (value.method && value.methods) {
18
+ context.addIssue({
19
+ code: z.ZodIssueCode.custom,
20
+ message: "model auth must not declare both method and methods"
21
+ });
22
+ }
23
+ if (value.methods && Object.keys(value.methods).length === 0) {
24
+ context.addIssue({
25
+ code: z.ZodIssueCode.custom,
26
+ message: "model auth methods must not be empty"
27
+ });
28
+ }
29
+ });
30
+ export const modelEntryAuthSchema = z
31
+ .object({
32
+ key: z.string().optional(),
33
+ method: modelAuthMethodSchema.optional()
34
+ })
35
+ .strict()
36
+ .superRefine((value, context) => {
37
+ if (!value.method) {
38
+ context.addIssue({
39
+ code: z.ZodIssueCode.custom,
40
+ message: "model auth must declare method"
41
+ });
42
+ }
43
+ if (value.key && value.method !== "api_key") {
44
+ context.addIssue({
45
+ code: z.ZodIssueCode.custom,
46
+ message: "model auth key is only valid for api_key auth"
47
+ });
48
+ }
49
+ });
50
+ export const modelEndpointSchema = z
51
+ .object({
52
+ base_url: z.string().min(1),
53
+ compatibility: modelEndpointCompatibilitySchema
54
+ })
55
+ .strict();
56
+ export const modelTargetSchema = z
57
+ .object({
58
+ auth: modelEntryAuthSchema.optional(),
59
+ endpoint: modelEndpointSchema.optional(),
60
+ name: z.string(),
61
+ provider: z.string()
62
+ })
63
+ .strict()
64
+ .superRefine((value, context) => {
65
+ const usesCustomEndpoint = value.provider === "custom" || value.provider === "local";
66
+ if (usesCustomEndpoint && !value.endpoint) {
67
+ context.addIssue({
68
+ code: z.ZodIssueCode.custom,
69
+ message: `${value.provider} models must declare endpoint`
70
+ });
71
+ }
72
+ if (!usesCustomEndpoint && value.endpoint) {
73
+ context.addIssue({
74
+ code: z.ZodIssueCode.custom,
75
+ message: "endpoint is only valid for custom or local models"
76
+ });
77
+ }
78
+ });
79
+ export const executionSchema = z
80
+ .object({
81
+ model: z
82
+ .object({
83
+ auth: modelAuthSchema.optional(),
84
+ fallback: z.array(modelTargetSchema).optional(),
85
+ primary: modelTargetSchema
86
+ })
87
+ .superRefine((value, context) => {
88
+ const declaredProviders = new Set([
89
+ value.primary.provider,
90
+ ...(value.fallback ?? []).map((model) => model.provider)
91
+ ]);
92
+ if (value.auth?.methods) {
93
+ for (const provider of declaredProviders) {
94
+ if (!(provider in value.auth.methods)) {
95
+ context.addIssue({
96
+ code: z.ZodIssueCode.custom,
97
+ message: `model auth methods must declare provider ${provider}`
98
+ });
99
+ }
100
+ }
101
+ for (const provider of Object.keys(value.auth.methods)) {
102
+ if (!declaredProviders.has(provider)) {
103
+ context.addIssue({
104
+ code: z.ZodIssueCode.custom,
105
+ message: `model auth methods declared unknown provider ${provider}`
106
+ });
107
+ }
108
+ }
109
+ }
110
+ for (const target of [value.primary, ...(value.fallback ?? [])]) {
111
+ const method = target.auth?.method ??
112
+ value.auth?.methods?.[target.provider] ??
113
+ value.auth?.method ??
114
+ (target.provider === "local" ? "none" : undefined);
115
+ if (target.provider === "custom" && !method) {
116
+ context.addIssue({
117
+ code: z.ZodIssueCode.custom,
118
+ message: "custom models must declare auth.method or inherit legacy model auth"
119
+ });
120
+ }
121
+ if ((target.provider === "custom" || target.provider === "local") &&
122
+ method === "api_key" &&
123
+ !target.auth?.key) {
124
+ context.addIssue({
125
+ code: z.ZodIssueCode.custom,
126
+ message: `${target.provider} api_key auth must declare auth.key`
127
+ });
128
+ }
129
+ }
130
+ })
131
+ .strict()
132
+ .optional(),
133
+ sandbox: z
134
+ .object({
135
+ mode: z.enum(["sandboxed", "unrestricted", "workspace"])
136
+ })
137
+ .strict()
138
+ .optional()
139
+ })
140
+ .strict();
@@ -30,8 +30,7 @@ const assertMarkdownDocumentPath = (documentPath) => {
30
30
  throw new SpawnfileError("validation_error", `Document paths must point to Markdown files: ${documentPath}`);
31
31
  }
32
32
  };
33
- const validateDocFiles = async (manifestPath, manifest) => {
34
- const docs = manifest.docs;
33
+ const validateDocFiles = async (manifestPath, docs) => {
35
34
  if (!docs) {
36
35
  return;
37
36
  }
@@ -86,21 +85,25 @@ const validateSkills = async (manifestPath, skills) => {
86
85
  }));
87
86
  };
88
87
  const validateLocalAgentManifest = async (manifestPath, manifest) => {
89
- ensureUniqueNames((manifest.mcp_servers ?? []).map((server) => server.name), "MCP server");
88
+ const agentWorkspaceSkills = manifest.workspace?.skills;
89
+ const agentEnvironment = manifest.environment;
90
+ ensureUniqueNames((agentEnvironment?.mcp_servers ?? []).map((server) => server.name), "MCP server");
90
91
  ensureUniqueNames((manifest.subagents ?? []).map((subagent) => subagent.id), "subagent id");
91
- await validateDocFiles(manifestPath, manifest);
92
- await validateSkills(manifestPath, manifest.skills);
92
+ await validateDocFiles(manifestPath, manifest.workspace?.docs);
93
+ await validateSkills(manifestPath, agentWorkspaceSkills);
93
94
  await validateManifestRefs(manifestPath, manifest.subagents?.map((subagent) => subagent.ref), "Subagent");
94
- validateSkillRequirements(manifest.skills, getMcpNames(manifest.mcp_servers));
95
+ validateSkillRequirements(agentWorkspaceSkills, getMcpNames(agentEnvironment?.mcp_servers));
95
96
  };
96
- const getSharedMcpNames = (shared) => getMcpNames(shared?.mcp_servers);
97
+ const getSharedMcpNames = (shared) => getMcpNames(shared?.environment?.mcp_servers);
97
98
  const validateLocalTeamManifest = async (manifestPath, manifest) => {
98
- ensureUniqueNames((manifest.shared?.mcp_servers ?? []).map((server) => server.name), "MCP server");
99
+ const sharedWorkspace = manifest.shared?.workspace;
100
+ const sharedEnvironment = manifest.shared?.environment;
101
+ ensureUniqueNames((sharedEnvironment?.mcp_servers ?? []).map((server) => server.name), "MCP server");
99
102
  ensureUniqueNames(manifest.members.map((member) => member.id), "member id");
100
- await validateDocFiles(manifestPath, manifest);
101
- await validateSkills(manifestPath, manifest.shared?.skills);
103
+ await validateDocFiles(manifestPath, sharedWorkspace?.docs);
104
+ await validateSkills(manifestPath, sharedWorkspace?.skills);
102
105
  await validateManifestRefs(manifestPath, manifest.members.map((member) => member.ref), "Member");
103
- validateSkillRequirements(manifest.shared?.skills, getSharedMcpNames(manifest.shared));
106
+ validateSkillRequirements(sharedWorkspace?.skills, getSharedMcpNames(manifest.shared));
104
107
  const memberIds = new Set(manifest.members.map((member) => member.id));
105
108
  if (manifest.lead && !memberIds.has(manifest.lead)) {
106
109
  throw new SpawnfileError("validation_error", `Lead is not a declared team member: ${manifest.lead}`);
@@ -172,15 +175,6 @@ export const mergeExecution = (parentExecution, childExecution) => {
172
175
  if (sandbox && !sandbox.mode) {
173
176
  throw new SpawnfileError("validation_error", "Merged execution sandbox is missing mode");
174
177
  }
175
- const workspace = parentExecution.workspace || childExecution.workspace
176
- ? {
177
- ...parentExecution.workspace,
178
- ...childExecution.workspace
179
- }
180
- : undefined;
181
- if (workspace && !workspace.isolation) {
182
- throw new SpawnfileError("validation_error", "Merged execution workspace is missing isolation");
183
- }
184
178
  const resolvedModel = model
185
179
  ? {
186
180
  auth: model.auth,
@@ -193,16 +187,10 @@ export const mergeExecution = (parentExecution, childExecution) => {
193
187
  mode: sandbox.mode
194
188
  }
195
189
  : undefined;
196
- const resolvedWorkspace = workspace
197
- ? {
198
- isolation: workspace.isolation
199
- }
200
- : undefined;
201
190
  return {
202
191
  ...parentExecution,
203
192
  ...childExecution,
204
193
  model: resolvedModel,
205
- sandbox: resolvedSandbox,
206
- workspace: resolvedWorkspace
194
+ sandbox: resolvedSandbox
207
195
  };
208
196
  };
@@ -1,4 +1,6 @@
1
1
  import YAML from "yaml";
2
+ import { orderTeamNetworks } from "./renderSpawnfileNetworks.js";
3
+ import { orderWorkspace } from "./renderSpawnfileWorkspace.js";
2
4
  const withDefinedEntries = (entries) => Object.fromEntries(entries.filter((entry) => entry[1] !== undefined));
3
5
  const hasEntries = (value) => Object.keys(value).length > 0;
4
6
  const orderRuntimeBinding = (runtime) => {
@@ -10,19 +12,6 @@ const orderRuntimeBinding = (runtime) => {
10
12
  ["options", runtime.options]
11
13
  ]);
12
14
  };
13
- const orderDocs = (docs) => {
14
- if (!docs) {
15
- return undefined;
16
- }
17
- return withDefinedEntries([
18
- ["identity", docs.identity],
19
- ["soul", docs.soul],
20
- ["system", docs.system],
21
- ["memory", docs.memory],
22
- ["heartbeat", docs.heartbeat],
23
- ["extras", docs.extras]
24
- ]);
25
- };
26
15
  const orderDiscordSurface = (surface) => {
27
16
  if (!surface) {
28
17
  return undefined;
@@ -180,19 +169,49 @@ const orderExecution = (execution) => {
180
169
  ])
181
170
  : undefined
182
171
  ],
183
- ["workspace", execution.workspace],
184
172
  ["sandbox", execution.sandbox]
185
173
  ]);
186
174
  };
175
+ const orderAgentSchedule = (schedule) => {
176
+ if (!schedule) {
177
+ return undefined;
178
+ }
179
+ if (schedule.kind === "cron") {
180
+ return withDefinedEntries([
181
+ ["kind", schedule.kind],
182
+ ["cron", schedule.cron],
183
+ ["timezone", schedule.timezone],
184
+ ["prompt", schedule.prompt]
185
+ ]);
186
+ }
187
+ if (schedule.kind === "every") {
188
+ return withDefinedEntries([
189
+ ["kind", schedule.kind],
190
+ ["every", schedule.every],
191
+ ["timezone", schedule.timezone],
192
+ ["prompt", schedule.prompt]
193
+ ]);
194
+ }
195
+ return { kind: schedule.kind };
196
+ };
197
+ const orderEnvironment = (environment) => {
198
+ if (!environment) {
199
+ return undefined;
200
+ }
201
+ return withDefinedEntries([
202
+ ["env", environment.env],
203
+ ["secrets", environment.secrets],
204
+ ["packages", environment.packages],
205
+ ["mcp_servers", environment.mcp_servers]
206
+ ]);
207
+ };
187
208
  const orderSharedSurface = (shared) => {
188
209
  if (!shared) {
189
210
  return undefined;
190
211
  }
191
212
  return withDefinedEntries([
192
- ["env", shared.env],
193
- ["mcp_servers", shared.mcp_servers],
194
- ["secrets", shared.secrets],
195
- ["skills", shared.skills]
213
+ ["workspace", orderWorkspace(shared.workspace)],
214
+ ["environment", orderEnvironment(shared.environment)]
196
215
  ]);
197
216
  };
198
217
  const orderSurfaces = (surfaces) => {
@@ -208,19 +227,6 @@ const orderSurfaces = (surfaces) => {
208
227
  ["moltnet", orderMoltnetSurface(surfaces.moltnet)]
209
228
  ]);
210
229
  };
211
- const orderTeamNetworks = (networks) => networks?.map((network) => withDefinedEntries([
212
- ["id", network.id],
213
- ["provider", network.provider],
214
- ["name", network.name],
215
- ["expose", network.expose],
216
- [
217
- "rooms",
218
- network.rooms.map((room) => withDefinedEntries([
219
- ["id", room.id],
220
- ["members", room.members]
221
- ]))
222
- ]
223
- ]));
224
230
  const renderSections = (sections) => sections
225
231
  .filter(hasEntries)
226
232
  .map((section) => YAML.stringify(section))
@@ -234,15 +240,11 @@ const orderAgentManifestSections = (manifest) => [
234
240
  ]),
235
241
  withDefinedEntries([["runtime", orderRuntimeBinding(manifest.runtime)]]),
236
242
  withDefinedEntries([["execution", orderExecution(manifest.execution)]]),
237
- withDefinedEntries([["docs", orderDocs(manifest.docs)]]),
243
+ withDefinedEntries([["schedule", orderAgentSchedule(manifest.schedule)]]),
244
+ withDefinedEntries([["workspace", orderWorkspace(manifest.workspace)]]),
245
+ withDefinedEntries([["environment", orderEnvironment(manifest.environment)]]),
238
246
  withDefinedEntries([["surfaces", orderSurfaces(manifest.surfaces)]]),
239
- withDefinedEntries([
240
- ["skills", manifest.skills],
241
- ["mcp_servers", manifest.mcp_servers],
242
- ["secrets", manifest.secrets],
243
- ["env", manifest.env],
244
- ["policy", manifest.policy]
245
- ]),
247
+ withDefinedEntries([["policy", manifest.policy]]),
246
248
  withDefinedEntries([["subagents", manifest.subagents]])
247
249
  ];
248
250
  const orderTeamManifestSections = (manifest) => [
@@ -251,20 +253,10 @@ const orderTeamManifestSections = (manifest) => [
251
253
  ["kind", manifest.kind],
252
254
  ["name", manifest.name]
253
255
  ]),
254
- withDefinedEntries([["runtime", orderRuntimeBinding(manifest.runtime)]]),
255
256
  withDefinedEntries([["execution", orderExecution(manifest.execution)]]),
256
- withDefinedEntries([
257
- ["docs", orderDocs(manifest.docs)],
258
- ["shared", orderSharedSurface(manifest.shared)],
259
- ["networks", orderTeamNetworks(manifest.networks)]
260
- ]),
261
- withDefinedEntries([
262
- ["skills", manifest.skills],
263
- ["mcp_servers", manifest.mcp_servers],
264
- ["secrets", manifest.secrets],
265
- ["env", manifest.env],
266
- ["policy", manifest.policy]
267
- ]),
257
+ withDefinedEntries([["shared", orderSharedSurface(manifest.shared)]]),
258
+ withDefinedEntries([["networks", orderTeamNetworks(manifest.networks)]]),
259
+ withDefinedEntries([["policy", manifest.policy]]),
268
260
  withDefinedEntries([
269
261
  ["members", manifest.members],
270
262
  ["mode", manifest.mode],
@@ -0,0 +1,2 @@
1
+ import type { TeamManifest } from "./schemas.js";
2
+ export declare const orderTeamNetworks: (networks: TeamManifest["networks"]) => TeamManifest["networks"] | undefined;
@@ -0,0 +1,63 @@
1
+ const withDefinedEntries = (entries) => Object.fromEntries(entries.filter((entry) => entry[1] !== undefined));
2
+ const orderTeamAuthToken = (token) => withDefinedEntries([
3
+ ["id", token.id],
4
+ ["agents", token.agents],
5
+ ["scopes", token.scopes]
6
+ ]);
7
+ const orderTeamAuthPairing = (pairing) => withDefinedEntries([
8
+ ["id", pairing.id],
9
+ ["remote_base_url", pairing.remote_base_url],
10
+ ["remote_network_id", pairing.remote_network_id],
11
+ ["remote_network_name", pairing.remote_network_name]
12
+ ]);
13
+ const orderTeamAuth = (server) => withDefinedEntries([
14
+ ["mode", server.mode],
15
+ ["url", server.url],
16
+ ["listen", server.mode === "managed" ? server.listen : undefined],
17
+ [
18
+ "auth",
19
+ withDefinedEntries([
20
+ ["mode", server.auth.mode],
21
+ ["tokens", server.auth.tokens?.map(orderTeamAuthToken)],
22
+ [
23
+ "client",
24
+ server.auth.client
25
+ ? withDefinedEntries([
26
+ ["static_token", server.auth.client.static_token],
27
+ ["token_id", server.auth.client.token_id],
28
+ ["token_env", server.auth.client.token_env],
29
+ ["token_path", server.auth.client.token_path]
30
+ ])
31
+ : undefined
32
+ ]
33
+ ])
34
+ ],
35
+ ["store", server.mode === "managed" ? server.store : undefined],
36
+ [
37
+ "pairings",
38
+ server.mode === "managed" && server.pairings
39
+ ? server.pairings.map(orderTeamAuthPairing)
40
+ : undefined
41
+ ],
42
+ ["human_ingress", server.mode === "managed" ? server.human_ingress : undefined],
43
+ ["direct_messages", server.mode === "managed" ? server.direct_messages : undefined],
44
+ [
45
+ "trust_forwarded_proto",
46
+ server.mode === "managed" ? server.trust_forwarded_proto : undefined
47
+ ],
48
+ ["allowed_origins", server.mode === "managed" ? server.allowed_origins : undefined]
49
+ ]);
50
+ export const orderTeamNetworks = (networks) => networks?.map((network) => withDefinedEntries([
51
+ ["id", network.id],
52
+ ["provider", network.provider],
53
+ ["name", network.name],
54
+ ["server", orderTeamAuth(network.server)],
55
+ [
56
+ "rooms",
57
+ network.rooms.map((room) => withDefinedEntries([
58
+ ["id", room.id],
59
+ ["name", room.name],
60
+ ["members", room.members]
61
+ ]))
62
+ ]
63
+ ]));
@@ -0,0 +1,2 @@
1
+ import type { TeamWorkspace } from "./schemas.js";
2
+ export declare const orderWorkspace: (workspace: TeamWorkspace | undefined) => TeamWorkspace | undefined;
@@ -0,0 +1,47 @@
1
+ const withDefinedEntries = (entries) => Object.fromEntries(entries.filter((entry) => entry[1] !== undefined));
2
+ const orderDocs = (docs) => {
3
+ if (!docs) {
4
+ return undefined;
5
+ }
6
+ return withDefinedEntries([
7
+ ["identity", docs.identity],
8
+ ["soul", docs.soul],
9
+ ["system", docs.system],
10
+ ["memory", docs.memory],
11
+ ["heartbeat", docs.heartbeat],
12
+ ["extras", docs.extras]
13
+ ]);
14
+ };
15
+ const orderWorkspaceResource = (resource) => {
16
+ if (resource.kind === "git") {
17
+ return withDefinedEntries([
18
+ ["id", resource.id],
19
+ ["kind", resource.kind],
20
+ ["url", resource.url],
21
+ ["branch", resource.branch],
22
+ ["ref", resource.ref],
23
+ ["tag", resource.tag],
24
+ ["mount", resource.mount],
25
+ ["mode", resource.mode],
26
+ ["sharing", resource.sharing]
27
+ ]);
28
+ }
29
+ return withDefinedEntries([
30
+ ["id", resource.id],
31
+ ["kind", resource.kind],
32
+ ["mount", resource.mount],
33
+ ["mode", resource.mode],
34
+ ["name", resource.name],
35
+ ["sharing", resource.sharing]
36
+ ]);
37
+ };
38
+ export const orderWorkspace = (workspace) => {
39
+ if (!workspace) {
40
+ return undefined;
41
+ }
42
+ return withDefinedEntries([
43
+ ["docs", orderDocs(workspace.docs)],
44
+ ["resources", workspace.resources?.map(orderWorkspaceResource)],
45
+ ["skills", workspace.skills]
46
+ ]);
47
+ };
@@ -20,10 +20,12 @@ export const createAgentScaffoldManifest = (options) => {
20
20
  }
21
21
  }
22
22
  },
23
- docs: {
24
- ...(options.docs.identity ? { identity: options.docs.identity } : {}),
25
- ...(options.docs.soul ? { soul: options.docs.soul } : {}),
26
- system: options.docs.system
23
+ workspace: {
24
+ docs: {
25
+ ...(options.docs.identity ? { identity: options.docs.identity } : {}),
26
+ ...(options.docs.soul ? { soul: options.docs.soul } : {}),
27
+ system: options.docs.system
28
+ }
27
29
  }
28
30
  };
29
31
  };
@@ -31,8 +33,12 @@ export const createTeamScaffoldManifest = () => ({
31
33
  spawnfile_version: "0.1",
32
34
  kind: "team",
33
35
  name: "my-team",
34
- docs: {
35
- system: "TEAM.md"
36
+ shared: {
37
+ workspace: {
38
+ docs: {
39
+ system: "TEAM.md"
40
+ }
41
+ }
36
42
  },
37
43
  members: [],
38
44
  mode: "swarm"
@@ -0,0 +1,15 @@
1
+ import { z } from "zod";
2
+ export declare const agentScheduleSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
3
+ cron: z.ZodString;
4
+ kind: z.ZodLiteral<"cron">;
5
+ prompt: z.ZodOptional<z.ZodString>;
6
+ timezone: z.ZodOptional<z.ZodString>;
7
+ }, z.core.$strict>, z.ZodObject<{
8
+ every: z.ZodString;
9
+ kind: z.ZodLiteral<"every">;
10
+ prompt: z.ZodOptional<z.ZodString>;
11
+ timezone: z.ZodOptional<z.ZodString>;
12
+ }, z.core.$strict>, z.ZodObject<{
13
+ kind: z.ZodLiteral<"disabled">;
14
+ }, z.core.$strict>], "kind">;
15
+ export type AgentSchedule = z.infer<typeof agentScheduleSchema>;
@@ -0,0 +1,26 @@
1
+ import { z } from "zod";
2
+ const schedulePromptSchema = z.string().min(1);
3
+ const scheduleTimezoneSchema = z.string().min(1);
4
+ export const agentScheduleSchema = z.discriminatedUnion("kind", [
5
+ z
6
+ .object({
7
+ cron: z.string().min(1),
8
+ kind: z.literal("cron"),
9
+ prompt: schedulePromptSchema.optional(),
10
+ timezone: scheduleTimezoneSchema.optional()
11
+ })
12
+ .strict(),
13
+ z
14
+ .object({
15
+ every: z.string().min(1),
16
+ kind: z.literal("every"),
17
+ prompt: schedulePromptSchema.optional(),
18
+ timezone: scheduleTimezoneSchema.optional()
19
+ })
20
+ .strict(),
21
+ z
22
+ .object({
23
+ kind: z.literal("disabled")
24
+ })
25
+ .strict()
26
+ ]);