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.
- package/README.md +3 -0
- package/dist/cli/index.js +0 -0
- package/dist/cli/runCli.d.ts +18 -2
- package/dist/cli/runCli.js +75 -62
- package/dist/cli/viewCommand.d.ts +3 -0
- package/dist/cli/viewCommand.js +87 -0
- package/dist/compiler/buildCompilePlan.js +2 -0
- package/dist/compiler/containerEntrypointRender.js +3 -3
- package/dist/compiler/index.d.ts +2 -0
- package/dist/compiler/index.js +2 -0
- package/dist/compiler/moltnetArtifacts.js +7 -3
- package/dist/compiler/moltnetResolution.js +29 -48
- package/dist/compiler/moltnetRoomMemberships.d.ts +3 -0
- package/dist/compiler/moltnetRoomMemberships.js +140 -0
- package/dist/compiler/runProject.d.ts +2 -0
- package/dist/compiler/runProject.js +20 -6
- package/dist/compiler/syncProjectAuth.js +53 -19
- package/dist/compiler/types.d.ts +18 -0
- package/dist/compiler/view/buildOrganizationView.d.ts +2 -0
- package/dist/compiler/view/buildOrganizationView.js +180 -0
- package/dist/compiler/view/index.d.ts +4 -0
- package/dist/compiler/view/index.js +4 -0
- package/dist/compiler/view/renderNetworks.d.ts +2 -0
- package/dist/compiler/view/renderNetworks.js +93 -0
- package/dist/compiler/view/renderTree.d.ts +2 -0
- package/dist/compiler/view/renderTree.js +59 -0
- package/dist/compiler/view/sourcePaths.d.ts +2 -0
- package/dist/compiler/view/sourcePaths.js +19 -0
- package/dist/compiler/view/types.d.ts +80 -0
- package/dist/compiler/view/types.js +1 -0
- package/dist/runtime/picoclaw/adapter.js +7 -0
- package/dist/runtime/picoclaw/runAuth.js +5 -41
- 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,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
|
|
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
|
|
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
|
-
|
|
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
|
|
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.
|
|
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",
|