ai-cc-router 0.5.0 → 0.5.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/dist/cli/cmd-status.js +39 -18
- package/dist/ui/Dashboard.js +9 -3
- package/package.json +1 -1
package/dist/cli/cmd-status.js
CHANGED
|
@@ -70,9 +70,17 @@ async function jsonOutput(port) {
|
|
|
70
70
|
* Launches the Ink dashboard and handles "re-launch" intents.
|
|
71
71
|
*
|
|
72
72
|
* The dashboard cannot run inquirer prompts while Ink owns stdin, so when
|
|
73
|
-
* the user presses `n` to add an account, Ink unmounts
|
|
74
|
-
*
|
|
73
|
+
* the user presses `n` to add an account, Ink unmounts **completely** first.
|
|
74
|
+
* Only after `waitUntilExit()` resolves — and stdin is restored from raw mode
|
|
75
|
+
* — does the OAuth flow run. Once tokens are obtained and POSTed to the
|
|
75
76
|
* server, the dashboard is re-rendered and polling resumes.
|
|
77
|
+
*
|
|
78
|
+
* IMPORTANT: The previous design resolved the outer promise from inside
|
|
79
|
+
* `onIntent` (before Ink unmounted), then raced with `waitUntilExit`. That
|
|
80
|
+
* caused inquirer to see a half-released stdin and force-close itself.
|
|
81
|
+
* The fix: `onIntent` writes to a mutable variable; `waitUntilExit()`
|
|
82
|
+
* is the ONLY thing that resolves the await; stdin is explicitly restored
|
|
83
|
+
* before inquirer runs.
|
|
76
84
|
*/
|
|
77
85
|
async function dashboardLoop(port) {
|
|
78
86
|
// Dynamic imports keep these heavy deps out of the cold-start path
|
|
@@ -83,23 +91,36 @@ async function dashboardLoop(port) {
|
|
|
83
91
|
]);
|
|
84
92
|
while (true) {
|
|
85
93
|
const target = resolveStatusTarget(port);
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
94
|
+
// `pendingIntent` is set by the Dashboard component via `onIntent`;
|
|
95
|
+
// it defaults to "quit" so Ctrl+C (exitOnCtrlC) does the right thing
|
|
96
|
+
// without the Dashboard ever firing onIntent.
|
|
97
|
+
let pendingIntent = "quit";
|
|
98
|
+
const instance = render(createElement(Dashboard, {
|
|
99
|
+
port,
|
|
100
|
+
baseUrl: target.baseUrl,
|
|
101
|
+
authToken: target.authToken,
|
|
102
|
+
onIntent: (i) => { pendingIntent = i; },
|
|
103
|
+
}), { exitOnCtrlC: true });
|
|
104
|
+
// Block until Ink has FULLY unmounted and released stdin.
|
|
105
|
+
// The Dashboard's keyboard handler calls exit() for both `q` and `n`;
|
|
106
|
+
// Ctrl+C also triggers exit via exitOnCtrlC.
|
|
107
|
+
await instance.waitUntilExit();
|
|
108
|
+
// Yield the event loop so any of Ink's pending stdin cleanup tasks
|
|
109
|
+
// (listeners detach, raw-mode restore) run before inquirer grabs stdin.
|
|
110
|
+
// Without this, inquirer can see a half-released stdin and throw
|
|
111
|
+
// "User force closed the prompt".
|
|
112
|
+
await new Promise(resolve => setImmediate(resolve));
|
|
113
|
+
// Ink leaves stdin in raw mode. Restore it before running inquirer or
|
|
114
|
+
// exiting, otherwise the terminal may remain in a broken state.
|
|
115
|
+
if (process.stdin.isTTY) {
|
|
116
|
+
process.stdin.setRawMode(false);
|
|
117
|
+
}
|
|
118
|
+
// Ink may have paused stdin — resume it so inquirer can read input.
|
|
119
|
+
process.stdin.resume();
|
|
120
|
+
if (pendingIntent === "quit")
|
|
100
121
|
return;
|
|
101
|
-
// Intent: addAccount —
|
|
102
|
-
//
|
|
122
|
+
// Intent: addAccount — run the OAuth flow, then POST the resulting
|
|
123
|
+
// tokens to the server we're connected to (local or remote).
|
|
103
124
|
console.log();
|
|
104
125
|
console.log(chalk.cyan("→ Adding a new account..."));
|
|
105
126
|
console.log();
|
package/dist/ui/Dashboard.js
CHANGED
|
@@ -202,8 +202,11 @@ function LiveDashboard({ data, port, lastUpdate, api, onIntent, }) {
|
|
|
202
202
|
return;
|
|
203
203
|
}
|
|
204
204
|
// ── Normal view mode ────────────────────────────────────────────────
|
|
205
|
+
// Always call exit() so Ink fully unmounts and releases stdin.
|
|
206
|
+
// The outer dashboardLoop reads `pendingIntent` after waitUntilExit().
|
|
205
207
|
if (input === "q") {
|
|
206
|
-
onIntent
|
|
208
|
+
onIntent?.("quit");
|
|
209
|
+
exit();
|
|
207
210
|
return;
|
|
208
211
|
}
|
|
209
212
|
if (key.escape) {
|
|
@@ -211,7 +214,8 @@ function LiveDashboard({ data, port, lastUpdate, api, onIntent, }) {
|
|
|
211
214
|
setFocus("logs");
|
|
212
215
|
return;
|
|
213
216
|
}
|
|
214
|
-
onIntent
|
|
217
|
+
onIntent?.("quit");
|
|
218
|
+
exit();
|
|
215
219
|
return;
|
|
216
220
|
}
|
|
217
221
|
if (key.tab) {
|
|
@@ -258,7 +262,9 @@ function LiveDashboard({ data, port, lastUpdate, api, onIntent, }) {
|
|
|
258
262
|
return;
|
|
259
263
|
}
|
|
260
264
|
}
|
|
261
|
-
// n = add account — works regardless of focus
|
|
265
|
+
// n = add account — works regardless of focus.
|
|
266
|
+
// Requires an onIntent handler because the outer loop runs the OAuth
|
|
267
|
+
// flow after Ink unmounts; if none is wired, this key is a no-op.
|
|
262
268
|
if (input === "n") {
|
|
263
269
|
if (onIntent) {
|
|
264
270
|
onIntent("addAccount");
|