@ritualai/cli 0.7.2 → 0.7.5
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 +56 -5
- package/dist/commands/init.js +262 -40
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/login.js +120 -13
- package/dist/commands/login.js.map +1 -1
- package/dist/commands/logout.js +55 -8
- package/dist/commands/logout.js.map +1 -1
- package/dist/index.js +8 -2
- package/dist/index.js.map +1 -1
- package/dist/lib/agents/providers.js +14 -3
- package/dist/lib/agents/providers.js.map +1 -1
- package/dist/lib/auth-flow.js +1 -1
- package/dist/lib/auth-flow.js.map +1 -1
- package/dist/lib/colors.js +182 -0
- package/dist/lib/colors.js.map +1 -0
- package/dist/lib/config.js +30 -17
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/credentials-backup.js +282 -0
- package/dist/lib/credentials-backup.js.map +1 -0
- package/dist/lib/identity-banner.js +88 -0
- package/dist/lib/identity-banner.js.map +1 -0
- package/dist/lib/oidc.js +55 -0
- package/dist/lib/oidc.js.map +1 -1
- package/dist/lib/package-info.js +76 -0
- package/dist/lib/package-info.js.map +1 -0
- package/dist/lib/welcome-banner.js +290 -0
- package/dist/lib/welcome-banner.js.map +1 -0
- package/package.json +1 -1
- package/skills/claude-code/ritual/agents/openai.yaml +2 -2
- package/skills/codex/ritual/agents/openai.yaml +2 -2
- package/skills/cursor/ritual/agents/openai.yaml +2 -2
- package/skills/gemini/ritual/agents/openai.yaml +2 -2
- package/skills/kiro/ritual/agents/openai.yaml +2 -2
- package/skills/vscode/ritual/agents/openai.yaml +2 -2
package/dist/commands/login.js
CHANGED
|
@@ -2,7 +2,13 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.loginCommand = loginCommand;
|
|
4
4
|
const auth_flow_1 = require("../lib/auth-flow");
|
|
5
|
+
const config_1 = require("../lib/config");
|
|
6
|
+
const credentials_backup_1 = require("../lib/credentials-backup");
|
|
7
|
+
const identity_banner_1 = require("../lib/identity-banner");
|
|
8
|
+
const prompt_1 = require("../lib/prompt");
|
|
5
9
|
const init_1 = require("./init");
|
|
10
|
+
const welcome_banner_1 = require("../lib/welcome-banner");
|
|
11
|
+
const package_info_1 = require("../lib/package-info");
|
|
6
12
|
/**
|
|
7
13
|
* `ritual login` — browser-based Auth Code + PKCE flow against
|
|
8
14
|
* Keycloak. On success, stores the access + refresh tokens in
|
|
@@ -12,27 +18,128 @@ const init_1 = require("./init");
|
|
|
12
18
|
* `--issuer https://auth.dev.ritualapp.cloud/realms/ritual` for dev,
|
|
13
19
|
* `--dev` as the shortcut, or set `RITUAL_KEYCLOAK_URL` env var.
|
|
14
20
|
*
|
|
21
|
+
* Three sign-in paths:
|
|
22
|
+
*
|
|
23
|
+
* 1. No valid local session: open browser, sign in normally.
|
|
24
|
+
* 2. Valid local session, no --switch-account: print identity
|
|
25
|
+
* banner to stderr, no-op (success), exit 0. The user already
|
|
26
|
+
* has what they need; we just confirm who they are.
|
|
27
|
+
* 3. Valid local session, --switch-account: atomic backup + forced
|
|
28
|
+
* sign-in (OIDC prompt=login so Keycloak's SSO cookie is
|
|
29
|
+
* ignored). On failure, prior session is restored.
|
|
30
|
+
*
|
|
15
31
|
* The flow itself lives in `lib/auth-flow.ts` so `ritual init` can
|
|
16
32
|
* invoke the same path when it lazily prompts the user to sign in.
|
|
17
33
|
*/
|
|
18
34
|
async function loginCommand(options) {
|
|
19
|
-
console.log('');
|
|
20
|
-
console.log(' Ritual — sign in');
|
|
21
|
-
console.log('');
|
|
22
35
|
// --dev wins over --issuer (consistent with init); both win over env.
|
|
23
36
|
const issuer = options.dev ? init_1.DEV_ISSUER : options.issuer;
|
|
37
|
+
// Welcome banner first — surfaces identity for the
|
|
38
|
+
// already-signed-in case BEFORE we decide whether to short-circuit.
|
|
39
|
+
const tokenStatus = await (0, config_1.getValidAccessToken)();
|
|
40
|
+
const projectDir = process.cwd();
|
|
41
|
+
const ws = (0, welcome_banner_1.readBoundWorkspace)(projectDir);
|
|
42
|
+
const currentUser = tokenStatus.kind === 'signed-in'
|
|
43
|
+
? (tokenStatus.creds.user?.email ?? tokenStatus.creds.user?.sub)
|
|
44
|
+
: undefined;
|
|
45
|
+
(0, welcome_banner_1.printWelcomeBanner)({
|
|
46
|
+
currentUser,
|
|
47
|
+
workspaceBound: ws.bound,
|
|
48
|
+
workspaceName: ws.name,
|
|
49
|
+
projectDir,
|
|
50
|
+
cliVersion: (0, package_info_1.readPackageVersionSafe)(),
|
|
51
|
+
// `ritual login`'s "tips" are different from init's — focus on
|
|
52
|
+
// the auth surface specifically.
|
|
53
|
+
tips: tokenStatus.kind === 'signed-in'
|
|
54
|
+
? undefined
|
|
55
|
+
: [
|
|
56
|
+
'1. Open your browser to Keycloak',
|
|
57
|
+
'2. Sign in (or verify email if brand-new)',
|
|
58
|
+
'3. Bounce back here; tokens cached locally',
|
|
59
|
+
],
|
|
60
|
+
quickCommands: [
|
|
61
|
+
'ritual whoami',
|
|
62
|
+
'ritual login --switch-account',
|
|
63
|
+
'ritual logout --all',
|
|
64
|
+
'ritual doctor',
|
|
65
|
+
],
|
|
66
|
+
});
|
|
67
|
+
// If a valid session exists and no --switch-account, also keep
|
|
68
|
+
// the existing compact identity banner for the textual "already
|
|
69
|
+
// signed in" message + exit.
|
|
70
|
+
if (tokenStatus.kind === 'signed-in' && !options.switchAccount) {
|
|
71
|
+
(0, identity_banner_1.printIdentityBanner)((0, identity_banner_1.identityFromCreds)(tokenStatus.creds), { indent: ' ' });
|
|
72
|
+
console.log('');
|
|
73
|
+
console.log(' Already signed in. Nothing to do.');
|
|
74
|
+
console.log('');
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
const isSwitching = options.switchAccount && tokenStatus.kind === 'signed-in';
|
|
78
|
+
const currentEmail = tokenStatus.kind === 'signed-in'
|
|
79
|
+
? (tokenStatus.creds.user?.email ?? tokenStatus.creds.user?.sub ?? '(unknown)')
|
|
80
|
+
: undefined;
|
|
81
|
+
if (isSwitching) {
|
|
82
|
+
console.log(` Currently signed in as ${currentEmail}.`);
|
|
83
|
+
console.log(` Continuing will:`);
|
|
84
|
+
console.log(` • Back up your local credentials, then atomically replace them on success`);
|
|
85
|
+
console.log(` • Open your browser with OIDC \`prompt=login\` (Keycloak will show its`);
|
|
86
|
+
console.log(` sign-in form even if its SSO cookie says otherwise — no incognito needed)`);
|
|
87
|
+
console.log(` If anything goes wrong, your existing session is restored.`);
|
|
88
|
+
console.log('');
|
|
89
|
+
if (!process.stdin.isTTY) {
|
|
90
|
+
if (!options.yes) {
|
|
91
|
+
console.error(` ✗ --switch-account requires interactive confirmation; pass --yes for scripted use.`);
|
|
92
|
+
console.error('');
|
|
93
|
+
process.exitCode = 1;
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
else if (!options.yes) {
|
|
98
|
+
try {
|
|
99
|
+
await (0, prompt_1.prompt)(' Press Enter to switch, or Ctrl-C to keep the current session: ');
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
console.log('');
|
|
103
|
+
console.log(' Switch aborted.');
|
|
104
|
+
process.exitCode = 1;
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
const loginRunner = async () => (0, auth_flow_1.runBrowserLoginAndSave)({
|
|
110
|
+
issuer,
|
|
111
|
+
clientId: options.clientId,
|
|
112
|
+
forceLogin: !!options.switchAccount,
|
|
113
|
+
});
|
|
24
114
|
let creds;
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
115
|
+
if (isSwitching) {
|
|
116
|
+
const { release, backup } = (0, credentials_backup_1.beginCredentialSwap)();
|
|
117
|
+
(0, config_1.clearCredentials)();
|
|
118
|
+
try {
|
|
119
|
+
creds = await loginRunner();
|
|
120
|
+
backup.commit();
|
|
121
|
+
}
|
|
122
|
+
catch (err) {
|
|
123
|
+
backup.restore();
|
|
124
|
+
release();
|
|
125
|
+
console.error('');
|
|
126
|
+
console.error(` ✗ Switch failed: ${err.message}`);
|
|
127
|
+
console.error(` Restored previous session for ${currentEmail}.`);
|
|
128
|
+
process.exitCode = 1;
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
release();
|
|
30
132
|
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
133
|
+
else {
|
|
134
|
+
try {
|
|
135
|
+
creds = await loginRunner();
|
|
136
|
+
}
|
|
137
|
+
catch (err) {
|
|
138
|
+
console.error('');
|
|
139
|
+
console.error(` ✗ Login failed: ${err.message}`);
|
|
140
|
+
process.exitCode = 1;
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
36
143
|
}
|
|
37
144
|
const display = creds.user?.email ?? creds.user?.sub ?? 'unknown';
|
|
38
145
|
console.log('');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"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"}
|
package/dist/commands/logout.js
CHANGED
|
@@ -1,25 +1,72 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
6
|
exports.logoutCommand = logoutCommand;
|
|
7
|
+
const open_1 = __importDefault(require("open"));
|
|
4
8
|
const config_1 = require("../lib/config");
|
|
9
|
+
const oidc_1 = require("../lib/oidc");
|
|
5
10
|
/**
|
|
6
|
-
* `ritual logout` — clears local credentials.
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
11
|
+
* `ritual logout` — clears local credentials. With `--all`, also
|
|
12
|
+
* opens the Keycloak browser logout endpoint to drop the IdP's SSO
|
|
13
|
+
* cookie (so the next sign-in won't silently auto-re-sign-you-in).
|
|
14
|
+
*
|
|
15
|
+
* Why no `--all` by default: the local-only case is the fast, common
|
|
16
|
+
* one. Most users want "this CLI forgets me"; few want the more
|
|
17
|
+
* heavyweight "this CLI forgets me AND my browser session ends."
|
|
10
18
|
*/
|
|
11
|
-
async function logoutCommand() {
|
|
19
|
+
async function logoutCommand(options = {}) {
|
|
12
20
|
const had = (0, config_1.loadCredentials)();
|
|
21
|
+
const display = had?.user?.email ?? had?.user?.sub ?? 'unknown';
|
|
13
22
|
(0, config_1.clearCredentials)();
|
|
14
23
|
console.log('');
|
|
15
24
|
if (had) {
|
|
16
|
-
|
|
17
|
-
console.log(` ✓ Signed out (${display}).`);
|
|
25
|
+
console.log(` ✓ Local credentials cleared (${display}).`);
|
|
18
26
|
}
|
|
19
27
|
else {
|
|
20
|
-
console.log(' No active session — nothing to clear.');
|
|
28
|
+
console.log(' No active session — nothing to clear locally.');
|
|
21
29
|
}
|
|
22
30
|
console.log(` Credentials path: ${(0, config_1.getCredentialsPath)()}`);
|
|
31
|
+
if (options.all) {
|
|
32
|
+
if (!had) {
|
|
33
|
+
// Nothing to logout from on the IdP side either — no
|
|
34
|
+
// active session means no useful logout URL.
|
|
35
|
+
console.log('');
|
|
36
|
+
console.log(' No active browser SSO session to end (no local creds found).');
|
|
37
|
+
console.log('');
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
// Build a logout URL with id_token_hint (recommended by OIDC
|
|
41
|
+
// RP-Initiated Logout 1.0 §2) and client_id. We intentionally
|
|
42
|
+
// do NOT set post_logout_redirect_uri — Keycloak requires
|
|
43
|
+
// pre-registration of those URIs on the client, and we don't
|
|
44
|
+
// want to couple this CLI feature to the realm-import path.
|
|
45
|
+
// Users land on Keycloak's default post-logout page, which
|
|
46
|
+
// reads "you have been logged out" — fine for our purposes.
|
|
47
|
+
const url = (0, oidc_1.buildLogoutUrl)({
|
|
48
|
+
issuer: had.issuer,
|
|
49
|
+
clientId: had.clientId,
|
|
50
|
+
idToken: had.tokenSet.id_token,
|
|
51
|
+
});
|
|
52
|
+
console.log('');
|
|
53
|
+
console.log(' Opening browser to end Keycloak SSO session…');
|
|
54
|
+
console.log(` If the browser doesn\'t open, visit:`);
|
|
55
|
+
console.log(` ${url}`);
|
|
56
|
+
try {
|
|
57
|
+
await (0, open_1.default)(url);
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
// Best-effort; the user can still paste the URL manually.
|
|
61
|
+
}
|
|
62
|
+
console.log('');
|
|
63
|
+
console.log(' ✓ Browser SSO logout requested.');
|
|
64
|
+
console.log('');
|
|
65
|
+
console.log(' Note: this does NOT revoke any of the following — manage them separately:');
|
|
66
|
+
console.log(' • Personal Access Tokens minted by `ritual init` (revoke via /settings/tokens)');
|
|
67
|
+
console.log(' • MCP server entries in your AI coding agents (edit each agent\'s mcp.json)');
|
|
68
|
+
console.log(' • Server-side refresh tokens (handled by Keycloak realm policy)');
|
|
69
|
+
}
|
|
23
70
|
console.log('');
|
|
24
71
|
}
|
|
25
72
|
//# sourceMappingURL=logout.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logout.js","sourceRoot":"","sources":["../../src/commands/logout.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"logout.js","sourceRoot":"","sources":["../../src/commands/logout.ts"],"names":[],"mappings":";;;;;AA6BA,sCAwDC;AArFD,gDAAwB;AACxB,0CAAsF;AACtF,sCAA6C;AAkB7C;;;;;;;;GAQG;AACI,KAAK,UAAU,aAAa,CAAC,UAAyB,EAAE;IAC9D,MAAM,GAAG,GAAG,IAAA,wBAAe,GAAE,CAAC;IAC9B,MAAM,OAAO,GAAG,GAAG,EAAE,IAAI,EAAE,KAAK,IAAI,GAAG,EAAE,IAAI,EAAE,GAAG,IAAI,SAAS,CAAC;IAEhE,IAAA,yBAAgB,GAAE,CAAC;IAEnB,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChB,IAAI,GAAG,EAAE,CAAC;QACT,OAAO,CAAC,GAAG,CAAC,kCAAkC,OAAO,IAAI,CAAC,CAAC;IAC5D,CAAC;SAAM,CAAC;QACP,OAAO,CAAC,GAAG,CAAC,iDAAiD,CAAC,CAAC;IAChE,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,uBAAuB,IAAA,2BAAkB,GAAE,EAAE,CAAC,CAAC;IAE3D,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;QACjB,IAAI,CAAC,GAAG,EAAE,CAAC;YACV,qDAAqD;YACrD,6CAA6C;YAC7C,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YAChB,OAAO,CAAC,GAAG,CAAC,gEAAgE,CAAC,CAAC;YAC9E,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YAChB,OAAO;QACR,CAAC;QAED,6DAA6D;QAC7D,8DAA8D;QAC9D,0DAA0D;QAC1D,6DAA6D;QAC7D,4DAA4D;QAC5D,2DAA2D;QAC3D,4DAA4D;QAC5D,MAAM,GAAG,GAAG,IAAA,qBAAc,EAAC;YAC1B,MAAM,EAAE,GAAG,CAAC,MAAM;YAClB,QAAQ,EAAE,GAAG,CAAC,QAAQ;YACtB,OAAO,EAAE,GAAG,CAAC,QAAQ,CAAC,QAAQ;SAC9B,CAAC,CAAC;QAEH,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAChB,OAAO,CAAC,GAAG,CAAC,gDAAgD,CAAC,CAAC;QAC9D,OAAO,CAAC,GAAG,CAAC,wCAAwC,CAAC,CAAC;QACtD,OAAO,CAAC,GAAG,CAAC,OAAO,GAAG,EAAE,CAAC,CAAC;QAC1B,IAAI,CAAC;YACJ,MAAM,IAAA,cAAI,EAAC,GAAG,CAAC,CAAC;QACjB,CAAC;QAAC,MAAM,CAAC;YACR,0DAA0D;QAC3D,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAChB,OAAO,CAAC,GAAG,CAAC,mCAAmC,CAAC,CAAC;QACjD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAChB,OAAO,CAAC,GAAG,CAAC,6EAA6E,CAAC,CAAC;QAC3F,OAAO,CAAC,GAAG,CAAC,oFAAoF,CAAC,CAAC;QAClG,OAAO,CAAC,GAAG,CAAC,iFAAiF,CAAC,CAAC;QAC/F,OAAO,CAAC,GAAG,CAAC,qEAAqE,CAAC,CAAC;IACpF,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;AACjB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -9,12 +9,13 @@ const refresh_1 = require("./commands/refresh");
|
|
|
9
9
|
const init_1 = require("./commands/init");
|
|
10
10
|
const doctor_1 = require("./commands/doctor");
|
|
11
11
|
const graph_1 = require("./commands/graph");
|
|
12
|
+
const package_info_1 = require("./lib/package-info");
|
|
12
13
|
const program = new commander_1.Command();
|
|
13
14
|
program
|
|
14
15
|
.name('ritual')
|
|
15
16
|
.description('Ritual CLI — connect AI coding agents to Ritual Cloud. ' +
|
|
16
17
|
'Scaffold skills, register MCP servers, manage sessions.')
|
|
17
|
-
.version(
|
|
18
|
+
.version((0, package_info_1.readPackageVersionSafe)());
|
|
18
19
|
// `init` is the headline command: scaffold + register against every
|
|
19
20
|
// detected agent. Listed first so `ritual --help` surfaces it.
|
|
20
21
|
program
|
|
@@ -26,6 +27,8 @@ program
|
|
|
26
27
|
.option('--client-id <id>', 'OIDC client id (defaults to "ritual-cli")')
|
|
27
28
|
.option('--dev', '[internal] shortcut for --issuer https://auth.dev.ritualapp.cloud/realms/ritual')
|
|
28
29
|
.option('--no-workspace', 'Skip the "create a workspace for this repo?" prompt. Useful for CI or when you want to bind a workspace by hand later.')
|
|
30
|
+
.option('--switch-account', 'Force a fresh sign-in even if you already have valid local credentials. Uses OIDC prompt=login so Keycloak ignores its SSO cookie. Atomic — your previous session is restored if anything fails.')
|
|
31
|
+
.option('--yes', 'Skip interactive confirmation prompts (required for --switch-account in non-TTY mode).')
|
|
29
32
|
.action(init_1.initCommand);
|
|
30
33
|
program
|
|
31
34
|
.command('login')
|
|
@@ -33,10 +36,13 @@ program
|
|
|
33
36
|
.option('--issuer <url>', 'OIDC issuer (defaults to https://auth.ritualapp.cloud/realms/ritual or RITUAL_KEYCLOAK_URL env)')
|
|
34
37
|
.option('--client-id <id>', 'OIDC client id (defaults to "ritual-cli" or RITUAL_KEYCLOAK_CLIENT_ID env)')
|
|
35
38
|
.option('--dev', '[internal] shortcut for --issuer https://auth.dev.ritualapp.cloud/realms/ritual')
|
|
39
|
+
.option('--switch-account', 'Force a fresh sign-in even if you already have valid local credentials. Uses OIDC prompt=login so Keycloak ignores its SSO cookie.')
|
|
40
|
+
.option('--yes', 'Skip interactive confirmation prompts (required for --switch-account in non-TTY mode).')
|
|
36
41
|
.action(login_1.loginCommand);
|
|
37
42
|
program
|
|
38
43
|
.command('logout')
|
|
39
|
-
.description('Clear local credentials')
|
|
44
|
+
.description('Clear local credentials. With --all, also end the Keycloak browser SSO session.')
|
|
45
|
+
.option('--all', 'Also open the browser to end your Keycloak SSO session (so the next sign-in shows the form instead of auto-re-using your previous account).')
|
|
40
46
|
.action(logout_1.logoutCommand);
|
|
41
47
|
program
|
|
42
48
|
.command('whoami')
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAEA,yCAAoC;AACpC,4CAAgD;AAChD,8CAAkD;AAClD,8CAAkD;AAClD,gDAAoD;AACpD,0CAA8C;AAC9C,8CAAkD;AAClD,4CAAsD;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAEA,yCAAoC;AACpC,4CAAgD;AAChD,8CAAkD;AAClD,8CAAkD;AAClD,gDAAoD;AACpD,0CAA8C;AAC9C,8CAAkD;AAClD,4CAAsD;AACtD,qDAA4D;AAE5D,MAAM,OAAO,GAAG,IAAI,mBAAO,EAAE,CAAC;AAE9B,OAAO;KACL,IAAI,CAAC,QAAQ,CAAC;KACd,WAAW,CACX,yDAAyD;IACxD,yDAAyD,CAC1D;KACA,OAAO,CAAC,IAAA,qCAAsB,GAAE,CAAC,CAAC;AAEpC,oEAAoE;AACpE,+DAA+D;AAC/D,OAAO;KACL,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,kFAAkF,CAAC;KAC/F,MAAM,CAAC,cAAc,EAAE,wDAAwD,CAAC;KAChF,MAAM,CAAC,QAAQ,EAAE,4BAA4B,CAAC;KAC9C,MAAM,CACN,gBAAgB,EAChB,kFAAkF,CAClF;KACA,MAAM,CAAC,kBAAkB,EAAE,2CAA2C,CAAC;KACvE,MAAM,CAAC,OAAO,EAAE,iFAAiF,CAAC;KAClG,MAAM,CACN,gBAAgB,EAChB,wHAAwH,CACxH;KACA,MAAM,CACN,kBAAkB,EAClB,kMAAkM,CAClM;KACA,MAAM,CACN,OAAO,EACP,wFAAwF,CACxF;KACA,MAAM,CAAC,kBAAW,CAAC,CAAC;AAEtB,OAAO;KACL,OAAO,CAAC,OAAO,CAAC;KAChB,WAAW,CAAC,2CAA2C,CAAC;KACxD,MAAM,CACN,gBAAgB,EAChB,iGAAiG,CACjG;KACA,MAAM,CACN,kBAAkB,EAClB,4EAA4E,CAC5E;KACA,MAAM,CAAC,OAAO,EAAE,iFAAiF,CAAC;KAClG,MAAM,CACN,kBAAkB,EAClB,oIAAoI,CACpI;KACA,MAAM,CACN,OAAO,EACP,wFAAwF,CACxF;KACA,MAAM,CAAC,oBAAY,CAAC,CAAC;AAEvB,OAAO;KACL,OAAO,CAAC,QAAQ,CAAC;KACjB,WAAW,CAAC,iFAAiF,CAAC;KAC9F,MAAM,CACN,OAAO,EACP,6IAA6I,CAC7I;KACA,MAAM,CAAC,sBAAa,CAAC,CAAC;AAExB,OAAO;KACL,OAAO,CAAC,QAAQ,CAAC;KACjB,WAAW,CAAC,6DAA6D,CAAC;KAC1E,MAAM,CAAC,sBAAa,CAAC,CAAC;AAExB,OAAO;KACL,OAAO,CAAC,SAAS,CAAC;KAClB,WAAW,CAAC,sEAAsE,CAAC;KACnF,MAAM,CAAC,wBAAc,CAAC,CAAC;AAEzB,OAAO;KACL,OAAO,CAAC,QAAQ,CAAC;KACjB,WAAW,CAAC,2EAA2E,CAAC;KACxF,MAAM,CAAC,sBAAa,CAAC,CAAC;AAExB,iEAAiE;AACjE,+DAA+D;AAC/D,kDAAkD;AAClD,MAAM,KAAK,GAAG,OAAO;KACnB,OAAO,CAAC,OAAO,CAAC;KAChB,WAAW,CAAC,oEAAoE,CAAC,CAAC;AAEpF,KAAK;KACH,OAAO,CAAC,QAAQ,CAAC;KACjB,WAAW,CAAC,mEAAmE,CAAC;KAChF,MAAM,CACN,kBAAkB,EAClB,0FAA0F,CAC1F;KACA,MAAM,CAAC,aAAa,EAAE,8DAA8D,CAAC;KACrF,MAAM,CAAC,0BAAkB,CAAC,CAAC;AAE7B,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,GAAU,EAAE,EAAE;IACrD,OAAO,CAAC,KAAK,CAAC,SAAS,GAAG,CAAC,OAAO,IAAI,CAAC,CAAC;IACxC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACjB,CAAC,CAAC,CAAC"}
|
|
@@ -49,7 +49,14 @@ exports.PROVIDERS = [
|
|
|
49
49
|
{
|
|
50
50
|
name: 'Cursor',
|
|
51
51
|
id: 'cursor',
|
|
52
|
-
|
|
52
|
+
// Tightened 2026-05-13: `~/.cursor` exists as soon as a user
|
|
53
|
+
// downloads Cursor; that's not strong enough evidence the IDE
|
|
54
|
+
// is actually in use. Require either an extensions dir, the
|
|
55
|
+
// settings file, or an existing MCP config — all of which only
|
|
56
|
+
// appear after Cursor has been launched at least once.
|
|
57
|
+
detect: () => (0, node_fs_1.existsSync)((0, node_path_1.join)((0, node_os_1.homedir)(), '.cursor', 'extensions')) ||
|
|
58
|
+
(0, node_fs_1.existsSync)((0, node_path_1.join)((0, node_os_1.homedir)(), '.cursor', 'settings.json')) ||
|
|
59
|
+
(0, node_fs_1.existsSync)((0, node_path_1.join)((0, node_os_1.homedir)(), '.cursor', 'mcp.json')),
|
|
53
60
|
projectSkillDir: '.cursor/rules',
|
|
54
61
|
packageSkillDir: 'skills/cursor',
|
|
55
62
|
mcpConfigMethod: 'json-file',
|
|
@@ -58,8 +65,12 @@ exports.PROVIDERS = [
|
|
|
58
65
|
{
|
|
59
66
|
name: 'Windsurf',
|
|
60
67
|
id: 'windsurf',
|
|
61
|
-
//
|
|
62
|
-
|
|
68
|
+
// Tightened 2026-05-13: `~/.codeium` is created by the Codeium
|
|
69
|
+
// VS Code/JetBrains extension too — most dev machines that have
|
|
70
|
+
// ever installed Codeium autocomplete have it, even if they
|
|
71
|
+
// never installed Windsurf the IDE. The `windsurf` subdir is
|
|
72
|
+
// specifically created by Windsurf itself.
|
|
73
|
+
detect: () => (0, node_fs_1.existsSync)((0, node_path_1.join)((0, node_os_1.homedir)(), '.codeium', 'windsurf')),
|
|
63
74
|
projectSkillDir: '.windsurf/rules',
|
|
64
75
|
// Windsurf accepts the same rules format Cursor does, so we ship
|
|
65
76
|
// the same bundle.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"providers.js","sourceRoot":"","sources":["../../../src/lib/agents/providers.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"providers.js","sourceRoot":"","sources":["../../../src/lib/agents/providers.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/auth-flow.js
CHANGED
|
@@ -39,7 +39,7 @@ async function runBrowserLoginAndSave(opts = {}) {
|
|
|
39
39
|
const issuer = opts.issuer ?? exports.DEFAULT_ISSUER;
|
|
40
40
|
const clientId = opts.clientId ?? exports.DEFAULT_CLIENT_ID;
|
|
41
41
|
const onMessage = opts.onMessage ?? ((msg) => console.log(` ${msg}`));
|
|
42
|
-
const tokenSet = await (0, oidc_1.performLoginFlow)({ issuer, clientId, scope: exports.DEFAULT_SCOPE }, (url) => (0, open_1.default)(url), onMessage);
|
|
42
|
+
const tokenSet = await (0, oidc_1.performLoginFlow)({ issuer, clientId, scope: exports.DEFAULT_SCOPE, forceLogin: opts.forceLogin }, (url) => (0, open_1.default)(url), onMessage);
|
|
43
43
|
const claims = (0, oidc_1.decodeJwtPayloadUnsafe)(tokenSet.access_token);
|
|
44
44
|
const creds = {
|
|
45
45
|
version: 1,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth-flow.js","sourceRoot":"","sources":["../../src/lib/auth-flow.ts"],"names":[],"mappings":";;;;;;
|
|
1
|
+
{"version":3,"file":"auth-flow.js","sourceRoot":"","sources":["../../src/lib/auth-flow.ts"],"names":[],"mappings":";;;;;;AAqDA,wDAoCC;AAzFD,gDAAwB;AACxB,iCAAkE;AAClE,qCAAgE;AAEhE;;;;;;;;;GASG;AAEU,QAAA,cAAc,GAC1B,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,4CAA4C,CAAC;AACpE,QAAA,iBAAiB,GAAG,OAAO,CAAC,GAAG,CAAC,yBAAyB,IAAI,YAAY,CAAC;AAC1E,QAAA,aAAa,GAAG,+CAA+C,CAAC;AAqB7E;;;;;;;;;;;;;GAaG;AACI,KAAK,UAAU,sBAAsB,CAC3C,OAA4B,EAAE;IAE9B,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,sBAAc,CAAC;IAC7C,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,yBAAiB,CAAC;IACpD,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,IAAI,CAAC,CAAC,GAAW,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,GAAG,EAAE,CAAC,CAAC,CAAC;IAE/E,MAAM,QAAQ,GAAG,MAAM,IAAA,uBAAgB,EACtC,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,qBAAa,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,EACvE,CAAC,GAAG,EAAE,EAAE,CAAC,IAAA,cAAI,EAAC,GAAG,CAAC,EAClB,SAAS,CACT,CAAC;IAEF,MAAM,MAAM,GAAG,IAAA,6BAAsB,EAIlC,QAAQ,CAAC,YAAY,CAAC,CAAC;IAE1B,MAAM,KAAK,GAAmB;QAC7B,OAAO,EAAE,CAAC;QACV,MAAM;QACN,QAAQ;QACR,QAAQ,EAAE;YACT,YAAY,EAAE,QAAQ,CAAC,YAAY;YACnC,aAAa,EAAE,QAAQ,CAAC,aAAa;YACrC,UAAU,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,QAAQ,CAAC,UAAU;YAC/D,QAAQ,EAAE,QAAQ,CAAC,QAAQ;YAC3B,KAAK,EAAE,QAAQ,CAAC,KAAK;SACrB;QACD,IAAI,EAAE,MAAM;YACX,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,kBAAkB,EAAE;YACvE,CAAC,CAAC,SAAS;KACZ,CAAC;IACF,IAAA,wBAAe,EAAC,KAAK,CAAC,CAAC;IACvB,OAAO,KAAK,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Tiny ANSI color helper. Zero dependencies — we hand-roll the
|
|
4
|
+
* escape codes so the CLI install footprint stays minimal.
|
|
5
|
+
*
|
|
6
|
+
* Capabilities:
|
|
7
|
+
*
|
|
8
|
+
* - **Truecolor (24-bit)** when the terminal advertises it
|
|
9
|
+
* (`COLORTERM=truecolor|24bit`) — used to render Ritual's exact
|
|
10
|
+
* brand teal `#1FAF9F` faithfully.
|
|
11
|
+
* - **256-color (8-bit) fallback** for terminals that only
|
|
12
|
+
* advertise 256 colors — quantized to the nearest 256-color slot
|
|
13
|
+
* so brand identity survives.
|
|
14
|
+
* - **No color at all** when the user has set `NO_COLOR` (see
|
|
15
|
+
* <https://no-color.org/>), is piping output to a non-TTY, or is
|
|
16
|
+
* on a terminal that doesn't claim color support.
|
|
17
|
+
*
|
|
18
|
+
* Detection precedence (highest to lowest):
|
|
19
|
+
*
|
|
20
|
+
* 1. `process.env.NO_COLOR` set → strip all color
|
|
21
|
+
* 2. Not a TTY (`!process.stdout.isTTY`) → strip all color
|
|
22
|
+
* 3. `process.env.FORCE_COLOR=1|2|3` → force on (debug, screenshots)
|
|
23
|
+
* 4. `process.env.COLORTERM=truecolor|24bit` → 24-bit
|
|
24
|
+
* 5. `process.env.TERM` includes `256color` → 8-bit
|
|
25
|
+
* 6. Anything else → 4-bit (16 colors) basic ANSI
|
|
26
|
+
*/
|
|
27
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
28
|
+
exports.RITUAL_TEAL = exports.DIM = exports.BOLD = exports.RESET = void 0;
|
|
29
|
+
exports.detectColorMode = detectColorMode;
|
|
30
|
+
exports.fg = fg;
|
|
31
|
+
exports.color = color;
|
|
32
|
+
exports.boldColor = boldColor;
|
|
33
|
+
exports.dim = dim;
|
|
34
|
+
/**
|
|
35
|
+
* Detect the highest color tier we can use on this terminal. Cached
|
|
36
|
+
* after first call since env vars don't change mid-process for
|
|
37
|
+
* practical terminal sessions. Re-exported as a function (not a
|
|
38
|
+
* constant) so tests can `jest.resetModules()` and re-detect.
|
|
39
|
+
*/
|
|
40
|
+
function detectColorMode() {
|
|
41
|
+
if (process.env.NO_COLOR !== undefined)
|
|
42
|
+
return 'none';
|
|
43
|
+
if (!process.stdout.isTTY && process.env.FORCE_COLOR === undefined)
|
|
44
|
+
return 'none';
|
|
45
|
+
if (process.env.FORCE_COLOR === '3')
|
|
46
|
+
return 'truecolor';
|
|
47
|
+
const colorterm = (process.env.COLORTERM ?? '').toLowerCase();
|
|
48
|
+
if (colorterm === 'truecolor' || colorterm === '24bit')
|
|
49
|
+
return 'truecolor';
|
|
50
|
+
const term = (process.env.TERM ?? '').toLowerCase();
|
|
51
|
+
if (term.includes('256color'))
|
|
52
|
+
return 'ansi256';
|
|
53
|
+
if (term && term !== 'dumb')
|
|
54
|
+
return 'ansi16';
|
|
55
|
+
return process.env.FORCE_COLOR !== undefined ? 'ansi16' : 'none';
|
|
56
|
+
}
|
|
57
|
+
/** Reset all formatting. */
|
|
58
|
+
exports.RESET = '\x1b[0m';
|
|
59
|
+
/** Bold. */
|
|
60
|
+
exports.BOLD = '\x1b[1m';
|
|
61
|
+
/** Dim. Used for secondary text in the welcome box. */
|
|
62
|
+
exports.DIM = '\x1b[2m';
|
|
63
|
+
/**
|
|
64
|
+
* Build a foreground-color escape sequence for the given RGB triple,
|
|
65
|
+
* downgraded according to the terminal's color tier.
|
|
66
|
+
*
|
|
67
|
+
* - `truecolor` → `\x1b[38;2;R;G;Bm`
|
|
68
|
+
* - `ansi256` → `\x1b[38;5;Nm` (quantized to nearest 256-color slot)
|
|
69
|
+
* - `ansi16` → `\x1b[36m` (nearest base color — for teal/cyan we
|
|
70
|
+
* pick cyan; same for any cool color)
|
|
71
|
+
* - `none` → empty string
|
|
72
|
+
*/
|
|
73
|
+
function fg(rgb, mode = detectColorMode()) {
|
|
74
|
+
if (mode === 'none')
|
|
75
|
+
return '';
|
|
76
|
+
if (mode === 'truecolor') {
|
|
77
|
+
return `\x1b[38;2;${rgb[0]};${rgb[1]};${rgb[2]}m`;
|
|
78
|
+
}
|
|
79
|
+
if (mode === 'ansi256') {
|
|
80
|
+
return `\x1b[38;5;${rgbToAnsi256(rgb)}m`;
|
|
81
|
+
}
|
|
82
|
+
// ansi16: pick the closest of the 16 base colors. We classify by
|
|
83
|
+
// hue rather than by Euclidean distance — for brand teal that
|
|
84
|
+
// means "cyan-ish" not "green-ish."
|
|
85
|
+
return `\x1b[${rgbToBase16Fg(rgb)}m`;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Convenience: Ritual brand teal. Pulled from the canonical SVG icon
|
|
89
|
+
* at `apps/cli/assets/...` (`fill="#1FAF9F"`). One place to change
|
|
90
|
+
* if the brand ever shifts.
|
|
91
|
+
*/
|
|
92
|
+
exports.RITUAL_TEAL = [0x1f, 0xaf, 0x9f]; // #1FAF9F
|
|
93
|
+
/**
|
|
94
|
+
* Convenience helper to wrap text in foreground color + reset.
|
|
95
|
+
*
|
|
96
|
+
* color(RITUAL_TEAL, 'Hello') → '\x1b[38;2;31;175;159mHello\x1b[0m'
|
|
97
|
+
*
|
|
98
|
+
* Safe when color mode is `none` — returns the text untouched (no
|
|
99
|
+
* empty escape sequences in the output).
|
|
100
|
+
*/
|
|
101
|
+
function color(rgb, text) {
|
|
102
|
+
const mode = detectColorMode();
|
|
103
|
+
if (mode === 'none')
|
|
104
|
+
return text;
|
|
105
|
+
return `${fg(rgb, mode)}${text}${exports.RESET}`;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Bold-and-colored variant. Used for the brand wordmark in the
|
|
109
|
+
* welcome box header.
|
|
110
|
+
*/
|
|
111
|
+
function boldColor(rgb, text) {
|
|
112
|
+
const mode = detectColorMode();
|
|
113
|
+
if (mode === 'none')
|
|
114
|
+
return text;
|
|
115
|
+
return `${exports.BOLD}${fg(rgb, mode)}${text}${exports.RESET}`;
|
|
116
|
+
}
|
|
117
|
+
/** Wrap text in dim. Used for secondary info inside the welcome box. */
|
|
118
|
+
function dim(text) {
|
|
119
|
+
const mode = detectColorMode();
|
|
120
|
+
if (mode === 'none')
|
|
121
|
+
return text;
|
|
122
|
+
return `${exports.DIM}${text}${exports.RESET}`;
|
|
123
|
+
}
|
|
124
|
+
// ─── internal: color-space conversions ──────────────────────────────────────
|
|
125
|
+
/**
|
|
126
|
+
* Map an RGB triple to its nearest 256-color (xterm 256) slot.
|
|
127
|
+
*
|
|
128
|
+
* The 256-color palette is structured as:
|
|
129
|
+
* - 0–15: the 16 base ANSI colors (varies by terminal theme)
|
|
130
|
+
* - 16–231: a 6×6×6 RGB cube (each channel ∈ {0,95,135,175,215,255})
|
|
131
|
+
* - 232–255: a 24-step grayscale ramp
|
|
132
|
+
*
|
|
133
|
+
* For brand fidelity we map into the 6×6×6 cube — the base 16 are
|
|
134
|
+
* user-themeable and unreliable for "exact" colors.
|
|
135
|
+
*/
|
|
136
|
+
function rgbToAnsi256(rgb) {
|
|
137
|
+
const cubeAxis = (c) => {
|
|
138
|
+
// 6×6×6 cube quantization: 0, 95, 135, 175, 215, 255.
|
|
139
|
+
if (c < 48)
|
|
140
|
+
return 0;
|
|
141
|
+
if (c < 115)
|
|
142
|
+
return 1;
|
|
143
|
+
return Math.floor((c - 35) / 40);
|
|
144
|
+
};
|
|
145
|
+
const r = cubeAxis(rgb[0]);
|
|
146
|
+
const g = cubeAxis(rgb[1]);
|
|
147
|
+
const b = cubeAxis(rgb[2]);
|
|
148
|
+
return 16 + 36 * r + 6 * g + b;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Map an RGB triple to the nearest of the 8 standard ANSI foreground
|
|
152
|
+
* codes (30–37). We extend to bright variants (90–97) when the input
|
|
153
|
+
* is bright enough — `#1FAF9F` is mid-saturation cyan so it lands on
|
|
154
|
+
* 36 (cyan) cleanly.
|
|
155
|
+
*/
|
|
156
|
+
function rgbToBase16Fg(rgb) {
|
|
157
|
+
const [r, g, b] = rgb;
|
|
158
|
+
const max = Math.max(r, g, b);
|
|
159
|
+
const min = Math.min(r, g, b);
|
|
160
|
+
const bright = max > 170;
|
|
161
|
+
// Grayscale-ish (low saturation): default to white if bright, else neutral.
|
|
162
|
+
if (max - min < 30) {
|
|
163
|
+
return bright ? 97 : 37;
|
|
164
|
+
}
|
|
165
|
+
// Color classification by dominant channel(s):
|
|
166
|
+
// - High green + high blue → cyan
|
|
167
|
+
// - High red + high blue → magenta
|
|
168
|
+
// - High red + high green → yellow
|
|
169
|
+
// - High red → red, high green → green, high blue → blue
|
|
170
|
+
if (g > 80 && b > 80 && g + b > r * 1.5)
|
|
171
|
+
return bright ? 96 : 36; // cyan
|
|
172
|
+
if (r > 80 && b > 80 && r + b > g * 1.5)
|
|
173
|
+
return bright ? 95 : 35; // magenta
|
|
174
|
+
if (r > 80 && g > 80 && r + g > b * 1.5)
|
|
175
|
+
return bright ? 93 : 33; // yellow
|
|
176
|
+
if (r >= g && r >= b)
|
|
177
|
+
return bright ? 91 : 31; // red
|
|
178
|
+
if (g >= r && g >= b)
|
|
179
|
+
return bright ? 92 : 32; // green
|
|
180
|
+
return bright ? 94 : 34; // blue
|
|
181
|
+
}
|
|
182
|
+
//# sourceMappingURL=colors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"colors.js","sourceRoot":"","sources":["../../src/lib/colors.ts"],"names":[],"mappings":"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"}
|