@rooaak/cli 0.1.0-beta.1
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 +121 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +4 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1 -0
- package/dist/src/commands/auth-login.d.ts +3 -0
- package/dist/src/commands/auth-login.d.ts.map +1 -0
- package/dist/src/commands/auth-login.js +97 -0
- package/dist/src/commands/config-profile-use.d.ts +3 -0
- package/dist/src/commands/config-profile-use.d.ts.map +1 -0
- package/dist/src/commands/config-profile-use.js +88 -0
- package/dist/src/commands/config-whoami.d.ts +3 -0
- package/dist/src/commands/config-whoami.d.ts.map +1 -0
- package/dist/src/commands/config-whoami.js +101 -0
- package/dist/src/commands/help.d.ts +3 -0
- package/dist/src/commands/help.d.ts.map +1 -0
- package/dist/src/commands/help.js +61 -0
- package/dist/src/commands/init/index.d.ts +3 -0
- package/dist/src/commands/init/index.d.ts.map +1 -0
- package/dist/src/commands/init/index.js +756 -0
- package/dist/src/commands/init/prompting.d.ts +16 -0
- package/dist/src/commands/init/prompting.d.ts.map +1 -0
- package/dist/src/commands/init/prompting.js +63 -0
- package/dist/src/commands/init/wait-for-message.d.ts +45 -0
- package/dist/src/commands/init/wait-for-message.d.ts.map +1 -0
- package/dist/src/commands/init/wait-for-message.js +27 -0
- package/dist/src/commands/version.d.ts +3 -0
- package/dist/src/commands/version.d.ts.map +1 -0
- package/dist/src/commands/version.js +14 -0
- package/dist/src/generated/handlers.d.ts +5 -0
- package/dist/src/generated/handlers.d.ts.map +1 -0
- package/dist/src/generated/handlers.js +17 -0
- package/dist/src/generated/manifest.d.ts +3 -0
- package/dist/src/generated/manifest.d.ts.map +1 -0
- package/dist/src/generated/manifest.js +56 -0
- package/dist/src/lib/argv.d.ts +16 -0
- package/dist/src/lib/argv.d.ts.map +1 -0
- package/dist/src/lib/argv.js +68 -0
- package/dist/src/lib/base-url.d.ts +7 -0
- package/dist/src/lib/base-url.d.ts.map +1 -0
- package/dist/src/lib/base-url.js +6 -0
- package/dist/src/lib/exit-codes.d.ts +11 -0
- package/dist/src/lib/exit-codes.d.ts.map +1 -0
- package/dist/src/lib/exit-codes.js +29 -0
- package/dist/src/lib/generated-command.d.ts +25 -0
- package/dist/src/lib/generated-command.d.ts.map +1 -0
- package/dist/src/lib/generated-command.js +357 -0
- package/dist/src/lib/normalize-error.d.ts +45 -0
- package/dist/src/lib/normalize-error.d.ts.map +1 -0
- package/dist/src/lib/normalize-error.js +128 -0
- package/dist/src/lib/options.d.ts +12 -0
- package/dist/src/lib/options.d.ts.map +1 -0
- package/dist/src/lib/options.js +49 -0
- package/dist/src/lib/package-version.d.ts +2 -0
- package/dist/src/lib/package-version.d.ts.map +1 -0
- package/dist/src/lib/package-version.js +22 -0
- package/dist/src/lib/paths.d.ts +2 -0
- package/dist/src/lib/paths.d.ts.map +1 -0
- package/dist/src/lib/paths.js +21 -0
- package/dist/src/lib/profile-name.d.ts +2 -0
- package/dist/src/lib/profile-name.d.ts.map +1 -0
- package/dist/src/lib/profile-name.js +4 -0
- package/dist/src/lib/profile-store.d.ts +31 -0
- package/dist/src/lib/profile-store.d.ts.map +1 -0
- package/dist/src/lib/profile-store.js +179 -0
- package/dist/src/lib/renderer.d.ts +10 -0
- package/dist/src/lib/renderer.d.ts.map +1 -0
- package/dist/src/lib/renderer.js +25 -0
- package/dist/src/lib/run.d.ts +12 -0
- package/dist/src/lib/run.d.ts.map +1 -0
- package/dist/src/lib/run.js +108 -0
- package/dist/src/lib/transport.d.ts +37 -0
- package/dist/src/lib/transport.d.ts.map +1 -0
- package/dist/src/lib/transport.js +65 -0
- package/dist/src/lib/types.d.ts +22 -0
- package/dist/src/lib/types.d.ts.map +1 -0
- package/dist/src/lib/types.js +1 -0
- package/package.json +46 -0
- package/rooaak.js +39 -0
- package/schemas/openapi.v1.json +6013 -0
package/README.md
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# @rooaak/cli
|
|
2
|
+
|
|
3
|
+
Rooaak CLI companion package for `/api/v1` workflows.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
### Global install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install -g @rooaak/cli
|
|
11
|
+
rooaak version
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
### One-off (no install)
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npx @rooaak/cli version
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
### From source (this repo)
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
cd /Users/darian/Documents/Dev/rooaak/rooaak-core/packages/rooaak-cli
|
|
24
|
+
npm run build
|
|
25
|
+
node ./rooaak.js version
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Authentication
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
rooaak auth login --api-key <YOUR_API_KEY>
|
|
32
|
+
rooaak config whoami
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Optional base URL override for staging/self-hosted environments:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
rooaak auth login --api-key <YOUR_API_KEY> --base-url https://staging.example.com
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Interactive vs automation modes
|
|
42
|
+
|
|
43
|
+
### Interactive mode (developer-first)
|
|
44
|
+
|
|
45
|
+
Use `rooaak init` for the guided flow:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
rooaak init
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
This walks through auth/profile setup, project + agent creation, and first test message.
|
|
52
|
+
|
|
53
|
+
### Automation mode (script/CI/agent-safe)
|
|
54
|
+
|
|
55
|
+
Use `--json` and `--non-interactive` for deterministic machine behavior:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
rooaak auth login --api-key "$ROOAAK_API_KEY" --json --non-interactive
|
|
59
|
+
rooaak projects create --name "automation-project" --json --non-interactive
|
|
60
|
+
rooaak agents create --name "automation-agent" --json --non-interactive
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Automation contract:
|
|
64
|
+
|
|
65
|
+
- `stdout` contains one JSON object only.
|
|
66
|
+
- `stderr` carries human hints/warnings/debug.
|
|
67
|
+
- Required input must be passed explicitly (no prompts in `--non-interactive`).
|
|
68
|
+
|
|
69
|
+
## AI coding agent guidance
|
|
70
|
+
|
|
71
|
+
When driving the CLI from an AI agent or orchestration script:
|
|
72
|
+
|
|
73
|
+
- Always pass `--json`.
|
|
74
|
+
- Always pass `--non-interactive`.
|
|
75
|
+
- Parse `stdout` as a strict JSON envelope.
|
|
76
|
+
- Route `stderr` to logs/diagnostics only.
|
|
77
|
+
- Branch logic by exit code.
|
|
78
|
+
|
|
79
|
+
### Exit codes
|
|
80
|
+
|
|
81
|
+
- `0`: success
|
|
82
|
+
- `2`: usage/validation error
|
|
83
|
+
- `3`: auth failure
|
|
84
|
+
- `4`: permission/scope denied
|
|
85
|
+
- `5`: not found
|
|
86
|
+
- `6`: conflict/idempotency
|
|
87
|
+
- `7`: remote/server/transient failure
|
|
88
|
+
|
|
89
|
+
### Example machine-safe command
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
rooaak messages send \
|
|
93
|
+
--agent-id "$AGENT_ID" \
|
|
94
|
+
--session-id "$SESSION_ID" \
|
|
95
|
+
--message "Hello" \
|
|
96
|
+
--json \
|
|
97
|
+
--non-interactive
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Drift checks and test gates
|
|
101
|
+
|
|
102
|
+
Run from `/Users/darian/Documents/Dev/rooaak/rooaak-core`:
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
npm run openapi:v1:check
|
|
106
|
+
npm run cli:v1:check-commands
|
|
107
|
+
npm run test:run:cli
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Opt-in staging e2e harness:
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
ROOAAK_CLI_E2E=1 \
|
|
114
|
+
ROOAAK_CLI_E2E_BASE_URL=https://staging.example.com \
|
|
115
|
+
ROOAAK_CLI_E2E_ADMIN_API_KEY=<ADMIN_KEY> \
|
|
116
|
+
npm run test:run:cli:e2e
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
The staging e2e test is skipped by default and only runs when `ROOAAK_CLI_E2E=1`.
|
|
120
|
+
`ROOAAK_CLI_E2E_BASE_URL` is required for e2e runs.
|
|
121
|
+
Production hosts (`rooaak.com`, `www.rooaak.com`) are rejected by default; use `ROOAAK_CLI_E2E_ALLOW_PRODUCTION=1` only when intentional.
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../cli.ts"],"names":[],"mappings":"AAEA,wBAAsB,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAE1D"}
|
package/dist/cli.js
ADDED
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { main } from "./cli.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-login.d.ts","sourceRoot":"","sources":["../../../src/commands/auth-login.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAGtD,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CA4F3F"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { resolveBaseUrl } from "../lib/base-url.js";
|
|
2
|
+
import { normalizeLocalUsageError, toJsonErrorEnvelope, toJsonOkEnvelope } from "../lib/normalize-error.js";
|
|
3
|
+
import { parseOptions } from "../lib/options.js";
|
|
4
|
+
import { createProfileStore } from "../lib/profile-store.js";
|
|
5
|
+
import { isValidProfileName } from "../lib/profile-name.js";
|
|
6
|
+
import { createRenderer } from "../lib/renderer.js";
|
|
7
|
+
import { ExitCode } from "../lib/exit-codes.js";
|
|
8
|
+
export async function authLoginCommand(ctx, argv) {
|
|
9
|
+
const r = createRenderer(ctx);
|
|
10
|
+
const parsed = parseOptions(argv, [
|
|
11
|
+
{ name: "--api-key", takesValue: true },
|
|
12
|
+
{ name: "--profile", takesValue: true },
|
|
13
|
+
]);
|
|
14
|
+
if (parsed.unknownOption) {
|
|
15
|
+
const err = normalizeLocalUsageError(`Unknown option: ${parsed.unknownOption}`);
|
|
16
|
+
if (ctx.flags.json)
|
|
17
|
+
r.json(toJsonErrorEnvelope(err));
|
|
18
|
+
else
|
|
19
|
+
r.error(err.message);
|
|
20
|
+
return ExitCode.Usage;
|
|
21
|
+
}
|
|
22
|
+
if (parsed.missingValueOption) {
|
|
23
|
+
const err = normalizeLocalUsageError(`Missing value for: ${parsed.missingValueOption}`);
|
|
24
|
+
if (ctx.flags.json)
|
|
25
|
+
r.json(toJsonErrorEnvelope(err));
|
|
26
|
+
else
|
|
27
|
+
r.error(err.message);
|
|
28
|
+
return ExitCode.Usage;
|
|
29
|
+
}
|
|
30
|
+
if (parsed.positionals.length > 0) {
|
|
31
|
+
// Never echo raw argv back (can contain secrets if user pasted something sensitive).
|
|
32
|
+
const err = normalizeLocalUsageError("Unexpected extra arguments", {
|
|
33
|
+
argc: parsed.positionals.length,
|
|
34
|
+
});
|
|
35
|
+
if (ctx.flags.json)
|
|
36
|
+
r.json(toJsonErrorEnvelope(err));
|
|
37
|
+
else
|
|
38
|
+
r.error(err.message);
|
|
39
|
+
return ExitCode.Usage;
|
|
40
|
+
}
|
|
41
|
+
const apiKey = parsed.values["--api-key"];
|
|
42
|
+
if (typeof apiKey !== "string" || apiKey.length === 0) {
|
|
43
|
+
const err = normalizeLocalUsageError("Missing required flag: --api-key");
|
|
44
|
+
if (ctx.flags.json)
|
|
45
|
+
r.json(toJsonErrorEnvelope(err));
|
|
46
|
+
else
|
|
47
|
+
r.error(err.message);
|
|
48
|
+
return ExitCode.Usage;
|
|
49
|
+
}
|
|
50
|
+
const profile = typeof parsed.values["--profile"] === "string" && parsed.values["--profile"].length > 0
|
|
51
|
+
? parsed.values["--profile"]
|
|
52
|
+
: "default";
|
|
53
|
+
if (!isValidProfileName(profile)) {
|
|
54
|
+
const err = normalizeLocalUsageError("Invalid profile name", { profile });
|
|
55
|
+
if (ctx.flags.json)
|
|
56
|
+
r.json(toJsonErrorEnvelope(err));
|
|
57
|
+
else
|
|
58
|
+
r.error(err.message);
|
|
59
|
+
return ExitCode.Usage;
|
|
60
|
+
}
|
|
61
|
+
const store = createProfileStore({ configPath: ctx.profileConfigPath });
|
|
62
|
+
const existingRes = store.readConfig();
|
|
63
|
+
if (existingRes.kind === "corrupt") {
|
|
64
|
+
// Login is an allowed remediation path; overwrite but surface a hint.
|
|
65
|
+
r.warn(existingRes.message);
|
|
66
|
+
}
|
|
67
|
+
const existing = existingRes.kind === "ok" ? existingRes.config : null;
|
|
68
|
+
const existingProfile = existing?.profiles?.[profile];
|
|
69
|
+
const baseUrl = resolveBaseUrl({
|
|
70
|
+
cliFlag: ctx.flags.baseUrl,
|
|
71
|
+
env: ctx.env.ROOAAK_BASE_URL,
|
|
72
|
+
profile: existingProfile?.baseUrl,
|
|
73
|
+
});
|
|
74
|
+
const now = new Date().toISOString();
|
|
75
|
+
const next = {
|
|
76
|
+
version: 1,
|
|
77
|
+
currentProfile: profile,
|
|
78
|
+
profiles: {
|
|
79
|
+
...(existing?.profiles ?? {}),
|
|
80
|
+
[profile]: {
|
|
81
|
+
apiKey,
|
|
82
|
+
baseUrl,
|
|
83
|
+
updatedAt: now,
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
};
|
|
87
|
+
store.writeConfig(next);
|
|
88
|
+
r.debug(`Wrote config: ${store.getConfigPath()}`);
|
|
89
|
+
if (ctx.flags.json) {
|
|
90
|
+
r.json(toJsonOkEnvelope({ profile, baseUrl }));
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
r.text(`Saved profile '${profile}'.`);
|
|
94
|
+
r.text(`Base URL: ${baseUrl}`);
|
|
95
|
+
}
|
|
96
|
+
return ExitCode.Success;
|
|
97
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-profile-use.d.ts","sourceRoot":"","sources":["../../../src/commands/config-profile-use.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEtD,wBAAsB,uBAAuB,CAAC,GAAG,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CA+ElG"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { ExitCode } from "../lib/exit-codes.js";
|
|
2
|
+
import { exitCodeForError, normalizeLocalUsageError, toJsonErrorEnvelope, toJsonOkEnvelope, } from "../lib/normalize-error.js";
|
|
3
|
+
import { isValidProfileName } from "../lib/profile-name.js";
|
|
4
|
+
import { createProfileStore } from "../lib/profile-store.js";
|
|
5
|
+
import { createRenderer } from "../lib/renderer.js";
|
|
6
|
+
export async function configProfileUseCommand(ctx, argv) {
|
|
7
|
+
const r = createRenderer(ctx);
|
|
8
|
+
const name = argv[0];
|
|
9
|
+
if (!name) {
|
|
10
|
+
const err = normalizeLocalUsageError("Missing required argument: <name>");
|
|
11
|
+
if (ctx.flags.json)
|
|
12
|
+
r.json(toJsonErrorEnvelope(err));
|
|
13
|
+
else
|
|
14
|
+
r.error(err.message);
|
|
15
|
+
return ExitCode.Usage;
|
|
16
|
+
}
|
|
17
|
+
if (argv.length !== 1) {
|
|
18
|
+
const err = normalizeLocalUsageError("Unexpected extra arguments");
|
|
19
|
+
if (ctx.flags.json)
|
|
20
|
+
r.json(toJsonErrorEnvelope(err));
|
|
21
|
+
else
|
|
22
|
+
r.error(err.message);
|
|
23
|
+
return ExitCode.Usage;
|
|
24
|
+
}
|
|
25
|
+
if (!isValidProfileName(name)) {
|
|
26
|
+
const err = normalizeLocalUsageError("Invalid profile name", { profile: name });
|
|
27
|
+
if (ctx.flags.json)
|
|
28
|
+
r.json(toJsonErrorEnvelope(err));
|
|
29
|
+
else
|
|
30
|
+
r.error(err.message);
|
|
31
|
+
return ExitCode.Usage;
|
|
32
|
+
}
|
|
33
|
+
const store = createProfileStore({ configPath: ctx.profileConfigPath });
|
|
34
|
+
const res = store.readConfig();
|
|
35
|
+
if (res.kind === "missing") {
|
|
36
|
+
const err = {
|
|
37
|
+
code: "auth.not_logged_in",
|
|
38
|
+
message: "Not logged in",
|
|
39
|
+
details: {},
|
|
40
|
+
meta: {},
|
|
41
|
+
};
|
|
42
|
+
if (ctx.flags.json)
|
|
43
|
+
r.json(toJsonErrorEnvelope(err));
|
|
44
|
+
else
|
|
45
|
+
r.error("Not logged in. Run `rooaak auth login --api-key ...`.");
|
|
46
|
+
return exitCodeForError(err);
|
|
47
|
+
}
|
|
48
|
+
if (res.kind === "corrupt") {
|
|
49
|
+
const err = {
|
|
50
|
+
code: "config.corrupt",
|
|
51
|
+
message: res.message,
|
|
52
|
+
details: { path: res.path },
|
|
53
|
+
meta: {},
|
|
54
|
+
};
|
|
55
|
+
if (ctx.flags.json)
|
|
56
|
+
r.json(toJsonErrorEnvelope(err));
|
|
57
|
+
else
|
|
58
|
+
r.error(err.message);
|
|
59
|
+
return exitCodeForError(err);
|
|
60
|
+
}
|
|
61
|
+
const config = res.config;
|
|
62
|
+
if (!config.profiles[name]) {
|
|
63
|
+
const err = {
|
|
64
|
+
code: "not_found.profile",
|
|
65
|
+
message: `Profile not found: ${name}`,
|
|
66
|
+
details: { profile: name },
|
|
67
|
+
meta: {},
|
|
68
|
+
};
|
|
69
|
+
if (ctx.flags.json)
|
|
70
|
+
r.json(toJsonErrorEnvelope(err));
|
|
71
|
+
else
|
|
72
|
+
r.error(err.message);
|
|
73
|
+
return exitCodeForError(err);
|
|
74
|
+
}
|
|
75
|
+
const next = {
|
|
76
|
+
version: 1,
|
|
77
|
+
currentProfile: name,
|
|
78
|
+
profiles: config.profiles,
|
|
79
|
+
};
|
|
80
|
+
store.writeConfig(next);
|
|
81
|
+
if (ctx.flags.json) {
|
|
82
|
+
r.json(toJsonOkEnvelope({ profile: name }));
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
r.text(`Using profile '${name}'.`);
|
|
86
|
+
}
|
|
87
|
+
return ExitCode.Success;
|
|
88
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-whoami.d.ts","sourceRoot":"","sources":["../../../src/commands/config-whoami.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAOtD,wBAAsB,mBAAmB,CAAC,GAAG,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CA+F9F"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { resolveBaseUrl } from "../lib/base-url.js";
|
|
2
|
+
import { ExitCode } from "../lib/exit-codes.js";
|
|
3
|
+
import { exitCodeForError, toJsonErrorEnvelope, toJsonOkEnvelope, } from "../lib/normalize-error.js";
|
|
4
|
+
import { createProfileStore } from "../lib/profile-store.js";
|
|
5
|
+
import { createRenderer } from "../lib/renderer.js";
|
|
6
|
+
import { createTransport } from "../lib/transport.js";
|
|
7
|
+
export async function configWhoamiCommand(ctx, argv) {
|
|
8
|
+
const r = createRenderer(ctx);
|
|
9
|
+
const store = createProfileStore({ configPath: ctx.profileConfigPath });
|
|
10
|
+
if (argv.length !== 0) {
|
|
11
|
+
const err = {
|
|
12
|
+
code: "usage.validation_error",
|
|
13
|
+
message: "Unexpected arguments",
|
|
14
|
+
// Never echo raw argv back (can contain secrets if user pasted something sensitive).
|
|
15
|
+
details: { argc: argv.length },
|
|
16
|
+
meta: {},
|
|
17
|
+
};
|
|
18
|
+
if (ctx.flags.json)
|
|
19
|
+
r.json(toJsonErrorEnvelope(err));
|
|
20
|
+
else
|
|
21
|
+
r.error(err.message);
|
|
22
|
+
return exitCodeForError(err);
|
|
23
|
+
}
|
|
24
|
+
const cfgRes = store.readConfig();
|
|
25
|
+
if (cfgRes.kind === "missing") {
|
|
26
|
+
const err = {
|
|
27
|
+
code: "auth.not_logged_in",
|
|
28
|
+
message: "Not logged in. Run `rooaak auth login --api-key ...`.",
|
|
29
|
+
details: {},
|
|
30
|
+
meta: {},
|
|
31
|
+
};
|
|
32
|
+
if (ctx.flags.json)
|
|
33
|
+
r.json(toJsonErrorEnvelope(err));
|
|
34
|
+
else
|
|
35
|
+
r.error(err.message);
|
|
36
|
+
return exitCodeForError(err);
|
|
37
|
+
}
|
|
38
|
+
if (cfgRes.kind === "corrupt") {
|
|
39
|
+
const err = {
|
|
40
|
+
code: "config.corrupt",
|
|
41
|
+
message: cfgRes.message,
|
|
42
|
+
details: { path: cfgRes.path },
|
|
43
|
+
meta: {},
|
|
44
|
+
};
|
|
45
|
+
if (ctx.flags.json)
|
|
46
|
+
r.json(toJsonErrorEnvelope(err));
|
|
47
|
+
else
|
|
48
|
+
r.error(err.message);
|
|
49
|
+
return exitCodeForError(err);
|
|
50
|
+
}
|
|
51
|
+
const config = cfgRes.config;
|
|
52
|
+
const profileName = config.currentProfile;
|
|
53
|
+
const profile = config.profiles[profileName];
|
|
54
|
+
if (!profile?.apiKey) {
|
|
55
|
+
const err = {
|
|
56
|
+
code: "auth.not_logged_in",
|
|
57
|
+
message: "Not logged in. Run `rooaak auth login --api-key ...`.",
|
|
58
|
+
details: {},
|
|
59
|
+
meta: {},
|
|
60
|
+
};
|
|
61
|
+
if (ctx.flags.json)
|
|
62
|
+
r.json(toJsonErrorEnvelope(err));
|
|
63
|
+
else
|
|
64
|
+
r.error(err.message);
|
|
65
|
+
return exitCodeForError(err);
|
|
66
|
+
}
|
|
67
|
+
const baseUrl = resolveBaseUrl({
|
|
68
|
+
cliFlag: ctx.flags.baseUrl,
|
|
69
|
+
env: ctx.env.ROOAAK_BASE_URL,
|
|
70
|
+
profile: profile.baseUrl,
|
|
71
|
+
});
|
|
72
|
+
const transport = createTransport({
|
|
73
|
+
baseUrl,
|
|
74
|
+
apiKey: profile.apiKey,
|
|
75
|
+
fetchFn: ctx.fetchFn,
|
|
76
|
+
});
|
|
77
|
+
r.debug(`GET ${baseUrl}/api/v1/agents?limit=1`);
|
|
78
|
+
const httpRes = await transport.getJson("/api/v1/agents?limit=1");
|
|
79
|
+
if (!httpRes.ok) {
|
|
80
|
+
const err = httpRes.error;
|
|
81
|
+
if (ctx.flags.json)
|
|
82
|
+
r.json(toJsonErrorEnvelope(err));
|
|
83
|
+
else
|
|
84
|
+
r.error(err.message);
|
|
85
|
+
return exitCodeForError(err);
|
|
86
|
+
}
|
|
87
|
+
const meta = { status: httpRes.status, requestId: httpRes.requestId };
|
|
88
|
+
const data = {
|
|
89
|
+
profile: profileName,
|
|
90
|
+
baseUrl,
|
|
91
|
+
authenticated: true,
|
|
92
|
+
};
|
|
93
|
+
if (ctx.flags.json) {
|
|
94
|
+
r.json(toJsonOkEnvelope(data, meta));
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
r.text(`Authenticated (profile: '${profileName}').`);
|
|
98
|
+
r.text(`Base URL: ${baseUrl}`);
|
|
99
|
+
}
|
|
100
|
+
return ExitCode.Success;
|
|
101
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"help.d.ts","sourceRoot":"","sources":["../../../src/commands/help.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEtD,wBAAgB,WAAW,CAAC,GAAG,EAAE,cAAc,GAAG,MAAM,CA8DvD"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { ExitCode } from "../lib/exit-codes.js";
|
|
2
|
+
import { toJsonOkEnvelope } from "../lib/normalize-error.js";
|
|
3
|
+
import { createRenderer } from "../lib/renderer.js";
|
|
4
|
+
export function helpCommand(ctx) {
|
|
5
|
+
const r = createRenderer(ctx);
|
|
6
|
+
if (ctx.flags.json) {
|
|
7
|
+
// Machine mode: single JSON object on stdout, no prose.
|
|
8
|
+
r.json(toJsonOkEnvelope({
|
|
9
|
+
type: "help",
|
|
10
|
+
usage: "rooaak <group> <command> [flags]",
|
|
11
|
+
commands: [
|
|
12
|
+
{ name: "help", description: "Show help" },
|
|
13
|
+
{ name: "version", description: "Print version" },
|
|
14
|
+
{ name: "init", description: "Guided onboarding: project -> agent -> first message" },
|
|
15
|
+
{ name: "auth login", description: "Store API key in a local profile" },
|
|
16
|
+
{ name: "config whoami", description: "Validate current profile against the API" },
|
|
17
|
+
{ name: "config profile use <name>", description: "Switch active profile" },
|
|
18
|
+
],
|
|
19
|
+
flags: [
|
|
20
|
+
{ name: "--help", description: "Show help" },
|
|
21
|
+
{ name: "--version", description: "Print version" },
|
|
22
|
+
{ name: "--json", description: "Machine output (single JSON object on stdout)" },
|
|
23
|
+
{ name: "--non-interactive", description: "Fail fast instead of prompting" },
|
|
24
|
+
{ name: "--quiet", description: "Suppress non-error output on stderr" },
|
|
25
|
+
{ name: "--verbose", description: "Debug output on stderr (no secrets)" },
|
|
26
|
+
{ name: "--base-url <url>", description: "Override API base URL" },
|
|
27
|
+
],
|
|
28
|
+
env: [{ name: "ROOAAK_BASE_URL", description: "API base URL (used if --base-url is not provided)" }],
|
|
29
|
+
}));
|
|
30
|
+
return ExitCode.Success;
|
|
31
|
+
}
|
|
32
|
+
ctx.stdout.write([
|
|
33
|
+
"Usage:",
|
|
34
|
+
" rooaak <group> <command> [flags]",
|
|
35
|
+
"",
|
|
36
|
+
"Commands:",
|
|
37
|
+
" help Show help",
|
|
38
|
+
" version Print version",
|
|
39
|
+
" init Guided onboarding: project -> agent -> first message",
|
|
40
|
+
" auth login Store API key in a local profile",
|
|
41
|
+
" config whoami Validate current profile against the API",
|
|
42
|
+
" config profile use <name> Switch active profile",
|
|
43
|
+
"",
|
|
44
|
+
"Global flags:",
|
|
45
|
+
" -h, --help Show help",
|
|
46
|
+
" -v, --version Print version",
|
|
47
|
+
" --json Machine output (single JSON object on stdout)",
|
|
48
|
+
" --non-interactive Fail fast instead of prompting",
|
|
49
|
+
" --quiet Suppress non-error output on stderr",
|
|
50
|
+
" --verbose Debug output on stderr (no secrets)",
|
|
51
|
+
" --base-url <url> Override API base URL",
|
|
52
|
+
"",
|
|
53
|
+
"Environment:",
|
|
54
|
+
" ROOAAK_BASE_URL API base URL (used if --base-url is not provided)",
|
|
55
|
+
"",
|
|
56
|
+
"Generated command help:",
|
|
57
|
+
" rooaak <resource> <action> --help",
|
|
58
|
+
""
|
|
59
|
+
].join("\n") + "\n");
|
|
60
|
+
return ExitCode.Success;
|
|
61
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/commands/init/index.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AA4XzD,wBAAsB,WAAW,CAAC,GAAG,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAgctF"}
|