rivet-design 0.11.7 → 0.11.9
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/dist/config/flags.d.ts +3 -0
- package/dist/config/flags.d.ts.map +1 -1
- package/dist/config/flags.js +1 -0
- package/dist/config/flags.js.map +1 -1
- package/dist/index.d.ts +1 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +96 -590
- package/dist/index.js.map +1 -1
- package/dist/install/harnesses.d.ts +82 -0
- package/dist/install/harnesses.d.ts.map +1 -0
- package/dist/install/harnesses.js +537 -0
- package/dist/install/harnesses.js.map +1 -0
- package/dist/mcp/agent-variants/WorktreeOrchestrator.d.ts +25 -0
- package/dist/mcp/agent-variants/WorktreeOrchestrator.d.ts.map +1 -1
- package/dist/mcp/agent-variants/WorktreeOrchestrator.js +121 -0
- package/dist/mcp/agent-variants/WorktreeOrchestrator.js.map +1 -1
- package/dist/mcp/auth/tools.d.ts.map +1 -1
- package/dist/mcp/auth/tools.js +63 -12
- package/dist/mcp/auth/tools.js.map +1 -1
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +2 -7
- package/dist/mcp/server.js.map +1 -1
- package/dist/onboarding/signin.d.ts +31 -0
- package/dist/onboarding/signin.d.ts.map +1 -0
- package/dist/onboarding/signin.js +235 -0
- package/dist/onboarding/signin.js.map +1 -0
- package/dist/routes/agentVariants.d.ts.map +1 -1
- package/dist/routes/agentVariants.js +528 -72
- package/dist/routes/agentVariants.js.map +1 -1
- package/dist/services/PrototypeDeployService.d.ts +2 -0
- package/dist/services/PrototypeDeployService.d.ts.map +1 -1
- package/dist/services/PrototypeDeployService.js +6 -0
- package/dist/services/PrototypeDeployService.js.map +1 -1
- package/dist/services/TelemetryService.d.ts +70 -0
- package/dist/services/TelemetryService.d.ts.map +1 -1
- package/dist/services/TelemetryService.js +85 -0
- package/dist/services/TelemetryService.js.map +1 -1
- package/dist/services/VariantHistoryService.d.ts +18 -0
- package/dist/services/VariantHistoryService.d.ts.map +1 -1
- package/dist/services/VariantHistoryService.js +27 -3
- package/dist/services/VariantHistoryService.js.map +1 -1
- package/package.json +2 -1
- package/src/ui/dist/assets/main-BtohezP4.js +641 -0
- package/src/ui/dist/assets/{main-CtRINpOq.css → main-IY99De7M.css} +1 -1
- package/src/ui/dist/index.html +2 -2
- package/src/ui/dist/assets/main-DM4pFbJk.js +0 -641
package/dist/index.js
CHANGED
|
@@ -36,13 +36,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
36
36
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
37
|
};
|
|
38
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
-
exports.
|
|
39
|
+
exports.parseArgs = exports.main = exports.registerOwnedDevServerSignalHandlers = exports.registerAgentSignalHandlers = exports.isAgentVariantsEnabled = exports.updateOwnedDevServerHealthOnExit = exports.buildAgentDevServerHealth = exports.resolveAgentDevServer = exports.buildAgentDevServerContext = exports.DEFAULT_USER_PORT = exports.DEFAULT_PORT = exports.buildCursorLocalRivetEntry = exports.buildCursorHostedRivetEntry = void 0;
|
|
40
40
|
/* eslint-disable no-console */
|
|
41
|
-
const child_process_1 = require("child_process");
|
|
42
41
|
const dotenv = __importStar(require("dotenv"));
|
|
43
42
|
const fs_1 = __importDefault(require("fs"));
|
|
44
43
|
const open_1 = __importDefault(require("open"));
|
|
45
|
-
const os_1 = __importDefault(require("os"));
|
|
46
44
|
const path_1 = __importDefault(require("path"));
|
|
47
45
|
const index_core_1 = require("./index-core");
|
|
48
46
|
const server_1 = require("./server");
|
|
@@ -53,7 +51,12 @@ const ConfigManager_1 = require("./services/ConfigManager");
|
|
|
53
51
|
const SessionBridgeService_1 = require("./services/SessionBridgeService");
|
|
54
52
|
const DevServerRuntimeService_1 = require("./services/DevServerRuntimeService");
|
|
55
53
|
const TelemetryService_1 = require("./services/TelemetryService");
|
|
56
|
-
const
|
|
54
|
+
const harnesses_1 = require("./install/harnesses");
|
|
55
|
+
const signin_1 = require("./onboarding/signin");
|
|
56
|
+
// Re-exported for back-compat with existing tests that import them from here.
|
|
57
|
+
var harnesses_2 = require("./install/harnesses");
|
|
58
|
+
Object.defineProperty(exports, "buildCursorHostedRivetEntry", { enumerable: true, get: function () { return harnesses_2.buildCursorHostedRivetEntry; } });
|
|
59
|
+
Object.defineProperty(exports, "buildCursorLocalRivetEntry", { enumerable: true, get: function () { return harnesses_2.buildCursorLocalRivetEntry; } });
|
|
57
60
|
const portUtils_1 = require("./utils/portUtils");
|
|
58
61
|
const VariantsRuntime_1 = require("./services/VariantsRuntime");
|
|
59
62
|
const VisualVariantAgentRunner_1 = require("./services/VisualVariantAgentRunner");
|
|
@@ -315,6 +318,13 @@ const main = async (args = process.argv.slice(2)) => {
|
|
|
315
318
|
await handleInstall(args[1]);
|
|
316
319
|
return;
|
|
317
320
|
}
|
|
321
|
+
if (command === 'signin' || command === 'sign-in') {
|
|
322
|
+
const result = await (0, signin_1.runSignIn)({
|
|
323
|
+
noBrowser: args.includes('--no-browser'),
|
|
324
|
+
nextStepHint: "You're all set — open your agent and say \"Open Rivet\".",
|
|
325
|
+
});
|
|
326
|
+
process.exit(result.ok ? 0 : 1);
|
|
327
|
+
}
|
|
318
328
|
if (command === 'update') {
|
|
319
329
|
await handleUpdate();
|
|
320
330
|
return;
|
|
@@ -518,22 +528,32 @@ const main = async (args = process.argv.slice(2)) => {
|
|
|
518
528
|
console.log('\n❌ E2E auth required: set RIVET_E2E_EMAIL and RIVET_E2E_PASSWORD (or RIVET_TEST_EMAIL and RIVET_TEST_PASSWORD) in repo secrets. Must be e2etest@gmail.com.');
|
|
519
529
|
process.exit(1);
|
|
520
530
|
}
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
+
if (options.noBrowser) {
|
|
532
|
+
// Headless: can't show the in-browser sign-in page, so fall back to
|
|
533
|
+
// the terminal OAuth flow.
|
|
534
|
+
console.log('\n🔐 Authentication required');
|
|
535
|
+
console.log('Opening browser for Google login...\n');
|
|
536
|
+
const authService = new AuthService_1.AuthService();
|
|
537
|
+
const oauthRedirectOrigin = useLocalhostRivetUiRootEntrypoint
|
|
538
|
+
? `http://localhost:${rivetPort}`
|
|
539
|
+
: `http://localhost:${rivetPort}/rivet`;
|
|
540
|
+
const loginResult = await authService.loginWithGoogle(oauthRedirectOrigin);
|
|
541
|
+
if (!loginResult.success) {
|
|
542
|
+
console.log(`\n❌ Authentication failed: ${loginResult.error || loginResult.message}`);
|
|
543
|
+
process.exit(1);
|
|
544
|
+
}
|
|
545
|
+
console.log(`\n✅ Authenticated as ${loginResult.user?.email}`);
|
|
546
|
+
if (loginResult.profile) {
|
|
547
|
+
console.log(`💰 Balance: $${loginResult.profile.remaining_spend_usd.toFixed(2)}`);
|
|
548
|
+
}
|
|
549
|
+
didAuthenticate = true;
|
|
531
550
|
}
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
551
|
+
else {
|
|
552
|
+
// Interactive: the Rivet UI we open below renders its sign-in screen
|
|
553
|
+
// for unauthenticated users. They sign in there and the editor
|
|
554
|
+
// unlocks live — no need to jump straight to Google from the terminal.
|
|
555
|
+
console.log('\n🔐 Sign in to Rivet in the browser window that opens next.');
|
|
535
556
|
}
|
|
536
|
-
didAuthenticate = true;
|
|
537
557
|
}
|
|
538
558
|
}
|
|
539
559
|
// Open browser to Rivet UI (only if we didn't just authenticate, since OAuth already opened it)
|
|
@@ -876,14 +896,12 @@ USAGE:
|
|
|
876
896
|
COMMANDS:
|
|
877
897
|
rivet Start Rivet (auto-login if needed)
|
|
878
898
|
rivet agent Start Rivet with a terminal AI agent applying visual changes
|
|
879
|
-
rivet install
|
|
880
|
-
rivet install cursor Set up Rivet for
|
|
881
|
-
rivet
|
|
882
|
-
rivet uninstall claude Remove Rivet from Claude Code
|
|
883
|
-
rivet uninstall cursor Remove Rivet from Cursor
|
|
884
|
-
rivet uninstall codex Remove Rivet from OpenAI Codex CLI
|
|
899
|
+
rivet install Set up Rivet for every detected agent (Claude Code, Cursor, Codex, …)
|
|
900
|
+
rivet install cursor Set up Rivet for a specific agent only
|
|
901
|
+
rivet uninstall <name> Remove Rivet from one agent (claude|claude-desktop|cursor|codex)
|
|
885
902
|
rivet uninstall all Remove Rivet from all editors
|
|
886
903
|
rivet update Update Rivet MCP server for all installed editors
|
|
904
|
+
rivet signin Sign in or create a Rivet account in your browser
|
|
887
905
|
rivet login Login with Google
|
|
888
906
|
rivet logout Logout from Rivet
|
|
889
907
|
|
|
@@ -922,9 +940,8 @@ EXAMPLES:
|
|
|
922
940
|
rivet --rivet-port 4000 # Use port 4000 for Rivet (fails if in use)
|
|
923
941
|
rivet --framework static # Serve static HTML from ./index.html
|
|
924
942
|
rivet --framework static --entry dist/ # Serve static files from ./dist/ directory
|
|
925
|
-
rivet install
|
|
926
|
-
rivet install cursor # Configure Rivet for Cursor
|
|
927
|
-
rivet install codex # Configure Rivet for OpenAI Codex CLI
|
|
943
|
+
rivet install # Configure Rivet for every detected agent at once
|
|
944
|
+
rivet install cursor # Configure Rivet for Cursor only
|
|
928
945
|
rivet uninstall cursor # Remove Rivet from Cursor
|
|
929
946
|
rivet uninstall all # Remove Rivet from all editors
|
|
930
947
|
rivet login # Manually login with Google
|
|
@@ -943,593 +960,82 @@ const showVersion = () => {
|
|
|
943
960
|
log.error('Could not read version from package.json', error);
|
|
944
961
|
}
|
|
945
962
|
};
|
|
946
|
-
const MCP_INSTALL_WELCOME = `
|
|
947
|
-
Welcome to Rivet!
|
|
948
|
-
|
|
949
|
-
Rivet is a visual editor for your coding agent.
|
|
950
|
-
`;
|
|
951
|
-
const RIVET_ASCII_LOGO = `
|
|
952
|
-
|
|
953
|
-
****************************************************************************************************
|
|
954
|
-
****************************************************************************************************
|
|
955
|
-
*******************************+. :****************************************************************
|
|
956
|
-
*******************************: =*************************************:...=*********************
|
|
957
|
-
*******************************+=--=*************************************+. =*********************
|
|
958
|
-
*****************-....... ..:+*-....**:....=*****:....=**:..........-**+.. ....-*****************
|
|
959
|
-
*****************- .... .+*- .***: +***- -*+. :*+. :*****************
|
|
960
|
-
*****************- .+****++**- .****. :**+. :**+ :====: .***+ =*********************
|
|
961
|
-
*****************- .+********- .****+. -+. :***+ .***+ =*********************
|
|
962
|
-
*****************- .+********- .*****+. .: :****+ .++++==--****+ :+++******************
|
|
963
|
-
*****************- .+********- .******+. :******:. .+***. =*****************
|
|
964
|
-
*****************+++++*********+++++*******+++++++********+++++++++++******+++++++******************
|
|
965
|
-
****************************************************************************************************
|
|
966
|
-
****************************************************************************************************
|
|
967
|
-
|
|
968
|
-
`;
|
|
969
|
-
/**
|
|
970
|
-
* Handle install command — configure Rivet as an MCP server for the specified editor
|
|
971
|
-
*/
|
|
972
|
-
const handleInstall = async (editor) => {
|
|
973
|
-
switch (editor) {
|
|
974
|
-
case 'claude':
|
|
975
|
-
console.log(MCP_INSTALL_WELCOME);
|
|
976
|
-
await handleInstallClaude();
|
|
977
|
-
break;
|
|
978
|
-
case 'claude-desktop':
|
|
979
|
-
console.log(MCP_INSTALL_WELCOME);
|
|
980
|
-
await handleInstallClaudeDesktop();
|
|
981
|
-
break;
|
|
982
|
-
case 'cursor':
|
|
983
|
-
console.log(MCP_INSTALL_WELCOME);
|
|
984
|
-
await handleInstallCursor();
|
|
985
|
-
break;
|
|
986
|
-
case 'codex':
|
|
987
|
-
console.log(MCP_INSTALL_WELCOME);
|
|
988
|
-
await handleInstallCodex();
|
|
989
|
-
break;
|
|
990
|
-
default:
|
|
991
|
-
console.log('\nUsage: rivet install <editor>\n');
|
|
992
|
-
console.log(' rivet install claude Set up for Claude Code');
|
|
993
|
-
console.log(' rivet install claude-desktop Set up for the Claude desktop app');
|
|
994
|
-
console.log(' rivet install cursor Set up for Cursor');
|
|
995
|
-
console.log(' rivet install codex Set up for OpenAI Codex CLI');
|
|
996
|
-
console.log('');
|
|
997
|
-
process.exit(editor ? 1 : 0);
|
|
998
|
-
}
|
|
999
|
-
console.log(RIVET_ASCII_LOGO);
|
|
1000
|
-
};
|
|
1001
963
|
/**
|
|
1002
|
-
*
|
|
1003
|
-
*
|
|
964
|
+
* Ask a yes/no question on the terminal. Defaults to yes on a bare Enter.
|
|
965
|
+
* Resolves false immediately if stdin isn't interactive.
|
|
1004
966
|
*/
|
|
1005
|
-
const
|
|
1006
|
-
|
|
1007
|
-
try {
|
|
1008
|
-
const output = (0, child_process_1.execSync)(mcpAddCommand, { stdio: 'pipe', encoding: 'utf8' });
|
|
1009
|
-
process.stdout.write(output);
|
|
1010
|
-
console.log('✓ Rivet MCP server added to Claude Code');
|
|
1011
|
-
return true;
|
|
1012
|
-
}
|
|
1013
|
-
catch (err) {
|
|
1014
|
-
const stderr = err.stderr ?? '';
|
|
1015
|
-
if (stderr.includes('already exists')) {
|
|
1016
|
-
console.log('✓ Rivet MCP server already registered');
|
|
1017
|
-
return true;
|
|
1018
|
-
}
|
|
1019
|
-
process.stderr.write(stderr);
|
|
1020
|
-
console.log('Run manually:', 'claude mcp add --transport stdio --scope user rivet -- npx -y rivet-design@latest mcp --editor claude');
|
|
967
|
+
const promptYesNo = async (question) => {
|
|
968
|
+
if (!process.stdin.isTTY)
|
|
1021
969
|
return false;
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
(0, child_process_1.execSync)('claude --version', { stdio: 'ignore' });
|
|
1028
|
-
}
|
|
1029
|
-
catch {
|
|
1030
|
-
console.log('Claude Code is not installed or not in your PATH.');
|
|
1031
|
-
console.log('Install it: https://claude.ai/download');
|
|
1032
|
-
process.exit(1);
|
|
1033
|
-
}
|
|
1034
|
-
if (!registerClaudeMCP()) {
|
|
1035
|
-
process.exit(1);
|
|
1036
|
-
}
|
|
1037
|
-
const skillResult = (0, skillWriter_1.writeSkillFileIfNeeded)();
|
|
1038
|
-
if (skillResult.success) {
|
|
1039
|
-
console.log('✓ Rivet skill installed');
|
|
1040
|
-
}
|
|
1041
|
-
else {
|
|
1042
|
-
console.log(` Warning: could not write skill file to ${path_1.default.join(os_1.default.homedir(), '.claude', 'skills', 'rivet')}: ${skillResult.error}`);
|
|
1043
|
-
console.log(' Claude Code will still work with Rivet, but may need manual guidance on tool usage.');
|
|
1044
|
-
}
|
|
1045
|
-
console.log(`
|
|
1046
|
-
Next steps:
|
|
1047
|
-
1. Start a new Claude Code session
|
|
1048
|
-
2. Type /rivet or say "Open Rivet"
|
|
1049
|
-
`);
|
|
1050
|
-
};
|
|
1051
|
-
/**
|
|
1052
|
-
* Resolve `npx` to an absolute path using the install-time shell PATH.
|
|
1053
|
-
*
|
|
1054
|
-
* Why: editors like Claude desktop inherit a sanitized PATH at launch that
|
|
1055
|
-
* can put stale node versions (e.g. legacy nvm installs) first, causing
|
|
1056
|
-
* `npx` to dispatch to a node so old it can't even `require('node:url')`.
|
|
1057
|
-
* Writing the absolute path into the MCP config bypasses that lookup so the
|
|
1058
|
-
* editor uses the same `npx` the user has in their interactive shell.
|
|
1059
|
-
*
|
|
1060
|
-
* Falls back to the literal "npx" with a warning if resolution fails — the
|
|
1061
|
-
* prior behavior — so install never hard-blocks on a quirky environment.
|
|
1062
|
-
*/
|
|
1063
|
-
const resolveNpxCommand = () => {
|
|
1064
|
-
const which = process.platform === 'win32' ? 'where' : 'which';
|
|
970
|
+
const readline = await Promise.resolve().then(() => __importStar(require('node:readline/promises')));
|
|
971
|
+
const rl = readline.createInterface({
|
|
972
|
+
input: process.stdin,
|
|
973
|
+
output: process.stdout,
|
|
974
|
+
});
|
|
1065
975
|
try {
|
|
1066
|
-
const
|
|
1067
|
-
|
|
1068
|
-
encoding: 'utf8',
|
|
1069
|
-
});
|
|
1070
|
-
// `where` on Windows can return multiple lines (npx, npx.cmd, npx.ps1).
|
|
1071
|
-
// Prefer .cmd / .exe over a shebanged shell script so Windows can spawn
|
|
1072
|
-
// the resolved path directly.
|
|
1073
|
-
const lines = out
|
|
1074
|
-
.split(/\r?\n/)
|
|
1075
|
-
.map((l) => l.trim())
|
|
1076
|
-
.filter((l) => l.length > 0 && fs_1.default.existsSync(l));
|
|
1077
|
-
if (lines.length === 0) {
|
|
1078
|
-
throw new Error('which returned no usable paths');
|
|
1079
|
-
}
|
|
1080
|
-
if (process.platform === 'win32') {
|
|
1081
|
-
const directlySpawnable = lines.find((l) => /\.(cmd|exe|bat)$/i.test(l));
|
|
1082
|
-
return directlySpawnable ?? lines[0];
|
|
1083
|
-
}
|
|
1084
|
-
return lines[0];
|
|
976
|
+
const answer = (await rl.question(`${question} [Y/n] `)).trim().toLowerCase();
|
|
977
|
+
return answer === '' || answer === 'y' || answer === 'yes';
|
|
1085
978
|
}
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
return 'npx';
|
|
979
|
+
finally {
|
|
980
|
+
rl.close();
|
|
1089
981
|
}
|
|
1090
982
|
};
|
|
1091
|
-
const CURSOR_HOSTED_MCP_URL = 'https://rivet-proxy.onrender.com/mcp';
|
|
1092
|
-
const buildCursorHostedRivetEntry = () => ({
|
|
1093
|
-
url: CURSOR_HOSTED_MCP_URL,
|
|
1094
|
-
});
|
|
1095
|
-
exports.buildCursorHostedRivetEntry = buildCursorHostedRivetEntry;
|
|
1096
|
-
const buildCursorLocalRivetEntry = () => ({
|
|
1097
|
-
command: resolveNpxCommand(),
|
|
1098
|
-
args: ['-y', 'rivet-design@latest', 'mcp', '--editor', 'cursor'],
|
|
1099
|
-
});
|
|
1100
|
-
exports.buildCursorLocalRivetEntry = buildCursorLocalRivetEntry;
|
|
1101
983
|
/**
|
|
1102
|
-
*
|
|
1103
|
-
*
|
|
1104
|
-
*
|
|
1105
|
-
* anyway, but the note explains *why* the entry needed refreshing.
|
|
984
|
+
* After a successful install, nudge the user into Rivet. If they're not signed
|
|
985
|
+
* in yet, offer to open the sign-in page; if they already are, point them at
|
|
986
|
+
* their agent. Stays silent-but-helpful in non-interactive / CI runs.
|
|
1106
987
|
*/
|
|
1107
|
-
const
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
if (typeof cmd !== 'string')
|
|
1112
|
-
return;
|
|
1113
|
-
if (!path_1.default.isAbsolute(cmd))
|
|
988
|
+
const promptPostInstall = async () => {
|
|
989
|
+
// Non-interactive / CI: don't probe auth or prompt — just leave guidance.
|
|
990
|
+
if (!process.stdin.isTTY || process.env.CI === 'true') {
|
|
991
|
+
console.log('\nOne more step: run `rivet login` to sign in (or create an account) and start using Rivet.\n');
|
|
1114
992
|
return;
|
|
1115
|
-
if (fs_1.default.existsSync(cmd))
|
|
1116
|
-
return;
|
|
1117
|
-
console.log(` Note: previous Rivet command for ${editorLabel} (${cmd}) no longer exists. Re-resolving.`);
|
|
1118
|
-
};
|
|
1119
|
-
const handleInstallCursor = async () => {
|
|
1120
|
-
console.log('\nSetting up Rivet for Cursor...\n');
|
|
1121
|
-
const cursorDir = path_1.default.join(os_1.default.homedir(), '.cursor');
|
|
1122
|
-
if (!fs_1.default.existsSync(cursorDir)) {
|
|
1123
|
-
console.log('Cursor does not appear to be installed (~/.cursor not found).');
|
|
1124
|
-
console.log('Install it: https://cursor.com');
|
|
1125
|
-
process.exit(1);
|
|
1126
|
-
}
|
|
1127
|
-
const mcpConfigPath = path_1.default.join(cursorDir, 'mcp.json');
|
|
1128
|
-
const hostedEntry = (0, exports.buildCursorHostedRivetEntry)();
|
|
1129
|
-
const localEntry = (0, exports.buildCursorLocalRivetEntry)();
|
|
1130
|
-
let config = {};
|
|
1131
|
-
if (fs_1.default.existsSync(mcpConfigPath)) {
|
|
1132
|
-
const raw = fs_1.default.readFileSync(mcpConfigPath, 'utf8');
|
|
1133
|
-
try {
|
|
1134
|
-
const parsed = JSON.parse(raw);
|
|
1135
|
-
if (parsed !== null &&
|
|
1136
|
-
typeof parsed === 'object' &&
|
|
1137
|
-
!Array.isArray(parsed)) {
|
|
1138
|
-
config = parsed;
|
|
1139
|
-
}
|
|
1140
|
-
else {
|
|
1141
|
-
console.log(` Error: ${mcpConfigPath} is not a JSON object. Aborting to avoid data loss.`);
|
|
1142
|
-
console.log(` Fix or delete the file manually, then re-run.`);
|
|
1143
|
-
process.exit(1);
|
|
1144
|
-
}
|
|
1145
|
-
}
|
|
1146
|
-
catch {
|
|
1147
|
-
console.log(` Error: could not parse ${mcpConfigPath}. Aborting to avoid data loss.`);
|
|
1148
|
-
console.log(` Fix or delete the file manually, then re-run.`);
|
|
1149
|
-
process.exit(1);
|
|
1150
|
-
}
|
|
1151
|
-
}
|
|
1152
|
-
// Ensure mcpServers is an object, not some other type
|
|
1153
|
-
if (config.mcpServers !== undefined &&
|
|
1154
|
-
(typeof config.mcpServers !== 'object' || Array.isArray(config.mcpServers))) {
|
|
1155
|
-
console.log(` Error: mcpServers in ${mcpConfigPath} is not an object. Aborting to avoid data loss.`);
|
|
1156
|
-
process.exit(1);
|
|
1157
|
-
}
|
|
1158
|
-
config.mcpServers = {
|
|
1159
|
-
...config.mcpServers,
|
|
1160
|
-
rivet: hostedEntry,
|
|
1161
|
-
'rivet-local': localEntry,
|
|
1162
|
-
};
|
|
1163
|
-
fs_1.default.writeFileSync(mcpConfigPath, JSON.stringify(config, null, 2) + '\n', 'utf8');
|
|
1164
|
-
console.log(`✓ Rivet MCP servers added to ${mcpConfigPath}`);
|
|
1165
|
-
console.log(`
|
|
1166
|
-
Next steps:
|
|
1167
|
-
1. Fully restart Cursor
|
|
1168
|
-
2. Open a new chat and say "Open Rivet"
|
|
1169
|
-
`);
|
|
1170
|
-
};
|
|
1171
|
-
const buildClaudeDesktopRivetEntry = () => ({
|
|
1172
|
-
command: resolveNpxCommand(),
|
|
1173
|
-
args: ['-y', 'rivet-design@latest', 'mcp', '--editor', 'claude-desktop'],
|
|
1174
|
-
});
|
|
1175
|
-
/**
|
|
1176
|
-
* Path to the Claude desktop app's MCP config file.
|
|
1177
|
-
* macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
|
|
1178
|
-
* Win: %APPDATA%\Claude\claude_desktop_config.json
|
|
1179
|
-
* Linux: ~/.config/Claude/claude_desktop_config.json (unofficial, but the
|
|
1180
|
-
* freedesktop default if Anthropic ships a Linux build)
|
|
1181
|
-
*/
|
|
1182
|
-
const claudeDesktopConfigPath = () => {
|
|
1183
|
-
const home = os_1.default.homedir();
|
|
1184
|
-
if (process.platform === 'darwin') {
|
|
1185
|
-
return path_1.default.join(home, 'Library', 'Application Support', 'Claude', 'claude_desktop_config.json');
|
|
1186
|
-
}
|
|
1187
|
-
if (process.platform === 'win32') {
|
|
1188
|
-
const appData = process.env.APPDATA ?? path_1.default.join(home, 'AppData', 'Roaming');
|
|
1189
|
-
return path_1.default.join(appData, 'Claude', 'claude_desktop_config.json');
|
|
1190
|
-
}
|
|
1191
|
-
return path_1.default.join(home, '.config', 'Claude', 'claude_desktop_config.json');
|
|
1192
|
-
};
|
|
1193
|
-
const handleInstallClaudeDesktop = async () => {
|
|
1194
|
-
console.log('\nSetting up Rivet for the Claude desktop app...\n');
|
|
1195
|
-
const mcpConfigPath = claudeDesktopConfigPath();
|
|
1196
|
-
const claudeDir = path_1.default.dirname(mcpConfigPath);
|
|
1197
|
-
if (!fs_1.default.existsSync(claudeDir)) {
|
|
1198
|
-
console.log(`Claude desktop does not appear to be installed (${claudeDir} not found).`);
|
|
1199
|
-
console.log('Install it: https://claude.ai/download');
|
|
1200
|
-
process.exit(1);
|
|
1201
|
-
}
|
|
1202
|
-
const rivetEntry = buildClaudeDesktopRivetEntry();
|
|
1203
|
-
let config = {};
|
|
1204
|
-
if (fs_1.default.existsSync(mcpConfigPath)) {
|
|
1205
|
-
const raw = fs_1.default.readFileSync(mcpConfigPath, 'utf8');
|
|
1206
|
-
try {
|
|
1207
|
-
const parsed = JSON.parse(raw);
|
|
1208
|
-
if (parsed !== null &&
|
|
1209
|
-
typeof parsed === 'object' &&
|
|
1210
|
-
!Array.isArray(parsed)) {
|
|
1211
|
-
config = parsed;
|
|
1212
|
-
}
|
|
1213
|
-
else {
|
|
1214
|
-
console.log(` Error: ${mcpConfigPath} is not a JSON object. Aborting to avoid data loss.`);
|
|
1215
|
-
console.log(` Fix or delete the file manually, then re-run.`);
|
|
1216
|
-
process.exit(1);
|
|
1217
|
-
}
|
|
1218
|
-
}
|
|
1219
|
-
catch {
|
|
1220
|
-
console.log(` Error: could not parse ${mcpConfigPath}. Aborting to avoid data loss.`);
|
|
1221
|
-
console.log(` Fix or delete the file manually, then re-run.`);
|
|
1222
|
-
process.exit(1);
|
|
1223
|
-
}
|
|
1224
|
-
}
|
|
1225
|
-
if (config.mcpServers !== undefined &&
|
|
1226
|
-
(typeof config.mcpServers !== 'object' || Array.isArray(config.mcpServers))) {
|
|
1227
|
-
console.log(` Error: mcpServers in ${mcpConfigPath} is not an object. Aborting to avoid data loss.`);
|
|
1228
|
-
process.exit(1);
|
|
1229
|
-
}
|
|
1230
|
-
config.mcpServers = { ...config.mcpServers, rivet: rivetEntry };
|
|
1231
|
-
fs_1.default.writeFileSync(mcpConfigPath, JSON.stringify(config, null, 2) + '\n', 'utf8');
|
|
1232
|
-
console.log(`✓ Rivet MCP server added to ${mcpConfigPath}`);
|
|
1233
|
-
console.log(`
|
|
1234
|
-
Next steps:
|
|
1235
|
-
1. Fully quit and reopen the Claude desktop app
|
|
1236
|
-
2. Open a new chat and say "Open Rivet"
|
|
1237
|
-
`);
|
|
1238
|
-
};
|
|
1239
|
-
/**
|
|
1240
|
-
* Register Rivet with Codex MCP. Returns true on success, false on failure.
|
|
1241
|
-
* Does NOT call process.exit — callers decide how to handle failure.
|
|
1242
|
-
*/
|
|
1243
|
-
const registerCodexMCP = () => {
|
|
1244
|
-
const mcpAddCommand = 'codex mcp add rivet -- npx -y rivet-design@latest mcp --editor codex';
|
|
1245
|
-
try {
|
|
1246
|
-
(0, child_process_1.execSync)(mcpAddCommand, { stdio: 'inherit' });
|
|
1247
|
-
console.log('✓ Rivet MCP server added to Codex');
|
|
1248
|
-
return true;
|
|
1249
|
-
}
|
|
1250
|
-
catch {
|
|
1251
|
-
console.log('Run manually:', 'codex mcp add rivet -- npx -y rivet-design@latest mcp --editor codex');
|
|
1252
|
-
return false;
|
|
1253
|
-
}
|
|
1254
|
-
};
|
|
1255
|
-
const handleInstallCodex = async () => {
|
|
1256
|
-
console.log('\nSetting up Rivet for OpenAI Codex CLI...\n');
|
|
1257
|
-
// Check codex binary
|
|
1258
|
-
try {
|
|
1259
|
-
(0, child_process_1.execSync)('codex --version', { stdio: 'ignore' });
|
|
1260
|
-
}
|
|
1261
|
-
catch {
|
|
1262
|
-
console.log('Codex CLI is not installed or not in your PATH.');
|
|
1263
|
-
console.log('Install it: https://github.com/openai/codex');
|
|
1264
|
-
process.exit(1);
|
|
1265
|
-
}
|
|
1266
|
-
if (!registerCodexMCP()) {
|
|
1267
|
-
process.exit(1);
|
|
1268
993
|
}
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
`);
|
|
1274
|
-
|
|
1275
|
-
const handleUninstallClaude = () => {
|
|
1276
|
-
try {
|
|
1277
|
-
(0, child_process_1.execSync)('claude --version', { stdio: 'ignore' });
|
|
1278
|
-
}
|
|
1279
|
-
catch {
|
|
1280
|
-
console.log('Claude Code is not installed or not in your PATH — skipping.');
|
|
1281
|
-
return false;
|
|
1282
|
-
}
|
|
1283
|
-
let madeChanges = false;
|
|
1284
|
-
try {
|
|
1285
|
-
(0, child_process_1.execSync)('claude mcp remove rivet', { stdio: 'pipe' });
|
|
1286
|
-
console.log('✓ Rivet MCP server removed from Claude Code');
|
|
1287
|
-
madeChanges = true;
|
|
1288
|
-
}
|
|
1289
|
-
catch {
|
|
1290
|
-
console.log(' Rivet was not registered with Claude Code (nothing to remove).');
|
|
1291
|
-
}
|
|
1292
|
-
// Remove skill file
|
|
1293
|
-
const skillDir = path_1.default.join(os_1.default.homedir(), '.claude', 'skills', 'rivet');
|
|
1294
|
-
if (fs_1.default.existsSync(skillDir)) {
|
|
1295
|
-
fs_1.default.rmSync(skillDir, { recursive: true, force: true });
|
|
1296
|
-
console.log('✓ Rivet skill file removed');
|
|
1297
|
-
madeChanges = true;
|
|
1298
|
-
}
|
|
1299
|
-
return madeChanges;
|
|
1300
|
-
};
|
|
1301
|
-
const handleUninstallCursor = () => {
|
|
1302
|
-
const mcpConfigPath = path_1.default.join(os_1.default.homedir(), '.cursor', 'mcp.json');
|
|
1303
|
-
if (!fs_1.default.existsSync(mcpConfigPath)) {
|
|
1304
|
-
console.log(' No Cursor MCP config found — nothing to remove.');
|
|
1305
|
-
return false;
|
|
1306
|
-
}
|
|
1307
|
-
try {
|
|
1308
|
-
const raw = fs_1.default.readFileSync(mcpConfigPath, 'utf8');
|
|
1309
|
-
const config = JSON.parse(raw);
|
|
1310
|
-
if (!config.mcpServers ||
|
|
1311
|
-
(!('rivet' in config.mcpServers) && !('rivet-local' in config.mcpServers))) {
|
|
1312
|
-
console.log(' Rivet was not registered with Cursor (nothing to remove).');
|
|
1313
|
-
return false;
|
|
1314
|
-
}
|
|
1315
|
-
delete config.mcpServers['rivet'];
|
|
1316
|
-
delete config.mcpServers['rivet-local'];
|
|
1317
|
-
fs_1.default.writeFileSync(mcpConfigPath, JSON.stringify(config, null, 2) + '\n', 'utf8');
|
|
1318
|
-
console.log(`✓ Rivet MCP server removed from ${mcpConfigPath}`);
|
|
1319
|
-
return true;
|
|
1320
|
-
}
|
|
1321
|
-
catch {
|
|
1322
|
-
console.log(` Error: could not parse ${mcpConfigPath}. Fix or delete the file manually.`);
|
|
1323
|
-
return false;
|
|
1324
|
-
}
|
|
1325
|
-
};
|
|
1326
|
-
const handleUninstallClaudeDesktop = () => {
|
|
1327
|
-
const mcpConfigPath = claudeDesktopConfigPath();
|
|
1328
|
-
if (!fs_1.default.existsSync(mcpConfigPath)) {
|
|
1329
|
-
console.log(' No Claude desktop MCP config found — nothing to remove.');
|
|
1330
|
-
return false;
|
|
994
|
+
// Validate the token (refreshing if stale) rather than trusting its presence,
|
|
995
|
+
// so a revoked/expired token still gets a fresh sign-in prompt.
|
|
996
|
+
if (await new AuthService_1.AuthService().ensureAuthenticated()) {
|
|
997
|
+
const email = (0, ConfigManager_1.getConfigManager)().getEmail();
|
|
998
|
+
console.log(`\nYou're signed in${email ? ` as ${email}` : ''}. Open your agent and say "Open Rivet" to start.\n`);
|
|
999
|
+
return;
|
|
1331
1000
|
}
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
return false;
|
|
1338
|
-
}
|
|
1339
|
-
delete config.mcpServers['rivet'];
|
|
1340
|
-
fs_1.default.writeFileSync(mcpConfigPath, JSON.stringify(config, null, 2) + '\n', 'utf8');
|
|
1341
|
-
console.log(`✓ Rivet MCP server removed from ${mcpConfigPath}`);
|
|
1342
|
-
return true;
|
|
1001
|
+
const wantsSignIn = await promptYesNo('Sign in or create your Rivet account now?');
|
|
1002
|
+
if (wantsSignIn) {
|
|
1003
|
+
await (0, signin_1.runSignIn)({
|
|
1004
|
+
nextStepHint: "You're all set — open your agent and say \"Open Rivet\".",
|
|
1005
|
+
});
|
|
1343
1006
|
}
|
|
1344
|
-
|
|
1345
|
-
console.log(
|
|
1346
|
-
return false;
|
|
1007
|
+
else {
|
|
1008
|
+
console.log("\nNo problem — run `rivet login` whenever you're ready.\n");
|
|
1347
1009
|
}
|
|
1348
1010
|
};
|
|
1349
|
-
const
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
console.log('Codex CLI is not installed or not in your PATH — skipping.');
|
|
1355
|
-
return false;
|
|
1356
|
-
}
|
|
1357
|
-
try {
|
|
1358
|
-
(0, child_process_1.execSync)('codex mcp remove rivet', { stdio: 'pipe' });
|
|
1359
|
-
console.log('✓ Rivet MCP server removed from Codex');
|
|
1360
|
-
return true;
|
|
1361
|
-
}
|
|
1362
|
-
catch {
|
|
1363
|
-
console.log(' Rivet was not registered with Codex (nothing to remove).');
|
|
1364
|
-
return false;
|
|
1365
|
-
}
|
|
1011
|
+
const handleInstall = async (editor) => {
|
|
1012
|
+
const { exitCode } = (0, harnesses_1.installHarnesses)(editor);
|
|
1013
|
+
if (exitCode !== 0)
|
|
1014
|
+
process.exit(exitCode);
|
|
1015
|
+
await promptPostInstall();
|
|
1366
1016
|
};
|
|
1367
|
-
/**
|
|
1368
|
-
* Handle uninstall command — remove Rivet MCP server for the specified editor (or all)
|
|
1369
|
-
*/
|
|
1370
1017
|
const handleUninstall = async (editor) => {
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
const changed = handleUninstallClaude();
|
|
1375
|
-
if (changed)
|
|
1376
|
-
console.log('\nRestart Claude Code to apply changes.\n');
|
|
1377
|
-
break;
|
|
1378
|
-
}
|
|
1379
|
-
case 'claude-desktop': {
|
|
1380
|
-
console.log('\nUninstalling Rivet from the Claude desktop app...\n');
|
|
1381
|
-
const changed = handleUninstallClaudeDesktop();
|
|
1382
|
-
if (changed)
|
|
1383
|
-
console.log('\nFully restart the Claude desktop app to apply changes.\n');
|
|
1384
|
-
break;
|
|
1385
|
-
}
|
|
1386
|
-
case 'cursor': {
|
|
1387
|
-
console.log('\nUninstalling Rivet from Cursor...\n');
|
|
1388
|
-
const changed = handleUninstallCursor();
|
|
1389
|
-
if (changed)
|
|
1390
|
-
console.log('\nRestart Cursor to apply changes.\n');
|
|
1391
|
-
break;
|
|
1392
|
-
}
|
|
1393
|
-
case 'codex': {
|
|
1394
|
-
console.log('\nUninstalling Rivet from OpenAI Codex CLI...\n');
|
|
1395
|
-
const changed = handleUninstallCodex();
|
|
1396
|
-
if (changed)
|
|
1397
|
-
console.log('\nStart a new Codex session to apply changes.\n');
|
|
1398
|
-
break;
|
|
1399
|
-
}
|
|
1400
|
-
case 'all': {
|
|
1401
|
-
console.log('\nUninstalling Rivet from all editors...\n');
|
|
1402
|
-
const claudeChanged = handleUninstallClaude();
|
|
1403
|
-
const claudeDesktopChanged = handleUninstallClaudeDesktop();
|
|
1404
|
-
const cursorChanged = handleUninstallCursor();
|
|
1405
|
-
const codexChanged = handleUninstallCodex();
|
|
1406
|
-
if (claudeChanged ||
|
|
1407
|
-
claudeDesktopChanged ||
|
|
1408
|
-
cursorChanged ||
|
|
1409
|
-
codexChanged) {
|
|
1410
|
-
console.log('\nRestart your editor sessions to apply changes.\n');
|
|
1411
|
-
}
|
|
1412
|
-
break;
|
|
1413
|
-
}
|
|
1414
|
-
default:
|
|
1415
|
-
console.log('\nUsage: rivet uninstall <editor>\n');
|
|
1416
|
-
console.log(' rivet uninstall claude Remove from Claude Code');
|
|
1417
|
-
console.log(' rivet uninstall claude-desktop Remove from the Claude desktop app');
|
|
1418
|
-
console.log(' rivet uninstall cursor Remove from Cursor');
|
|
1419
|
-
console.log(' rivet uninstall codex Remove from OpenAI Codex CLI');
|
|
1420
|
-
console.log(' rivet uninstall all Remove from all editors');
|
|
1421
|
-
console.log('');
|
|
1422
|
-
process.exit(editor ? 1 : 0);
|
|
1423
|
-
}
|
|
1018
|
+
const { exitCode } = (0, harnesses_1.uninstallHarnesses)(editor);
|
|
1019
|
+
if (exitCode !== 0)
|
|
1020
|
+
process.exit(exitCode);
|
|
1424
1021
|
};
|
|
1425
|
-
/**
|
|
1426
|
-
* Handle update command — re-register Rivet MCP server for all detected editors
|
|
1427
|
-
*/
|
|
1428
1022
|
const handleUpdate = async () => {
|
|
1429
|
-
|
|
1430
|
-
let updatedAny = false;
|
|
1431
|
-
// Claude Code — only run if installed; surface re-add failure so we don't leave user without MCP
|
|
1432
|
-
let claudeInstalled = false;
|
|
1433
|
-
try {
|
|
1434
|
-
(0, child_process_1.execSync)('claude --version', { stdio: 'ignore' });
|
|
1435
|
-
claudeInstalled = true;
|
|
1436
|
-
}
|
|
1437
|
-
catch {
|
|
1438
|
-
// Claude not installed — skip
|
|
1439
|
-
}
|
|
1440
|
-
if (claudeInstalled) {
|
|
1441
|
-
try {
|
|
1442
|
-
(0, child_process_1.execSync)('claude mcp remove rivet', { stdio: 'pipe' });
|
|
1443
|
-
}
|
|
1444
|
-
catch {
|
|
1445
|
-
// not registered, that's fine
|
|
1446
|
-
}
|
|
1447
|
-
if (registerClaudeMCP()) {
|
|
1448
|
-
console.log('✓ Updated Rivet MCP server for Claude Code');
|
|
1449
|
-
const skillResult = (0, skillWriter_1.writeSkillFileIfNeeded)();
|
|
1450
|
-
if (skillResult.success) {
|
|
1451
|
-
console.log('✓ Updated Rivet skill for Claude Code');
|
|
1452
|
-
}
|
|
1453
|
-
else {
|
|
1454
|
-
console.log(` Warning: could not write skill file (${skillResult.error})`);
|
|
1455
|
-
}
|
|
1456
|
-
updatedAny = true;
|
|
1457
|
-
}
|
|
1458
|
-
else {
|
|
1459
|
-
console.log(' Failed to re-add Rivet for Claude Code. Run: rivet install claude');
|
|
1460
|
-
}
|
|
1461
|
-
}
|
|
1462
|
-
// Cursor — only update if rivet was already registered
|
|
1463
|
-
const cursorMcpPath = path_1.default.join(os_1.default.homedir(), '.cursor', 'mcp.json');
|
|
1464
|
-
if (fs_1.default.existsSync(cursorMcpPath)) {
|
|
1465
|
-
try {
|
|
1466
|
-
const raw = fs_1.default.readFileSync(cursorMcpPath, 'utf8');
|
|
1467
|
-
const config = JSON.parse(raw);
|
|
1468
|
-
if (config.mcpServers &&
|
|
1469
|
-
('rivet' in config.mcpServers || 'rivet-local' in config.mcpServers)) {
|
|
1470
|
-
warnIfStaleRivetCommand(config.mcpServers['rivet'], 'Cursor');
|
|
1471
|
-
warnIfStaleRivetCommand(config.mcpServers['rivet-local'], 'Cursor');
|
|
1472
|
-
config.mcpServers['rivet'] = (0, exports.buildCursorHostedRivetEntry)();
|
|
1473
|
-
config.mcpServers['rivet-local'] = (0, exports.buildCursorLocalRivetEntry)();
|
|
1474
|
-
fs_1.default.writeFileSync(cursorMcpPath, JSON.stringify(config, null, 2) + '\n', 'utf8');
|
|
1475
|
-
console.log('✓ Updated Rivet MCP servers for Cursor');
|
|
1476
|
-
updatedAny = true;
|
|
1477
|
-
}
|
|
1478
|
-
}
|
|
1479
|
-
catch {
|
|
1480
|
-
console.log(' Warning: could not update Cursor MCP config');
|
|
1481
|
-
}
|
|
1482
|
-
}
|
|
1483
|
-
// Claude desktop — only update if rivet was already registered
|
|
1484
|
-
const claudeDesktopMcpPath = claudeDesktopConfigPath();
|
|
1485
|
-
if (fs_1.default.existsSync(claudeDesktopMcpPath)) {
|
|
1486
|
-
try {
|
|
1487
|
-
const raw = fs_1.default.readFileSync(claudeDesktopMcpPath, 'utf8');
|
|
1488
|
-
const config = JSON.parse(raw);
|
|
1489
|
-
if (config.mcpServers && 'rivet' in config.mcpServers) {
|
|
1490
|
-
warnIfStaleRivetCommand(config.mcpServers['rivet'], 'the Claude desktop app');
|
|
1491
|
-
config.mcpServers['rivet'] = buildClaudeDesktopRivetEntry();
|
|
1492
|
-
fs_1.default.writeFileSync(claudeDesktopMcpPath, JSON.stringify(config, null, 2) + '\n', 'utf8');
|
|
1493
|
-
console.log('✓ Updated Rivet MCP server for the Claude desktop app');
|
|
1494
|
-
updatedAny = true;
|
|
1495
|
-
}
|
|
1496
|
-
}
|
|
1497
|
-
catch {
|
|
1498
|
-
console.log(' Warning: could not update Claude desktop MCP config');
|
|
1499
|
-
}
|
|
1500
|
-
}
|
|
1501
|
-
// Codex — remove then re-add so update works when already registered
|
|
1502
|
-
try {
|
|
1503
|
-
(0, child_process_1.execSync)('codex --version', { stdio: 'ignore' });
|
|
1504
|
-
try {
|
|
1505
|
-
(0, child_process_1.execSync)('codex mcp remove rivet', { stdio: 'pipe' });
|
|
1506
|
-
}
|
|
1507
|
-
catch {
|
|
1508
|
-
// not registered, that's fine
|
|
1509
|
-
}
|
|
1510
|
-
if (registerCodexMCP()) {
|
|
1511
|
-
console.log('✓ Updated Rivet MCP server for Codex');
|
|
1512
|
-
updatedAny = true;
|
|
1513
|
-
}
|
|
1514
|
-
}
|
|
1515
|
-
catch {
|
|
1516
|
-
// Codex not installed — skip
|
|
1517
|
-
}
|
|
1518
|
-
if (!updatedAny) {
|
|
1519
|
-
console.log("No editors found to update. Run 'rivet install <editor>' first.");
|
|
1520
|
-
console.log(' rivet install claude');
|
|
1521
|
-
console.log(' rivet install claude-desktop');
|
|
1522
|
-
console.log(' rivet install cursor');
|
|
1523
|
-
console.log(' rivet install codex');
|
|
1524
|
-
}
|
|
1525
|
-
else {
|
|
1526
|
-
console.log('\nRestart your editor session to use the latest Rivet.\n');
|
|
1527
|
-
}
|
|
1023
|
+
(0, harnesses_1.updateHarnesses)();
|
|
1528
1024
|
};
|
|
1529
1025
|
/**
|
|
1530
1026
|
* Handle login command
|
|
1531
1027
|
*/
|
|
1532
1028
|
const handleLogin = async () => {
|
|
1029
|
+
// Interactive terminal: open Rivet's own sign-in page rather than shelling
|
|
1030
|
+
// straight to Google. The page's "Sign in with Google" button kicks off the
|
|
1031
|
+
// OAuth flow and stores the token locally.
|
|
1032
|
+
if (process.stdin.isTTY) {
|
|
1033
|
+
const result = await (0, signin_1.runSignIn)({ nextStepHint: 'You can now run: rivet' });
|
|
1034
|
+
if (!result.ok)
|
|
1035
|
+
process.exit(1);
|
|
1036
|
+
return;
|
|
1037
|
+
}
|
|
1038
|
+
// Headless / non-interactive: fall back to the terminal OAuth flow.
|
|
1533
1039
|
console.log('\n🔐 Rivet Login with Google\n');
|
|
1534
1040
|
const authService = new AuthService_1.AuthService();
|
|
1535
1041
|
console.log('Opening browser for Google authentication...');
|