spawnfile 0.1.3 → 0.1.5

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 (78) hide show
  1. package/README.md +2 -0
  2. package/dist/cli/lifecycleCommands.d.ts +3 -0
  3. package/dist/cli/lifecycleCommands.js +80 -0
  4. package/dist/cli/runCli.d.ts +2 -1
  5. package/dist/cli/runCli.js +5 -47
  6. package/dist/compiler/buildCompilePlan.js +12 -202
  7. package/dist/compiler/buildCompilePlanRuntime.d.ts +6 -1
  8. package/dist/compiler/buildCompilePlanRuntime.js +9 -0
  9. package/dist/compiler/buildCompilePlanTeams.js +16 -10
  10. package/dist/compiler/buildCompilePlanTraversal.d.ts +16 -0
  11. package/dist/compiler/buildCompilePlanTraversal.js +214 -0
  12. package/dist/compiler/buildCompilePlanTraversalHelpers.d.ts +18 -0
  13. package/dist/compiler/buildCompilePlanTraversalHelpers.js +22 -0
  14. package/dist/compiler/compilePlanHelpers.d.ts +3 -1
  15. package/dist/compiler/compilePlanHelpers.js +37 -1
  16. package/dist/compiler/compileProject.js +14 -0
  17. package/dist/compiler/containerArtifacts.js +18 -3
  18. package/dist/compiler/containerArtifactsPlans.js +32 -0
  19. package/dist/compiler/containerArtifactsRender.js +86 -3
  20. package/dist/compiler/containerArtifactsTypes.d.ts +7 -3
  21. package/dist/compiler/containerEntrypointRender.d.ts +1 -1
  22. package/dist/compiler/containerEntrypointRender.js +37 -27
  23. package/dist/compiler/containerTargetResources.d.ts +4 -0
  24. package/dist/compiler/containerTargetResources.js +54 -0
  25. package/dist/compiler/containerWorkspaceResourceRender.d.ts +3 -0
  26. package/dist/compiler/containerWorkspaceResourceRender.js +128 -0
  27. package/dist/compiler/executionDefaults.js +0 -3
  28. package/dist/compiler/helpers.d.ts +1 -1
  29. package/dist/compiler/index.d.ts +1 -0
  30. package/dist/compiler/index.js +1 -0
  31. package/dist/compiler/moltnetArtifacts.d.ts +11 -5
  32. package/dist/compiler/moltnetArtifacts.js +133 -117
  33. package/dist/compiler/moltnetClientConfig.js +8 -2
  34. package/dist/compiler/moltnetConfigLowering.d.ts +36 -0
  35. package/dist/compiler/moltnetConfigLowering.js +125 -0
  36. package/dist/compiler/moltnetRuntimeConfig.d.ts +2 -0
  37. package/dist/compiler/moltnetRuntimeConfig.js +69 -0
  38. package/dist/compiler/runProject.d.ts +2 -0
  39. package/dist/compiler/runProject.js +20 -6
  40. package/dist/compiler/surfaces.d.ts +3 -13
  41. package/dist/compiler/surfaces.js +1 -6
  42. package/dist/compiler/syncProjectAuth.js +67 -19
  43. package/dist/compiler/types.d.ts +16 -1
  44. package/dist/compiler/upProject.d.ts +19 -0
  45. package/dist/compiler/upProject.js +37 -0
  46. package/dist/compiler/view/buildOrganizationView.js +22 -2
  47. package/dist/compiler/view/renderNetworks.js +14 -3
  48. package/dist/compiler/view/renderTree.js +8 -2
  49. package/dist/compiler/view/types.d.ts +18 -3
  50. package/dist/compiler/workspaceResources.d.ts +34 -0
  51. package/dist/compiler/workspaceResources.js +120 -0
  52. package/dist/manifest/executionSchemas.d.ts +106 -0
  53. package/dist/manifest/executionSchemas.js +140 -0
  54. package/dist/manifest/loadManifest.js +15 -27
  55. package/dist/manifest/renderSpawnfile.js +44 -52
  56. package/dist/manifest/renderSpawnfileNetworks.d.ts +2 -0
  57. package/dist/manifest/renderSpawnfileNetworks.js +63 -0
  58. package/dist/manifest/renderSpawnfileWorkspace.d.ts +2 -0
  59. package/dist/manifest/renderSpawnfileWorkspace.js +47 -0
  60. package/dist/manifest/scaffold.js +12 -6
  61. package/dist/manifest/scheduleSchemas.d.ts +15 -0
  62. package/dist/manifest/scheduleSchemas.js +26 -0
  63. package/dist/manifest/schemas.d.ts +626 -368
  64. package/dist/manifest/schemas.js +51 -191
  65. package/dist/manifest/teamNetworkSchemas.d.ts +228 -0
  66. package/dist/manifest/teamNetworkSchemas.js +295 -0
  67. package/dist/manifest/workspaceSchemas.d.ts +96 -0
  68. package/dist/manifest/workspaceSchemas.js +166 -0
  69. package/dist/report/types.d.ts +10 -0
  70. package/dist/runtime/common.d.ts +2 -1
  71. package/dist/runtime/common.js +3 -3
  72. package/dist/runtime/picoclaw/adapter.js +7 -0
  73. package/dist/runtime/picoclaw/runAuth.js +5 -41
  74. package/dist/runtime/tinyclaw/adapter.js +9 -2
  75. package/dist/runtime/tinyclaw/schedules.d.ts +9 -0
  76. package/dist/runtime/tinyclaw/schedules.js +62 -0
  77. package/dist/runtime/types.d.ts +1 -0
  78. package/package.json +2 -1
