@undefineds.co/linx 0.3.22 → 0.3.23
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/lib/linx-tui-contract.js +2 -1
- package/dist/lib/linx-tui-contract.js.map +1 -1
- package/dist/lib/pi-adapter/branding.js +33 -7
- package/dist/lib/pi-adapter/branding.js.map +1 -1
- package/dist/lib/pi-adapter/interactive.js +306 -52
- package/dist/lib/pi-adapter/interactive.js.map +1 -1
- package/dist/plugins/linx-symphony-codex/.codex-plugin/plugin.json +1 -1
- package/package.json +1 -1
|
@@ -8,7 +8,7 @@ import { listArchivedAutoModeSessions, runAutoMode } from '../auto-mode/runner.j
|
|
|
8
8
|
import { resolveAutoModeCommandRoute, } from '../../../vendor/agent-runtime/dist/auto-mode.js';
|
|
9
9
|
import { getAIConfigProviderCatalog, getAIConfigProviderMetadata } from '../models.js';
|
|
10
10
|
import { runSymphony } from '../symphony-command.js';
|
|
11
|
-
import { applyLinxInteractiveBranding, requestLinxCloudLogin } from './branding.js';
|
|
11
|
+
import { applyLinxInteractiveBranding, checkAndShowLinxUpdate, requestLinxCloudLogin } from './branding.js';
|
|
12
12
|
import { installPodStatusOutputFilter } from './pod-status-output.js';
|
|
13
13
|
import { createPodBackedExtensionUiContext } from './pod-approval.js';
|
|
14
14
|
import { DEFAULT_SECRETARY_CHAT_ID, secretaryChatUri, secretaryThreadUri } from './pod-mirror-mapping.js';
|
|
@@ -41,6 +41,11 @@ const COMPACT_STATUS_LINE_TOKENS = [
|
|
|
41
41
|
'context-remaining',
|
|
42
42
|
'current-dir',
|
|
43
43
|
];
|
|
44
|
+
const STATUS_LINE_CODEX_PRESET_OPTION = 'Preset: Codex-style';
|
|
45
|
+
const STATUS_LINE_COMPACT_PRESET_OPTION = 'Preset: Compact';
|
|
46
|
+
const STATUS_LINE_TOGGLE_COLORS_OPTION = 'Toggle colors';
|
|
47
|
+
const STATUS_LINE_RESET_OPTION = 'Reset to default';
|
|
48
|
+
const STATUS_LINE_DONE_OPTION = 'Done';
|
|
44
49
|
/** Module-level reference to interactive for footer mode state (set during bootstrap). */
|
|
45
50
|
let _linxFooterInteractive = null;
|
|
46
51
|
export function bootstrapLinxInteractiveMode(runtime, options = {}) {
|
|
@@ -554,6 +559,9 @@ function parseLinxGlobalCommand(input) {
|
|
|
554
559
|
: input.slice('/status-line'.length).trim();
|
|
555
560
|
return { action: 'statusline', args: splitInteractiveCommandArgs(body) };
|
|
556
561
|
}
|
|
562
|
+
if (input === '/update' || input === '/upgrade') {
|
|
563
|
+
return { action: 'update' };
|
|
564
|
+
}
|
|
557
565
|
if (input === '/rewind') {
|
|
558
566
|
return { action: 'rewind-select' };
|
|
559
567
|
}
|
|
@@ -679,6 +687,10 @@ async function handleLinxGlobalCommand(interactive, runtime, command) {
|
|
|
679
687
|
await handleInteractiveStatusLineCommand(interactive, command.args);
|
|
680
688
|
return;
|
|
681
689
|
}
|
|
690
|
+
if (command.action === 'update') {
|
|
691
|
+
await checkAndShowLinxUpdate(interactive, { manual: true });
|
|
692
|
+
return;
|
|
693
|
+
}
|
|
682
694
|
if (command.action === 'rewind-select') {
|
|
683
695
|
await handleInteractiveRewindSelector(interactive, runtime);
|
|
684
696
|
return;
|
|
@@ -695,53 +707,133 @@ async function handleInteractiveStatusLineCommand(interactive, args) {
|
|
|
695
707
|
return;
|
|
696
708
|
}
|
|
697
709
|
const summary = formatInteractiveStatusLineSummary();
|
|
698
|
-
if (typeof interactive.
|
|
699
|
-
interactive
|
|
700
|
-
interactive.ui?.requestRender?.();
|
|
710
|
+
if (typeof interactive.showSelector === 'function') {
|
|
711
|
+
await showInteractiveStatusLineMultiSelect(interactive);
|
|
701
712
|
return;
|
|
702
713
|
}
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
'Use compact preset',
|
|
706
|
-
'Configure tokens manually',
|
|
707
|
-
'Toggle colors',
|
|
708
|
-
'Show available tokens',
|
|
709
|
-
'Reset to default',
|
|
710
|
-
]);
|
|
711
|
-
if (choice === 'Use Codex-style preset') {
|
|
712
|
-
writeInteractiveStatusLineConfig(interactive, {
|
|
713
|
-
statusLine: CODEX_STYLE_STATUS_LINE_TOKENS,
|
|
714
|
-
message: 'Status line set to Codex-style preset.',
|
|
715
|
-
});
|
|
714
|
+
if (typeof interactive.showExtensionSelector === 'function') {
|
|
715
|
+
await showInteractiveStatusLineFallbackSelector(interactive);
|
|
716
716
|
return;
|
|
717
717
|
}
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
message: 'Status line set to compact preset.',
|
|
722
|
-
});
|
|
718
|
+
{
|
|
719
|
+
interactive.showStatus?.(`${summary} · Use /statusline set <tokens...>, /statusline tokens, /statusline colors <on|off>, or /statusline reset.`);
|
|
720
|
+
interactive.ui?.requestRender?.();
|
|
723
721
|
return;
|
|
724
722
|
}
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
723
|
+
}
|
|
724
|
+
async function showInteractiveStatusLineFallbackSelector(interactive) {
|
|
725
|
+
while (true) {
|
|
726
|
+
const currentSummary = formatInteractiveStatusLineSummary();
|
|
727
|
+
const config = readLinxStatusLineConfig();
|
|
728
|
+
const options = buildInteractiveStatusLineOptions(config);
|
|
729
|
+
const choice = await interactive.showExtensionSelector(`Status line\n${currentSummary}`, options);
|
|
730
|
+
if (!choice || choice === STATUS_LINE_DONE_OPTION) {
|
|
731
|
+
return;
|
|
732
|
+
}
|
|
733
|
+
const token = parseInteractiveStatusLineTokenChoice(choice);
|
|
734
|
+
if (token) {
|
|
735
|
+
toggleInteractiveStatusLineToken(interactive, token);
|
|
736
|
+
continue;
|
|
737
|
+
}
|
|
738
|
+
if (choice === STATUS_LINE_CODEX_PRESET_OPTION) {
|
|
739
|
+
writeInteractiveStatusLineConfig(interactive, {
|
|
740
|
+
statusLine: CODEX_STYLE_STATUS_LINE_TOKENS,
|
|
741
|
+
message: 'Status line set to Codex-style preset.',
|
|
742
|
+
});
|
|
743
|
+
continue;
|
|
744
|
+
}
|
|
745
|
+
if (choice === STATUS_LINE_COMPACT_PRESET_OPTION) {
|
|
746
|
+
writeInteractiveStatusLineConfig(interactive, {
|
|
747
|
+
statusLine: COMPACT_STATUS_LINE_TOKENS,
|
|
748
|
+
message: 'Status line set to compact preset.',
|
|
749
|
+
});
|
|
750
|
+
continue;
|
|
751
|
+
}
|
|
752
|
+
if (choice === STATUS_LINE_TOGGLE_COLORS_OPTION) {
|
|
753
|
+
const current = readLinxStatusLineConfig();
|
|
754
|
+
writeInteractiveStatusLineConfig(interactive, {
|
|
755
|
+
statusLineUseColors: !current.useColors,
|
|
756
|
+
message: `Status line colors ${current.useColors ? 'disabled' : 'enabled'}.`,
|
|
757
|
+
});
|
|
758
|
+
continue;
|
|
759
|
+
}
|
|
760
|
+
if (choice === STATUS_LINE_RESET_OPTION) {
|
|
761
|
+
resetLinxStatusLineConfig();
|
|
762
|
+
finishInteractiveStatusLineUpdate(interactive, `Status line reset to default: ${DEFAULT_STATUS_LINE_TOKENS.join(', ')}`);
|
|
763
|
+
}
|
|
732
764
|
}
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
765
|
+
}
|
|
766
|
+
async function showInteractiveStatusLineMultiSelect(interactive) {
|
|
767
|
+
await new Promise((resolvePromise, rejectPromise) => {
|
|
768
|
+
let resolved = false;
|
|
769
|
+
const resolveOnce = () => {
|
|
770
|
+
if (!resolved) {
|
|
771
|
+
resolved = true;
|
|
772
|
+
resolvePromise();
|
|
773
|
+
}
|
|
774
|
+
};
|
|
775
|
+
try {
|
|
776
|
+
interactive.showSelector((done) => {
|
|
777
|
+
const close = () => {
|
|
778
|
+
done();
|
|
779
|
+
resolveOnce();
|
|
780
|
+
};
|
|
781
|
+
const selector = new LinxStatusLineSelectorComponent(readLinxStatusLineConfig(), ({ tokens, useColors }) => {
|
|
782
|
+
writeInteractiveStatusLineConfig(interactive, {
|
|
783
|
+
statusLine: tokens,
|
|
784
|
+
statusLineUseColors: useColors,
|
|
785
|
+
message: `Status line updated: ${tokens.join(', ')}`,
|
|
786
|
+
});
|
|
787
|
+
close();
|
|
788
|
+
}, () => {
|
|
789
|
+
close();
|
|
790
|
+
interactive.ui?.requestRender?.();
|
|
791
|
+
});
|
|
792
|
+
return { component: selector, focus: selector.getList() };
|
|
793
|
+
});
|
|
794
|
+
}
|
|
795
|
+
catch (error) {
|
|
796
|
+
rejectPromise(error);
|
|
797
|
+
}
|
|
798
|
+
});
|
|
799
|
+
}
|
|
800
|
+
function buildInteractiveStatusLineOptions(config = readLinxStatusLineConfig()) {
|
|
801
|
+
const enabled = new Set(config.tokens);
|
|
802
|
+
return [
|
|
803
|
+
...LINX_STATUS_LINE_TOKEN_NAMES.map((token) => `${enabled.has(token) ? '✓' : '○'} ${token}`),
|
|
804
|
+
STATUS_LINE_CODEX_PRESET_OPTION,
|
|
805
|
+
STATUS_LINE_COMPACT_PRESET_OPTION,
|
|
806
|
+
STATUS_LINE_TOGGLE_COLORS_OPTION,
|
|
807
|
+
STATUS_LINE_RESET_OPTION,
|
|
808
|
+
STATUS_LINE_DONE_OPTION,
|
|
809
|
+
];
|
|
810
|
+
}
|
|
811
|
+
function parseInteractiveStatusLineTokenChoice(choice) {
|
|
812
|
+
if (typeof choice !== 'string') {
|
|
813
|
+
return null;
|
|
736
814
|
}
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
return;
|
|
815
|
+
const token = choice.replace(/^[✓○]\s*/u, '').trim();
|
|
816
|
+
if (!token) {
|
|
817
|
+
return null;
|
|
741
818
|
}
|
|
742
|
-
|
|
743
|
-
|
|
819
|
+
return LINX_STATUS_LINE_TOKEN_NAMES.includes(token)
|
|
820
|
+
? token
|
|
821
|
+
: null;
|
|
822
|
+
}
|
|
823
|
+
function toggleInteractiveStatusLineToken(interactive, token) {
|
|
824
|
+
const current = readLinxStatusLineConfig().tokens;
|
|
825
|
+
const exists = current.includes(token);
|
|
826
|
+
if (exists && current.length <= 1) {
|
|
827
|
+
interactive.showError?.('Status line needs at least one item.');
|
|
828
|
+
return;
|
|
744
829
|
}
|
|
830
|
+
const next = exists
|
|
831
|
+
? current.filter((item) => item !== token)
|
|
832
|
+
: [...current, token];
|
|
833
|
+
writeInteractiveStatusLineConfig(interactive, {
|
|
834
|
+
statusLine: next,
|
|
835
|
+
message: `Status line ${exists ? 'removed' : 'added'}: ${token}`,
|
|
836
|
+
});
|
|
745
837
|
}
|
|
746
838
|
function handleInteractiveStatusLineArgs(interactive, args) {
|
|
747
839
|
const action = args[0]?.toLowerCase();
|
|
@@ -779,20 +871,6 @@ function handleInteractiveStatusLineArgs(interactive, args) {
|
|
|
779
871
|
interactive.showError?.(`${message}. Use /statusline tokens to list valid tokens.`);
|
|
780
872
|
}
|
|
781
873
|
}
|
|
782
|
-
async function promptInteractiveStatusLineTokens(interactive) {
|
|
783
|
-
if (typeof interactive.showExtensionInput !== 'function') {
|
|
784
|
-
interactive.showStatus?.(`Use /statusline set ${CODEX_STYLE_STATUS_LINE_TOKENS.join(' ')}`);
|
|
785
|
-
interactive.ui?.requestRender?.();
|
|
786
|
-
return;
|
|
787
|
-
}
|
|
788
|
-
const value = await interactive.showExtensionInput('Status line tokens', CODEX_STYLE_STATUS_LINE_TOKENS.join(' '));
|
|
789
|
-
if (typeof value !== 'string' || !value.trim()) {
|
|
790
|
-
interactive.showStatus?.('Status line unchanged.');
|
|
791
|
-
interactive.ui?.requestRender?.();
|
|
792
|
-
return;
|
|
793
|
-
}
|
|
794
|
-
handleInteractiveStatusLineArgs(interactive, ['set', ...splitInteractiveCommandArgs(value)]);
|
|
795
|
-
}
|
|
796
874
|
function writeInteractiveStatusLineConfig(interactive, patch) {
|
|
797
875
|
writeLinxStatusLineConfigPatch({
|
|
798
876
|
...(patch.statusLine ? { statusLine: patch.statusLine } : {}),
|
|
@@ -1159,6 +1237,178 @@ function refreshInteractiveTranscriptFromSessionManager(interactive) {
|
|
|
1159
1237
|
interactive?.showWarning?.(`Rewind transcript refresh failed: ${message}`);
|
|
1160
1238
|
}
|
|
1161
1239
|
}
|
|
1240
|
+
class LinxMultiSelectList {
|
|
1241
|
+
getRows;
|
|
1242
|
+
onToggle;
|
|
1243
|
+
onAction;
|
|
1244
|
+
onCancel;
|
|
1245
|
+
selectedIndex = 0;
|
|
1246
|
+
constructor(getRows, onToggle, onAction, onCancel) {
|
|
1247
|
+
this.getRows = getRows;
|
|
1248
|
+
this.onToggle = onToggle;
|
|
1249
|
+
this.onAction = onAction;
|
|
1250
|
+
this.onCancel = onCancel;
|
|
1251
|
+
}
|
|
1252
|
+
invalidate() {
|
|
1253
|
+
// No cached render state.
|
|
1254
|
+
}
|
|
1255
|
+
render(width) {
|
|
1256
|
+
const rows = this.normalizedRows();
|
|
1257
|
+
if (rows.length === 0) {
|
|
1258
|
+
return [' No options'];
|
|
1259
|
+
}
|
|
1260
|
+
const lines = [];
|
|
1261
|
+
for (let index = 0; index < rows.length; index += 1) {
|
|
1262
|
+
const row = rows[index];
|
|
1263
|
+
const cursor = index === this.selectedIndex ? '> ' : ' ';
|
|
1264
|
+
const label = row.kind === 'item'
|
|
1265
|
+
? `${row.selected ? '✓' : '○'} ${row.label}`
|
|
1266
|
+
: row.label;
|
|
1267
|
+
lines.push(`${cursor}${truncateToWidth(label, Math.max(1, width - 2))}`);
|
|
1268
|
+
if (row.description) {
|
|
1269
|
+
lines.push(` ${truncateToWidth(row.description, Math.max(1, width - 2))}`);
|
|
1270
|
+
}
|
|
1271
|
+
}
|
|
1272
|
+
lines.push('');
|
|
1273
|
+
lines.push('↑↓ navigate Enter toggles items/actions Escape/Ctrl+C cancel');
|
|
1274
|
+
return lines;
|
|
1275
|
+
}
|
|
1276
|
+
handleInput(keyData) {
|
|
1277
|
+
const rows = this.normalizedRows();
|
|
1278
|
+
if (rows.length === 0) {
|
|
1279
|
+
return;
|
|
1280
|
+
}
|
|
1281
|
+
const keybindings = getKeybindings();
|
|
1282
|
+
if (keybindings.matches(keyData, 'tui.select.up')) {
|
|
1283
|
+
this.selectedIndex = this.selectedIndex === 0 ? rows.length - 1 : this.selectedIndex - 1;
|
|
1284
|
+
return;
|
|
1285
|
+
}
|
|
1286
|
+
if (keybindings.matches(keyData, 'tui.select.down')) {
|
|
1287
|
+
this.selectedIndex = this.selectedIndex === rows.length - 1 ? 0 : this.selectedIndex + 1;
|
|
1288
|
+
return;
|
|
1289
|
+
}
|
|
1290
|
+
if (keybindings.matches(keyData, 'tui.select.confirm')) {
|
|
1291
|
+
const selected = rows[this.selectedIndex];
|
|
1292
|
+
if (selected?.kind === 'item') {
|
|
1293
|
+
this.onToggle(selected.id);
|
|
1294
|
+
}
|
|
1295
|
+
else if (selected?.kind === 'action') {
|
|
1296
|
+
this.onAction(selected.id);
|
|
1297
|
+
}
|
|
1298
|
+
return;
|
|
1299
|
+
}
|
|
1300
|
+
if (keybindings.matches(keyData, 'tui.select.cancel')) {
|
|
1301
|
+
this.onCancel();
|
|
1302
|
+
}
|
|
1303
|
+
}
|
|
1304
|
+
normalizedRows() {
|
|
1305
|
+
const rows = this.getRows();
|
|
1306
|
+
if (this.selectedIndex >= rows.length) {
|
|
1307
|
+
this.selectedIndex = Math.max(0, rows.length - 1);
|
|
1308
|
+
}
|
|
1309
|
+
return rows;
|
|
1310
|
+
}
|
|
1311
|
+
}
|
|
1312
|
+
class LinxStatusLineSelectorComponent extends Container {
|
|
1313
|
+
list;
|
|
1314
|
+
draftTokens;
|
|
1315
|
+
draftUseColors;
|
|
1316
|
+
notice = null;
|
|
1317
|
+
constructor(config, onCommit, onCancel) {
|
|
1318
|
+
super();
|
|
1319
|
+
this.draftTokens = [...config.tokens];
|
|
1320
|
+
this.draftUseColors = config.useColors;
|
|
1321
|
+
this.addChild(new Spacer(1));
|
|
1322
|
+
this.addChild(new Text('Status line', 1, 0));
|
|
1323
|
+
this.addChild(new Text('Select the items that appear in the bottom TUI status line.', 1, 0));
|
|
1324
|
+
this.addChild(new Text(`Current source: tokens ${config.tokenSource}, colors ${config.colorSource}.`, 1, 0));
|
|
1325
|
+
this.addChild(new Spacer(1));
|
|
1326
|
+
this.list = new LinxMultiSelectList(() => this.rows(), (id) => this.toggleToken(id), (id) => this.handleAction(id, onCommit), onCancel);
|
|
1327
|
+
this.addChild(this.list);
|
|
1328
|
+
}
|
|
1329
|
+
getList() {
|
|
1330
|
+
return this.list;
|
|
1331
|
+
}
|
|
1332
|
+
rows() {
|
|
1333
|
+
const enabled = new Set(this.draftTokens);
|
|
1334
|
+
const rows = LINX_STATUS_LINE_TOKEN_NAMES.map((token) => ({
|
|
1335
|
+
kind: 'item',
|
|
1336
|
+
id: token,
|
|
1337
|
+
label: token,
|
|
1338
|
+
selected: enabled.has(token),
|
|
1339
|
+
}));
|
|
1340
|
+
rows.push({
|
|
1341
|
+
kind: 'action',
|
|
1342
|
+
id: 'preset-codex',
|
|
1343
|
+
label: STATUS_LINE_CODEX_PRESET_OPTION,
|
|
1344
|
+
description: CODEX_STYLE_STATUS_LINE_TOKENS.join(', '),
|
|
1345
|
+
}, {
|
|
1346
|
+
kind: 'action',
|
|
1347
|
+
id: 'preset-compact',
|
|
1348
|
+
label: STATUS_LINE_COMPACT_PRESET_OPTION,
|
|
1349
|
+
description: COMPACT_STATUS_LINE_TOKENS.join(', '),
|
|
1350
|
+
}, {
|
|
1351
|
+
kind: 'action',
|
|
1352
|
+
id: 'toggle-colors',
|
|
1353
|
+
label: `${STATUS_LINE_TOGGLE_COLORS_OPTION}: ${this.draftUseColors ? 'on' : 'off'}`,
|
|
1354
|
+
}, {
|
|
1355
|
+
kind: 'action',
|
|
1356
|
+
id: 'reset',
|
|
1357
|
+
label: STATUS_LINE_RESET_OPTION,
|
|
1358
|
+
description: DEFAULT_STATUS_LINE_TOKENS.join(', '),
|
|
1359
|
+
}, {
|
|
1360
|
+
kind: 'action',
|
|
1361
|
+
id: 'done',
|
|
1362
|
+
label: STATUS_LINE_DONE_OPTION,
|
|
1363
|
+
description: this.notice ?? 'Save changes and close.',
|
|
1364
|
+
});
|
|
1365
|
+
return rows;
|
|
1366
|
+
}
|
|
1367
|
+
toggleToken(id) {
|
|
1368
|
+
const token = id;
|
|
1369
|
+
if (!LINX_STATUS_LINE_TOKEN_NAMES.includes(token)) {
|
|
1370
|
+
return;
|
|
1371
|
+
}
|
|
1372
|
+
const exists = this.draftTokens.includes(token);
|
|
1373
|
+
if (exists && this.draftTokens.length <= 1) {
|
|
1374
|
+
this.notice = 'Status line needs at least one item.';
|
|
1375
|
+
return;
|
|
1376
|
+
}
|
|
1377
|
+
this.draftTokens = exists
|
|
1378
|
+
? this.draftTokens.filter((item) => item !== token)
|
|
1379
|
+
: [...this.draftTokens, token];
|
|
1380
|
+
this.notice = null;
|
|
1381
|
+
}
|
|
1382
|
+
handleAction(id, onCommit) {
|
|
1383
|
+
if (id === 'preset-codex') {
|
|
1384
|
+
this.draftTokens = [...CODEX_STYLE_STATUS_LINE_TOKENS];
|
|
1385
|
+
this.notice = 'Draft changed to Codex-style preset.';
|
|
1386
|
+
return;
|
|
1387
|
+
}
|
|
1388
|
+
if (id === 'preset-compact') {
|
|
1389
|
+
this.draftTokens = [...COMPACT_STATUS_LINE_TOKENS];
|
|
1390
|
+
this.notice = 'Draft changed to compact preset.';
|
|
1391
|
+
return;
|
|
1392
|
+
}
|
|
1393
|
+
if (id === 'toggle-colors') {
|
|
1394
|
+
this.draftUseColors = !this.draftUseColors;
|
|
1395
|
+
this.notice = `Draft colors ${this.draftUseColors ? 'enabled' : 'disabled'}.`;
|
|
1396
|
+
return;
|
|
1397
|
+
}
|
|
1398
|
+
if (id === 'reset') {
|
|
1399
|
+
this.draftTokens = [...DEFAULT_STATUS_LINE_TOKENS];
|
|
1400
|
+
this.draftUseColors = true;
|
|
1401
|
+
this.notice = 'Draft reset to default.';
|
|
1402
|
+
return;
|
|
1403
|
+
}
|
|
1404
|
+
if (id === 'done') {
|
|
1405
|
+
onCommit({
|
|
1406
|
+
tokens: this.draftTokens,
|
|
1407
|
+
useColors: this.draftUseColors,
|
|
1408
|
+
});
|
|
1409
|
+
}
|
|
1410
|
+
}
|
|
1411
|
+
}
|
|
1162
1412
|
function collectRewindUserMessages(_session, sessionManager) {
|
|
1163
1413
|
return getActiveSessionBranch(sessionManager)
|
|
1164
1414
|
.filter((entry) => entry?.type === 'message' && entry.message?.role === 'user')
|
|
@@ -1520,6 +1770,10 @@ const LINX_INTERACTIVE_SLASH_COMMANDS = [
|
|
|
1520
1770
|
{ value: 'reset', description: 'Restore default status line tokens' },
|
|
1521
1771
|
]),
|
|
1522
1772
|
},
|
|
1773
|
+
{
|
|
1774
|
+
name: 'update',
|
|
1775
|
+
description: 'check for a LinX CLI update and install from the TUI',
|
|
1776
|
+
},
|
|
1523
1777
|
{
|
|
1524
1778
|
name: 'ai',
|
|
1525
1779
|
argumentHint: 'connect <provider>',
|