codex-slot 0.1.31 → 0.1.33
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/app/account-service.js +12 -1
- package/dist/status-command.js +65 -14
- package/package.json +1 -1
|
@@ -12,6 +12,7 @@ const node_fs_1 = __importDefault(require("node:fs"));
|
|
|
12
12
|
const account_store_1 = require("../account-store");
|
|
13
13
|
const config_1 = require("../config");
|
|
14
14
|
const login_1 = require("../login");
|
|
15
|
+
const relay_store_1 = require("../relay-store");
|
|
15
16
|
const state_1 = require("../state");
|
|
16
17
|
const text_1 = require("../text");
|
|
17
18
|
/**
|
|
@@ -49,7 +50,11 @@ async function loginAccount(slotName) {
|
|
|
49
50
|
* @throws 无显式抛出。
|
|
50
51
|
*/
|
|
51
52
|
function removeAccount(slotName) {
|
|
52
|
-
|
|
53
|
+
const removed = (0, account_store_1.removeManagedAccount)(slotName);
|
|
54
|
+
if (removed) {
|
|
55
|
+
(0, relay_store_1.removeRelaySlot)(slotName);
|
|
56
|
+
}
|
|
57
|
+
return removed;
|
|
53
58
|
}
|
|
54
59
|
/**
|
|
55
60
|
* 列出当前所有受管账号配置。
|
|
@@ -74,6 +79,9 @@ function listAccounts() {
|
|
|
74
79
|
* @throws 当旧槽位不存在、新槽位已存在或目录迁移失败时抛出异常。
|
|
75
80
|
*/
|
|
76
81
|
function renameAccount(oldName, newName) {
|
|
82
|
+
if ((0, relay_store_1.findRelaySlot)(oldName) && (0, relay_store_1.findRelaySlot)(newName)) {
|
|
83
|
+
throw new Error((0, text_1.bi)(`中转槽位 ${newName} 已存在`, `Relay slot already exists: ${newName}`));
|
|
84
|
+
}
|
|
77
85
|
const config = (0, config_1.loadConfig)();
|
|
78
86
|
const index = config.accounts.findIndex((item) => item.id === oldName);
|
|
79
87
|
if (index < 0) {
|
|
@@ -121,5 +129,8 @@ function renameAccount(oldName, newName) {
|
|
|
121
129
|
delete state.scheduler_stats[oldName];
|
|
122
130
|
}
|
|
123
131
|
});
|
|
132
|
+
if ((0, relay_store_1.findRelaySlot)(oldName)) {
|
|
133
|
+
(0, relay_store_1.renameRelaySlot)(oldName, newName);
|
|
134
|
+
}
|
|
124
135
|
return renamedAccount;
|
|
125
136
|
}
|
package/dist/status-command.js
CHANGED
|
@@ -4,6 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.renderInteractiveHelpLines = renderInteractiveHelpLines;
|
|
7
|
+
exports.renderInteractiveStatusLayout = renderInteractiveStatusLayout;
|
|
7
8
|
exports.handleStatus = handleStatus;
|
|
8
9
|
const node_readline_1 = __importDefault(require("node:readline"));
|
|
9
10
|
const account_store_1 = require("./account-store");
|
|
@@ -218,18 +219,64 @@ function truncateVisible(value, maxWidth) {
|
|
|
218
219
|
* @param leftLines 左栏文本行。
|
|
219
220
|
* @param rightLines 右栏文本行。
|
|
220
221
|
* @param gap 两栏之间的空格数量。
|
|
222
|
+
* @param leftWidth 左栏固定显示宽度;未传入时按左栏最长行自适应。
|
|
221
223
|
* @returns 合并后的双栏文本行。
|
|
222
224
|
* @throws 无显式抛出。
|
|
223
225
|
*/
|
|
224
|
-
function renderColumns(leftLines, rightLines, gap) {
|
|
225
|
-
const
|
|
226
|
+
function renderColumns(leftLines, rightLines, gap, leftWidth) {
|
|
227
|
+
const resolvedLeftWidth = leftWidth ?? Math.max(0, ...leftLines.map((line) => getDisplayWidth(line)));
|
|
226
228
|
const rowCount = Math.max(leftLines.length, rightLines.length);
|
|
227
229
|
const rows = [];
|
|
228
230
|
for (let index = 0; index < rowCount; index += 1) {
|
|
229
|
-
rows.push(`${padVisible(leftLines[index] ?? "",
|
|
231
|
+
rows.push(`${padVisible(leftLines[index] ?? "", resolvedLeftWidth)}${" ".repeat(gap)}${rightLines[index] ?? ""}`.trimEnd());
|
|
230
232
|
}
|
|
231
233
|
return rows;
|
|
232
234
|
}
|
|
235
|
+
/**
|
|
236
|
+
* 按终端高度裁剪交互式面板输出行,避免写到最后一行后继续换行触发滚屏。
|
|
237
|
+
*
|
|
238
|
+
* 业务含义:
|
|
239
|
+
* 1. 交互面板每次都从左上角整屏重绘。
|
|
240
|
+
* 2. 当输出行数超过当前终端高度时,终端会滚动备用屏缓冲区,后续重绘会出现残影或错位。
|
|
241
|
+
* 3. 保留最后一行作为安全缓冲,兼容不同终端对末行写入与换行的处理差异。
|
|
242
|
+
*
|
|
243
|
+
* @param lines 已完成布局的面板行。
|
|
244
|
+
* @param screenHeight 当前终端行数;为空或非法时不裁剪。
|
|
245
|
+
* @returns 可安全输出到当前终端的面板行。
|
|
246
|
+
* @throws 无显式抛出。
|
|
247
|
+
*/
|
|
248
|
+
function clipInteractiveLines(lines, screenHeight) {
|
|
249
|
+
if (screenHeight === undefined || !Number.isFinite(screenHeight) || screenHeight <= 1) {
|
|
250
|
+
return lines;
|
|
251
|
+
}
|
|
252
|
+
return lines.slice(0, Math.max(1, Math.floor(screenHeight) - 1));
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* 构建交互式状态面板的最终屏幕行。
|
|
256
|
+
*
|
|
257
|
+
* 业务含义:
|
|
258
|
+
* 1. 该方法只负责布局,不读取或写入 cslot 状态,便于用纯测试覆盖终端尺寸边界。
|
|
259
|
+
* 2. 宽屏时使用固定左栏宽度,让右侧详情栏在账号/relay 选择切换时保持稳定锚点。
|
|
260
|
+
* 3. 窄屏时改为上下布局,并按终端高度裁剪,避免上下移动触发重绘后滚屏。
|
|
261
|
+
*
|
|
262
|
+
* @param options 布局参数;`leftLines` 为账号与 relay 主列表,`sideLines` 为当前项、摘要与 help,`screenWidth`/`screenHeight` 来自当前终端尺寸,`styled` 控制分隔线样式。
|
|
263
|
+
* @returns 可直接传给终端输出函数的屏幕行。
|
|
264
|
+
* @throws 无显式抛出。
|
|
265
|
+
*/
|
|
266
|
+
function renderInteractiveStatusLayout(options) {
|
|
267
|
+
const screenWidth = Math.max(1, Math.floor(options.screenWidth));
|
|
268
|
+
const wideLayout = screenWidth >= 104;
|
|
269
|
+
const leftWidth = wideLayout ? Math.max(68, Math.floor(screenWidth * 0.64)) : screenWidth;
|
|
270
|
+
const lines = wideLayout
|
|
271
|
+
? renderColumns(options.leftLines, options.sideLines, 3, leftWidth)
|
|
272
|
+
: [
|
|
273
|
+
...options.leftLines,
|
|
274
|
+
"",
|
|
275
|
+
renderDivider(screenWidth, options.styled),
|
|
276
|
+
...options.sideLines
|
|
277
|
+
];
|
|
278
|
+
return clipInteractiveLines(lines, options.screenHeight);
|
|
279
|
+
}
|
|
233
280
|
/**
|
|
234
281
|
* 进入交互式全屏缓冲区,并隐藏光标,确保后续重绘始终基于固定画布。
|
|
235
282
|
*
|
|
@@ -261,7 +308,6 @@ function renderInteractiveScreen(lines) {
|
|
|
261
308
|
node_readline_1.default.cursorTo(process.stdout, 0, 0);
|
|
262
309
|
node_readline_1.default.clearScreenDown(process.stdout);
|
|
263
310
|
process.stdout.write(lines.join("\n"));
|
|
264
|
-
process.stdout.write("\n");
|
|
265
311
|
}
|
|
266
312
|
/**
|
|
267
313
|
* 计算交互式状态面板的初始光标位置。
|
|
@@ -378,6 +424,7 @@ async function handleInteractiveToggle(initialStatuses) {
|
|
|
378
424
|
let refreshStatusText = null;
|
|
379
425
|
const render = () => {
|
|
380
426
|
const screenWidth = process.stdout.columns ?? 80;
|
|
427
|
+
const screenHeight = process.stdout.rows;
|
|
381
428
|
const styled = shouldUseAnsiStyle();
|
|
382
429
|
const latestSnapshot = (0, status_service_1.getStatusSnapshot)();
|
|
383
430
|
const items = buildInteractiveItems(accounts, relaySlots);
|
|
@@ -465,16 +512,13 @@ async function handleInteractiveToggle(initialStatuses) {
|
|
|
465
512
|
"",
|
|
466
513
|
...relayLines
|
|
467
514
|
];
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
renderDivider(screenWidth, styled),
|
|
476
|
-
...sideLines
|
|
477
|
-
]);
|
|
515
|
+
renderInteractiveScreen(renderInteractiveStatusLayout({
|
|
516
|
+
leftLines,
|
|
517
|
+
sideLines,
|
|
518
|
+
screenWidth,
|
|
519
|
+
screenHeight,
|
|
520
|
+
styled
|
|
521
|
+
}));
|
|
478
522
|
};
|
|
479
523
|
const applyChanges = () => {
|
|
480
524
|
if (!accountChanged && !relayChanged) {
|
|
@@ -497,6 +541,7 @@ async function handleInteractiveToggle(initialStatuses) {
|
|
|
497
541
|
closed = true;
|
|
498
542
|
applyChanges();
|
|
499
543
|
stdin.off("keypress", onKeypress);
|
|
544
|
+
process.stdout.off("resize", onResize);
|
|
500
545
|
stdin.setRawMode?.(false);
|
|
501
546
|
stdin.pause();
|
|
502
547
|
leaveInteractiveScreen();
|
|
@@ -629,8 +674,14 @@ async function handleInteractiveToggle(initialStatuses) {
|
|
|
629
674
|
exitInteractive();
|
|
630
675
|
}
|
|
631
676
|
};
|
|
677
|
+
const onResize = () => {
|
|
678
|
+
if (!closed) {
|
|
679
|
+
render();
|
|
680
|
+
}
|
|
681
|
+
};
|
|
632
682
|
render();
|
|
633
683
|
stdin.on("keypress", onKeypress);
|
|
684
|
+
process.stdout.on("resize", onResize);
|
|
634
685
|
});
|
|
635
686
|
}
|
|
636
687
|
/**
|