spawnfile 0.1.1 → 0.1.3
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 +80 -396
- package/dist/cli/index.js +0 -0
- package/dist/cli/modelCommands.d.ts +3 -0
- package/dist/cli/modelCommands.js +68 -0
- package/dist/cli/runCli.d.ts +23 -2
- package/dist/cli/runCli.js +78 -122
- package/dist/cli/runtimeCommands.d.ts +3 -0
- package/dist/cli/runtimeCommands.js +20 -0
- package/dist/cli/surfaceCommands.d.ts +3 -0
- package/dist/cli/surfaceCommands.js +98 -0
- package/dist/cli/viewCommand.d.ts +3 -0
- package/dist/cli/viewCommand.js +87 -0
- package/dist/compiler/agentSurfaces.js +51 -5
- package/dist/compiler/buildCompilePlan.js +38 -40
- package/dist/compiler/buildCompilePlanRuntime.d.ts +14 -0
- package/dist/compiler/buildCompilePlanRuntime.js +39 -0
- package/dist/compiler/buildCompilePlanTeams.d.ts +5 -0
- package/dist/compiler/buildCompilePlanTeams.js +38 -0
- package/dist/compiler/compilePlanHelpers.js +4 -1
- package/dist/compiler/compileProject.js +62 -13
- package/dist/compiler/compileProjectSupport.d.ts +17 -0
- package/dist/compiler/compileProjectSupport.js +136 -0
- package/dist/compiler/containerArtifacts.d.ts +6 -1
- package/dist/compiler/containerArtifacts.js +26 -4
- package/dist/compiler/containerArtifactsPlans.js +16 -1
- package/dist/compiler/containerArtifactsRender.d.ts +4 -2
- package/dist/compiler/containerArtifactsRender.js +21 -126
- package/dist/compiler/containerArtifactsTypes.d.ts +7 -0
- package/dist/compiler/containerEntrypointRender.d.ts +12 -0
- package/dist/compiler/containerEntrypointRender.js +186 -0
- package/dist/compiler/index.d.ts +4 -0
- package/dist/compiler/index.js +4 -0
- package/dist/compiler/interactiveSurfaceScopes.d.ts +2 -0
- package/dist/compiler/interactiveSurfaceScopes.js +21 -0
- package/dist/compiler/moltnetArtifacts.d.ts +27 -0
- package/dist/compiler/moltnetArtifacts.js +208 -0
- package/dist/compiler/moltnetBinaries.d.ts +4 -0
- package/dist/compiler/moltnetBinaries.js +103 -0
- package/dist/compiler/moltnetClientConfig.d.ts +11 -0
- package/dist/compiler/moltnetClientConfig.js +89 -0
- package/dist/compiler/moltnetRepresentativeResolution.d.ts +16 -0
- package/dist/compiler/moltnetRepresentativeResolution.js +86 -0
- package/dist/compiler/moltnetResolution.d.ts +3 -0
- package/dist/compiler/moltnetResolution.js +182 -0
- package/dist/compiler/moltnetRoomMemberships.d.ts +3 -0
- package/dist/compiler/moltnetRoomMemberships.js +140 -0
- package/dist/compiler/runProject.js +1 -1
- package/dist/compiler/surfaceDefinitions.d.ts +55 -0
- package/dist/compiler/surfaceDefinitions.js +204 -0
- package/dist/compiler/teamContextHelpers.d.ts +18 -0
- package/dist/compiler/teamContextHelpers.js +112 -0
- package/dist/compiler/teamContextSupport.d.ts +4 -0
- package/dist/compiler/teamContextSupport.js +264 -0
- package/dist/compiler/teamContextSupport.testHelpers.d.ts +16 -0
- package/dist/compiler/teamContextSupport.testHelpers.js +68 -0
- package/dist/compiler/teamContextTypes.d.ts +28 -0
- package/dist/compiler/teamContextTypes.js +1 -0
- package/dist/compiler/teamRoster.d.ts +12 -0
- package/dist/compiler/teamRoster.js +48 -0
- package/dist/compiler/teamRosterEntries.d.ts +13 -0
- package/dist/compiler/teamRosterEntries.js +230 -0
- package/dist/compiler/teamRosterTypes.d.ts +45 -0
- package/dist/compiler/teamRosterTypes.js +1 -0
- package/dist/compiler/types.d.ts +90 -6
- package/dist/compiler/updateProjectRuntime.d.ts +9 -0
- package/dist/compiler/updateProjectRuntime.js +67 -0
- package/dist/compiler/updateProjectSurfaces.d.ts +8 -0
- package/dist/compiler/updateProjectSurfaces.js +106 -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/manifest/loadManifest.js +4 -4
- package/dist/manifest/renderSpawnfile.js +74 -8
- package/dist/manifest/scaffold.js +1 -3
- package/dist/manifest/schemas.d.ts +227 -17
- package/dist/manifest/schemas.js +62 -20
- package/dist/manifest/surfaceSchemas.d.ts +154 -0
- package/dist/manifest/surfaceSchemas.js +77 -5
- package/dist/runtime/common.js +3 -0
- package/dist/runtime/openclaw/adapter.js +38 -5
- package/dist/runtime/openclaw/moltnet.d.ts +12 -0
- package/dist/runtime/openclaw/moltnet.js +124 -0
- package/dist/runtime/openclaw/surfaces.js +3 -0
- package/dist/runtime/picoclaw/adapter.js +27 -8
- package/dist/runtime/picoclaw/pico.d.ts +2 -0
- package/dist/runtime/picoclaw/pico.js +2 -0
- package/dist/runtime/picoclaw/surfaces.js +11 -0
- package/dist/runtime/tinyclaw/adapter.js +22 -8
- package/dist/runtime/tinyclaw/runAuth.js +28 -1
- package/dist/runtime/tinyclaw/surfaces.js +8 -0
- package/dist/runtime/types.d.ts +11 -0
- package/package.json +5 -3
- package/runtimes.yaml +4 -4
package/dist/cli/runCli.d.ts
CHANGED
|
@@ -1,16 +1,23 @@
|
|
|
1
1
|
import { importClaudeCodeAuth, importCodexAuth, importEnvFile, requireAuthProfile } from "../auth/index.js";
|
|
2
|
-
import { addAgentProject, addProjectModelFallback, addSubagentProject, addTeamProject, buildCompilePlan, buildProject, clearProjectModelFallbacks, compileProject, initProject, runProject, setProjectPrimaryModel, syncProjectAuth } from "../compiler/index.js";
|
|
2
|
+
import { addAgentProject, addProjectSurface, addProjectModelFallback, addSubagentProject, addTeamProject, buildOrganizationView, buildCompilePlan, buildProject, clearProjectModelFallbacks, compileProject, initProject, removeProjectSurface, runProject, setProjectPrimaryModel, setProjectRuntime, setProjectSurfaceAccess, showProjectSurfaces, syncProjectAuth } from "../compiler/index.js";
|
|
3
3
|
import { listRuntimeAdapters } from "../runtime/index.js";
|
|
4
4
|
export interface CliStreams {
|
|
5
5
|
stderr: (message: string) => void;
|
|
6
6
|
stdout: (message: string) => void;
|
|
7
7
|
}
|
|
8
|
+
export interface CliRenderEnvironment {
|
|
9
|
+
ci: boolean;
|
|
10
|
+
noColor: boolean;
|
|
11
|
+
stdoutIsTty: boolean;
|
|
12
|
+
}
|
|
8
13
|
export interface CliHandlers {
|
|
9
14
|
buildCompilePlan: typeof buildCompilePlan;
|
|
15
|
+
buildOrganizationView: typeof buildOrganizationView;
|
|
10
16
|
buildProject: typeof buildProject;
|
|
11
17
|
compileProject: typeof compileProject;
|
|
12
18
|
addAgentProject: typeof addAgentProject;
|
|
13
19
|
addProjectModelFallback: typeof addProjectModelFallback;
|
|
20
|
+
addProjectSurface: typeof addProjectSurface;
|
|
14
21
|
addSubagentProject: typeof addSubagentProject;
|
|
15
22
|
addTeamProject: typeof addTeamProject;
|
|
16
23
|
clearProjectModelFallbacks: typeof clearProjectModelFallbacks;
|
|
@@ -19,9 +26,23 @@ export interface CliHandlers {
|
|
|
19
26
|
importEnvFile: typeof importEnvFile;
|
|
20
27
|
initProject: typeof initProject;
|
|
21
28
|
listRuntimeAdapters: typeof listRuntimeAdapters;
|
|
29
|
+
removeProjectSurface: typeof removeProjectSurface;
|
|
22
30
|
requireAuthProfile: typeof requireAuthProfile;
|
|
23
31
|
runProject: typeof runProject;
|
|
24
32
|
setProjectPrimaryModel: typeof setProjectPrimaryModel;
|
|
33
|
+
setProjectRuntime: typeof setProjectRuntime;
|
|
34
|
+
setProjectSurfaceAccess: typeof setProjectSurfaceAccess;
|
|
35
|
+
showProjectSurfaces: typeof showProjectSurfaces;
|
|
25
36
|
syncProjectAuth: typeof syncProjectAuth;
|
|
26
37
|
}
|
|
27
|
-
export
|
|
38
|
+
export interface RunCliOptions {
|
|
39
|
+
handlers?: Partial<CliHandlers>;
|
|
40
|
+
renderEnvironment?: CliRenderEnvironment;
|
|
41
|
+
streams?: CliStreams;
|
|
42
|
+
}
|
|
43
|
+
type RunCli = {
|
|
44
|
+
(argv: string[], options?: RunCliOptions): Promise<number>;
|
|
45
|
+
(argv: string[], streams?: CliStreams, handlerOverrides?: Partial<CliHandlers>): Promise<number>;
|
|
46
|
+
};
|
|
47
|
+
export declare const runCli: RunCli;
|
|
48
|
+
export {};
|
package/dist/cli/runCli.js
CHANGED
|
@@ -1,31 +1,60 @@
|
|
|
1
1
|
import { Command } from "commander";
|
|
2
2
|
import { importClaudeCodeAuth, importCodexAuth, importEnvFile, requireAuthProfile } from "../auth/index.js";
|
|
3
|
-
import { addAgentProject, addProjectModelFallback, addSubagentProject, addTeamProject, buildCompilePlan, buildProject, clearProjectModelFallbacks, compileProject, initProject, runProject, setProjectPrimaryModel, syncProjectAuth } from "../compiler/index.js";
|
|
3
|
+
import { addAgentProject, addProjectSurface, addProjectModelFallback, addSubagentProject, addTeamProject, buildOrganizationView, buildCompilePlan, buildProject, clearProjectModelFallbacks, compileProject, initProject, removeProjectSurface, runProject, setProjectPrimaryModel, setProjectRuntime, setProjectSurfaceAccess, showProjectSurfaces, syncProjectAuth } from "../compiler/index.js";
|
|
4
4
|
import { isSpawnfileError } from "../shared/index.js";
|
|
5
5
|
import { listRuntimeAdapters } from "../runtime/index.js";
|
|
6
|
+
import { registerModelCommands } from "./modelCommands.js";
|
|
7
|
+
import { registerRuntimeCommands } from "./runtimeCommands.js";
|
|
8
|
+
import { registerSurfaceCommands } from "./surfaceCommands.js";
|
|
9
|
+
import { registerViewCommand } from "./viewCommand.js";
|
|
6
10
|
const createDefaultStreams = () => ({
|
|
7
11
|
stderr: (message) => process.stderr.write(`${message}\n`),
|
|
8
12
|
stdout: (message) => process.stdout.write(`${message}\n`)
|
|
9
13
|
});
|
|
14
|
+
const createDefaultRenderEnvironment = () => ({
|
|
15
|
+
ci: process.env.CI !== undefined && process.env.CI !== "" && process.env.CI !== "0",
|
|
16
|
+
noColor: process.env.NO_COLOR !== undefined && process.env.NO_COLOR !== "",
|
|
17
|
+
stdoutIsTty: process.stdout.isTTY === true
|
|
18
|
+
});
|
|
10
19
|
const createDefaultHandlers = () => ({
|
|
11
|
-
buildCompilePlan,
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
clearProjectModelFallbacks,
|
|
19
|
-
importClaudeCodeAuth,
|
|
20
|
-
importCodexAuth,
|
|
21
|
-
importEnvFile,
|
|
22
|
-
initProject,
|
|
23
|
-
listRuntimeAdapters,
|
|
24
|
-
requireAuthProfile,
|
|
25
|
-
runProject,
|
|
26
|
-
setProjectPrimaryModel,
|
|
27
|
-
syncProjectAuth
|
|
20
|
+
buildCompilePlan, buildOrganizationView, buildProject, compileProject,
|
|
21
|
+
addAgentProject, addProjectModelFallback, addProjectSurface,
|
|
22
|
+
addSubagentProject, addTeamProject, clearProjectModelFallbacks,
|
|
23
|
+
importClaudeCodeAuth, importCodexAuth, importEnvFile,
|
|
24
|
+
initProject, listRuntimeAdapters, removeProjectSurface, requireAuthProfile,
|
|
25
|
+
runProject, setProjectPrimaryModel, setProjectRuntime,
|
|
26
|
+
setProjectSurfaceAccess, showProjectSurfaces, syncProjectAuth
|
|
28
27
|
});
|
|
28
|
+
const isCliStreams = (value) => {
|
|
29
|
+
const candidate = value;
|
|
30
|
+
return typeof candidate?.stderr === "function" && typeof candidate.stdout === "function";
|
|
31
|
+
};
|
|
32
|
+
const normalizeRunCliOptions = (optionsOrStreams, handlerOverrides = {}) => isCliStreams(optionsOrStreams)
|
|
33
|
+
? {
|
|
34
|
+
handlers: handlerOverrides,
|
|
35
|
+
renderEnvironment: createDefaultRenderEnvironment(),
|
|
36
|
+
streams: optionsOrStreams
|
|
37
|
+
}
|
|
38
|
+
: {
|
|
39
|
+
handlers: optionsOrStreams?.handlers ?? handlerOverrides,
|
|
40
|
+
renderEnvironment: optionsOrStreams?.renderEnvironment ?? createDefaultRenderEnvironment(),
|
|
41
|
+
streams: optionsOrStreams?.streams ?? createDefaultStreams()
|
|
42
|
+
};
|
|
43
|
+
const writeCommanderOutput = (write, message) => {
|
|
44
|
+
const normalized = message.replace(/\n$/, "");
|
|
45
|
+
if (normalized.length > 0) {
|
|
46
|
+
write(normalized);
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
const isCommanderError = (error) => {
|
|
50
|
+
if (typeof error !== "object" || error === null) {
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
const candidate = error;
|
|
54
|
+
return typeof candidate.code === "string"
|
|
55
|
+
&& candidate.code.startsWith("commander.")
|
|
56
|
+
&& typeof candidate.exitCode === "number";
|
|
57
|
+
};
|
|
29
58
|
const formatPlanSummary = (plan) => [
|
|
30
59
|
`root: ${plan.root}`,
|
|
31
60
|
`nodes: ${plan.nodes.length}`,
|
|
@@ -40,10 +69,20 @@ const formatAuthProfileSummary = (profile) => {
|
|
|
40
69
|
`imports: ${importedKinds.length > 0 ? importedKinds.join(", ") : "none"}`
|
|
41
70
|
];
|
|
42
71
|
};
|
|
43
|
-
|
|
44
|
-
|
|
72
|
+
const emitLines = (streams, lines) => lines.forEach((line) => streams.stdout(line));
|
|
73
|
+
const emitFileLines = (streams, label, filePaths) => emitLines(streams, filePaths.map((filePath) => `${label} ${filePath}`));
|
|
74
|
+
export const runCli = async (argv, optionsOrStreams, handlerOverrides = {}) => {
|
|
75
|
+
const cliOptions = normalizeRunCliOptions(optionsOrStreams, handlerOverrides);
|
|
76
|
+
const streams = cliOptions.streams;
|
|
77
|
+
const handlers = { ...createDefaultHandlers(), ...cliOptions.handlers };
|
|
45
78
|
const program = new Command();
|
|
46
79
|
program.name("spawnfile").description("Spawnfile v0.1 compiler");
|
|
80
|
+
program.exitOverride();
|
|
81
|
+
program.configureOutput({
|
|
82
|
+
outputError: (message, write) => write(message),
|
|
83
|
+
writeErr: (message) => writeCommanderOutput(streams.stderr, message),
|
|
84
|
+
writeOut: (message) => writeCommanderOutput(streams.stdout, message)
|
|
85
|
+
});
|
|
47
86
|
program
|
|
48
87
|
.command("compile")
|
|
49
88
|
.argument("[path]", "Project directory or Spawnfile path", process.cwd())
|
|
@@ -100,9 +139,7 @@ export const runCli = async (argv, streams = createDefaultStreams(), handlerOver
|
|
|
100
139
|
team: options.team
|
|
101
140
|
});
|
|
102
141
|
streams.stdout(`initialized ${result.directory}`);
|
|
103
|
-
|
|
104
|
-
streams.stdout(`created ${filePath}`);
|
|
105
|
-
}
|
|
142
|
+
emitFileLines(streams, "created", result.createdFiles);
|
|
106
143
|
});
|
|
107
144
|
const addCommand = program.command("add").description("Add children to an existing Spawnfile project");
|
|
108
145
|
addCommand
|
|
@@ -116,12 +153,8 @@ export const runCli = async (argv, streams = createDefaultStreams(), handlerOver
|
|
|
116
153
|
path: inputPath,
|
|
117
154
|
runtime: options.runtime
|
|
118
155
|
});
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
}
|
|
122
|
-
for (const filePath of result.createdFiles) {
|
|
123
|
-
streams.stdout(`created ${filePath}`);
|
|
124
|
-
}
|
|
156
|
+
emitFileLines(streams, "updated", result.updatedFiles);
|
|
157
|
+
emitFileLines(streams, "created", result.createdFiles);
|
|
125
158
|
});
|
|
126
159
|
addCommand
|
|
127
160
|
.command("subagent")
|
|
@@ -132,12 +165,8 @@ export const runCli = async (argv, streams = createDefaultStreams(), handlerOver
|
|
|
132
165
|
id,
|
|
133
166
|
path: inputPath
|
|
134
167
|
});
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
}
|
|
138
|
-
for (const filePath of result.createdFiles) {
|
|
139
|
-
streams.stdout(`created ${filePath}`);
|
|
140
|
-
}
|
|
168
|
+
emitFileLines(streams, "updated", result.updatedFiles);
|
|
169
|
+
emitFileLines(streams, "created", result.createdFiles);
|
|
141
170
|
});
|
|
142
171
|
addCommand
|
|
143
172
|
.command("team")
|
|
@@ -148,79 +177,13 @@ export const runCli = async (argv, streams = createDefaultStreams(), handlerOver
|
|
|
148
177
|
id,
|
|
149
178
|
path: inputPath
|
|
150
179
|
});
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
}
|
|
154
|
-
for (const filePath of result.createdFiles) {
|
|
155
|
-
streams.stdout(`created ${filePath}`);
|
|
156
|
-
}
|
|
157
|
-
});
|
|
158
|
-
const modelCommand = program
|
|
159
|
-
.command("model")
|
|
160
|
-
.description("Edit primary and fallback model declarations");
|
|
161
|
-
modelCommand
|
|
162
|
-
.command("set")
|
|
163
|
-
.argument("<provider>", "Model provider")
|
|
164
|
-
.argument("<name>", "Model name")
|
|
165
|
-
.argument("[path]", "Project directory or Spawnfile path", process.cwd())
|
|
166
|
-
.option("--auth <method>", "Model auth method")
|
|
167
|
-
.option("--key <env>", "Environment variable for api_key auth")
|
|
168
|
-
.option("--compat <compatibility>", "Endpoint compatibility for custom/local models")
|
|
169
|
-
.option("--base-url <url>", "Endpoint base URL for custom/local models")
|
|
170
|
-
.option("--recursive", "Update the target project and its descendants")
|
|
171
|
-
.action(async (provider, name, inputPath, options) => {
|
|
172
|
-
const result = await handlers.setProjectPrimaryModel({
|
|
173
|
-
authKey: options.key,
|
|
174
|
-
authMethod: options.auth,
|
|
175
|
-
endpointBaseUrl: options.baseUrl,
|
|
176
|
-
endpointCompatibility: options.compat,
|
|
177
|
-
name,
|
|
178
|
-
path: inputPath,
|
|
179
|
-
provider,
|
|
180
|
-
recursive: options.recursive
|
|
181
|
-
});
|
|
182
|
-
for (const filePath of result.updatedFiles) {
|
|
183
|
-
streams.stdout(`updated ${filePath}`);
|
|
184
|
-
}
|
|
185
|
-
});
|
|
186
|
-
modelCommand
|
|
187
|
-
.command("add-fallback")
|
|
188
|
-
.argument("<provider>", "Model provider")
|
|
189
|
-
.argument("<name>", "Model name")
|
|
190
|
-
.argument("[path]", "Project directory or Spawnfile path", process.cwd())
|
|
191
|
-
.option("--auth <method>", "Model auth method")
|
|
192
|
-
.option("--key <env>", "Environment variable for api_key auth")
|
|
193
|
-
.option("--compat <compatibility>", "Endpoint compatibility for custom/local models")
|
|
194
|
-
.option("--base-url <url>", "Endpoint base URL for custom/local models")
|
|
195
|
-
.option("--recursive", "Update the target project and its descendants")
|
|
196
|
-
.action(async (provider, name, inputPath, options) => {
|
|
197
|
-
const result = await handlers.addProjectModelFallback({
|
|
198
|
-
authKey: options.key,
|
|
199
|
-
authMethod: options.auth,
|
|
200
|
-
endpointBaseUrl: options.baseUrl,
|
|
201
|
-
endpointCompatibility: options.compat,
|
|
202
|
-
name,
|
|
203
|
-
path: inputPath,
|
|
204
|
-
provider,
|
|
205
|
-
recursive: options.recursive
|
|
206
|
-
});
|
|
207
|
-
for (const filePath of result.updatedFiles) {
|
|
208
|
-
streams.stdout(`updated ${filePath}`);
|
|
209
|
-
}
|
|
210
|
-
});
|
|
211
|
-
modelCommand
|
|
212
|
-
.command("clear-fallbacks")
|
|
213
|
-
.argument("[path]", "Project directory or Spawnfile path", process.cwd())
|
|
214
|
-
.option("--recursive", "Update the target project and its descendants")
|
|
215
|
-
.action(async (inputPath, options) => {
|
|
216
|
-
const result = await handlers.clearProjectModelFallbacks({
|
|
217
|
-
path: inputPath,
|
|
218
|
-
recursive: options.recursive
|
|
219
|
-
});
|
|
220
|
-
for (const filePath of result.updatedFiles) {
|
|
221
|
-
streams.stdout(`updated ${filePath}`);
|
|
222
|
-
}
|
|
180
|
+
emitFileLines(streams, "updated", result.updatedFiles);
|
|
181
|
+
emitFileLines(streams, "created", result.createdFiles);
|
|
223
182
|
});
|
|
183
|
+
registerModelCommands(program, handlers, streams);
|
|
184
|
+
registerRuntimeCommands(program, handlers, streams);
|
|
185
|
+
registerSurfaceCommands(program, handlers, streams);
|
|
186
|
+
registerViewCommand(program, handlers, streams, cliOptions.renderEnvironment);
|
|
224
187
|
program
|
|
225
188
|
.command("validate")
|
|
226
189
|
.argument("[path]", "Project directory or Spawnfile path", process.cwd())
|
|
@@ -247,9 +210,7 @@ export const runCli = async (argv, streams = createDefaultStreams(), handlerOver
|
|
|
247
210
|
.option("-p, --profile <name>", "Auth profile name", "default")
|
|
248
211
|
.action(async (filePath, options) => {
|
|
249
212
|
const profile = await handlers.importEnvFile(options.profile, filePath);
|
|
250
|
-
|
|
251
|
-
streams.stdout(line);
|
|
252
|
-
}
|
|
213
|
+
emitLines(streams, formatAuthProfileSummary(profile));
|
|
253
214
|
});
|
|
254
215
|
authImportCommand
|
|
255
216
|
.command("claude-code")
|
|
@@ -257,9 +218,7 @@ export const runCli = async (argv, streams = createDefaultStreams(), handlerOver
|
|
|
257
218
|
.option("--from <directory>", "Source Claude Code config directory")
|
|
258
219
|
.action(async (options) => {
|
|
259
220
|
const profile = await handlers.importClaudeCodeAuth(options.profile, options.from);
|
|
260
|
-
|
|
261
|
-
streams.stdout(line);
|
|
262
|
-
}
|
|
221
|
+
emitLines(streams, formatAuthProfileSummary(profile));
|
|
263
222
|
});
|
|
264
223
|
authImportCommand
|
|
265
224
|
.command("codex")
|
|
@@ -267,9 +226,7 @@ export const runCli = async (argv, streams = createDefaultStreams(), handlerOver
|
|
|
267
226
|
.option("--from <directory>", "Source Codex config directory")
|
|
268
227
|
.action(async (options) => {
|
|
269
228
|
const profile = await handlers.importCodexAuth(options.profile, options.from);
|
|
270
|
-
|
|
271
|
-
streams.stdout(line);
|
|
272
|
-
}
|
|
229
|
+
emitLines(streams, formatAuthProfileSummary(profile));
|
|
273
230
|
});
|
|
274
231
|
authCommand
|
|
275
232
|
.command("sync")
|
|
@@ -285,24 +242,23 @@ export const runCli = async (argv, streams = createDefaultStreams(), handlerOver
|
|
|
285
242
|
envFilePath: options.envFile,
|
|
286
243
|
profileName: options.profile
|
|
287
244
|
});
|
|
288
|
-
|
|
289
|
-
streams.stdout(line);
|
|
290
|
-
}
|
|
245
|
+
emitLines(streams, formatAuthProfileSummary(profile));
|
|
291
246
|
});
|
|
292
247
|
authCommand
|
|
293
248
|
.command("show")
|
|
294
249
|
.option("-p, --profile <name>", "Auth profile name", "default")
|
|
295
250
|
.action(async (options) => {
|
|
296
251
|
const profile = await handlers.requireAuthProfile(options.profile);
|
|
297
|
-
|
|
298
|
-
streams.stdout(line);
|
|
299
|
-
}
|
|
252
|
+
emitLines(streams, formatAuthProfileSummary(profile));
|
|
300
253
|
});
|
|
301
254
|
try {
|
|
302
255
|
await program.parseAsync(argv, { from: "user" });
|
|
303
256
|
return 0;
|
|
304
257
|
}
|
|
305
258
|
catch (error) {
|
|
259
|
+
if (isCommanderError(error)) {
|
|
260
|
+
return error.exitCode === 0 ? 0 : 1;
|
|
261
|
+
}
|
|
306
262
|
const message = isSpawnfileError(error)
|
|
307
263
|
? `${error.code}: ${error.message}`
|
|
308
264
|
: error instanceof Error
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export const registerRuntimeCommands = (program, handlers, streams) => {
|
|
2
|
+
const runtimeCommand = program
|
|
3
|
+
.command("runtime")
|
|
4
|
+
.description("Edit runtime declarations");
|
|
5
|
+
runtimeCommand
|
|
6
|
+
.command("set")
|
|
7
|
+
.argument("<name>", "Runtime name")
|
|
8
|
+
.argument("[path]", "Project directory or Spawnfile path", process.cwd())
|
|
9
|
+
.option("--recursive", "Update the target project and its descendants")
|
|
10
|
+
.action(async (runtime, inputPath, options) => {
|
|
11
|
+
const result = await handlers.setProjectRuntime({
|
|
12
|
+
path: inputPath,
|
|
13
|
+
recursive: options.recursive,
|
|
14
|
+
runtime
|
|
15
|
+
});
|
|
16
|
+
for (const filePath of result.updatedFiles) {
|
|
17
|
+
streams.stdout(`updated ${filePath}`);
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
};
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import YAML from "yaml";
|
|
2
|
+
import { resolvePortableSurfaceName } from "../compiler/index.js";
|
|
3
|
+
const collectStringOption = (value, previous) => [...previous, value];
|
|
4
|
+
const emitSurfaceSummaries = (streams, entries) => {
|
|
5
|
+
entries.forEach((entry, index) => {
|
|
6
|
+
if (index > 0) {
|
|
7
|
+
streams.stdout("");
|
|
8
|
+
}
|
|
9
|
+
streams.stdout(`path: ${entry.manifestPath}`);
|
|
10
|
+
streams.stdout(`kind: ${entry.kind}`);
|
|
11
|
+
streams.stdout(`name: ${entry.name}`);
|
|
12
|
+
if (!entry.surfaces) {
|
|
13
|
+
streams.stdout("surfaces: none");
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
streams.stdout(YAML.stringify({ surfaces: entry.surfaces }).trimEnd());
|
|
17
|
+
});
|
|
18
|
+
};
|
|
19
|
+
export const registerSurfaceCommands = (program, handlers, streams) => {
|
|
20
|
+
const surfaceCommand = program
|
|
21
|
+
.command("surface")
|
|
22
|
+
.description("Edit agent surfaces");
|
|
23
|
+
surfaceCommand
|
|
24
|
+
.command("add")
|
|
25
|
+
.argument("<surface>", "Surface name")
|
|
26
|
+
.argument("[path]", "Project directory or Spawnfile path", process.cwd())
|
|
27
|
+
.option("--bot-token-secret <env>", "Override the bot token env var name")
|
|
28
|
+
.option("--app-token-secret <env>", "Override the Slack app token env var name")
|
|
29
|
+
.option("--recursive", "Update the target project and its descendants")
|
|
30
|
+
.action(async (surface, inputPath, options) => {
|
|
31
|
+
const surfaceName = resolvePortableSurfaceName(surface);
|
|
32
|
+
const result = await handlers.addProjectSurface({
|
|
33
|
+
appTokenSecret: options.appTokenSecret,
|
|
34
|
+
botTokenSecret: options.botTokenSecret,
|
|
35
|
+
path: inputPath,
|
|
36
|
+
recursive: options.recursive,
|
|
37
|
+
surface: surfaceName
|
|
38
|
+
});
|
|
39
|
+
for (const filePath of result.updatedFiles) {
|
|
40
|
+
streams.stdout(`updated ${filePath}`);
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
surfaceCommand
|
|
44
|
+
.command("remove")
|
|
45
|
+
.argument("<surface>", "Surface name")
|
|
46
|
+
.argument("[path]", "Project directory or Spawnfile path", process.cwd())
|
|
47
|
+
.option("--recursive", "Update the target project and its descendants")
|
|
48
|
+
.action(async (surface, inputPath, options) => {
|
|
49
|
+
const surfaceName = resolvePortableSurfaceName(surface);
|
|
50
|
+
const result = await handlers.removeProjectSurface({
|
|
51
|
+
path: inputPath,
|
|
52
|
+
recursive: options.recursive,
|
|
53
|
+
surface: surfaceName
|
|
54
|
+
});
|
|
55
|
+
for (const filePath of result.updatedFiles) {
|
|
56
|
+
streams.stdout(`updated ${filePath}`);
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
surfaceCommand
|
|
60
|
+
.command("set-access")
|
|
61
|
+
.argument("<surface>", "Surface name")
|
|
62
|
+
.argument("[path]", "Project directory or Spawnfile path", process.cwd())
|
|
63
|
+
.requiredOption("--mode <mode>", "Access mode")
|
|
64
|
+
.option("--user <id>", "Allowlisted user id", collectStringOption, [])
|
|
65
|
+
.option("--channel <id>", "Allowlisted channel id", collectStringOption, [])
|
|
66
|
+
.option("--guild <id>", "Allowlisted guild id", collectStringOption, [])
|
|
67
|
+
.option("--chat <id>", "Allowlisted chat id", collectStringOption, [])
|
|
68
|
+
.option("--group <id>", "Allowlisted group id", collectStringOption, [])
|
|
69
|
+
.option("--recursive", "Update the target project and its descendants")
|
|
70
|
+
.action(async (surface, inputPath, options) => {
|
|
71
|
+
const surfaceName = resolvePortableSurfaceName(surface);
|
|
72
|
+
const result = await handlers.setProjectSurfaceAccess({
|
|
73
|
+
channels: options.channel,
|
|
74
|
+
chats: options.chat,
|
|
75
|
+
groups: options.group,
|
|
76
|
+
guilds: options.guild,
|
|
77
|
+
mode: options.mode,
|
|
78
|
+
path: inputPath,
|
|
79
|
+
recursive: options.recursive,
|
|
80
|
+
surface: surfaceName,
|
|
81
|
+
users: options.user
|
|
82
|
+
});
|
|
83
|
+
for (const filePath of result.updatedFiles) {
|
|
84
|
+
streams.stdout(`updated ${filePath}`);
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
surfaceCommand
|
|
88
|
+
.command("show")
|
|
89
|
+
.argument("[path]", "Project directory or Spawnfile path", process.cwd())
|
|
90
|
+
.option("--recursive", "Show descendant agent surfaces too")
|
|
91
|
+
.action(async (inputPath, options) => {
|
|
92
|
+
const result = await handlers.showProjectSurfaces({
|
|
93
|
+
path: inputPath,
|
|
94
|
+
recursive: options.recursive
|
|
95
|
+
});
|
|
96
|
+
emitSurfaceSummaries(streams, result.entries);
|
|
97
|
+
});
|
|
98
|
+
};
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import type { CliHandlers, CliRenderEnvironment, CliStreams } from "./runCli.js";
|
|
3
|
+
export declare const registerViewCommand: (program: Command, handlers: CliHandlers, streams: CliStreams, renderEnvironment: CliRenderEnvironment) => void;
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { stat } from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { Option } from "commander";
|
|
4
|
+
import { renderOrganizationNetworks, renderOrganizationTree } from "../compiler/index.js";
|
|
5
|
+
import { SpawnfileError } from "../shared/index.js";
|
|
6
|
+
const VIEW_MODES = ["tree", "networks"];
|
|
7
|
+
const VIEW_SHOW_OPTIONS = ["paths", "declared"];
|
|
8
|
+
const VIEW_COLOR_OPTIONS = ["auto", "always", "never"];
|
|
9
|
+
const isViewMode = (value) => VIEW_MODES.includes(value);
|
|
10
|
+
const isViewShow = (value) => VIEW_SHOW_OPTIONS.includes(value);
|
|
11
|
+
const manifestPathFor = (inputPath) => path.basename(inputPath) === "Spawnfile"
|
|
12
|
+
? path.resolve(inputPath)
|
|
13
|
+
: path.resolve(inputPath, "Spawnfile");
|
|
14
|
+
const hasResolvedSpawnfile = async (inputPath) => {
|
|
15
|
+
try {
|
|
16
|
+
return (await stat(manifestPathFor(inputPath))).isFile();
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
const suggestModeOptionForPathToken = async (inputPath) => {
|
|
23
|
+
if (!inputPath || !isViewMode(inputPath) || await hasResolvedSpawnfile(inputPath)) {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
throw new SpawnfileError("validation_error", `No Spawnfile found for path "${inputPath}". Did you mean "spawnfile view --mode ${inputPath}"?`);
|
|
27
|
+
};
|
|
28
|
+
const resolveColor = (color, environment) => {
|
|
29
|
+
if (color === "always") {
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
if (color === "never") {
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
return environment.stdoutIsTty && !environment.ci && !environment.noColor;
|
|
36
|
+
};
|
|
37
|
+
const parseShowLayers = (value) => {
|
|
38
|
+
const layers = new Set();
|
|
39
|
+
if (!value) {
|
|
40
|
+
return layers;
|
|
41
|
+
}
|
|
42
|
+
for (const layer of value.split(",")) {
|
|
43
|
+
const normalized = layer.trim();
|
|
44
|
+
if (!isViewShow(normalized)) {
|
|
45
|
+
throw new SpawnfileError("validation_error", `Unsupported view detail layer "${normalized}". Supported layers: paths, declared.`);
|
|
46
|
+
}
|
|
47
|
+
layers.add(normalized);
|
|
48
|
+
}
|
|
49
|
+
return layers;
|
|
50
|
+
};
|
|
51
|
+
const toRenderOptions = (options, environment) => {
|
|
52
|
+
const showLayers = parseShowLayers(options.show);
|
|
53
|
+
if (options.paths) {
|
|
54
|
+
showLayers.add("paths");
|
|
55
|
+
}
|
|
56
|
+
return {
|
|
57
|
+
ascii: options.ascii,
|
|
58
|
+
color: resolveColor(options.color, environment),
|
|
59
|
+
declared: showLayers.has("declared"),
|
|
60
|
+
paths: showLayers.has("paths")
|
|
61
|
+
};
|
|
62
|
+
};
|
|
63
|
+
const emitRenderedView = (streams, output) => {
|
|
64
|
+
for (const line of output.split("\n")) {
|
|
65
|
+
streams.stdout(line);
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
export const registerViewCommand = (program, handlers, streams, renderEnvironment) => {
|
|
69
|
+
program
|
|
70
|
+
.command("view")
|
|
71
|
+
.description("Render a read-only organization view")
|
|
72
|
+
.argument("[path]", "Project directory or Spawnfile path")
|
|
73
|
+
.addOption(new Option("--mode <mode>", "View mode").choices(VIEW_MODES).default("tree"))
|
|
74
|
+
.option("--show <show>", "Comma-separated additional details")
|
|
75
|
+
.option("--ascii", "Use ASCII tree connectors")
|
|
76
|
+
.addOption(new Option("--color <when>", "Color output").choices(VIEW_COLOR_OPTIONS).default("auto"))
|
|
77
|
+
.option("--paths", "Show source paths")
|
|
78
|
+
.action(async (inputPath, options) => {
|
|
79
|
+
await suggestModeOptionForPathToken(inputPath);
|
|
80
|
+
const renderOptions = toRenderOptions(options, renderEnvironment);
|
|
81
|
+
const view = await handlers.buildOrganizationView(inputPath ?? process.cwd());
|
|
82
|
+
const output = options.mode === "networks"
|
|
83
|
+
? renderOrganizationNetworks(view, renderOptions)
|
|
84
|
+
: renderOrganizationTree(view, renderOptions);
|
|
85
|
+
emitRenderedView(streams, output);
|
|
86
|
+
});
|
|
87
|
+
};
|
|
@@ -5,6 +5,7 @@ export const resolveAgentSurfaces = (surfaces) => {
|
|
|
5
5
|
}
|
|
6
6
|
const resolved = {};
|
|
7
7
|
if (surfaces.discord) {
|
|
8
|
+
const identity = surfaces.discord.identity;
|
|
8
9
|
resolved.discord = {
|
|
9
10
|
...(surfaces.discord.access
|
|
10
11
|
? {
|
|
@@ -16,10 +17,41 @@ export const resolveAgentSurfaces = (surfaces) => {
|
|
|
16
17
|
}
|
|
17
18
|
}
|
|
18
19
|
: {}),
|
|
19
|
-
botTokenSecret: surfaces.discord.bot_token_secret ?? DEFAULT_DISCORD_BOT_TOKEN_SECRET
|
|
20
|
+
botTokenSecret: surfaces.discord.bot_token_secret ?? DEFAULT_DISCORD_BOT_TOKEN_SECRET,
|
|
21
|
+
...(identity ? { identity: { userId: identity.user_id } } : {})
|
|
20
22
|
};
|
|
21
23
|
}
|
|
24
|
+
if (surfaces.moltnet) {
|
|
25
|
+
resolved.moltnet = surfaces.moltnet.map((attachment) => ({
|
|
26
|
+
...(attachment.dms
|
|
27
|
+
? {
|
|
28
|
+
dms: {
|
|
29
|
+
enabled: attachment.dms.enabled,
|
|
30
|
+
...(attachment.dms.read ? { read: attachment.dms.read } : {}),
|
|
31
|
+
...(attachment.dms.reply ? { reply: attachment.dms.reply } : {})
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
: {}),
|
|
35
|
+
memberId: null,
|
|
36
|
+
network: attachment.network,
|
|
37
|
+
...(attachment.rooms
|
|
38
|
+
? {
|
|
39
|
+
rooms: Object.fromEntries(Object.entries(attachment.rooms)
|
|
40
|
+
.sort(([left], [right]) => left.localeCompare(right))
|
|
41
|
+
.map(([roomId, behavior]) => [
|
|
42
|
+
roomId,
|
|
43
|
+
{
|
|
44
|
+
...(behavior.read ? { read: behavior.read } : {}),
|
|
45
|
+
...(behavior.reply ? { reply: behavior.reply } : {})
|
|
46
|
+
}
|
|
47
|
+
]))
|
|
48
|
+
}
|
|
49
|
+
: {}),
|
|
50
|
+
teamSource: null
|
|
51
|
+
}));
|
|
52
|
+
}
|
|
22
53
|
if (surfaces.telegram) {
|
|
54
|
+
const identity = surfaces.telegram.identity;
|
|
23
55
|
resolved.telegram = {
|
|
24
56
|
...(surfaces.telegram.access
|
|
25
57
|
? {
|
|
@@ -30,21 +62,34 @@ export const resolveAgentSurfaces = (surfaces) => {
|
|
|
30
62
|
}
|
|
31
63
|
}
|
|
32
64
|
: {}),
|
|
33
|
-
botTokenSecret: surfaces.telegram.bot_token_secret ?? DEFAULT_TELEGRAM_BOT_TOKEN_SECRET
|
|
65
|
+
botTokenSecret: surfaces.telegram.bot_token_secret ?? DEFAULT_TELEGRAM_BOT_TOKEN_SECRET,
|
|
66
|
+
...(identity
|
|
67
|
+
? {
|
|
68
|
+
identity: {
|
|
69
|
+
...(identity.user_id ? { userId: identity.user_id } : {}),
|
|
70
|
+
...(identity.username ? { username: identity.username } : {})
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
: {})
|
|
34
74
|
};
|
|
35
75
|
}
|
|
36
76
|
if (surfaces.whatsapp) {
|
|
77
|
+
const identity = surfaces.whatsapp.identity;
|
|
37
78
|
resolved.whatsapp = surfaces.whatsapp.access
|
|
38
79
|
? {
|
|
39
80
|
access: {
|
|
40
81
|
groups: [...(surfaces.whatsapp.access.groups ?? [])],
|
|
41
82
|
mode: surfaces.whatsapp.access.mode ?? "allowlist",
|
|
42
83
|
users: [...(surfaces.whatsapp.access.users ?? [])]
|
|
43
|
-
}
|
|
84
|
+
},
|
|
85
|
+
...(identity ? { identity: { phone: identity.phone } } : {})
|
|
44
86
|
}
|
|
45
|
-
: {
|
|
87
|
+
: {
|
|
88
|
+
...(identity ? { identity: { phone: identity.phone } } : {})
|
|
89
|
+
};
|
|
46
90
|
}
|
|
47
91
|
if (surfaces.slack) {
|
|
92
|
+
const identity = surfaces.slack.identity;
|
|
48
93
|
resolved.slack = {
|
|
49
94
|
...(surfaces.slack.access
|
|
50
95
|
? {
|
|
@@ -56,7 +101,8 @@ export const resolveAgentSurfaces = (surfaces) => {
|
|
|
56
101
|
}
|
|
57
102
|
: {}),
|
|
58
103
|
appTokenSecret: surfaces.slack.app_token_secret ?? DEFAULT_SLACK_APP_TOKEN_SECRET,
|
|
59
|
-
botTokenSecret: surfaces.slack.bot_token_secret ?? DEFAULT_SLACK_BOT_TOKEN_SECRET
|
|
104
|
+
botTokenSecret: surfaces.slack.bot_token_secret ?? DEFAULT_SLACK_BOT_TOKEN_SECRET,
|
|
105
|
+
...(identity ? { identity: { userId: identity.user_id } } : {})
|
|
60
106
|
};
|
|
61
107
|
}
|
|
62
108
|
return Object.keys(resolved).length > 0 ? resolved : undefined;
|