@@ -1,12 +1,12 @@
1
1
  import path from "node:path";
2
- import { loadImportedClaudeCodeCredential, loadImportedCodexCredential } from "../../auth/index.js";
2
+ import { loadImportedClaudeCodeCredential } from "../../auth/index.js";
3
3
  import { copyDirectory, ensureDirectory, readUtf8File, writeUtf8File } from "../../filesystem/index.js";
4
4
  const resolveRootfsSourcePath = (outputDirectory, containerPath) => path.join(outputDirectory, "container", "rootfs", ...path.posix.relative("/", containerPath).split("/"));
5
5
  const createMountArgs = (hostPath, containerPath) => [
6
6
  "-v",
7
7
  `${hostPath}:${containerPath}`
8
8
  ];
9
- const createMountedHomeDirectory = async (input, patchedConfig, authStore) => {
9
+ const createMountedHomeDirectory = async (input, patchedConfig) => {
10
10
  const sourceHomePath = resolveRootfsSourcePath(input.outputDirectory, input.instance.home_path);
11
11
  const mountedHomePath = path.join("runtime-auth", "picoclaw", input.instance.id, "home");
12
12
  const hostHomePath = path.join(input.tempRoot, mountedHomePath);
@@ -14,26 +14,10 @@ const createMountedHomeDirectory = async (input, patchedConfig, authStore) => {
14
14
  await copyDirectory(sourceHomePath, hostHomePath);
15
15
  const relativeConfigPath = path.posix.relative(input.instance.home_path, input.instance.config_path);
16
16
  const hostConfigPath = path.join(hostHomePath, ...relativeConfigPath.split("/"));
17
- const hostAuthPath = path.join(hostHomePath, "auth.json");
18
17
  await ensureDirectory(path.dirname(hostConfigPath));
19
18
  await writeUtf8File(hostConfigPath, `${JSON.stringify(patchedConfig, null, 2)}\n`);
20
- if (authStore) {
21
- await writeUtf8File(hostAuthPath, `${JSON.stringify(authStore, null, 2)}\n`);
22
- }
23
19
  return hostHomePath;
24
20
  };
25
- const createPicoClawCredential = (provider, credential) => ({
26
- access_token: credential.access,
27
- ...("type" in credential && credential.type === "oauth" && credential.refresh
28
- ? { refresh_token: credential.refresh }
29
- : !("type" in credential)
30
- ? { refresh_token: credential.refresh }
31
- : {}),
32
- ...("accountId" in credential && credential.accountId ? { account_id: credential.accountId } : {}),
33
- auth_method: "oauth",
34
- expires_at: new Date(credential.expires).toISOString(),
35
- provider
36
- });
37
21
  const normalizeClaudeCliModelName = (modelName) => modelName.replaceAll(".", "-");
38
22
  const patchPicoClawConfig = (config, options) => {
39
23
  const agents = config.agents ?? {};
@@ -55,21 +39,11 @@ const patchPicoClawConfig = (config, options) => {
55
39
  record.model = `claude-cli/${normalizeClaudeCliModelName(modelName)}`;
56
40
  }
57
41
  }
58
- if (options.useCodex && typeof model === "string" && model.startsWith("openai/")) {
59
- delete record.api_key;
60
- record.auth_method = "oauth";
61
- }
62
42
  return record;
63
43
  });
64
44
  if (options.useClaudeCode) {
65
45
  delete nextProviders.anthropic;
66
46
  }
