spawnfile 0.1.2 → 0.1.4

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 (33) hide show
  1. package/README.md +3 -0
  2. package/dist/cli/index.js +0 -0
  3. package/dist/cli/runCli.d.ts +18 -2
  4. package/dist/cli/runCli.js +75 -62
  5. package/dist/cli/viewCommand.d.ts +3 -0
  6. package/dist/cli/viewCommand.js +87 -0
  7. package/dist/compiler/buildCompilePlan.js +2 -0
  8. package/dist/compiler/containerEntrypointRender.js +3 -3
  9. package/dist/compiler/index.d.ts +2 -0
  10. package/dist/compiler/index.js +2 -0
  11. package/dist/compiler/moltnetArtifacts.js +7 -3
  12. package/dist/compiler/moltnetResolution.js +29 -48
  13. package/dist/compiler/moltnetRoomMemberships.d.ts +3 -0
  14. package/dist/compiler/moltnetRoomMemberships.js +140 -0
  15. package/dist/compiler/runProject.d.ts +2 -0
  16. package/dist/compiler/runProject.js +20 -6
  17. package/dist/compiler/syncProjectAuth.js +53 -19
  18. package/dist/compiler/types.d.ts +18 -0
  19. package/dist/compiler/view/buildOrganizationView.d.ts +2 -0
  20. package/dist/compiler/view/buildOrganizationView.js +180 -0
  21. package/dist/compiler/view/index.d.ts +4 -0
  22. package/dist/compiler/view/index.js +4 -0
  23. package/dist/compiler/view/renderNetworks.d.ts +2 -0
  24. package/dist/compiler/view/renderNetworks.js +93 -0
  25. package/dist/compiler/view/renderTree.d.ts +2 -0
  26. package/dist/compiler/view/renderTree.js +59 -0
  27. package/dist/compiler/view/sourcePaths.d.ts +2 -0
  28. package/dist/compiler/view/sourcePaths.js +19 -0
  29. package/dist/compiler/view/types.d.ts +80 -0
  30. package/dist/compiler/view/types.js +1 -0
  31. package/dist/runtime/picoclaw/adapter.js +7 -0
  32. package/dist/runtime/picoclaw/runAuth.js +5 -41
  33. package/package.json +2 -2
