@rigkit/cli 0.0.0-canary-20260518T014918-c5bc0c2
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 +34 -0
- package/package.json +42 -0
- package/src/cli.test.ts +419 -0
- package/src/cli.ts +2496 -0
- package/src/completion.test.ts +413 -0
- package/src/completion.ts +844 -0
- package/src/init.test.ts +90 -0
- package/src/init.ts +269 -0
- package/src/interaction.test.ts +28 -0
- package/src/interaction.ts +33 -0
- package/src/project.test.ts +81 -0
- package/src/project.ts +184 -0
- package/src/run-logger.test.ts +92 -0
- package/src/run-logger.ts +203 -0
- package/src/run-presenter.ts +250 -0
- package/src/ui.ts +159 -0
- package/src/version.ts +1 -0
- package/src/workspace-name.test.ts +17 -0
- package/src/workspace-name.ts +59 -0
package/README.md
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# @rigkit/cli
|
|
2
|
+
|
|
3
|
+
Global `rig` CLI.
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
npm i -g @rigkit/cli
|
|
7
|
+
rig init
|
|
8
|
+
rig plan
|
|
9
|
+
rig ls
|
|
10
|
+
rig -chdir=examples/smoke plan
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
`rig init` asks for a project name, Freestyle API key, and package manager. It creates a project folder containing a workflow-based `rig.config.ts`, `.env`, `.env.example`, `package.json`, and local ignore rules.
|
|
14
|
+
|
|
15
|
+
Interactive terminals use Inquirer prompts and a chalk/log-update run timeline. Set `RIGKIT_RENDER=0` to force the plain text renderer; `--json` and flag-driven flows remain suitable for agents and scripts.
|
|
16
|
+
|
|
17
|
+
Interactive providers can ask the CLI to open provider-owned URLs. For example, Freestyle terminal sessions are served by the Freestyle provider, while the CLI only opens the presented URL in a browser.
|
|
18
|
+
|
|
19
|
+
Workspace lifecycle commands are built in: `rig create <workspace>` creates a
|
|
20
|
+
workspace and `rig rm <workspace>` removes one. Workspace-specific operations
|
|
21
|
+
defined by the project run as `rig run <workspace> <operation>`, for example
|
|
22
|
+
`rig run website-workspace open-cmux`.
|
|
23
|
+
|
|
24
|
+
`rig ls` lists workspaces for the selected project. `rig ls snapshots` lists cached snapshot runs, and `rig ls config` shows the resolved project paths.
|
|
25
|
+
|
|
26
|
+
Use Terraform-style global context options before the command to select another
|
|
27
|
+
project or config:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
rig -chdir=examples/smoke plan
|
|
31
|
+
rig -chdir=examples/global-fragments -config=api.rig.config.ts apply
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Projects should install matching `@rigkit/sdk` versions locally.
|
package/package.json
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@rigkit/cli",
|
|
3
|
+
"version": "0.0.0-canary-20260518T014918-c5bc0c2",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "git+https://github.com/freestyle-sh/rigkit.git",
|
|
8
|
+
"directory": "packages/cli"
|
|
9
|
+
},
|
|
10
|
+
"bin": {
|
|
11
|
+
"rig": "./src/cli.ts"
|
|
12
|
+
},
|
|
13
|
+
"exports": {
|
|
14
|
+
".": "./src/cli.ts",
|
|
15
|
+
"./package.json": "./package.json"
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"src",
|
|
19
|
+
"README.md"
|
|
20
|
+
],
|
|
21
|
+
"dependencies": {
|
|
22
|
+
"chalk": "^5.6.2",
|
|
23
|
+
"commander": "^14.0.3",
|
|
24
|
+
"inquirer": "^13.4.3",
|
|
25
|
+
"@rigkit/runtime-client": "0.0.0-canary-20260518T014918-c5bc0c2",
|
|
26
|
+
"@rigkit/engine": "0.0.0-canary-20260518T014918-c5bc0c2",
|
|
27
|
+
"@rigkit/provider-cmux": "0.0.0-canary-20260518T014918-c5bc0c2"
|
|
28
|
+
},
|
|
29
|
+
"devDependencies": {
|
|
30
|
+
"@types/bun": "latest",
|
|
31
|
+
"typescript": "latest"
|
|
32
|
+
},
|
|
33
|
+
"publishConfig": {
|
|
34
|
+
"access": "public"
|
|
35
|
+
},
|
|
36
|
+
"scripts": {
|
|
37
|
+
"rig": "bun src/cli.ts",
|
|
38
|
+
"build": "tsc --noEmit",
|
|
39
|
+
"typecheck": "tsc --noEmit",
|
|
40
|
+
"test": "bun test"
|
|
41
|
+
}
|
|
42
|
+
}
|
package/src/cli.test.ts
ADDED
|
@@ -0,0 +1,419 @@
|
|
|
1
|
+
import { describe, expect, test } from "bun:test";
|
|
2
|
+
import { existsSync, mkdirSync, mkdtempSync, realpathSync, rmSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { projectIdFor, runtimeFingerprintFor, runtimePaths, SUPPORTED_RUNTIME_API_VERSION } from "@rigkit/runtime-client";
|
|
6
|
+
import { RIGKIT_CLI_VERSION } from "./version.ts";
|
|
7
|
+
|
|
8
|
+
const cliPath = join(import.meta.dir, "cli.ts");
|
|
9
|
+
|
|
10
|
+
describe("CLI entrypoint", () => {
|
|
11
|
+
test("renders CLI diagnostics as JSON", async () => {
|
|
12
|
+
const result = await runCli(["doctor", "--cli", "--json"]);
|
|
13
|
+
|
|
14
|
+
expect(result.exitCode).toBe(0);
|
|
15
|
+
expect(result.stderr).toBe("");
|
|
16
|
+
expect(JSON.parse(result.stdout)).toMatchObject({
|
|
17
|
+
cliVersion: RIGKIT_CLI_VERSION,
|
|
18
|
+
});
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
test("exposes static help and version bootstrap commands", async () => {
|
|
22
|
+
const rootHelp = await runCli([]);
|
|
23
|
+
expect(rootHelp.exitCode).toBe(0);
|
|
24
|
+
expect(rootHelp.stderr).toBe("");
|
|
25
|
+
expect(rootHelp.stdout).toContain("rig ");
|
|
26
|
+
expect(rootHelp.stdout).toContain("plan Plan project workflow changes");
|
|
27
|
+
expect(rootHelp.stdout).toContain("rm Remove a workspace");
|
|
28
|
+
expect(rootHelp.stdout).toContain("run Run a workspace operation");
|
|
29
|
+
expect(rootHelp.stdout).toContain("cache Inspect and clear Rigkit cache");
|
|
30
|
+
|
|
31
|
+
const version = await runCli(["version"]);
|
|
32
|
+
expect(version.exitCode).toBe(0);
|
|
33
|
+
expect(version.stderr).toBe("");
|
|
34
|
+
expect(version.stdout.trim()).toBe(RIGKIT_CLI_VERSION);
|
|
35
|
+
|
|
36
|
+
const help = await runCli(["help"]);
|
|
37
|
+
expect(help.exitCode).toBe(0);
|
|
38
|
+
expect(help.stderr).toBe("");
|
|
39
|
+
expect(help.stdout).toContain("rig ");
|
|
40
|
+
expect(help.stdout).toContain("plan Plan project workflow changes");
|
|
41
|
+
expect(help.stdout).toContain("rm Remove a workspace");
|
|
42
|
+
expect(help.stdout).toContain("run Run a workspace operation");
|
|
43
|
+
expect(help.stdout).toContain("cache Inspect and clear Rigkit cache");
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
test("rejects operation shorthand at the root", async () => {
|
|
47
|
+
const result = await runCli(["unknown"]);
|
|
48
|
+
|
|
49
|
+
expect(result.exitCode).toBe(1);
|
|
50
|
+
expect(result.stdout).toBe("");
|
|
51
|
+
expect(result.stderr).toContain("unknown command 'unknown'");
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
test("serves dynamic shell completion endpoint", async () => {
|
|
55
|
+
const result = await runCli(["__complete", "--shell", "zsh", "--index", "1", "--", "rig", "v"]);
|
|
56
|
+
|
|
57
|
+
expect(result.exitCode).toBe(0);
|
|
58
|
+
expect(result.stderr).toBe("");
|
|
59
|
+
expect(result.stdout.trim()).toBe("version\tshow CLI version\t\tCommands");
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
test("discovers projects without starting a runtime", async () => {
|
|
63
|
+
const cwd = mkdtempSync(join(tmpdir(), "rigkit-cli-projects-"));
|
|
64
|
+
mkdirSync(join(cwd, "api"));
|
|
65
|
+
writeFileSync(join(cwd, "api", "rig.config.ts"), "export default {}\n");
|
|
66
|
+
|
|
67
|
+
try {
|
|
68
|
+
const result = await runCli(["projects", "--json"], { cwd });
|
|
69
|
+
const realCwd = realpathSync(cwd);
|
|
70
|
+
|
|
71
|
+
expect(result.exitCode).toBe(0);
|
|
72
|
+
expect(result.stderr).toBe("");
|
|
73
|
+
expect(JSON.parse(result.stdout)).toEqual({
|
|
74
|
+
projects: [{
|
|
75
|
+
projectDir: join(realCwd, "api"),
|
|
76
|
+
configPath: join(realCwd, "api", "rig.config.ts"),
|
|
77
|
+
}],
|
|
78
|
+
});
|
|
79
|
+
} finally {
|
|
80
|
+
rmSync(cwd, { recursive: true, force: true });
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
test("shows named config choices when the default config is missing", async () => {
|
|
85
|
+
const cwd = mkdtempSync(join(tmpdir(), "rigkit-cli-named-configs-"));
|
|
86
|
+
writeFileSync(join(cwd, "api.rig.config.ts"), "export default {}\n");
|
|
87
|
+
writeFileSync(join(cwd, "web.rig.config.ts"), "export default {}\n");
|
|
88
|
+
|
|
89
|
+
try {
|
|
90
|
+
const result = await runCli(["create", "--json"], { cwd });
|
|
91
|
+
|
|
92
|
+
expect(result.exitCode).toBe(1);
|
|
93
|
+
expect(result.stdout).toBe("");
|
|
94
|
+
expect(result.stderr).toContain("No Rigkit config found from");
|
|
95
|
+
expect(result.stderr).toContain("Found named Rigkit configs");
|
|
96
|
+
expect(result.stderr).toContain("api.rig.config.ts");
|
|
97
|
+
expect(result.stderr).toContain("web.rig.config.ts");
|
|
98
|
+
expect(result.stderr).toContain("rig -chdir=. -config=api.rig.config.ts <command>");
|
|
99
|
+
} finally {
|
|
100
|
+
rmSync(cwd, { recursive: true, force: true });
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
test("clears all global fragment cache without loading a config", async () => {
|
|
105
|
+
const rigkitHome = mkdtempSync(join(tmpdir(), "rigkit-cli-cache-"));
|
|
106
|
+
const fragmentDir = join(rigkitHome, "fragments", "sha256-test");
|
|
107
|
+
mkdirSync(fragmentDir, { recursive: true });
|
|
108
|
+
writeFileSync(join(fragmentDir, "state.sqlite"), "");
|
|
109
|
+
|
|
110
|
+
try {
|
|
111
|
+
const result = await runCli(["cache", "clear", "--global", "--all", "--json"], {
|
|
112
|
+
env: { RIGKIT_HOME: rigkitHome },
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
expect(result.exitCode).toBe(0);
|
|
116
|
+
expect(result.stderr).toBe("");
|
|
117
|
+
expect(JSON.parse(result.stdout)).toMatchObject({
|
|
118
|
+
ok: true,
|
|
119
|
+
scope: "global-all",
|
|
120
|
+
});
|
|
121
|
+
expect(existsSync(fragmentDir)).toBe(false);
|
|
122
|
+
} finally {
|
|
123
|
+
rmSync(rigkitHome, { recursive: true, force: true });
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
test("lists workspaces from the project runtime", async () => {
|
|
128
|
+
const projectDir = mkdtempSync(join(tmpdir(), "rigkit-cli-ls-"));
|
|
129
|
+
|
|
130
|
+
await withWorkspaceRuntime({ projectDir }, async ({ env }) => {
|
|
131
|
+
const result = await runCli([`-chdir=${projectDir}`, "ls"], { env });
|
|
132
|
+
|
|
133
|
+
expect(result.exitCode).toBe(0);
|
|
134
|
+
expect(result.stderr).toBe("");
|
|
135
|
+
expect(result.stdout).toContain("name workflow");
|
|
136
|
+
expect(result.stdout).toContain("api smoke");
|
|
137
|
+
});
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
test("lists workspaces as JSON", async () => {
|
|
141
|
+
const projectDir = mkdtempSync(join(tmpdir(), "rigkit-cli-ls-json-"));
|
|
142
|
+
|
|
143
|
+
await withWorkspaceRuntime({ projectDir }, async ({ env }) => {
|
|
144
|
+
const result = await runCli([`-chdir=${projectDir}`, "ls", "--json"], { env });
|
|
145
|
+
|
|
146
|
+
expect(result.exitCode).toBe(0);
|
|
147
|
+
expect(result.stderr).toBe("");
|
|
148
|
+
expect(JSON.parse(result.stdout)).toMatchObject({
|
|
149
|
+
workspaces: [{
|
|
150
|
+
name: "api",
|
|
151
|
+
workflow: "smoke",
|
|
152
|
+
ctx: {},
|
|
153
|
+
}],
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
test("rejects workspace create names that are not shell-safe", async () => {
|
|
159
|
+
const projectDir = mkdtempSync(join(tmpdir(), "rigkit-cli-create-name-"));
|
|
160
|
+
|
|
161
|
+
await withWorkspaceRuntime({ projectDir }, async ({ env }) => {
|
|
162
|
+
const result = await runCli([`-chdir=${projectDir}`, "create", "--name", "some workspace", "--json"], { env });
|
|
163
|
+
|
|
164
|
+
expect(result.exitCode).toBe(1);
|
|
165
|
+
expect(result.stdout).toBe("");
|
|
166
|
+
expect(result.stderr).toContain('Invalid workspace name "some workspace"');
|
|
167
|
+
});
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
test("accepts create name as a positional argument", async () => {
|
|
171
|
+
const projectDir = mkdtempSync(join(tmpdir(), "rigkit-cli-create-positional-"));
|
|
172
|
+
|
|
173
|
+
await withWorkspaceRuntime({ projectDir }, async ({ env }) => {
|
|
174
|
+
const result = await runCli([`-chdir=${projectDir}`, "create", "new-workspace", "--json"], { env });
|
|
175
|
+
|
|
176
|
+
expect(result.exitCode).toBe(0);
|
|
177
|
+
expect(result.stderr).toBe("");
|
|
178
|
+
expect(JSON.parse(result.stdout)).toMatchObject({
|
|
179
|
+
name: "new-workspace",
|
|
180
|
+
});
|
|
181
|
+
});
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
test("removes a workspace with the built-in rm command", async () => {
|
|
185
|
+
const projectDir = mkdtempSync(join(tmpdir(), "rigkit-cli-rm-"));
|
|
186
|
+
|
|
187
|
+
await withWorkspaceRuntime({ projectDir }, async ({ env }) => {
|
|
188
|
+
const result = await runCli([`-chdir=${projectDir}`, "rm", "api", "-y", "--json"], { env });
|
|
189
|
+
|
|
190
|
+
expect(result.exitCode).toBe(0);
|
|
191
|
+
expect(result.stderr).toBe("");
|
|
192
|
+
expect(JSON.parse(result.stdout)).toMatchObject({
|
|
193
|
+
name: "api",
|
|
194
|
+
});
|
|
195
|
+
});
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
test("requires discovered projects for operation --all", async () => {
|
|
199
|
+
const cwd = mkdtempSync(join(tmpdir(), "rigkit-cli-run-all-"));
|
|
200
|
+
|
|
201
|
+
try {
|
|
202
|
+
const result = await runCli(["plan", "--all", "--json"], { cwd });
|
|
203
|
+
|
|
204
|
+
expect(result.exitCode).toBe(1);
|
|
205
|
+
expect(result.stdout).toBe("");
|
|
206
|
+
expect(result.stderr).toContain("No Rigkit projects found.");
|
|
207
|
+
} finally {
|
|
208
|
+
rmSync(cwd, { recursive: true, force: true });
|
|
209
|
+
}
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
test("requires selection for operation --discover with multiple projects", async () => {
|
|
213
|
+
const cwd = mkdtempSync(join(tmpdir(), "rigkit-cli-run-discover-"));
|
|
214
|
+
mkdirSync(join(cwd, "api"));
|
|
215
|
+
mkdirSync(join(cwd, "web"));
|
|
216
|
+
writeFileSync(join(cwd, "api", "rig.config.ts"), "export default {}\n");
|
|
217
|
+
writeFileSync(join(cwd, "web", "rig.config.ts"), "export default {}\n");
|
|
218
|
+
|
|
219
|
+
try {
|
|
220
|
+
const result = await runCli(["plan", "--discover", "--json"], { cwd });
|
|
221
|
+
|
|
222
|
+
expect(result.exitCode).toBe(1);
|
|
223
|
+
expect(result.stdout).toBe("");
|
|
224
|
+
expect(result.stderr).toContain("Multiple Rigkit projects found.");
|
|
225
|
+
expect(result.stderr).toContain("pass --all");
|
|
226
|
+
expect(result.stderr).toContain(join(realpathSync(cwd), "api", "rig.config.ts"));
|
|
227
|
+
expect(result.stderr).toContain(join(realpathSync(cwd), "web", "rig.config.ts"));
|
|
228
|
+
} finally {
|
|
229
|
+
rmSync(cwd, { recursive: true, force: true });
|
|
230
|
+
}
|
|
231
|
+
});
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
async function runCli(
|
|
235
|
+
args: string[],
|
|
236
|
+
options: { cwd?: string; env?: Record<string, string | undefined> } = {},
|
|
237
|
+
): Promise<{ exitCode: number; stdout: string; stderr: string }> {
|
|
238
|
+
const proc = Bun.spawn(["bun", cliPath, ...args], {
|
|
239
|
+
cwd: options.cwd,
|
|
240
|
+
stdout: "pipe",
|
|
241
|
+
stderr: "pipe",
|
|
242
|
+
env: {
|
|
243
|
+
...process.env,
|
|
244
|
+
...options.env,
|
|
245
|
+
FORCE_COLOR: "0",
|
|
246
|
+
NO_COLOR: "1",
|
|
247
|
+
},
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
const [exitCode, stdout, stderr] = await Promise.all([
|
|
251
|
+
proc.exited,
|
|
252
|
+
new Response(proc.stdout).text(),
|
|
253
|
+
new Response(proc.stderr).text(),
|
|
254
|
+
]);
|
|
255
|
+
return { exitCode, stdout, stderr };
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
async function withWorkspaceRuntime(
|
|
259
|
+
input: { projectDir: string },
|
|
260
|
+
run: (context: { env: Record<string, string> }) => Promise<void>,
|
|
261
|
+
): Promise<void> {
|
|
262
|
+
const rigkitHome = mkdtempSync(join(tmpdir(), "rigkit-home-"));
|
|
263
|
+
const token = "test-token";
|
|
264
|
+
const configPath = join(input.projectDir, "rig.config.ts");
|
|
265
|
+
mkdirSync(input.projectDir, { recursive: true });
|
|
266
|
+
writeFileSync(configPath, "export default {}\n");
|
|
267
|
+
const projectId = projectIdFor({ projectDir: input.projectDir, configPath });
|
|
268
|
+
const runtimeFingerprint = runtimeFingerprintFor({ projectDir: input.projectDir, configPath });
|
|
269
|
+
const paths = runtimePaths(projectId, rigkitHome);
|
|
270
|
+
mkdirSync(paths.root, { recursive: true });
|
|
271
|
+
writeFileSync(paths.tokenPath, `${token}\n`);
|
|
272
|
+
|
|
273
|
+
const now = new Date(0).toISOString();
|
|
274
|
+
let runResult: unknown = undefined;
|
|
275
|
+
const server = Bun.serve({
|
|
276
|
+
hostname: "127.0.0.1",
|
|
277
|
+
port: 0,
|
|
278
|
+
async fetch(request) {
|
|
279
|
+
if (request.headers.get("authorization") !== `Bearer ${token}`) {
|
|
280
|
+
return runtimeJson({ error: { message: "Unauthorized" } }, { status: 401 });
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
const { pathname } = new URL(request.url);
|
|
284
|
+
if (pathname === "/health") {
|
|
285
|
+
return runtimeJson({
|
|
286
|
+
ok: true,
|
|
287
|
+
projectId,
|
|
288
|
+
runtimeFingerprint,
|
|
289
|
+
projectDir: input.projectDir,
|
|
290
|
+
configPath,
|
|
291
|
+
statePath: join(input.projectDir, ".rigkit", "state.sqlite"),
|
|
292
|
+
engineVersion: "engine-test",
|
|
293
|
+
runtimeVersion: "runtime-test",
|
|
294
|
+
expiresAt: new Date(Date.now() + 60_000).toISOString(),
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
if (pathname === "/workspaces") {
|
|
298
|
+
return runtimeJson({
|
|
299
|
+
workspaces: [{
|
|
300
|
+
id: "workspace-api",
|
|
301
|
+
name: "api",
|
|
302
|
+
workflow: "smoke",
|
|
303
|
+
ctx: {},
|
|
304
|
+
createdAt: now,
|
|
305
|
+
updatedAt: now,
|
|
306
|
+
}],
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
if (pathname === "/operations") {
|
|
310
|
+
return runtimeJson({
|
|
311
|
+
operations: [{
|
|
312
|
+
id: "create",
|
|
313
|
+
kind: "command",
|
|
314
|
+
source: "core",
|
|
315
|
+
title: "Create",
|
|
316
|
+
description: "Create a workspace",
|
|
317
|
+
createsWorkspace: true,
|
|
318
|
+
cli: {
|
|
319
|
+
positionals: [{ name: "name", index: 0 }],
|
|
320
|
+
options: [{ name: "name", flag: "--name", required: true, type: "string" }],
|
|
321
|
+
},
|
|
322
|
+
inputSchema: {
|
|
323
|
+
type: "object",
|
|
324
|
+
additionalProperties: false,
|
|
325
|
+
properties: {
|
|
326
|
+
name: { type: "string", minLength: 1 },
|
|
327
|
+
},
|
|
328
|
+
required: ["name"],
|
|
329
|
+
},
|
|
330
|
+
}],
|
|
331
|
+
workspaceOperations: [{
|
|
332
|
+
id: "remove",
|
|
333
|
+
kind: "workspace-action",
|
|
334
|
+
source: "core",
|
|
335
|
+
title: "Remove",
|
|
336
|
+
description: "remove workspace",
|
|
337
|
+
cli: {
|
|
338
|
+
options: [{ name: "yes", flag: "--yes", aliases: ["-y"], type: "boolean", runtime: false }],
|
|
339
|
+
},
|
|
340
|
+
inputSchema: {
|
|
341
|
+
type: "object",
|
|
342
|
+
additionalProperties: false,
|
|
343
|
+
properties: {},
|
|
344
|
+
},
|
|
345
|
+
}],
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
if (pathname === "/runs") {
|
|
349
|
+
const body = await request.json() as { operation?: string; input?: { name?: string } };
|
|
350
|
+
runResult = body.operation === "api/remove"
|
|
351
|
+
? {
|
|
352
|
+
id: "workspace-api",
|
|
353
|
+
name: "api",
|
|
354
|
+
workflow: "smoke",
|
|
355
|
+
ctx: {},
|
|
356
|
+
createdAt: now,
|
|
357
|
+
updatedAt: now,
|
|
358
|
+
}
|
|
359
|
+
: {
|
|
360
|
+
id: "workspace-new",
|
|
361
|
+
name: body.input?.name ?? "new-workspace",
|
|
362
|
+
workflow: "smoke",
|
|
363
|
+
ctx: {},
|
|
364
|
+
createdAt: now,
|
|
365
|
+
updatedAt: now,
|
|
366
|
+
};
|
|
367
|
+
return runtimeJson({
|
|
368
|
+
runId: "run-test",
|
|
369
|
+
operation: body.operation ?? "test",
|
|
370
|
+
status: "running",
|
|
371
|
+
eventsUrl: "/runs/run-test/events",
|
|
372
|
+
sessionUrl: "",
|
|
373
|
+
}, { status: 202 });
|
|
374
|
+
}
|
|
375
|
+
if (pathname === "/runs/run-test/events") {
|
|
376
|
+
return new Response(
|
|
377
|
+
`data: ${JSON.stringify({
|
|
378
|
+
type: "run.completed",
|
|
379
|
+
result: runResult,
|
|
380
|
+
})}\n\n`,
|
|
381
|
+
{
|
|
382
|
+
headers: {
|
|
383
|
+
"content-type": "text/event-stream",
|
|
384
|
+
"x-rigkit-api-version": String(SUPPORTED_RUNTIME_API_VERSION),
|
|
385
|
+
},
|
|
386
|
+
},
|
|
387
|
+
);
|
|
388
|
+
}
|
|
389
|
+
return runtimeJson({ error: { message: "Not found" } }, { status: 404 });
|
|
390
|
+
},
|
|
391
|
+
});
|
|
392
|
+
|
|
393
|
+
writeFileSync(
|
|
394
|
+
paths.handlePath,
|
|
395
|
+
`${JSON.stringify({
|
|
396
|
+
projectId,
|
|
397
|
+
runtimeFingerprint,
|
|
398
|
+
projectDir: input.projectDir,
|
|
399
|
+
configPath,
|
|
400
|
+
pid: process.pid,
|
|
401
|
+
url: `http://127.0.0.1:${server.port}`,
|
|
402
|
+
tokenPath: paths.tokenPath,
|
|
403
|
+
}, null, 2)}\n`,
|
|
404
|
+
);
|
|
405
|
+
|
|
406
|
+
try {
|
|
407
|
+
await run({ env: { RIGKIT_HOME: rigkitHome } });
|
|
408
|
+
} finally {
|
|
409
|
+
server.stop(true);
|
|
410
|
+
rmSync(rigkitHome, { recursive: true, force: true });
|
|
411
|
+
rmSync(input.projectDir, { recursive: true, force: true });
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
function runtimeJson(body: unknown, init: ResponseInit = {}): Response {
|
|
416
|
+
const headers = new Headers(init.headers);
|
|
417
|
+
headers.set("x-rigkit-api-version", String(SUPPORTED_RUNTIME_API_VERSION));
|
|
418
|
+
return Response.json(body, { ...init, headers });
|
|
419
|
+
}
|