@toddzheng024/dscode-bundle 0.7.25 → 0.7.27
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/package.json +2 -1
- package/plugins/openrouter/wire.mjs +3 -0
- package/plugins/session-metrics/index.mjs +16 -7
- package/plugins/session-metrics/rate.mjs +26 -61
- package/plugins/session-metrics/view.mjs +26 -12
- package/plugins/triggers/cli.mjs +155 -36
- package/plugins/triggers/commands.mjs +140 -0
- package/plugins/triggers/config.mjs +32 -13
- package/plugins/triggers/host.mjs +28 -21
- package/plugins/triggers/index.mjs +17 -47
- package/plugins/triggers/job-cli.mjs +110 -0
- package/plugins/triggers/jobs.mjs +156 -0
- package/plugins/triggers/lease.mjs +24 -0
- package/plugins/triggers/management.mjs +181 -0
- package/plugins/triggers/options.mjs +8 -0
- package/plugins/triggers/poll.mjs +12 -4
- package/plugins/triggers/run.mjs +1 -0
- package/plugins/triggers/schedule.mjs +40 -0
- package/plugins/triggers/scheduler-service.mjs +46 -0
- package/plugins/triggers/scheduler.mjs +90 -0
- package/plugins/triggers/session.mjs +43 -0
- package/plugins/triggers/source-emit.mjs +19 -0
- package/plugins/triggers/source-host.mjs +78 -0
- package/plugins/triggers/source-ingress.mjs +70 -0
- package/plugins/triggers/source-sandbox.mjs +35 -0
- package/plugins/triggers/sources.mjs +45 -0
- package/plugins/triggers/spool.mjs +23 -6
- package/plugins/triggers/tools.mjs +74 -0
- package/vendor/tui/lib/app.mjs +66 -87
- package/vendor/tui/lib/dscode/preset.mjs +18 -0
- package/vendor/tui/lib/dscode/telemetry.mjs +25 -9
- package/vendor/tui/lib/index.mjs +22 -78
- package/vendor/tui/lib/kernel-panels.mjs +3 -2
- package/vendor/tui/lib/locales/en.mjs +3 -2
- package/vendor/tui/lib/locales/zh.mjs +3 -2
- package/vendor/tui/lib/models.mjs +8 -0
- package/vendor/tui/lib/render/inspector.mjs +1 -1
- package/vendor/tui/lib/render/projection.mjs +11 -6
- package/vendor/tui/lib/render/status.mjs +39 -10
- package/vendor/tui/lib/startup.mjs +4 -5
package/vendor/tui/lib/app.mjs
CHANGED
|
@@ -30,7 +30,7 @@ import { imeCursorRowsUp, useImeCursorAnchor } from './render/ime-cursor.mjs';
|
|
|
30
30
|
import { readClipboardImage } from './dscode/clipboard-image/index.mjs';
|
|
31
31
|
import { createChatLinesCache, dscodeChatLines } from './dscode/chat.mjs';
|
|
32
32
|
import { readFileSync } from 'node:fs';
|
|
33
|
-
import {
|
|
33
|
+
import { footerFiguresFor as dscodeFooterFiguresFor } from '../../../plugins/session-metrics/view.mjs';
|
|
34
34
|
import { newerVersion as dscodeNewerVersion } from '../../../plugins/tui-tools/update.mjs';
|
|
35
35
|
import { languageName as dscodeLanguageName, normalizeLanguage as dscodeNormalizeLanguage, t as dscodeMessage } from '../../../plugins/i18n/messages.mjs';
|
|
36
36
|
import { dscodeTelemetryNodes } from './dscode/telemetry.mjs';
|
|
@@ -89,10 +89,11 @@ import { visibleColumns } from './render/markdown.mjs';
|
|
|
89
89
|
import { busyChaseFrame, BUSY_CHASE_TICK_MS, CARET_BLINK_TICK_MS, caretVisible, DEEP_DIVING_SHIMMER_TICK_MS, DEEPSEEK_WAVE_TICK_MS, deepseekWaveColumnBg, deepseekWaveDuration, deepseekWaveSpark, deepseekWaveStyleRandom, deepseekWaveTier, deepseekWaveWordHue, deepseekWaveWordVisible, deepDivingGradientColor, deepDivingSparkColor, flowColor, effortAboveHigh, isOfficialDeepSeekLabel, parseAnimationsArgument, RAINBOW_BURST_DURATION_MS, RAINBOW_BURST_TICK_MS, rainbowBurstColumnBg, rainbowSpectrumHue, } from './render/animations.mjs';
|
|
90
90
|
import { isSlashLine, submissionPayload } from './commands.mjs';
|
|
91
91
|
import { rankByName } from './render/fuzzy.mjs';
|
|
92
|
+
import { resolveModelEffort } from './models.mjs';
|
|
92
93
|
import { isDeclaredReasoningEfforts, parseReasoningEffortsDraft, serializeReasoningEfforts, } from './provider-settings.mjs';
|
|
93
94
|
import { isPathLikeMentionQuery } from './mentions.mjs';
|
|
94
95
|
import { createTranscriptStore } from './store.mjs';
|
|
95
|
-
import { AgentsPanel, editQuery, EffortPanel as NativeEffortPanel, HistoryPanel, JobsPanel,
|
|
96
|
+
import { AgentsPanel, editQuery, EffortPanel as NativeEffortPanel, HistoryPanel, JobsPanel, PermissionPanel, PluginPanel, ResumePanel, ReviewPickerPanel, SchedulePanel, SearchPanel, StatuslinePanel, runClock, SubagentPanel, UsagePanel } from './kernel-panels.mjs';
|
|
96
97
|
import { beginRecall, recallEntries, recallNewer, recallOlder, recordLocalEntry, } from './history.mjs';
|
|
97
98
|
import { authorizationForProvider, providerAuthorizationStatus, } from './authorization.mjs';
|
|
98
99
|
import { ProviderAuthorizationLogoutPanel, ProviderAuthorizationPanel } from './authorization-panel.mjs';
|
|
@@ -137,7 +138,6 @@ const LOCAL_COMMANDS = [
|
|
|
137
138
|
{ label: '/help', descriptionKey: 'cmd.help' },
|
|
138
139
|
{ label: '/model', descriptionKey: 'cmd.model' },
|
|
139
140
|
{ label: '/effort', descriptionKey: 'cmd.effort' },
|
|
140
|
-
{ label: '/mode', descriptionKey: 'cmd.mode' },
|
|
141
141
|
{ label: '/permission', descriptionKey: 'cmd.permission' },
|
|
142
142
|
{ label: '/new', descriptionKey: 'cmd.new' },
|
|
143
143
|
{ label: '/fork', descriptionKey: 'cmd.fork' },
|
|
@@ -179,7 +179,7 @@ const LOCAL_COMMANDS = [
|
|
|
179
179
|
{ label: '/review', descriptionKey: 'cmd.review' },
|
|
180
180
|
{ label: '/quit', descriptionKey: 'cmd.quit' },
|
|
181
181
|
];
|
|
182
|
-
const LOCAL_COMMAND_NAMES = new Set(LOCAL_COMMANDS.map(command => command.label.slice(1)));
|
|
182
|
+
const LOCAL_COMMAND_NAMES = new Set([...LOCAL_COMMANDS.map(command => command.label.slice(1)), 'mode']);
|
|
183
183
|
/** Pad text with spaces to a visible-column target (menu name column). */
|
|
184
184
|
function padColumns(text, width) {
|
|
185
185
|
const clipped = truncateColumns(singleLineText(text), width);
|
|
@@ -990,13 +990,13 @@ function statusToneProps(tone, flowMs) {
|
|
|
990
990
|
}
|
|
991
991
|
}
|
|
992
992
|
/**
|
|
993
|
-
* The footer status line: two
|
|
993
|
+
* The footer status line: two rows, or three when finances need their own row. Row 1
|
|
994
994
|
* carries Claude-Code-style identity facts and session figures from the left
|
|
995
995
|
* with the Codex-style permission badge — the autonomous-selection anchor
|
|
996
996
|
* with its shift+tab cycle hint — pinned to the right edge. Row 2 (mode,
|
|
997
997
|
* context progress bar, cache, duration figures) renders only while it has
|
|
998
|
-
* content,
|
|
999
|
-
*
|
|
998
|
+
* content, and the financial group moves to row 3 when needed. All rows
|
|
999
|
+
* arrive pre-measured from the pure reducer, so Ink only paints;
|
|
1000
1000
|
* truncation degrades groups, it never wraps a row.
|
|
1001
1001
|
*
|
|
1002
1002
|
* The DeepSeek easter egg: when the model label *switches* to an official
|
|
@@ -1038,18 +1038,11 @@ export function StatusLine({ facts, stats, busy, columns, items, onRows, animate
|
|
|
1038
1038
|
const timer = setInterval(() => dscodeRefreshMetrics(n => n + 1), 1000);
|
|
1039
1039
|
return () => clearInterval(timer);
|
|
1040
1040
|
}, []);
|
|
1041
|
-
//
|
|
1042
|
-
//
|
|
1043
|
-
// laid out against the same width budget as before, and its own ladder decides
|
|
1044
|
-
// which figures fit.
|
|
1045
|
-
const telemetryWidth = Math.max(1, Math.min(columns - 8, Math.max(40, Math.floor(columns * 0.8) - 4) + FOOTER_FIGURE_RESERVE));
|
|
1046
|
-
// The figures belong to the provider serving the route (`provider/model`).
|
|
1041
|
+
// Keep the figures structured: the layout can move the complete financial
|
|
1042
|
+
// group to a third row instead of dropping it to make the left group fit.
|
|
1047
1043
|
const slash = facts.model.indexOf('/');
|
|
1048
1044
|
const provider = slash > 0 ? facts.model.slice(0, slash) : 'deepseek-official';
|
|
1049
|
-
|
|
1050
|
-
? dscodeFooterFor(facts.fullSessionId, stats, telemetryWidth, provider, getLanguage())
|
|
1051
|
-
: '';
|
|
1052
|
-
facts = { ...facts, telemetry };
|
|
1045
|
+
facts = { ...facts, telemetryFigures: dscodeFooterFiguresFor(facts.fullSessionId, stats, provider, getLanguage()) };
|
|
1053
1046
|
// Flowing-theme busy flow: the identity cluster's live dot cycles the
|
|
1054
1047
|
// anchor walk while a turn runs; static themes never start the timer.
|
|
1055
1048
|
const flow = themeFlow();
|
|
@@ -1065,6 +1058,12 @@ export function StatusLine({ facts, stats, busy, columns, items, onRows, animate
|
|
|
1065
1058
|
contextWidth: Math.max(5, columns - 6),
|
|
1066
1059
|
}), [
|
|
1067
1060
|
facts.telemetry,
|
|
1061
|
+
facts.telemetryFigures?.current,
|
|
1062
|
+
facts.telemetryFigures?.average,
|
|
1063
|
+
facts.telemetryFigures?.context,
|
|
1064
|
+
facts.telemetryFigures?.money,
|
|
1065
|
+
facts.telemetryFigures?.cache,
|
|
1066
|
+
facts.telemetryFigures?.turn,
|
|
1068
1067
|
facts.model,
|
|
1069
1068
|
facts.effort,
|
|
1070
1069
|
facts.mode,
|
|
@@ -1089,7 +1088,7 @@ export function StatusLine({ facts, stats, busy, columns, items, onRows, animate
|
|
|
1089
1088
|
// The IME anchor below the composer counts every row between the caret and
|
|
1090
1089
|
// Ink's parked cursor, so the footer reports its exact row count one-way
|
|
1091
1090
|
// (same contract as the composer's row report).
|
|
1092
|
-
const statusRowCount = layout.row2.left.length > 0 || layout.row2.right.length > 0 ? 2 : 1;
|
|
1091
|
+
const statusRowCount = layout.row3 !== undefined ? 3 : layout.row2.left.length > 0 || layout.row2.right.length > 0 ? 2 : 1;
|
|
1093
1092
|
useEffect(() => {
|
|
1094
1093
|
onRows?.(statusRowCount);
|
|
1095
1094
|
}, [onRows, statusRowCount]);
|
|
@@ -1099,10 +1098,10 @@ export function StatusLine({ facts, stats, busy, columns, items, onRows, animate
|
|
|
1099
1098
|
if (groupIndex > 0) {
|
|
1100
1099
|
leftParts.push(createElement(Text, { key: key + 'gs' + groupIndex, color: inkColor(getPalette().dim) }, STATUS_GROUP_SEPARATOR));
|
|
1101
1100
|
}
|
|
1102
|
-
const telemetryGroup = group.id ===
|
|
1101
|
+
const telemetryGroup = group.id?.startsWith('telemetry') === true;
|
|
1103
1102
|
group.spans.forEach((span, spanIndex) => {
|
|
1104
1103
|
const spanKey = key + 'g' + groupIndex + 's' + spanIndex;
|
|
1105
|
-
leftParts.push(createElement(Text, { key: spanKey, wrap: 'truncate-end', ...statusToneProps(span.tone, flowMs) }, telemetryGroup ? dscodeTelemetryNodes(span.text, spanKey) : span.text));
|
|
1104
|
+
leftParts.push(createElement(Text, { key: spanKey, wrap: 'truncate-end', ...statusToneProps(span.tone, flowMs) }, telemetryGroup ? dscodeTelemetryNodes(span.text, spanKey, animated) : span.text));
|
|
1106
1105
|
});
|
|
1107
1106
|
});
|
|
1108
1107
|
const rightParts = [];
|
|
@@ -1119,7 +1118,7 @@ export function StatusLine({ facts, stats, busy, columns, items, onRows, animate
|
|
|
1119
1118
|
if (index > 0) {
|
|
1120
1119
|
rightParts.push(createElement(Text, { key: key + 'rs' + index, color: inkColor(getPalette().dim) }, STATUS_ITEM_SEPARATOR));
|
|
1121
1120
|
}
|
|
1122
|
-
rightParts.push(createElement(Text, { key: key + 'r' + index, wrap: 'truncate-end', ...statusToneProps(span.tone, flowMs) }, span.text));
|
|
1121
|
+
rightParts.push(createElement(Text, { key: key + 'r' + index, wrap: 'truncate-end', ...statusToneProps(span.tone, flowMs) }, span.telemetry ? dscodeTelemetryNodes(span.text, key + 'r' + index, animated) : span.text));
|
|
1123
1122
|
});
|
|
1124
1123
|
// Each row already fits the column budget; truncate-end stays as the
|
|
1125
1124
|
// terminal-measurement backstop so a drifting cell count clips instead
|
|
@@ -1129,10 +1128,10 @@ export function StatusLine({ facts, stats, busy, columns, items, onRows, animate
|
|
|
1129
1128
|
// The secondary row adds the model-name indent
|
|
1130
1129
|
// (its budget already shrinks by the same amount) so its figures align
|
|
1131
1130
|
// under the model name rather than under the busy dot.
|
|
1132
|
-
{ paddingLeft: 2 + indent, width: columns, justifyContent: rightParts.length > 0 ? 'space-between' : undefined }, createElement(Text, { wrap: 'truncate-end' }, ...leftParts), rightParts.length > 0 ? createElement(Text, { wrap: 'truncate-end' }, ...rightParts) : undefined);
|
|
1131
|
+
{ paddingLeft: 2 + indent, width: columns, justifyContent: rightParts.length > 0 ? leftParts.length > 0 ? 'space-between' : 'flex-end' : undefined }, leftParts.length > 0 ? createElement(Text, { wrap: 'truncate-end' }, ...leftParts) : undefined, rightParts.length > 0 ? createElement(Text, { wrap: 'truncate-end' }, ...rightParts) : undefined);
|
|
1133
1132
|
};
|
|
1134
1133
|
const row2Present = layout.row2.left.length > 0 || layout.row2.right.length > 0;
|
|
1135
|
-
return createElement(Box, { flexDirection: 'column' }, renderRow(layout.row1, 's1'), row2Present ? renderRow(layout.row2, 's2', STATUS_ROW2_INDENT) : undefined);
|
|
1134
|
+
return createElement(Box, { flexDirection: 'column' }, renderRow(layout.row1, 's1'), row2Present ? renderRow(layout.row2, 's2', STATUS_ROW2_INDENT) : undefined, layout.row3 !== undefined ? renderRow(layout.row3, 's3', STATUS_ROW2_INDENT) : undefined);
|
|
1136
1135
|
}
|
|
1137
1136
|
/**
|
|
1138
1137
|
* One fixed-height local feedback row. Errors remain visible while a slash
|
|
@@ -3691,9 +3690,8 @@ function DscodeUltraFocus({ width, animations }) {
|
|
|
3691
3690
|
export function DscodeEffortBar({ row, current, select, back, onExit, animations = true }) {
|
|
3692
3691
|
const ids = ['low', 'high', 'max', 'ultra'];
|
|
3693
3692
|
const advertised = row.reasoning.efforts;
|
|
3694
|
-
const
|
|
3695
|
-
const
|
|
3696
|
-
const [cursor, setCursor] = useState(Math.max(0, ids.indexOf(initial)));
|
|
3693
|
+
const initial = resolveModelEffort(row, current);
|
|
3694
|
+
const [cursor, setCursor] = useState(Math.max(0, ids.indexOf(initial ?? '')));
|
|
3697
3695
|
useStableInput((input, key) => {
|
|
3698
3696
|
if (key.ctrl && input === 'c')
|
|
3699
3697
|
return onExit();
|
|
@@ -3726,7 +3724,7 @@ export function DscodeEffortBar({ row, current, select, back, onExit, animations
|
|
|
3726
3724
|
if (compact)
|
|
3727
3725
|
return createElement(Box, { flexDirection: 'column', paddingX: 2 }, createElement(Text, { color: inkColor(palette.brandBright), wrap: 'truncate-end' }, truncateColumns(ids.map(id => id === selected ? '[' + id + ']' : id).join(' '), contentWidth)), createElement(Text, { color: inkColor(palette.dim), wrap: 'truncate-end' }, truncateColumns('←→ adjust · enter confirm · esc cancel', contentWidth)));
|
|
3728
3726
|
const description = advertised.find(effort => effort.id === selected)?.description ?? '';
|
|
3729
|
-
const currentLabel =
|
|
3727
|
+
const currentLabel = initial || 'default';
|
|
3730
3728
|
const footer = '←/→ adjust · Enter confirm · Esc cancel' + (hasOff ? ' · o off' : '');
|
|
3731
3729
|
const trackNode = Math.floor((slot - 1) / 2);
|
|
3732
3730
|
const pointerColumn = barIndent + cursor * slot + trackNode;
|
|
@@ -3754,7 +3752,7 @@ export function DscodeEffortPanel(props) {
|
|
|
3754
3752
|
barIds.every(id => ids.includes(id)) && ids.every(id => id === 'off' || barIds.includes(id));
|
|
3755
3753
|
return createElement(barCatalog ? DscodeEffortBar : NativeEffortPanel, props);
|
|
3756
3754
|
}
|
|
3757
|
-
function Input({ effortSurface, ultraPulse, active, frozen, frozenHint, busy, descriptors, skills, dispatch, steer, submitMode, cycleSubmitMode, interrupt, quit, openEmail, openLogin, openProvider, openOpenRouter, openModel, openEffort, openHelp,
|
|
3755
|
+
function Input({ effortSurface, ultraPulse, active, frozen, frozenHint, busy, descriptors, skills, dispatch, steer, submitMode, cycleSubmitMode, interrupt, quit, openEmail, openLogin, openProvider, openOpenRouter, openModel, openEffort, openHelp, openPermission, openResume, openSearch, openPlugin, openUpdate, openSchedule, openJobs, openStatusline, openTheme, openLanguage, saveLanguage, openHistory, openQueue, openBtw, openAgents, openSubagent, openTodos, openUsage, openDelete, openDiff, openReviewPicker, reviewChanges, deleteConfirm, confirmDelete, cancelDelete, createSession, forkSession, cancelSessionSwitch, notify, applyEditorKeys, hasNotice, dismissNotice, toggleReasoning, openVerbose, clearView, refresh, loadMentions, inspectImages, prepareImages, inspectFiles, prepareFiles, readClipboardImage, cycleMode, exportTranscript, renameTitle, copyLastResponse, recallSpace, recordLocal, recordHistory, queued, updateQueued, historyFill, historyConsumed, animations, applyAnimations, applyRainbow, rainbowBurstId, waveTier, waveStyle, maxRows, anchorRowsBelow, tabTitle, onEditorRows, onMenuRows, sessionKey }) {
|
|
3758
3756
|
const { stdout: inputStdout } = useStdout();
|
|
3759
3757
|
const columns = inputStdout?.columns ?? 80;
|
|
3760
3758
|
const inputTerminalRows = inputStdout?.rows ?? 30;
|
|
@@ -4676,11 +4674,7 @@ function Input({ effortSurface, ultraPulse, active, frozen, frozenHint, busy, de
|
|
|
4676
4674
|
return;
|
|
4677
4675
|
}
|
|
4678
4676
|
if (text === '/mode' || text.startsWith('/mode ')) {
|
|
4679
|
-
|
|
4680
|
-
if (mode === '')
|
|
4681
|
-
openMode();
|
|
4682
|
-
else
|
|
4683
|
-
dispatch(text);
|
|
4677
|
+
notify(t('notice.modeLocked'), 'info');
|
|
4684
4678
|
return;
|
|
4685
4679
|
}
|
|
4686
4680
|
if (text === '/resume cancel') {
|
|
@@ -5599,7 +5593,6 @@ export function App(props) {
|
|
|
5599
5593
|
const [diffView, setDiffView] = useState(undefined);
|
|
5600
5594
|
const [reviewPickerOpen, setReviewPickerOpen] = useState(false);
|
|
5601
5595
|
const [helpOpen, setHelpOpen] = useState(false);
|
|
5602
|
-
const [modeOpen, setModeOpen] = useState(false);
|
|
5603
5596
|
const [permissionOpen, setPermissionOpen] = useState(false);
|
|
5604
5597
|
const [resumeOpen, setResumeOpen] = useState(false);
|
|
5605
5598
|
const [searchOpen, setSearchOpen] = useState(false);
|
|
@@ -5687,8 +5680,8 @@ export function App(props) {
|
|
|
5687
5680
|
// panel keypress.
|
|
5688
5681
|
const inputActive = deleteConfirmId !== undefined
|
|
5689
5682
|
? !approvalPending && !questionPending
|
|
5690
|
-
: !emailOpen && !modelOpen && !helpOpen && !
|
|
5691
|
-
const transcriptVisible = !btwOpen && !emailOpen && !modelOpen && !helpOpen && !
|
|
5683
|
+
: !emailOpen && !modelOpen && !helpOpen && !permissionOpen && !resumeOpen && !pluginOpen && !updateOpen && !scheduleOpen && !jobsOpen && !statuslineOpen && !themeOpen && !languageOpen && !historyOpen && !queueOpen && !agentsOpen && !subagentOpen && !todosOpen && !usageOpen && !verboseOpen && budgetPending === undefined && diffView === undefined && !reviewPickerOpen && !approvalPending && !questionPending;
|
|
5684
|
+
const transcriptVisible = !btwOpen && !emailOpen && !modelOpen && !helpOpen && !permissionOpen && !resumeOpen && !pluginOpen && !updateOpen && !scheduleOpen && !jobsOpen && !statuslineOpen && !themeOpen && !languageOpen && !historyOpen && !queueOpen && !agentsOpen && !subagentOpen && !todosOpen && !usageOpen && !verboseOpen && budgetPending === undefined && diffView === undefined && !reviewPickerOpen && !approvalPending && !questionPending;
|
|
5692
5685
|
// Human questions outrank local inspectors. Close the lower modal instead
|
|
5693
5686
|
// of leaving an approval/question visible but keyboard-locked behind it.
|
|
5694
5687
|
useEffect(() => {
|
|
@@ -5700,7 +5693,6 @@ export function App(props) {
|
|
|
5700
5693
|
setProviderAction(undefined);
|
|
5701
5694
|
setEffortFor(undefined);
|
|
5702
5695
|
setHelpOpen(false);
|
|
5703
|
-
setModeOpen(false);
|
|
5704
5696
|
setPermissionOpen(false);
|
|
5705
5697
|
setResumeOpen(false);
|
|
5706
5698
|
setPluginOpen(false);
|
|
@@ -5811,7 +5803,7 @@ export function App(props) {
|
|
|
5811
5803
|
setMenuRows(current => (current === rows ? current : rows));
|
|
5812
5804
|
}, []);
|
|
5813
5805
|
// The status footer's exact row count, reported one-way by StatusLine (the
|
|
5814
|
-
//
|
|
5806
|
+
// extra rows render only while they have content). The IME cursor anchor
|
|
5815
5807
|
// counts every row between the composer caret and Ink's parked cursor: the
|
|
5816
5808
|
// status footer plus Ink's own below-frame row. The gutter rows sit ABOVE
|
|
5817
5809
|
// the composer and never enter this distance.
|
|
@@ -5896,7 +5888,7 @@ export function App(props) {
|
|
|
5896
5888
|
const auditedReasoningRows = liveAudit.allocation.reasoning;
|
|
5897
5889
|
const auditedAnswerRows = liveAudit.allocation.answer;
|
|
5898
5890
|
const inspectorVisible = verboseOpen && !approvalPending && !questionPending;
|
|
5899
|
-
const modalVisible = budgetPending !== undefined || emailOpen || modelOpen || helpOpen
|
|
5891
|
+
const modalVisible = budgetPending !== undefined || emailOpen || modelOpen || helpOpen || permissionOpen || resumeOpen || pluginOpen || updateOpen || scheduleOpen || jobsOpen || statuslineOpen || themeOpen || languageOpen || historyOpen || queueOpen || agentsOpen || subagentOpen || todosOpen || usageOpen || inspectorVisible || diffView !== undefined || reviewPickerOpen || approvalPending || questionPending;
|
|
5900
5892
|
// The surface that currently owns the keyboard, named in the frozen band:
|
|
5901
5893
|
// an empty composer under a panel must not advertise typing it cannot
|
|
5902
5894
|
// accept — every key actually feeds the panel (which may or may not
|
|
@@ -5913,39 +5905,37 @@ export function App(props) {
|
|
|
5913
5905
|
? '/model'
|
|
5914
5906
|
: helpOpen
|
|
5915
5907
|
? '/help'
|
|
5916
|
-
:
|
|
5917
|
-
? '/
|
|
5918
|
-
:
|
|
5919
|
-
? '/
|
|
5920
|
-
:
|
|
5921
|
-
? '/
|
|
5922
|
-
:
|
|
5923
|
-
? '/
|
|
5924
|
-
:
|
|
5925
|
-
? '/
|
|
5926
|
-
:
|
|
5927
|
-
? '/
|
|
5928
|
-
:
|
|
5929
|
-
? '/
|
|
5930
|
-
:
|
|
5931
|
-
? '/
|
|
5932
|
-
:
|
|
5933
|
-
? '/
|
|
5934
|
-
:
|
|
5935
|
-
? '/
|
|
5936
|
-
:
|
|
5937
|
-
? '/
|
|
5938
|
-
:
|
|
5939
|
-
? '/
|
|
5940
|
-
:
|
|
5941
|
-
? '/
|
|
5942
|
-
:
|
|
5943
|
-
? '/
|
|
5944
|
-
:
|
|
5945
|
-
? '
|
|
5946
|
-
:
|
|
5947
|
-
? 'history details'
|
|
5948
|
-
: undefined;
|
|
5908
|
+
: permissionOpen
|
|
5909
|
+
? '/permission'
|
|
5910
|
+
: resumeOpen
|
|
5911
|
+
? '/resume'
|
|
5912
|
+
: pluginOpen
|
|
5913
|
+
? '/plugin'
|
|
5914
|
+
: updateOpen
|
|
5915
|
+
? '/update'
|
|
5916
|
+
: scheduleOpen
|
|
5917
|
+
? '/schedule'
|
|
5918
|
+
: jobsOpen
|
|
5919
|
+
? '/jobs'
|
|
5920
|
+
: statuslineOpen
|
|
5921
|
+
? '/statusline'
|
|
5922
|
+
: themeOpen
|
|
5923
|
+
? '/theme'
|
|
5924
|
+
: languageOpen
|
|
5925
|
+
? '/language'
|
|
5926
|
+
: historyOpen
|
|
5927
|
+
? '/history'
|
|
5928
|
+
: agentsOpen
|
|
5929
|
+
? '/agents'
|
|
5930
|
+
: subagentOpen
|
|
5931
|
+
? '/subagent'
|
|
5932
|
+
: todosOpen
|
|
5933
|
+
? '/todos'
|
|
5934
|
+
: usageOpen
|
|
5935
|
+
? '/usage'
|
|
5936
|
+
: inspectorVisible
|
|
5937
|
+
? 'history details'
|
|
5938
|
+
: undefined;
|
|
5949
5939
|
const frozenHint = keyboardOwner === undefined
|
|
5950
5940
|
? undefined
|
|
5951
5941
|
: `keys go to ${keyboardOwner} · esc ${approvalPending ? 'rejects' : questionPending ? 'cancels' : 'closes'}`;
|
|
@@ -6018,7 +6008,9 @@ export function App(props) {
|
|
|
6018
6008
|
try {
|
|
6019
6009
|
const label = props.selectModel(row, effortId);
|
|
6020
6010
|
setModelLabel(label);
|
|
6021
|
-
|
|
6011
|
+
// Keep the selected model's display default separate from the previous
|
|
6012
|
+
// request's effort. An empty label explicitly means no advertised default.
|
|
6013
|
+
setEffortLabel(resolveModelEffort(row, effortId) ?? '');
|
|
6022
6014
|
setUltraPulse(effortId === 'ultra' && animations ? Date.now() : 0);
|
|
6023
6015
|
const selected = `${label}${effortId === undefined || effortId === '' ? '' : `@${effortId}`}`;
|
|
6024
6016
|
if (sessionHasImages && row.inputModalities !== undefined && !row.inputModalities.includes('image')) {
|
|
@@ -6502,18 +6494,6 @@ export function App(props) {
|
|
|
6502
6494
|
entries: view.entries,
|
|
6503
6495
|
onClose: closeInspector,
|
|
6504
6496
|
})
|
|
6505
|
-
: undefined, modeOpen && !approvalPending && !questionPending
|
|
6506
|
-
? createElement(ModePanel, {
|
|
6507
|
-
current: props.mode,
|
|
6508
|
-
load: props.loadPresets,
|
|
6509
|
-
select: (id) => {
|
|
6510
|
-
void props.switchMode(id).then(label => {
|
|
6511
|
-
notify(t('notice.modeChangedSimple', { value: label }));
|
|
6512
|
-
setModeOpen(false);
|
|
6513
|
-
}, (reason) => notify(t('notice.modeSwitchFailed', { message: reason instanceof Error ? reason.message : String(reason) }), 'error'));
|
|
6514
|
-
},
|
|
6515
|
-
close: () => setModeOpen(false),
|
|
6516
|
-
})
|
|
6517
6497
|
: undefined, permissionOpen && !approvalPending && !questionPending
|
|
6518
6498
|
? createElement(PermissionPanel, {
|
|
6519
6499
|
current: props.permission,
|
|
@@ -6771,7 +6751,6 @@ export function App(props) {
|
|
|
6771
6751
|
openHelp: () => {
|
|
6772
6752
|
setHelpOpen(true);
|
|
6773
6753
|
},
|
|
6774
|
-
openMode: () => setModeOpen(true),
|
|
6775
6754
|
openPermission: () => setPermissionOpen(true),
|
|
6776
6755
|
openResume: () => { setResumeDelete({ mode: false }); setResumeOpen(true); },
|
|
6777
6756
|
openSearch: (query) => {
|
|
@@ -6878,7 +6857,7 @@ export function App(props) {
|
|
|
6878
6857
|
facts: {
|
|
6879
6858
|
fullSessionId: props.sessionKey,
|
|
6880
6859
|
model: modelLabel,
|
|
6881
|
-
effort: effortLabel,
|
|
6860
|
+
effort: effortLabel ?? (modelLabel === view.model ? view.stats.reasoningEffort : undefined),
|
|
6882
6861
|
mode: props.mode,
|
|
6883
6862
|
cwd: props.cwd,
|
|
6884
6863
|
branch: props.branch,
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { resolvePreset } from '../presets.mjs';
|
|
2
|
+
export const DSCODE_PRESET = 'dscode';
|
|
3
|
+
export function requireDscodePreset(id) {
|
|
4
|
+
if (id !== undefined && id !== DSCODE_PRESET)
|
|
5
|
+
throw new Error('DSCODE is locked to the dscode preset; use /new to start a DSCODE session.');
|
|
6
|
+
return DSCODE_PRESET;
|
|
7
|
+
}
|
|
8
|
+
/** Mount before recording a migration; failed composition must leave history intact. */
|
|
9
|
+
export async function mountDscodePreset(service, ctx, session) {
|
|
10
|
+
const mounted = await service.mount(ctx, DSCODE_PRESET);
|
|
11
|
+
if (mounted.id !== DSCODE_PRESET)
|
|
12
|
+
throw new Error('The dscode preset did not resolve to DSCODE.');
|
|
13
|
+
if (resolvePreset(session) !== DSCODE_PRESET) {
|
|
14
|
+
const writable = session;
|
|
15
|
+
writable.append('agent-preset/selected', { agentPreset: DSCODE_PRESET });
|
|
16
|
+
}
|
|
17
|
+
return mounted;
|
|
18
|
+
}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*
|
|
5
5
|
* @module dsh-code/dscode/telemetry
|
|
6
6
|
*/
|
|
7
|
-
import { createElement } from 'react';
|
|
7
|
+
import { createElement, useEffect, useState } from 'react';
|
|
8
8
|
import { Text } from 'ink';
|
|
9
9
|
import { getPalette, getTheme, inkColor } from '../theme.mjs';
|
|
10
10
|
/** Request-rate tiers: yellow under 75 tps, green to 150, blue to 250, purple above. */
|
|
@@ -60,13 +60,15 @@ export function dscodeTelemetryParts(value) {
|
|
|
60
60
|
result.push({ text: ' · ', tone: null });
|
|
61
61
|
// A rate figure reserves its columns, so the padding stays outside the tinted
|
|
62
62
|
// run and only the reading carries the tier.
|
|
63
|
-
const rate = /^(\s*)(
|
|
63
|
+
const rate = /^(◌ )?(\s*)(\d+(?:\.\d+)?|--) tps( \S+)?$/.exec(part);
|
|
64
64
|
if (rate) {
|
|
65
|
-
|
|
66
|
-
|
|
65
|
+
if (rate[1])
|
|
66
|
+
result.push({ text: rate[1], tone: null, activity: true });
|
|
67
|
+
const display = rate[3];
|
|
68
|
+
result.push({ text: rate[2], tone: null }, { text: display + ' tps', tone: dscodeTpsTone(Number(display)) });
|
|
67
69
|
// The average's trailing qualifier rides along untinted.
|
|
68
|
-
if (rate[
|
|
69
|
-
result.push({ text: rate[
|
|
70
|
+
if (rate[4] !== undefined)
|
|
71
|
+
result.push({ text: rate[4], tone: null });
|
|
70
72
|
continue;
|
|
71
73
|
}
|
|
72
74
|
// Only a recognised cache label on the very last figure is tinted; the label
|
|
@@ -83,7 +85,21 @@ export function dscodeTelemetryParts(value) {
|
|
|
83
85
|
}
|
|
84
86
|
return result;
|
|
85
87
|
}
|
|
86
|
-
/**
|
|
87
|
-
|
|
88
|
-
|
|
88
|
+
/** Only this leaf ticks; neither the numeric reading nor ledger polling animates. */
|
|
89
|
+
function TpsActivity({ animated }) {
|
|
90
|
+
const [frame, setFrame] = useState(0);
|
|
91
|
+
useEffect(() => {
|
|
92
|
+
if (!animated)
|
|
93
|
+
return;
|
|
94
|
+
const timer = setInterval(() => setFrame(value => value + 1), 120);
|
|
95
|
+
return () => clearInterval(timer);
|
|
96
|
+
}, [animated]);
|
|
97
|
+
const frames = '⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏';
|
|
98
|
+
return createElement(Text, { color: inkColor(getPalette().brandMid) }, (animated ? frames[frame % frames.length] : '◌') + ' ');
|
|
99
|
+
}
|
|
100
|
+
/** The telemetry run as Ink nodes; only the request activity slot may move. */
|
|
101
|
+
export function dscodeTelemetryNodes(value, key, animated = false) {
|
|
102
|
+
return dscodeTelemetryParts(value).map((part, index) => part.activity
|
|
103
|
+
? createElement(TpsActivity, { key: key + 'p' + index, animated })
|
|
104
|
+
: createElement(Text, { key: key + 'p' + index, color: dscodeTpsInkColor(part.tone) }, part.text));
|
|
89
105
|
}
|
package/vendor/tui/lib/index.mjs
CHANGED
|
@@ -51,7 +51,8 @@ import { beginProviderAuthorization, cancelProviderAuthorization, loadProviderAu
|
|
|
51
51
|
import { selectForkSeed } from './fork.mjs';
|
|
52
52
|
import { buildReviewPrompt, listReviewBranches, listReviewCommits, loadCommitDiff, loadGitDiff, mergeBaseWith, } from './git-workflow.mjs';
|
|
53
53
|
import { SessionSwitchQueue } from './session-switch.mjs';
|
|
54
|
-
import { agentPresetsFrom
|
|
54
|
+
import { agentPresetsFrom } from './presets.mjs';
|
|
55
|
+
import { DSCODE_PRESET, requireDscodePreset, mountDscodePreset } from './dscode/preset.mjs';
|
|
55
56
|
import { applyPendingPermission, effectivePermission, listPermissionRows, permissionPresetsFrom, selectPermission, } from './permissions.mjs';
|
|
56
57
|
import { listPluginRows } from './plugin-inventory.mjs';
|
|
57
58
|
import { applyLauncherUpdate, probeLauncherUpdate } from './update.mjs';
|
|
@@ -472,6 +473,8 @@ async function run(ctx, startup, io) {
|
|
|
472
473
|
// Early process shutdown can dispose the tree while settlement is pending.
|
|
473
474
|
if (agents === undefined || defaultModel === undefined || sessions === undefined)
|
|
474
475
|
return;
|
|
476
|
+
if (startup.kind === 'fresh' || startup.kind === 'named')
|
|
477
|
+
requireDscodePreset(startup.mode);
|
|
475
478
|
const cwd = process.cwd();
|
|
476
479
|
// Live deployment default (web selectModel parity): read on every use, not
|
|
477
480
|
// snapshotted at launch, so a /model pick this process saves becomes the
|
|
@@ -494,20 +497,12 @@ async function run(ctx, startup, io) {
|
|
|
494
497
|
const selectionState = pendingSelection === undefined
|
|
495
498
|
? {}
|
|
496
499
|
: { picked: pendingSelection };
|
|
497
|
-
|
|
498
|
-
// An explicit `--mode` or the settings-layer service default may still name
|
|
499
|
-
// an id an upstream rename retired (code → ptc); normalize both.
|
|
500
|
-
if (!next.resume)
|
|
501
|
-
mode = (await presets.resolve(normalizePresetId(mode ?? presets.defaultId))).id;
|
|
500
|
+
const mode = requireDscodePreset(next.mode);
|
|
502
501
|
// 0.1.5 AgentSetup passes the composed agent as its second argument (the
|
|
503
502
|
// former `ctx.agent` accessor is gone); the preset mount still needs the
|
|
504
503
|
// agent-scoped context.
|
|
505
504
|
const setup = async (agentCtx, agent) => {
|
|
506
|
-
|
|
507
|
-
? resolvePreset(agent.session)
|
|
508
|
-
: mode;
|
|
509
|
-
const mounted = await presets.mount(agentCtx, sessionPreset);
|
|
510
|
-
mode = mounted.id;
|
|
505
|
+
await mountDscodePreset(presets, agentCtx, agent.session);
|
|
511
506
|
const selection = {
|
|
512
507
|
get current() {
|
|
513
508
|
return resolveEffectiveSelection(selectionState.picked, agent.session.requestHeader()?.config, currentDefaults());
|
|
@@ -578,7 +573,7 @@ async function run(ctx, startup, io) {
|
|
|
578
573
|
session,
|
|
579
574
|
store: createTranscriptStore(seedEvents),
|
|
580
575
|
mentions: createMentions(ctx, handle.agent, session.header.cwd ?? nextCwd),
|
|
581
|
-
mode
|
|
576
|
+
mode,
|
|
582
577
|
selection: selectionState,
|
|
583
578
|
resumed: next.resume,
|
|
584
579
|
...(folderWarning === undefined ? {} : { folderWarning }),
|
|
@@ -665,10 +660,6 @@ async function run(ctx, startup, io) {
|
|
|
665
660
|
let mentions = createMentions(ctx, undefined, cwd);
|
|
666
661
|
/** Explicit model pick made before any session exists (a bare launch). */
|
|
667
662
|
let pendingSelection;
|
|
668
|
-
/** Agent preset selected before the first session exists. */
|
|
669
|
-
let pendingMode;
|
|
670
|
-
/** Ordered pre-session preset resolutions; first composition awaits them. */
|
|
671
|
-
let pendingModeWork = Promise.resolve();
|
|
672
663
|
/** Permission preset selected before the first session exists. */
|
|
673
664
|
let pendingPermission;
|
|
674
665
|
/**
|
|
@@ -701,7 +692,7 @@ async function run(ctx, startup, io) {
|
|
|
701
692
|
}
|
|
702
693
|
preSessionPlanKnown = false;
|
|
703
694
|
void presets.compositionInventory().then(inventory => {
|
|
704
|
-
const id =
|
|
695
|
+
const id = DSCODE_PRESET;
|
|
705
696
|
preSessionPlanAvailable = inventory.some(composition => composition.id === id
|
|
706
697
|
&& composition.rows.some(row => row.moduleName === '@deepseek-ai/dsh-plan-mode' && row.enabled !== false));
|
|
707
698
|
preSessionPlanKnown = true;
|
|
@@ -1276,9 +1267,6 @@ async function run(ctx, startup, io) {
|
|
|
1276
1267
|
creating = true;
|
|
1277
1268
|
void compose(async () => {
|
|
1278
1269
|
try {
|
|
1279
|
-
// A direct `/mode <preset>` resolves asynchronously. Preserve submit
|
|
1280
|
-
// order so the first composition cannot race ahead with the old mode.
|
|
1281
|
-
await pendingModeWork;
|
|
1282
1270
|
// Another composition (e.g. a /resume activated while this creation
|
|
1283
1271
|
// waited its turn) may have published a session already: deliver the
|
|
1284
1272
|
// queued lines there instead of minting a competing fresh session
|
|
@@ -1308,7 +1296,6 @@ async function run(ctx, startup, io) {
|
|
|
1308
1296
|
subagents.reset();
|
|
1309
1297
|
for (const event of next.catalogSeed)
|
|
1310
1298
|
subagents.apply(event.data.childId, event);
|
|
1311
|
-
pendingMode = undefined;
|
|
1312
1299
|
pendingPermission = undefined;
|
|
1313
1300
|
commands.setAgent(agent);
|
|
1314
1301
|
skills.setAgent(agent);
|
|
@@ -1369,8 +1356,8 @@ async function run(ctx, startup, io) {
|
|
|
1369
1356
|
const line = submissionPayload(text);
|
|
1370
1357
|
if (line.trim() === '' && images.length === 0)
|
|
1371
1358
|
return;
|
|
1372
|
-
if (images.length === 0 && line.startsWith('/mode ')) {
|
|
1373
|
-
|
|
1359
|
+
if (images.length === 0 && (line === '/mode' || line.startsWith('/mode '))) {
|
|
1360
|
+
bridge.notify('DSCODE mode is fixed to dscode.', 'info');
|
|
1374
1361
|
return;
|
|
1375
1362
|
}
|
|
1376
1363
|
if (images.length === 0 && line.startsWith('/permission ')) {
|
|
@@ -1801,50 +1788,6 @@ async function run(ctx, startup, io) {
|
|
|
1801
1788
|
turns: turnUsages(events, deriveTurnTokenUsage, turnCostsFor(current.id, events)),
|
|
1802
1789
|
});
|
|
1803
1790
|
};
|
|
1804
|
-
const switchModeAction = async (id) => {
|
|
1805
|
-
if (id === '')
|
|
1806
|
-
throw new Error('usage: /mode <preset>');
|
|
1807
|
-
const currentAgent = agent;
|
|
1808
|
-
if (currentAgent === undefined) {
|
|
1809
|
-
const choice = pendingModeWork.then(async () => {
|
|
1810
|
-
const preset = await selectPreset(presets, undefined, id);
|
|
1811
|
-
// A resume may have won while this roster read was in flight; never
|
|
1812
|
-
// leak the old pending choice into a later /new session.
|
|
1813
|
-
if (agent === undefined) {
|
|
1814
|
-
pendingMode = preset.id;
|
|
1815
|
-
renderCurrent();
|
|
1816
|
-
}
|
|
1817
|
-
return preset.id;
|
|
1818
|
-
});
|
|
1819
|
-
pendingModeWork = choice.then(() => { }, () => { });
|
|
1820
|
-
return choice;
|
|
1821
|
-
}
|
|
1822
|
-
// Serialize the recomposition with session activations: a /mode that
|
|
1823
|
-
// interleaves a switch must not rebind the shared command/skill
|
|
1824
|
-
// registries while the switch is composing the next agent.
|
|
1825
|
-
const currentActive = active;
|
|
1826
|
-
const atEpoch = epoch;
|
|
1827
|
-
let selected;
|
|
1828
|
-
await compose(async () => {
|
|
1829
|
-
const preset = await selectPreset(presets, currentAgent, id);
|
|
1830
|
-
// A switch/quit landed while the recomposition ran: applying here
|
|
1831
|
-
// would write the old choice into the new session's state and rebind
|
|
1832
|
-
// the registries back to a disposed agent. The preset-selection log
|
|
1833
|
-
// entry rode the old agent's session; only the local application is
|
|
1834
|
-
// dropped.
|
|
1835
|
-
if (epoch !== atEpoch || agent !== currentAgent || active !== currentActive) {
|
|
1836
|
-
throw new Error('session changed while switching mode — nothing applied; retry in the active session');
|
|
1837
|
-
}
|
|
1838
|
-
if (active === undefined)
|
|
1839
|
-
throw new Error('active Agent has no session state');
|
|
1840
|
-
active.mode = preset.id;
|
|
1841
|
-
commands.setAgent(currentAgent);
|
|
1842
|
-
skills.setAgent(currentAgent);
|
|
1843
|
-
selected = preset.id;
|
|
1844
|
-
renderCurrent();
|
|
1845
|
-
});
|
|
1846
|
-
return selected;
|
|
1847
|
-
};
|
|
1848
1791
|
const activate = (nextTarget) => {
|
|
1849
1792
|
if (quitting)
|
|
1850
1793
|
return Promise.resolve();
|
|
@@ -1885,12 +1828,11 @@ async function run(ctx, startup, io) {
|
|
|
1885
1828
|
renderCurrent();
|
|
1886
1829
|
// Only a successful handoff may clear the transient per-session
|
|
1887
1830
|
// surfaces: a rolled-back switch keeps the previous session's
|
|
1888
|
-
// subagent feed plus the user's pre-session
|
|
1831
|
+
// subagent feed plus the user's pre-session model and permission
|
|
1889
1832
|
// picks (the bare-launch promise: explicit choices survive until
|
|
1890
1833
|
// composition takes them). The in-flight cycle intent belonged to
|
|
1891
1834
|
// the previous session's presses; the new session's committed fold
|
|
1892
1835
|
// decides from here.
|
|
1893
|
-
pendingMode = undefined;
|
|
1894
1836
|
pendingPermission = undefined;
|
|
1895
1837
|
pendingPlan = false;
|
|
1896
1838
|
planIntent = undefined;
|
|
@@ -2007,6 +1949,13 @@ async function run(ctx, startup, io) {
|
|
|
2007
1949
|
}, (error) => bridge.notify(`resume failed: ${error instanceof Error ? error.message : String(error)}`, 'error'));
|
|
2008
1950
|
};
|
|
2009
1951
|
const createSession = (mode) => {
|
|
1952
|
+
try {
|
|
1953
|
+
requireDscodePreset(mode);
|
|
1954
|
+
}
|
|
1955
|
+
catch (error) {
|
|
1956
|
+
bridge.notify(error instanceof Error ? error.message : String(error), 'error');
|
|
1957
|
+
return;
|
|
1958
|
+
}
|
|
2010
1959
|
// /new before any input is the first-session creation itself, not a switch.
|
|
2011
1960
|
if (session === undefined) {
|
|
2012
1961
|
ensureSession(mode);
|
|
@@ -2199,12 +2148,9 @@ async function run(ctx, startup, io) {
|
|
|
2199
2148
|
const sessionCwd = session?.header.cwd ?? cwd;
|
|
2200
2149
|
const currentView = store.getView();
|
|
2201
2150
|
const defaults = currentDefaults();
|
|
2202
|
-
const
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
? `${pendingSelection.provider}/${pendingSelection.model}`
|
|
2206
|
-
: `${defaults.provider}/${defaults.model}`;
|
|
2207
|
-
const effort = resolveEffectiveSelection(active?.selection.picked ?? pendingSelection, session?.requestHeader()?.config, defaults).reasoningEffort;
|
|
2151
|
+
const selection = resolveEffectiveSelection(active?.selection.picked ?? pendingSelection, session?.requestHeader()?.config, defaults);
|
|
2152
|
+
const model = `${selection.provider}/${selection.model}`;
|
|
2153
|
+
const effort = selection.reasoningEffort;
|
|
2208
2154
|
const permission = permissionPresets === undefined
|
|
2209
2155
|
? currentView.permission
|
|
2210
2156
|
: effectivePermission(permissionPresets, session, pendingPermission);
|
|
@@ -2227,7 +2173,7 @@ async function run(ctx, startup, io) {
|
|
|
2227
2173
|
branch: gitBranch(sessionCwd),
|
|
2228
2174
|
sessionId: session === undefined ? '' : session.id.slice(-8),
|
|
2229
2175
|
resumed: active?.resumed ?? false,
|
|
2230
|
-
mode: active?.mode ??
|
|
2176
|
+
mode: active?.mode ?? DSCODE_PRESET,
|
|
2231
2177
|
permission,
|
|
2232
2178
|
/** Pre-session plan choice for the status badge until a session composes. */
|
|
2233
2179
|
pendingPlan: session === undefined && pendingPlan,
|
|
@@ -2277,8 +2223,6 @@ async function run(ctx, startup, io) {
|
|
|
2277
2223
|
listReviewBranches: (signal) => listReviewBranches(session?.header.cwd ?? cwd, signal),
|
|
2278
2224
|
listReviewCommits: (signal) => listReviewCommits(session?.header.cwd ?? cwd, signal),
|
|
2279
2225
|
reviewChanges,
|
|
2280
|
-
loadPresets: () => presets.list(),
|
|
2281
|
-
switchMode: switchModeAction,
|
|
2282
2226
|
loadPermissions: () => permissionPresets === undefined
|
|
2283
2227
|
? Promise.reject(new Error('permission presets are not mounted in this composition'))
|
|
2284
2228
|
: Promise.resolve(listPermissionRows(permissionPresets)),
|