@@ -0,0 +1,59 @@
1
+ import { formatSourceMeta } from "./sourcePaths.js";
2
+ const color = (value, code, options) => options.color ? `\u001b[${code}m${value}\u001b[0m` : value;
3
+ const formatNode = (node, options, projectRoot) => {
4
+ const kind = color(node.kind, node.kind === "team" ? "36" : "32", options);
5
+ const metadata = node.kind === "team"
6
+ ? [
7
+ node.mode ? `mode=${node.mode}` : undefined,
8
+ node.lead ? `lead=${node.lead}` : undefined,
9
+ node.external && node.external.length > 0
10
+ ? `external=${node.external.join(",")}`
11
+ : undefined
12
+ ]
13
+ : [
14
+ node.runtimeName ? `[${node.runtimeName}]` : undefined,
15
+ node.runtimeName ? `runtime=${node.runtimeName}` : undefined
16
+ ];
17
+ const details = metadata.filter((entry) => entry !== undefined);
18
+ const source = options.paths ? formatSourceMeta("source", node.source, projectRoot) : "";
19
+ const separator = details[0]?.startsWith("[") ? " " : " ";
20
+ return `${kind} ${node.displayName}${details.length > 0 ? `${separator}${details.join(" ")}` : ""}${source}`;
21
+ };
22
+ const formatEdgeLabel = (edge) => edge.relation === "subagent"
23
+ ? `subagent ${edge.label}`
24
+ : edge.label;
25
+ const formatNetworkSummary = (network, options) => {
26
+ const id = color(network.id, "36", options);
27
+ const exposed = network.expose ? " exposed" : "";
28
+ const rooms = network.rooms
29
+ .map((room) => `${room.id} [${room.declaredMembers.join(", ")}]`)
30
+ .join("; ");
31
+ return `network ${id} "${network.name}"${exposed}: ${rooms}`;
32
+ };
33
+ const renderChildren = (node, options, projectRoot, prefix = "") => {
34
+ const glyphs = options.ascii
35
+ ? { branch: "|-- ", last: "`-- ", pipe: "| ", space: " " }
36
+ : { branch: "├── ", last: "└── ", pipe: "│ ", space: " " };
37
+ const items = [
38
+ ...(node.networks ?? []).map((network) => ({ kind: "network", network })),
39
+ ...node.children.map((edge) => ({ kind: "edge", edge }))
40
+ ];
41
+ return items.flatMap((item, index) => {
42
+ const isLast = index === items.length - 1;
43
+ const connector = isLast ? glyphs.last : glyphs.branch;
44
+ const nextPrefix = `${prefix}${isLast ? glyphs.space : glyphs.pipe}`;
45
+ if (item.kind === "network") {
46
+ return [`${prefix}${connector}${formatNetworkSummary(item.network, options)}`];
47
+ }
48
+ const edge = item.edge;
49
+ const line = `${prefix}${connector}${formatEdgeLabel(edge)}: ${formatNode(edge.node, options, projectRoot)}`;
50
+ return [
51
+ line,
52
+ ...renderChildren(edge.node, options, projectRoot, nextPrefix)
53
+ ];
54
+ });
55
+ };
56
+ export const renderOrganizationTree = (view, options = {}) => [
57
+ formatNode(view.root, options, view.projectRoot),
58
+ ...renderChildren(view.root, options, view.projectRoot)
59
+ ].join("\n");
@@ -0,0 +1,2 @@
1
+ export declare const formatSourcePath: (sourcePath: string, projectRoot: string | undefined) => string;
2
+ export declare const formatSourceMeta: (label: string, sourcePath: string, projectRoot: string | undefined) => string;
@@ -0,0 +1,19 @@
1
+ import path from "node:path";
2
+ export const formatSourcePath = (sourcePath, projectRoot) => {
3
+ if (!projectRoot || !path.isAbsolute(sourcePath) || !path.isAbsolute(projectRoot)) {
4
+ return sourcePath;
5
+ }
6
+ const relativePath = path.relative(projectRoot, sourcePath);
7
+ if (relativePath === ""
8
+ || relativePath.startsWith("..")
9
+ || path.isAbsolute(relativePath)) {
10
+ return sourcePath;
11
+ }
12
+ return relativePath.split(path.sep).join("/");
13
+ };
14
+ export const formatSourceMeta = (label, sourcePath, projectRoot) => {
15
+ const formattedPath = formatSourcePath(sourcePath, projectRoot);
16
+ return projectRoot
17
+ ? ` ${label}=${formattedPath}`
18
+ : ` <${formattedPath}>`;
19
+ };
@@ -0,0 +1,80 @@
1
+ import type { ResolvedMoltnetRoomPolicy } from "../types.js";
2
+ export interface OrganizationViewTreeNode {
3
+ children: OrganizationViewTreeEdge[];
4
+ displayName: string;
5
+ external?: string[];
6
+ id: string;
7
+ kind: "agent" | "team";
8
+ lead?: string | null;
9
+ mode?: "hierarchical" | "swarm";
10
+ name: string;
11
+ networks?: OrganizationTreeNetworkSummary[];
12
+ runtimeName: string | null;
13
+ source: string;
14
+ }
15
+ export interface OrganizationTreeNetworkRoomSummary {
16
+ declaredMembers: string[];
17
+ id: string;
18
+ }
19
+ export interface OrganizationTreeNetworkSummary {
20
+ expose: boolean;
21
+ id: string;
22
+ name: string;
23
+ provider: "moltnet";
24
+ rooms: OrganizationTreeNetworkRoomSummary[];
25
+ }
26
+ export interface OrganizationViewTreeEdge {
27
+ label: string;
28
+ node: OrganizationViewTreeNode;
29
+ relation: "subagent" | "team_member";
30
+ }
31
+ export interface OrganizationNetworkMemberView {
32
+ agentName: string;
33
+ agentSource: string;
34
+ concreteMemberId: string;
35
+ declaredSlot: string;
36
+ directTeamName: string;
37
+ directTeamSource: string;
38
+ policy?: ResolvedMoltnetRoomPolicy;
39
+ representedSlot?: string;
40
+ representedTeamName?: string;
41
+ representedTeamSource?: string;
42
+ representativePath?: string[];
43
+ }
44
+ export interface OrganizationNetworkDeclarationView {
45
+ declaringTeamName: string;
46
+ declaringTeamSource: string;
47
+ expose: boolean;
48
+ name: string;
49
+ rooms: OrganizationNetworkRoomView[];
50
+ }
51
+ export interface OrganizationNetworkRoomView {
52
+ declaredMembers: string[];
53
+ id: string;
54
+ members: OrganizationNetworkMemberView[];
55
+ }
56
+ export interface OrganizationNetworkView {
57
+ declaringTeamName: string;
58
+ declaringTeamSource: string;
59
+ expose: boolean;
60
+ id: string;
61
+ name: string;
62
+ provider: "moltnet";
63
+ rooms: OrganizationNetworkRoomView[];
64
+ declarations?: OrganizationNetworkDeclarationView[];
65
+ }
66
+ export interface OrganizationView {
67
+ contexts: [];
68
+ diagnostics: [];
69
+ inputPath: string;
70
+ networks: OrganizationNetworkView[];
71
+ projectRoot?: string;
72
+ root: OrganizationViewTreeNode;
73
+ runtimes: [];
74
+ }
75
+ export interface RenderOrganizationViewOptions {
76
+ ascii?: boolean;
77
+ color?: boolean;
78
+ declared?: boolean;
79
+ paths?: boolean;
80
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -47,6 +47,13 @@ const buildModelList = (node) => {
47
47
  model_name: target.name
48
48
  };
49
49
  }
50
+ if (target.provider === "openai" && target.auth.method === "codex") {
51
+ return {
52
+ model: `codex-cli/${target.name}`,
53
+ model_name: target.name,
54
+ workspace: "<workspace-path>"
55
+ };
56
+ }
50
57
  return {
51
58
  ...(target.auth.method === "api_key"
52
59
  ? {
@@ -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)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "spawnfile",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "Canonical source compiler for autonomous agents and teams.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -16,7 +16,7 @@
16
16
  },
17
17
  "scripts": {
18
18
  "blueprints": "./scripts/blueprints.sh",
19
- "build": "rm -rf dist && tsc --project tsconfig.build.json && node ./scripts/copy-runtime-scaffold-assets.mjs",
19
+ "build": "rm -rf dist && tsc --project tsconfig.build.json && chmod +x dist/cli/index.js && node ./scripts/copy-runtime-scaffold-assets.mjs",
20
20
  "clean": "rm -rf coverage dist",
21
21
  "coverage": "vitest run --coverage",
22
22
  "dev": "tsx src/cli/index.ts",