67
- if (options.useCodex) {
68
- nextProviders.openai = {
69
- ...(nextProviders.openai ?? {}),
70
- auth_method: "oauth"
71
- };
72
- }
73
47
  return {
74
48
  ...config,
75
49
  agents: {
@@ -87,29 +61,19 @@ export const preparePicoClawRuntimeAuth = async (input) => {
87
61
  const claudeCode = input.authProfile.imports["claude-code"]
88
62
  ? await loadImportedClaudeCodeCredential(input.authProfile.imports["claude-code"].path)
89
63
  : null;
90
- const codex = input.authProfile.imports.codex
91
- ? await loadImportedCodexCredential(input.authProfile.imports.codex.path)
92
- : null;
93
64
  const useClaudeCode = input.instance.model_auth_methods.anthropic === "claude-code" && claudeCode;
94
- const useCodex = input.instance.model_auth_methods.openai === "codex" && codex;
95
- if (!useClaudeCode && !useCodex) {
65
+ if (!useClaudeCode) {
96
66
  return { coveredModelSecrets: [], mountArgs: [] };
97
67
  }
98
- const credentials = {};
99
68
  const coveredModelSecrets = [];
100
- if (useCodex) {
101
- credentials.openai = createPicoClawCredential("openai", codex);
102
- coveredModelSecrets.push("OPENAI_API_KEY");
103
- }
104
69
  if (useClaudeCode) {
105
70
  coveredModelSecrets.push("ANTHROPIC_API_KEY");
106
71
  }
107
72
  const sourceConfig = JSON.parse(await readUtf8File(resolveRootfsSourcePath(input.outputDirectory, input.instance.config_path)));
108
73
  const patchedConfig = patchPicoClawConfig(sourceConfig, {
109
- useClaudeCode: Boolean(useClaudeCode),
110
- useCodex: Boolean(useCodex)
74
+ useClaudeCode: Boolean(useClaudeCode)
111
75
  });
112
- const mountedHomePath = await createMountedHomeDirectory(input, patchedConfig, Object.keys(credentials).length > 0 ? { credentials } : null);
76
+ const mountedHomePath = await createMountedHomeDirectory(input, patchedConfig);
113
77
  return {
114
78
  coveredModelSecrets,
115
79
  mountArgs: createMountArgs(mountedHomePath, input.instance.home_path)
@@ -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[];
@@ -0,0 +1,62 @@
1
+ import { createDiagnostic } from "../common.js";
2
+ const TINYCLAW_SCHEDULE_CHANNEL = "schedule";
3
+ const TINYCLAW_SCHEDULE_SENDER = "Spawnfile Scheduler";
4
+ const createTinyClawSchedule = (node) => {
5
+ if (!node.schedule || node.schedule.kind !== "cron") {
6
+ return null;
7
+ }
8
+ return {
9
+ agentId: node.name,
10
+ channel: TINYCLAW_SCHEDULE_CHANNEL,
11
+ createdAt: 0,
12
+ cron: node.schedule.cron,
13
+ enabled: true,
14
+ id: `spawnfile-${node.name}`,
15
+ label: `Spawnfile schedule for ${node.name}`,
16
+ message: node.schedule.prompt ?? "Run the scheduled Spawnfile task.",
17
+ sender: TINYCLAW_SCHEDULE_SENDER
18
+ };
19
+ };
20
+ export const createTinyClawSchedulesFile = (inputs) => {
21
+ const schedules = inputs
22
+ .flatMap((input) => {
23
+ if (input.kind !== "agent" || input.value.kind !== "agent") {
24
+ return [];
25
+ }
26
+ return [createTinyClawSchedule(input.value)];
27
+ })
28
+ .filter((schedule) => Boolean(schedule))
29
+ .sort((left, right) => left.id.localeCompare(right.id));
30
+ return schedules.length > 0
31
+ ? {
32
+ content: `${JSON.stringify(schedules, null, 2)}\n`,
33
+ path: "home/schedules.json"
34
+ }
35
+ : null;
36
+ };
37
+ export const scheduleOutcomeFor = (node) => {
38
+ if (!node.schedule) {
39
+ return {};
40
+ }
41
+ if (node.schedule.kind === "cron") {
42
+ return {
43
+ message: "TinyClaw native cron scheduler is emitted as schedules.json",
44
+ outcome: "supported"
45
+ };
46
+ }
47
+ if (node.schedule.kind === "disabled") {
48
+ return {
49
+ message: "Disabled schedule emits no wake registration",
50
+ outcome: "supported"
51
+ };
52
+ }
53
+ return {
54
+ message: "TinyClaw native schedule lowering supports cron schedules in Spawnfile v0.1",
55
+ outcome: "degraded"
56
+ };
57
+ };
58
+ export const createScheduleDiagnostics = (node) => node.schedule?.kind === "every"
59
+ ? [
60
+ createDiagnostic("warn", "TinyClaw native schedule lowering supports cron schedules in Spawnfile v0.1; every schedules are degraded")
61
+ ]
62
+ : [];
@@ -33,6 +33,7 @@ export interface ContainerTarget {
33
33
  export interface RuntimeContainerInstancePaths {
34
34
  configPathTemplate: string;
35
35
  homePathTemplate?: string;
36
+ sourceWorkspacePathTemplate?: string;
36
37
  workspacePathTemplate: string;
37
38
  }
38
39
  export interface RuntimeContainerConfigEnvBinding {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "spawnfile",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "description": "Canonical source compiler for autonomous agents and teams.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -29,6 +29,7 @@
29
29
  "runtimes:sync": "./scripts/runtimes.sh && ./scripts/blueprints.sh",
30
30
  "test:e2e:docker-auth": "tsx src/e2e/cli.ts",
31
31
  "test:e2e:moltnet-team-chat": "tsx src/e2e/cli.ts moltnet-team-chat",
32
+ "test:e2e:operational-smoke": "tsx src/e2e/cli.ts operational-smoke",
32
33
  "test": "vitest run",
33
34
  "typecheck": "tsc --project tsconfig.json --noEmit"
34
35
  },