@toddzheng024/dscode-bundle 0.7.5 → 0.7.7
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/THIRD_PARTY_NOTICES.md +3 -3
- package/cordis.patch.yml +26 -5
- package/package.json +4 -4
- package/plugins/auto-review/index.mjs +6 -1
- package/plugins/code-review/index.mjs +9 -4
- package/plugins/compaction/tetris.mjs +65 -0
- package/plugins/compaction/threshold.mjs +46 -0
- package/plugins/credentials/index.mjs +2 -2
- package/plugins/dscode/index.mjs +4 -10
- package/plugins/exec/cli.mjs +3 -2
- package/plugins/exec/index.mjs +6 -1
- package/plugins/i18n/messages.mjs +18 -0
- package/plugins/memory/index.mjs +7 -3
- package/plugins/openrouter/adapter.mjs +157 -0
- package/plugins/openrouter/index.mjs +112 -0
- package/plugins/openrouter/models.mjs +151 -0
- package/plugins/openrouter/search.mjs +109 -0
- package/plugins/openrouter/wire.mjs +413 -0
- package/plugins/providers/catalog.mjs +28 -26
- package/plugins/providers/effort.mjs +35 -0
- package/plugins/providers/openrouter-account.mjs +171 -0
- package/plugins/session-cards/index.mjs +5 -1
- package/plugins/session-metrics/balance.mjs +29 -19
- package/plugins/session-metrics/index.mjs +19 -6
- package/plugins/session-metrics/pricing.mjs +45 -14
- package/plugins/session-metrics/view.mjs +1 -1
- package/plugins/tui-tools/doctor.mjs +3 -1
- package/plugins/tui-tools/index.mjs +1 -1
- package/plugins/ultra/policy.mjs +0 -16
- package/presets/dscode/agent.cordis.yml +1 -1
- package/vendor/compaction-basic/index.js +983 -0
- package/vendor/compaction-basic/types/config.d.ts +37 -0
- package/vendor/compaction-basic/types/index.d.ts +84 -0
- package/vendor/compaction-basic/types/region.d.ts +65 -0
- package/vendor/compaction-basic/types/summarizer.d.ts +64 -0
- package/vendor/compaction-basic/types/types.d.ts +73 -0
- package/vendor/deepseek/index.js +1 -1
- package/vendor/subagent/index.js +3 -3
- package/vendor/tui/dscode-providers/catalog.mjs +28 -26
- package/vendor/tui/dscode-providers/effort.mjs +35 -0
- package/vendor/tui/dscode-providers/openrouter-account.mjs +171 -0
- package/vendor/tui/index.mjs +395 -133
- package/vendor/pi-ai/index.js +0 -2702
- package/vendor/pi-ai/types/adapter.d.ts +0 -105
- package/vendor/pi-ai/types/auth.d.ts +0 -60
- package/vendor/pi-ai/types/catalog.d.ts +0 -355
- package/vendor/pi-ai/types/config.d.ts +0 -208
- package/vendor/pi-ai/types/context.d.ts +0 -42
- package/vendor/pi-ai/types/discovery.d.ts +0 -43
- package/vendor/pi-ai/types/index.d.ts +0 -69
- package/vendor/pi-ai/types/login.d.ts +0 -21
- package/vendor/pi-ai/types/provider.d.ts +0 -59
- package/vendor/pi-ai/types/replay.d.ts +0 -63
- package/vendor/pi-ai/types/stream.d.ts +0 -43
- /package/vendor/{pi-ai → compaction-basic}/LICENSE +0 -0
package/vendor/tui/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// dscode-language-v2
|
|
2
2
|
// dscode-language-v1
|
|
3
3
|
const DSCODE_LANGUAGES = [{"code":"en","name":"English"},{"code":"zh-CN","name":"简体中文"},{"code":"zh-TW","name":"繁體中文"},{"code":"ja","name":"日本語"},{"code":"ko","name":"한국어"},{"code":"es","name":"Español"}];
|
|
4
|
-
const DSCODE_MESSAGES = {"en":{"activity.replying":"Replying","activity.thinking":"Thinking","activity.running":"Running","activity.turn":"this turn","activity.interrupt":"Esc to interrupt","agents.running":"running","agents.idle":"idle","agents.done":"done","agents.total":"total","welcome.model":"model","welcome.effort":"effort","welcome.project":"project","verbose.on":"verbose on: thinking and tool calls are shown in the chat","verbose.off":"verbose off","mouse.on":"mouse on: the wheel scrolls the chat · hold Shift while dragging to select text (Option in iTerm2, Fn in Terminal)","mouse.off":"mouse off: select and copy freely · PageUp/PageDown scroll the chat · /mouse turns wheel scrolling on","language.current":"Language: {name} · /language en | zh-CN | zh-TW | ja | ko | es","language.set":"language → {name}","language.title":"/language — interface language","language.currentMark":"current","language.unknown":"Unknown language \"{value}\". Choose en, zh-CN, zh-TW, ja, ko or es.","language.saveFailed":"language save failed: {error}","doctor.logs.new":"Only warnings/errors since this TUI version started are recorded.","footer.current":"current","footer.average":"average","footer.context":"context","footer.cache":"cache hit","composer.placeholder":"type a message","doctor.nearTimeout":"Assessment: {count} Bash calls ended at about 300 seconds, which matches the tool timeout; traces alone cannot prove the root cause. Next, check those calls' shell completion markers and terminal errors.","doctor.logs.none":"No log file yet; earlier console logs were not persisted and cannot be recovered.","doctor.evidence":"Diagnostic evidence: {traces} recent sessions, {logs} warnings/errors.","doctor.noFindings":"No clear timeouts, unfinished tool calls or error events in recent traces.","doctor.noRoute":"No model route is available, so the model analysis could not run.","doctor.scope":"Evidence scope: {traces} recent sessions, {logs} warnings/errors; conversation text, tool arguments and tool output were not read.","doctor.failed":"Model analysis did not finish: {error}."},"zh-CN":{"activity.replying":"正在回复","activity.thinking":"正在思考","activity.running":"正在执行","activity.turn":"本轮","activity.interrupt":"Esc 中断","agents.running":"运行中","agents.idle":"空闲","agents.done":"已完成","agents.total":"总计","welcome.model":"模型","welcome.effort":"推理","welcome.project":"项目","verbose.on":"详细模式已开启:对话中显示思考与工具调用","verbose.off":"详细模式已关闭","mouse.on":"鼠标捕获已开启:滚轮滚动对话 · 拖选文本时按住 Shift(iTerm2 按住 Option、Terminal 按住 Fn)","mouse.off":"鼠标捕获已关闭:可自由选择复制 · PageUp/PageDown 滚动对话 · /mouse 重新开启","language.current":"语言:{name} · /language en | zh-CN | zh-TW | ja | ko | es","language.set":"语言 → {name}","language.title":"/language — 界面语言","language.currentMark":"当前","language.unknown":"未知语言 \"{value}\"。可选 en、zh-CN、zh-TW、ja、ko、es。","language.saveFailed":"语言设置保存失败:{error}","doctor.logs.new":"仅记录新版 TUI 启动后的 warning/error。","footer.current":"当前","footer.average":"平均","footer.context":"上下文","footer.cache":"缓存命中","composer.placeholder":"输入消息","doctor.nearTimeout":"判断:{count} 次 Bash 调用在约 300 秒结束,符合工具超时特征;trace 不能单独证明触发超时的根因。下一步检查这些调用的 shell 完成标记和终端错误。","doctor.logs.none":"日志文件尚未建立;旧版控制台日志未持久化,无法回溯。","doctor.evidence":"诊断证据:{traces} 个近期会话、{logs} 条 warning/error。","doctor.noFindings":"近期 trace 中未发现明确的超时、未完成工具调用或错误事件。","doctor.noRoute":"没有可用的模型路由,无法运行模型分析。","doctor.scope":"证据范围:{traces} 个近期会话、{logs} 条 warning/error;未读取对话正文、工具参数或工具输出。","doctor.failed":"模型分析未完成:{error}。"},"zh-TW":{"activity.replying":"正在回覆","activity.thinking":"正在思考","activity.running":"正在執行","activity.turn":"本輪","activity.interrupt":"Esc 中斷","agents.running":"執行中","agents.idle":"閒置","agents.done":"已完成","agents.total":"總計","welcome.model":"模型","welcome.effort":"推理","welcome.project":"專案","verbose.on":"詳細模式已開啟:對話中顯示思考與工具呼叫","verbose.off":"詳細模式已關閉","mouse.on":"滑鼠擷取已開啟:滾輪捲動對話 · 拖選文字時按住 Shift(iTerm2 按住 Option、Terminal 按住 Fn)","mouse.off":"滑鼠擷取已關閉:可自由選取複製 · PageUp/PageDown 捲動對話 · /mouse 重新開啟","language.current":"語言:{name} · /language en | zh-CN | zh-TW | ja | ko | es","language.set":"語言 → {name}","language.title":"/language — 介面語言","language.currentMark":"目前","language.unknown":"未知語言 \"{value}\"。可選 en、zh-CN、zh-TW、ja、ko、es。","language.saveFailed":"語言設定儲存失敗:{error}","doctor.logs.new":"僅記錄新版 TUI 啟動後的 warning/error。","footer.current":"目前","footer.average":"平均","footer.context":"上下文","footer.cache":"快取命中","composer.placeholder":"輸入訊息","doctor.nearTimeout":"判斷:{count} 次 Bash 呼叫在約 300 秒結束,符合工具逾時特徵;trace 無法單獨證明觸發逾時的根因。下一步檢查這些呼叫的 shell 完成標記和終端錯誤。","doctor.logs.none":"日誌檔尚未建立;舊版主控台日誌未持久化,無法回溯。","doctor.evidence":"診斷證據:{traces} 個近期工作階段、{logs} 筆 warning/error。","doctor.noFindings":"近期 trace 中未發現明確的逾時、未完成工具呼叫或錯誤事件。","doctor.noRoute":"沒有可用的模型路由,無法執行模型分析。","doctor.scope":"證據範圍:{traces} 個近期工作階段、{logs} 筆 warning/error;未讀取對話內容、工具參數或工具輸出。","doctor.failed":"模型分析未完成:{error}。"},"ja":{"activity.replying":"応答中","activity.thinking":"思考中","activity.running":"実行中","activity.turn":"今回のターン","activity.interrupt":"Esc で中断","agents.running":"実行中","agents.idle":"待機中","agents.done":"完了","agents.total":"合計","welcome.model":"モデル","welcome.effort":"推論","welcome.project":"プロジェクト","verbose.on":"詳細モード オン:思考とツール呼び出しをチャットに表示します","verbose.off":"詳細モード オフ","mouse.on":"マウス キャプチャ オン:ホイールでチャットをスクロール · Shift(iTerm2 は Option、Terminal は Fn)を押しながらドラッグでテキスト選択","mouse.off":"マウス キャプチャ オフ:自由に選択・コピーできます · PageUp/PageDown でスクロール · /mouse で再びオン","language.current":"言語:{name} · /language en | zh-CN | zh-TW | ja | ko | es","language.set":"言語 → {name}","language.title":"/language — 表示言語","language.currentMark":"現在","language.unknown":"不明な言語 \"{value}\"。en、zh-CN、zh-TW、ja、ko、es から選んでください。","language.saveFailed":"言語設定の保存に失敗しました:{error}","doctor.logs.new":"この TUI バージョンの起動以降の warning/error のみ記録されています。","footer.current":"現在","footer.average":"平均","footer.context":"コンテキスト","footer.cache":"キャッシュヒット","composer.placeholder":"メッセージを入力","doctor.nearTimeout":"判断:Bash 呼び出し {count} 件が約 300 秒で終了しており、ツールのタイムアウトの特徴に一致します。トレースだけでは根本原因を証明できません。次はこれらの呼び出しのシェル完了マーカーと端末エラーを確認してください。","doctor.logs.none":"ログファイルはまだありません。以前のコンソールログは保存されておらず、遡れません。","doctor.evidence":"診断の根拠:直近のセッション {traces} 件、warning/error {logs} 件。","doctor.noFindings":"直近のトレースに明確なタイムアウト、未完了ツール、停滞は見つかりませんでした。","doctor.noRoute":"利用できるモデルルートがないため、モデル分析を実行できません。","doctor.scope":"根拠の範囲:直近のセッション {traces} 件、warning/error {logs} 件。会話本文、ツール引数、ツール出力は読んでいません。","doctor.failed":"モデル分析が完了しませんでした:{error}。"},"ko":{"activity.replying":"응답 중","activity.thinking":"생각 중","activity.running":"실행 중","activity.turn":"이번 턴","activity.interrupt":"Esc 중단","agents.running":"실행 중","agents.idle":"대기","agents.done":"완료","agents.total":"전체","welcome.model":"모델","welcome.effort":"추론","welcome.project":"프로젝트","verbose.on":"상세 모드 켜짐: 생각과 도구 호출을 채팅에 표시합니다","verbose.off":"상세 모드 꺼짐","mouse.on":"마우스 캡처 켜짐: 휠로 채팅 스크롤 · Shift(iTerm2는 Option, Terminal은 Fn)를 누른 채 드래그하여 텍스트 선택","mouse.off":"마우스 캡처 꺼짐: 자유롭게 선택·복사 · PageUp/PageDown으로 채팅 스크롤 · /mouse로 다시 켜기","language.current":"언어: {name} · /language en | zh-CN | zh-TW | ja | ko | es","language.set":"언어 → {name}","language.title":"/language — 인터페이스 언어","language.currentMark":"현재","language.unknown":"알 수 없는 언어 \"{value}\". en, zh-CN, zh-TW, ja, ko, es 중에서 선택하세요.","language.saveFailed":"언어 설정 저장 실패: {error}","doctor.logs.new":"이 TUI 버전 시작 이후의 warning/error만 기록됩니다.","footer.current":"현재","footer.average":"평균","footer.context":"컨텍스트","footer.cache":"캐시 적중","composer.placeholder":"메시지를 입력하세요","doctor.nearTimeout":"판단: Bash 호출 {count}건이 약 300초에 종료되어 도구 시간 초과 특징과 일치합니다. 트레이스만으로는 근본 원인을 증명할 수 없습니다. 다음으로 해당 호출의 셸 완료 표시와 터미널 오류를 확인하세요.","doctor.logs.none":"아직 로그 파일이 없습니다. 이전 콘솔 로그는 저장되지 않아 복구할 수 없습니다.","doctor.evidence":"진단 근거: 최근 세션 {traces}개, warning/error {logs}건.","doctor.noFindings":"최근 트레이스에서 명확한 시간 초과, 미완료 도구, 정지는 발견되지 않았습니다.","doctor.noRoute":"사용 가능한 모델 경로가 없어 모델 분석을 실행할 수 없습니다.","doctor.scope":"근거 범위: 최근 세션 {traces}개, warning/error {logs}건. 대화 본문, 도구 인수, 도구 출력은 읽지 않았습니다.","doctor.failed":"모델 분석이 완료되지 않았습니다: {error}."},"es":{"activity.replying":"Respondiendo","activity.thinking":"Pensando","activity.running":"Ejecutando","activity.turn":"este turno","activity.interrupt":"Esc para interrumpir","agents.running":"en ejecución","agents.idle":"inactivo","agents.done":"terminado","agents.total":"en total","welcome.model":"modelo","welcome.effort":"esfuerzo","welcome.project":"proyecto","verbose.on":"modo detallado activado: el razonamiento y las llamadas a herramientas se muestran en el chat","verbose.off":"modo detallado desactivado","mouse.on":"ratón activado: la rueda desplaza el chat · mantén Shift al arrastrar para seleccionar texto (Option en iTerm2, Fn en Terminal)","mouse.off":"ratón desactivado: selecciona y copia libremente · PageUp/PageDown desplazan el chat · /mouse vuelve a activar la captura","language.current":"Idioma: {name} · /language en | zh-CN | zh-TW | ja | ko | es","language.set":"idioma → {name}","language.title":"/language — idioma de la interfaz","language.currentMark":"actual","language.unknown":"Idioma desconocido \"{value}\". Elige en, zh-CN, zh-TW, ja, ko o es.","language.saveFailed":"no se pudo guardar el idioma: {error}","doctor.logs.new":"Solo se registran los warnings/errores desde que arrancó esta versión del TUI.","footer.current":"actual","footer.average":"promedio","footer.context":"contexto","footer.cache":"éxitos de caché","composer.placeholder":"escribe un mensaje","doctor.nearTimeout":"Valoración: {count} llamadas a Bash terminaron a unos 300 segundos, lo que coincide con el tiempo de espera de la herramienta; las trazas por sí solas no prueban la causa raíz. A continuación, revisa los marcadores de finalización del shell y los errores de terminal de esas llamadas.","doctor.logs.none":"Aún no hay archivo de registro; los registros de consola anteriores no se conservaron y no se pueden recuperar.","doctor.evidence":"Evidencia del diagnóstico: {traces} sesiones recientes, {logs} warnings/errores.","doctor.noFindings":"No hay tiempos de espera, herramientas sin terminar ni bloqueos claros en las trazas recientes.","doctor.noRoute":"No hay una ruta de modelo disponible, así que el análisis con modelo no se pudo ejecutar.","doctor.scope":"Alcance de la evidencia: {traces} sesiones recientes, {logs} warnings/errores; no se leyó el texto de la conversación, los argumentos ni la salida de las herramientas.","doctor.failed":"El análisis con modelo no terminó: {error}."}};
|
|
4
|
+
const DSCODE_MESSAGES = {"en":{"activity.replying":"Replying","activity.thinking":"Thinking","activity.running":"Running","activity.turn":"this turn","activity.interrupt":"Esc to interrupt","agents.running":"running","agents.idle":"idle","agents.done":"done","agents.total":"total","welcome.model":"model","welcome.effort":"effort","welcome.project":"project","verbose.on":"verbose on: thinking and tool calls are shown in the chat","verbose.off":"verbose off","mouse.on":"mouse on: the wheel scrolls the chat · hold Shift while dragging to select text (Option in iTerm2, Fn in Terminal)","mouse.off":"mouse off: select and copy freely · PageUp/PageDown scroll the chat · /mouse turns wheel scrolling on","language.current":"Language: {name} · /language en | zh-CN | zh-TW | ja | ko | es","language.set":"language → {name}","language.title":"/language — interface language","language.currentMark":"current","language.unknown":"Unknown language \"{value}\". Choose en, zh-CN, zh-TW, ja, ko or es.","language.saveFailed":"language save failed: {error}","doctor.logs.new":"Only warnings/errors since this TUI version started are recorded.","footer.current":"current","footer.average":"average","footer.context":"context","footer.cache":"cache hit","composer.placeholder":"type a message","compaction.running":"Compacting context, please wait","compaction.confirm.title":"Switching to {model} will compact the conversation","compaction.confirm.usage":"context {used} ≥ compaction threshold {threshold} ({window} × {ratio})","compaction.confirm.next":"the next step compacts older history first","compaction.confirm.overflow":"it already exceeds the {window} window: the next request compacts and retries","compaction.confirm.hint":"y switch · n/esc back","doctor.nearTimeout":"Assessment: {count} Bash calls ended at about 300 seconds, which matches the tool timeout; traces alone cannot prove the root cause. Next, check those calls' shell completion markers and terminal errors.","doctor.logs.none":"No log file yet; earlier console logs were not persisted and cannot be recovered.","doctor.evidence":"Diagnostic evidence: {traces} recent sessions, {logs} warnings/errors.","doctor.noFindings":"No clear timeouts, unfinished tool calls or error events in recent traces.","doctor.noRoute":"No model route is available, so the model analysis could not run.","doctor.scope":"Evidence scope: {traces} recent sessions, {logs} warnings/errors; conversation text, tool arguments and tool output were not read.","doctor.failed":"Model analysis did not finish: {error}."},"zh-CN":{"activity.replying":"正在回复","activity.thinking":"正在思考","activity.running":"正在执行","activity.turn":"本轮","activity.interrupt":"Esc 中断","agents.running":"运行中","agents.idle":"空闲","agents.done":"已完成","agents.total":"总计","welcome.model":"模型","welcome.effort":"推理","welcome.project":"项目","verbose.on":"详细模式已开启:对话中显示思考与工具调用","verbose.off":"详细模式已关闭","mouse.on":"鼠标捕获已开启:滚轮滚动对话 · 拖选文本时按住 Shift(iTerm2 按住 Option、Terminal 按住 Fn)","mouse.off":"鼠标捕获已关闭:可自由选择复制 · PageUp/PageDown 滚动对话 · /mouse 重新开启","language.current":"语言:{name} · /language en | zh-CN | zh-TW | ja | ko | es","language.set":"语言 → {name}","language.title":"/language — 界面语言","language.currentMark":"当前","language.unknown":"未知语言 \"{value}\"。可选 en、zh-CN、zh-TW、ja、ko、es。","language.saveFailed":"语言设置保存失败:{error}","doctor.logs.new":"仅记录新版 TUI 启动后的 warning/error。","footer.current":"当前","footer.average":"平均","footer.context":"上下文","footer.cache":"缓存命中","composer.placeholder":"输入消息","compaction.running":"正在压缩上下文,请稍后","compaction.confirm.title":"切换到 {model} 会触发自动压缩","compaction.confirm.usage":"当前上下文 {used} ≥ 压缩阈值 {threshold}({window} × {ratio})","compaction.confirm.next":"下一步开始前会先压缩较早的对话","compaction.confirm.overflow":"已超出新模型的 {window} 上下文窗口:下一次请求会先压缩再重试","compaction.confirm.hint":"y 确认切换 · n/esc 返回","doctor.nearTimeout":"判断:{count} 次 Bash 调用在约 300 秒结束,符合工具超时特征;trace 不能单独证明触发超时的根因。下一步检查这些调用的 shell 完成标记和终端错误。","doctor.logs.none":"日志文件尚未建立;旧版控制台日志未持久化,无法回溯。","doctor.evidence":"诊断证据:{traces} 个近期会话、{logs} 条 warning/error。","doctor.noFindings":"近期 trace 中未发现明确的超时、未完成工具调用或错误事件。","doctor.noRoute":"没有可用的模型路由,无法运行模型分析。","doctor.scope":"证据范围:{traces} 个近期会话、{logs} 条 warning/error;未读取对话正文、工具参数或工具输出。","doctor.failed":"模型分析未完成:{error}。"},"zh-TW":{"activity.replying":"正在回覆","activity.thinking":"正在思考","activity.running":"正在執行","activity.turn":"本輪","activity.interrupt":"Esc 中斷","agents.running":"執行中","agents.idle":"閒置","agents.done":"已完成","agents.total":"總計","welcome.model":"模型","welcome.effort":"推理","welcome.project":"專案","verbose.on":"詳細模式已開啟:對話中顯示思考與工具呼叫","verbose.off":"詳細模式已關閉","mouse.on":"滑鼠擷取已開啟:滾輪捲動對話 · 拖選文字時按住 Shift(iTerm2 按住 Option、Terminal 按住 Fn)","mouse.off":"滑鼠擷取已關閉:可自由選取複製 · PageUp/PageDown 捲動對話 · /mouse 重新開啟","language.current":"語言:{name} · /language en | zh-CN | zh-TW | ja | ko | es","language.set":"語言 → {name}","language.title":"/language — 介面語言","language.currentMark":"目前","language.unknown":"未知語言 \"{value}\"。可選 en、zh-CN、zh-TW、ja、ko、es。","language.saveFailed":"語言設定儲存失敗:{error}","doctor.logs.new":"僅記錄新版 TUI 啟動後的 warning/error。","footer.current":"目前","footer.average":"平均","footer.context":"上下文","footer.cache":"快取命中","composer.placeholder":"輸入訊息","compaction.running":"正在壓縮上下文,請稍候","compaction.confirm.title":"切換到 {model} 會觸發自動壓縮","compaction.confirm.usage":"目前上下文 {used} ≥ 壓縮閾值 {threshold}({window} × {ratio})","compaction.confirm.next":"下一步開始前會先壓縮較早的對話","compaction.confirm.overflow":"已超出新模型的 {window} 上下文視窗:下一次請求會先壓縮再重試","compaction.confirm.hint":"y 確認切換 · n/esc 返回","doctor.nearTimeout":"判斷:{count} 次 Bash 呼叫在約 300 秒結束,符合工具逾時特徵;trace 無法單獨證明觸發逾時的根因。下一步檢查這些呼叫的 shell 完成標記和終端錯誤。","doctor.logs.none":"日誌檔尚未建立;舊版主控台日誌未持久化,無法回溯。","doctor.evidence":"診斷證據:{traces} 個近期工作階段、{logs} 筆 warning/error。","doctor.noFindings":"近期 trace 中未發現明確的逾時、未完成工具呼叫或錯誤事件。","doctor.noRoute":"沒有可用的模型路由,無法執行模型分析。","doctor.scope":"證據範圍:{traces} 個近期工作階段、{logs} 筆 warning/error;未讀取對話內容、工具參數或工具輸出。","doctor.failed":"模型分析未完成:{error}。"},"ja":{"activity.replying":"応答中","activity.thinking":"思考中","activity.running":"実行中","activity.turn":"今回のターン","activity.interrupt":"Esc で中断","agents.running":"実行中","agents.idle":"待機中","agents.done":"完了","agents.total":"合計","welcome.model":"モデル","welcome.effort":"推論","welcome.project":"プロジェクト","verbose.on":"詳細モード オン:思考とツール呼び出しをチャットに表示します","verbose.off":"詳細モード オフ","mouse.on":"マウス キャプチャ オン:ホイールでチャットをスクロール · Shift(iTerm2 は Option、Terminal は Fn)を押しながらドラッグでテキスト選択","mouse.off":"マウス キャプチャ オフ:自由に選択・コピーできます · PageUp/PageDown でスクロール · /mouse で再びオン","language.current":"言語:{name} · /language en | zh-CN | zh-TW | ja | ko | es","language.set":"言語 → {name}","language.title":"/language — 表示言語","language.currentMark":"現在","language.unknown":"不明な言語 \"{value}\"。en、zh-CN、zh-TW、ja、ko、es から選んでください。","language.saveFailed":"言語設定の保存に失敗しました:{error}","doctor.logs.new":"この TUI バージョンの起動以降の warning/error のみ記録されています。","footer.current":"現在","footer.average":"平均","footer.context":"コンテキスト","footer.cache":"キャッシュヒット","composer.placeholder":"メッセージを入力","compaction.running":"コンテキストを圧縮しています。しばらくお待ちください","compaction.confirm.title":"{model} に切り替えると自動圧縮が実行されます","compaction.confirm.usage":"現在のコンテキスト {used} ≥ 圧縮しきい値 {threshold}({window} × {ratio})","compaction.confirm.next":"次のステップの前に古い履歴を圧縮します","compaction.confirm.overflow":"新しいモデルの {window} ウィンドウを超えています。次のリクエストで圧縮して再試行します","compaction.confirm.hint":"y 切り替え · n/esc 戻る","doctor.nearTimeout":"判断:Bash 呼び出し {count} 件が約 300 秒で終了しており、ツールのタイムアウトの特徴に一致します。トレースだけでは根本原因を証明できません。次はこれらの呼び出しのシェル完了マーカーと端末エラーを確認してください。","doctor.logs.none":"ログファイルはまだありません。以前のコンソールログは保存されておらず、遡れません。","doctor.evidence":"診断の根拠:直近のセッション {traces} 件、warning/error {logs} 件。","doctor.noFindings":"直近のトレースに明確なタイムアウト、未完了ツール、停滞は見つかりませんでした。","doctor.noRoute":"利用できるモデルルートがないため、モデル分析を実行できません。","doctor.scope":"根拠の範囲:直近のセッション {traces} 件、warning/error {logs} 件。会話本文、ツール引数、ツール出力は読んでいません。","doctor.failed":"モデル分析が完了しませんでした:{error}。"},"ko":{"activity.replying":"응답 중","activity.thinking":"생각 중","activity.running":"실행 중","activity.turn":"이번 턴","activity.interrupt":"Esc 중단","agents.running":"실행 중","agents.idle":"대기","agents.done":"완료","agents.total":"전체","welcome.model":"모델","welcome.effort":"추론","welcome.project":"프로젝트","verbose.on":"상세 모드 켜짐: 생각과 도구 호출을 채팅에 표시합니다","verbose.off":"상세 모드 꺼짐","mouse.on":"마우스 캡처 켜짐: 휠로 채팅 스크롤 · Shift(iTerm2는 Option, Terminal은 Fn)를 누른 채 드래그하여 텍스트 선택","mouse.off":"마우스 캡처 꺼짐: 자유롭게 선택·복사 · PageUp/PageDown으로 채팅 스크롤 · /mouse로 다시 켜기","language.current":"언어: {name} · /language en | zh-CN | zh-TW | ja | ko | es","language.set":"언어 → {name}","language.title":"/language — 인터페이스 언어","language.currentMark":"현재","language.unknown":"알 수 없는 언어 \"{value}\". en, zh-CN, zh-TW, ja, ko, es 중에서 선택하세요.","language.saveFailed":"언어 설정 저장 실패: {error}","doctor.logs.new":"이 TUI 버전 시작 이후의 warning/error만 기록됩니다.","footer.current":"현재","footer.average":"평균","footer.context":"컨텍스트","footer.cache":"캐시 적중","composer.placeholder":"메시지를 입력하세요","compaction.running":"컨텍스트를 압축하는 중입니다. 잠시만 기다려 주세요","compaction.confirm.title":"{model}(으)로 전환하면 자동 압축이 실행됩니다","compaction.confirm.usage":"현재 컨텍스트 {used} ≥ 압축 임계값 {threshold} ({window} × {ratio})","compaction.confirm.next":"다음 단계 전에 이전 대화를 먼저 압축합니다","compaction.confirm.overflow":"새 모델의 {window} 창을 이미 넘었습니다. 다음 요청에서 압축한 뒤 재시도합니다","compaction.confirm.hint":"y 전환 · n/esc 뒤로","doctor.nearTimeout":"판단: Bash 호출 {count}건이 약 300초에 종료되어 도구 시간 초과 특징과 일치합니다. 트레이스만으로는 근본 원인을 증명할 수 없습니다. 다음으로 해당 호출의 셸 완료 표시와 터미널 오류를 확인하세요.","doctor.logs.none":"아직 로그 파일이 없습니다. 이전 콘솔 로그는 저장되지 않아 복구할 수 없습니다.","doctor.evidence":"진단 근거: 최근 세션 {traces}개, warning/error {logs}건.","doctor.noFindings":"최근 트레이스에서 명확한 시간 초과, 미완료 도구, 정지는 발견되지 않았습니다.","doctor.noRoute":"사용 가능한 모델 경로가 없어 모델 분석을 실행할 수 없습니다.","doctor.scope":"근거 범위: 최근 세션 {traces}개, warning/error {logs}건. 대화 본문, 도구 인수, 도구 출력은 읽지 않았습니다.","doctor.failed":"모델 분석이 완료되지 않았습니다: {error}."},"es":{"activity.replying":"Respondiendo","activity.thinking":"Pensando","activity.running":"Ejecutando","activity.turn":"este turno","activity.interrupt":"Esc para interrumpir","agents.running":"en ejecución","agents.idle":"inactivo","agents.done":"terminado","agents.total":"en total","welcome.model":"modelo","welcome.effort":"esfuerzo","welcome.project":"proyecto","verbose.on":"modo detallado activado: el razonamiento y las llamadas a herramientas se muestran en el chat","verbose.off":"modo detallado desactivado","mouse.on":"ratón activado: la rueda desplaza el chat · mantén Shift al arrastrar para seleccionar texto (Option en iTerm2, Fn en Terminal)","mouse.off":"ratón desactivado: selecciona y copia libremente · PageUp/PageDown desplazan el chat · /mouse vuelve a activar la captura","language.current":"Idioma: {name} · /language en | zh-CN | zh-TW | ja | ko | es","language.set":"idioma → {name}","language.title":"/language — idioma de la interfaz","language.currentMark":"actual","language.unknown":"Idioma desconocido \"{value}\". Elige en, zh-CN, zh-TW, ja, ko o es.","language.saveFailed":"no se pudo guardar el idioma: {error}","doctor.logs.new":"Solo se registran los warnings/errores desde que arrancó esta versión del TUI.","footer.current":"actual","footer.average":"promedio","footer.context":"contexto","footer.cache":"éxitos de caché","composer.placeholder":"escribe un mensaje","compaction.running":"Compactando el contexto, espera un momento","compaction.confirm.title":"Cambiar a {model} compactará la conversación","compaction.confirm.usage":"contexto {used} ≥ umbral de compactación {threshold} ({window} × {ratio})","compaction.confirm.next":"el siguiente paso compacta antes el historial antiguo","compaction.confirm.overflow":"ya supera la ventana de {window}: la siguiente petición compacta y reintenta","compaction.confirm.hint":"y cambiar · n/esc volver","doctor.nearTimeout":"Valoración: {count} llamadas a Bash terminaron a unos 300 segundos, lo que coincide con el tiempo de espera de la herramienta; las trazas por sí solas no prueban la causa raíz. A continuación, revisa los marcadores de finalización del shell y los errores de terminal de esas llamadas.","doctor.logs.none":"Aún no hay archivo de registro; los registros de consola anteriores no se conservaron y no se pueden recuperar.","doctor.evidence":"Evidencia del diagnóstico: {traces} sesiones recientes, {logs} warnings/errores.","doctor.noFindings":"No hay tiempos de espera, herramientas sin terminar ni bloqueos claros en las trazas recientes.","doctor.noRoute":"No hay una ruta de modelo disponible, así que el análisis con modelo no se pudo ejecutar.","doctor.scope":"Alcance de la evidencia: {traces} sesiones recientes, {logs} warnings/errores; no se leyó el texto de la conversación, los argumentos ni la salida de las herramientas.","doctor.failed":"El análisis con modelo no terminó: {error}."}};
|
|
5
5
|
const DSCODE_LANGUAGE_ALIASES = {"en":["en","english","eng","英文","英语","英語"],"zh-CN":["zh-cn","zh","zh-hans","zhhans","cn","chinese","simplified","中文","简体","简体中文","简中","中文简体"],"zh-TW":["zh-tw","zh-hant","zhhant","tw","hk","zh-hk","traditional","繁体","繁體","繁體中文","繁体中文","繁中"],"ja":["ja","jp","japanese","日本語","日语","日語"],"ko":["ko","kr","korean","한국어","韩语","韓語","韓文"],"es":["es","spanish","español","espanol","西班牙语","西班牙語"]};
|
|
6
6
|
function dscodeNormalizeLanguage(value) {
|
|
7
7
|
const aliasesByCode = DSCODE_LANGUAGE_ALIASES;
|
|
@@ -39,6 +39,13 @@ function dscodeLoadFlag(name, fallback = false) {
|
|
|
39
39
|
function dscodeSaveFlag(name, value) {
|
|
40
40
|
try { fs.mkdirSync(join(homedir(), ".dsh", "dsh-code"), { recursive: true }); fs.writeFileSync(dscodeFlagFile(name), JSON.stringify({ [name]: value }, null, 2) + "\n"); } catch {}
|
|
41
41
|
}
|
|
42
|
+
// dscode-openrouter-account-v1
|
|
43
|
+
import { MANAGEMENT_REF as DSCODE_OPENROUTER_MANAGEMENT_REF, loadOpenRouterAccount as dscodeLoadOpenRouterAccount, openRouterAccountLines as dscodeOpenRouterAccountLines, verifyManagementKey as dscodeVerifyManagementKey } from "./dscode-providers/openrouter-account.mjs";
|
|
44
|
+
// dscode-compaction-v1
|
|
45
|
+
import { TETRIS_TICK_MS as DSCODE_TETRIS_TICK_MS, TETRIS_WIDTH as DSCODE_TETRIS_WIDTH, tetrisFrame as dscodeTetrisFrame } from "../../plugins/compaction/tetris.mjs";
|
|
46
|
+
import { compactionPreview as dscodeCompactionPreview, pricedThresholdRatio as dscodePricedThresholdRatio } from "../../plugins/compaction/threshold.mjs";
|
|
47
|
+
// dscode-model-search-v3
|
|
48
|
+
import { migrateOpenRouterProfile as dscodeMigrateOpenRouter } from "./dscode-providers/catalog.mjs";
|
|
42
49
|
// dscode-provider-v1
|
|
43
50
|
import { PROVIDERS as DSCODE_PROVIDERS, providerSpec as dscodeProviderSpec, providerArgument as dscodeProviderArgument, providerOfLabel as dscodeProviderOfLabel, splitModelLabel as dscodeSplitModelLabel, pickModel as dscodePickModel, credentialState as dscodeCredentialState, ensureProviderRoute as dscodeEnsureProviderRoute, waitForModels as dscodeWaitForModels } from "./dscode-providers/catalog.mjs";
|
|
44
51
|
import { readClipboardImage as dscodeReadClipboardImage } from "./dscode-clipboard-image/index.mjs";
|
|
@@ -25726,6 +25733,7 @@ function createReplayAccumulator() {
|
|
|
25726
25733
|
toolCallOrdinal: 0,
|
|
25727
25734
|
busy: false,
|
|
25728
25735
|
busySince: 0,
|
|
25736
|
+
dscodeCompactingSince: 0,
|
|
25729
25737
|
model: "",
|
|
25730
25738
|
plan: false,
|
|
25731
25739
|
permission: "",
|
|
@@ -26095,6 +26103,7 @@ function replayProjectEvent(acc, event) {
|
|
|
26095
26103
|
const wasBusy = acc.busy;
|
|
26096
26104
|
acc.busy = true;
|
|
26097
26105
|
acc.busySince = wasBusy ? acc.busySince : event.time;
|
|
26106
|
+
acc.dscodeCompactingSince = 0;
|
|
26098
26107
|
acc.todos = [];
|
|
26099
26108
|
acc.stats = {
|
|
26100
26109
|
...acc.stats,
|
|
@@ -26157,6 +26166,7 @@ function replayProjectEvent(acc, event) {
|
|
|
26157
26166
|
finalizeReplayOrphans(acc);
|
|
26158
26167
|
acc.busy = false;
|
|
26159
26168
|
acc.busySince = 0;
|
|
26169
|
+
acc.dscodeCompactingSince = 0;
|
|
26160
26170
|
for (const entry of appended) appendReplayEntry(acc, entry);
|
|
26161
26171
|
return true;
|
|
26162
26172
|
}
|
|
@@ -26224,6 +26234,9 @@ function replayProjectEvent(acc, event) {
|
|
|
26224
26234
|
}
|
|
26225
26235
|
acc.compactionTokens.set(event.data.compactionId, event.data.shadowedTokenCount);
|
|
26226
26236
|
return true;
|
|
26237
|
+
case "compaction/start":
|
|
26238
|
+
acc.dscodeCompactingSince = event.time;
|
|
26239
|
+
return true;
|
|
26227
26240
|
case "compaction/prune":
|
|
26228
26241
|
acc.lastPruneTokens = event.data.shadowedTokenCount;
|
|
26229
26242
|
return true;
|
|
@@ -26231,6 +26244,7 @@ function replayProjectEvent(acc, event) {
|
|
|
26231
26244
|
const ok = event.data.error === void 0;
|
|
26232
26245
|
const tokens = acc.compactionTokens.get(event.data.compactionId) ?? acc.lastPruneTokens;
|
|
26233
26246
|
acc.compactionTokens.delete(event.data.compactionId);
|
|
26247
|
+
acc.dscodeCompactingSince = 0;
|
|
26234
26248
|
appendReplayEntry(acc, {
|
|
26235
26249
|
kind: "compaction",
|
|
26236
26250
|
ok,
|
|
@@ -26311,6 +26325,7 @@ function materializeReplayView(acc, copy) {
|
|
|
26311
26325
|
toolCallOrdinal: acc.toolCallOrdinal,
|
|
26312
26326
|
busy: acc.busy,
|
|
26313
26327
|
busySince: acc.busySince,
|
|
26328
|
+
dscodeCompactingSince: acc.dscodeCompactingSince,
|
|
26314
26329
|
model: acc.model,
|
|
26315
26330
|
plan: acc.plan,
|
|
26316
26331
|
permission: acc.permission,
|
|
@@ -31933,6 +31948,7 @@ const LOCAL_COMMANDS = [
|
|
|
31933
31948
|
{ label: "/email", description: "browse email and steer into this session" },
|
|
31934
31949
|
{ label: "/login", description: "save a provider API key locally (/login [deepseek|openrouter])" },
|
|
31935
31950
|
{ label: "/provider", description: "switch between DeepSeek and OpenRouter" },
|
|
31951
|
+
{ label: "/openrouter", description: "OpenRouter account: balance, key usage and 30-day spend" },
|
|
31936
31952
|
// dscode: startup command discovery
|
|
31937
31953
|
{"label":"/status","description":"session, model, permissions and usage"},
|
|
31938
31954
|
{"label":"/doctor","description":"read-only runtime diagnostics"},
|
|
@@ -32374,7 +32390,7 @@ function Header({ cwd = "", model = "", effort = "", animated = false }) {
|
|
|
32374
32390
|
if (!full) return (0, import_react.createElement)(Box, { flexDirection: "column", paddingX: 2, marginBottom: 1 },
|
|
32375
32391
|
(0, import_react.createElement)(Text, { wrap: "truncate-end" },
|
|
32376
32392
|
(0, import_react.createElement)(Text, { color: inkColor(getPalette().brandBright), bold: true }, "❄ DSCODE"),
|
|
32377
|
-
(0, import_react.createElement)(Text, { color: inkColor(getPalette().dim) }, " v0.7.
|
|
32393
|
+
(0, import_react.createElement)(Text, { color: inkColor(getPalette().dim) }, " v0.7.7")),
|
|
32378
32394
|
(0, import_react.createElement)(Text, { wrap: "truncate-end" }, truncateColumns(modelName + " · " + effortName, width)),
|
|
32379
32395
|
(0, import_react.createElement)(Text, { color: inkColor(getPalette().dim), wrap: "truncate-end" }, welcomePath(cwd, width)));
|
|
32380
32396
|
return (0, import_react.createElement)(Box, { flexDirection: "column", width, borderStyle: "round", borderColor: inkColor(getPalette().brand), paddingX: 1 },
|
|
@@ -32385,7 +32401,7 @@ function Header({ cwd = "", model = "", effort = "", animated = false }) {
|
|
|
32385
32401
|
(0, import_react.createElement)(Box, { flexDirection: "column", width: detailsWidth, marginTop: 2 },
|
|
32386
32402
|
(0, import_react.createElement)(Text, { color: inkColor(getPalette().text), bold: true }, "DSCODE"),
|
|
32387
32403
|
(0, import_react.createElement)(Text, { color: inkColor(getPalette().brandDeep) }, "────────────"),
|
|
32388
|
-
(0, import_react.createElement)(Text, { color: inkColor(getPalette().dim) }, "v0.7.
|
|
32404
|
+
(0, import_react.createElement)(Text, { color: inkColor(getPalette().dim) }, "v0.7.7"),
|
|
32389
32405
|
(0, import_react.createElement)(Text, { wrap: "truncate-end" }, truncateColumns(dscodePadEnd(dscodeT("welcome.model"), 9) + modelName, detailsWidth)),
|
|
32390
32406
|
(0, import_react.createElement)(Text, { wrap: "truncate-end" }, truncateColumns(dscodePadEnd(dscodeT("welcome.effort"), 9) + effortName, detailsWidth)),
|
|
32391
32407
|
(0, import_react.createElement)(Text, null, " "),
|
|
@@ -33162,123 +33178,161 @@ function QuestionBar({ store, snapshot, locked }) {
|
|
|
33162
33178
|
}, dim(truncateColumns(footer, viewport.contentColumns))));
|
|
33163
33179
|
}
|
|
33164
33180
|
/** The /model panel: a scrolling list over the advisory model directory. */
|
|
33181
|
+
function dscodeFilterModels(rows, query) {
|
|
33182
|
+
const tokenize = text => String(text ?? '').normalize('NFKC').toLowerCase().match(/[a-z]+|[0-9]+|[^\s\x00-\x7f]+/g) ?? [];
|
|
33183
|
+
const raw = String(query ?? '');
|
|
33184
|
+
const words = tokenize(raw);
|
|
33185
|
+
if (words.length === 0) return rows;
|
|
33186
|
+
const typing = /\s$/.test(raw) ? -1 : words.length - 1;
|
|
33187
|
+
const fields = [['modelName', 3], ['model', 2], ['providerName', 1], ['provider', 1]];
|
|
33188
|
+
const docs = rows.map(row => {
|
|
33189
|
+
const counts = new Map();
|
|
33190
|
+
let length = 0;
|
|
33191
|
+
for (const [field, weight] of fields) for (const token of tokenize(row[field])) { counts.set(token, (counts.get(token) ?? 0) + weight); length += weight; }
|
|
33192
|
+
return { row, counts, length };
|
|
33193
|
+
});
|
|
33194
|
+
const average = docs.reduce((sum, doc) => sum + doc.length, 0) / Math.max(1, docs.length);
|
|
33195
|
+
const frequency = (doc, word, prefix) => {
|
|
33196
|
+
if (!prefix) return doc.counts.get(word) ?? 0;
|
|
33197
|
+
let sum = 0;
|
|
33198
|
+
for (const [token, count] of doc.counts) if (token.startsWith(word)) sum += token === word ? count : count * 0.8;
|
|
33199
|
+
return sum;
|
|
33200
|
+
};
|
|
33201
|
+
const k1 = 1.2, b = 0.75;
|
|
33202
|
+
const terms = words.map((word, index) => {
|
|
33203
|
+
const matches = docs.map(doc => frequency(doc, word, index === typing));
|
|
33204
|
+
const found = matches.filter(value => value > 0).length;
|
|
33205
|
+
return { matches, idf: Math.log(1 + (docs.length - found + 0.5) / (found + 0.5)) };
|
|
33206
|
+
});
|
|
33207
|
+
const scored = docs.map((doc, index) => {
|
|
33208
|
+
let score = 0, hits = 0;
|
|
33209
|
+
for (const term of terms) {
|
|
33210
|
+
const tf = term.matches[index];
|
|
33211
|
+
if (tf <= 0) continue;
|
|
33212
|
+
hits += 1;
|
|
33213
|
+
score += term.idf * tf * (k1 + 1) / (tf + k1 * (1 - b + b * doc.length / average));
|
|
33214
|
+
}
|
|
33215
|
+
return { row: doc.row, score, hits, index };
|
|
33216
|
+
}).filter(entry => entry.hits > 0);
|
|
33217
|
+
const complete = scored.filter(entry => entry.hits === terms.length);
|
|
33218
|
+
return (complete.length > 0 ? complete : scored).sort((left, right) => right.score - left.score || left.index - right.index).map(entry => entry.row);
|
|
33219
|
+
}
|
|
33165
33220
|
function ModelPanel({ directory, error, current, onSelect, onProviders, onRetry, onClose }) {
|
|
33166
|
-
|
|
33167
|
-
|
|
33168
|
-
|
|
33169
|
-
|
|
33170
|
-
|
|
33171
|
-
|
|
33172
|
-
|
|
33173
|
-
|
|
33174
|
-
|
|
33175
|
-
|
|
33176
|
-
|
|
33177
|
-
|
|
33178
|
-
|
|
33179
|
-
|
|
33180
|
-
|
|
33181
|
-
|
|
33182
|
-
|
|
33183
|
-
|
|
33184
|
-
|
|
33185
|
-
|
|
33186
|
-
|
|
33187
|
-
|
|
33188
|
-
|
|
33189
|
-
|
|
33190
|
-
|
|
33191
|
-
|
|
33192
|
-
|
|
33193
|
-
|
|
33194
|
-
|
|
33195
|
-
|
|
33196
|
-
|
|
33197
|
-
|
|
33198
|
-
|
|
33199
|
-
|
|
33200
|
-
|
|
33201
|
-
|
|
33202
|
-
|
|
33203
|
-
|
|
33204
|
-
|
|
33205
|
-
|
|
33206
|
-
|
|
33207
|
-
|
|
33208
|
-
|
|
33209
|
-
|
|
33210
|
-
|
|
33211
|
-
|
|
33212
|
-
|
|
33213
|
-
|
|
33214
|
-
|
|
33215
|
-
|
|
33216
|
-
|
|
33217
|
-
|
|
33218
|
-
|
|
33219
|
-
|
|
33220
|
-
|
|
33221
|
-
|
|
33222
|
-
|
|
33223
|
-
|
|
33224
|
-
|
|
33225
|
-
|
|
33226
|
-
|
|
33227
|
-
|
|
33228
|
-
|
|
33229
|
-
|
|
33230
|
-
|
|
33231
|
-
|
|
33232
|
-
|
|
33233
|
-
|
|
33234
|
-
|
|
33235
|
-
|
|
33236
|
-
|
|
33237
|
-
|
|
33238
|
-
|
|
33239
|
-
|
|
33240
|
-
|
|
33241
|
-
|
|
33242
|
-
|
|
33243
|
-
|
|
33244
|
-
|
|
33245
|
-
|
|
33246
|
-
|
|
33247
|
-
|
|
33248
|
-
|
|
33249
|
-
|
|
33250
|
-
|
|
33251
|
-
|
|
33252
|
-
|
|
33253
|
-
|
|
33254
|
-
|
|
33255
|
-
|
|
33256
|
-
|
|
33257
|
-
|
|
33258
|
-
|
|
33259
|
-
|
|
33260
|
-
|
|
33261
|
-
|
|
33262
|
-
|
|
33263
|
-
|
|
33264
|
-
|
|
33265
|
-
|
|
33266
|
-
|
|
33267
|
-
|
|
33268
|
-
|
|
33269
|
-
|
|
33270
|
-
|
|
33271
|
-
|
|
33272
|
-
|
|
33273
|
-
|
|
33274
|
-
|
|
33275
|
-
|
|
33276
|
-
|
|
33277
|
-
|
|
33278
|
-
|
|
33279
|
-
|
|
33280
|
-
|
|
33281
|
-
}, dim(truncateColumns(`↑↓ move · pgup/pgdn page · enter select${onProviders === void 0 ? "" : " · tab providers"} · r retry · esc/q close`, viewport.contentColumns))));
|
|
33221
|
+
const [cursor, setCursor] = (0, import_react.useState)(0);
|
|
33222
|
+
const [dscodeQuery, setDscodeQuery] = (0, import_react.useState)("");
|
|
33223
|
+
const [dscodeFocused, setDscodeFocused] = (0, import_react.useState)(true);
|
|
33224
|
+
const stdout = useStdout().stdout;
|
|
33225
|
+
const viewport = panelViewport(stdout?.columns ?? 80, stdout?.rows ?? 30);
|
|
33226
|
+
const dscodeRows = directory?.rows ?? [];
|
|
33227
|
+
const rows = (0, import_react.useMemo)(() => dscodeFilterModels(dscodeRows, dscodeQuery), [dscodeRows, dscodeQuery]);
|
|
33228
|
+
const positioned = (0, import_react.useRef)(false);
|
|
33229
|
+
(0, import_react.useEffect)(() => {
|
|
33230
|
+
if (rows.length === 0) {
|
|
33231
|
+
if (cursor !== 0) setCursor(0);
|
|
33232
|
+
return;
|
|
33233
|
+
}
|
|
33234
|
+
if (cursor >= rows.length) {
|
|
33235
|
+
setCursor(rows.length - 1);
|
|
33236
|
+
return;
|
|
33237
|
+
}
|
|
33238
|
+
if (positioned.current || current === void 0 || dscodeQuery !== "") return;
|
|
33239
|
+
const index = rows.findIndex((row) => `${row.provider}/${row.model}` === current);
|
|
33240
|
+
if (index >= 0) {
|
|
33241
|
+
positioned.current = true;
|
|
33242
|
+
setCursor(index);
|
|
33243
|
+
}
|
|
33244
|
+
}, [rows, cursor, current, dscodeQuery]);
|
|
33245
|
+
const search = (next) => {
|
|
33246
|
+
setDscodeQuery(next.slice(0, 120));
|
|
33247
|
+
setCursor(0);
|
|
33248
|
+
setDscodeFocused(false);
|
|
33249
|
+
};
|
|
33250
|
+
useInput((input, key) => {
|
|
33251
|
+
if (key.ctrl && input === "c") { onClose(); return; }
|
|
33252
|
+
if (key.escape) {
|
|
33253
|
+
if (dscodeQuery === "") { onClose(); return; }
|
|
33254
|
+
positioned.current = false;
|
|
33255
|
+
setDscodeQuery("");
|
|
33256
|
+
setCursor(0);
|
|
33257
|
+
setDscodeFocused(true);
|
|
33258
|
+
return;
|
|
33259
|
+
}
|
|
33260
|
+
if (key.tab && onProviders !== void 0) { onProviders(); return; }
|
|
33261
|
+
if (key.ctrl && input === "r") { onRetry(); return; }
|
|
33262
|
+
if (key.return || key.upArrow || key.downArrow || key.pageUp || key.pageDown) {
|
|
33263
|
+
if (rows.length === 0) return;
|
|
33264
|
+
if (!dscodeFocused) {
|
|
33265
|
+
setCursor(0);
|
|
33266
|
+
setDscodeFocused(true);
|
|
33267
|
+
return;
|
|
33268
|
+
}
|
|
33269
|
+
const page = Math.max(1, viewport.bodyRows - 1);
|
|
33270
|
+
if (key.return) { if (rows[cursor] !== void 0) onSelect(rows[cursor]); }
|
|
33271
|
+
else if (key.upArrow) setCursor(cursor > 0 ? cursor - 1 : rows.length - 1);
|
|
33272
|
+
else if (key.downArrow) setCursor(cursor < rows.length - 1 ? cursor + 1 : 0);
|
|
33273
|
+
else if (key.pageUp) setCursor((value) => Math.max(0, value - page));
|
|
33274
|
+
else setCursor((value) => Math.min(rows.length - 1, value + page));
|
|
33275
|
+
return;
|
|
33276
|
+
}
|
|
33277
|
+
if (key.ctrl && input === "u") { if (dscodeQuery !== "") search(""); return; }
|
|
33278
|
+
if (key.ctrl || key.meta) return;
|
|
33279
|
+
const next = editQuery(dscodeQuery, input, key);
|
|
33280
|
+
if (next !== void 0 && next !== dscodeQuery) search(next);
|
|
33281
|
+
});
|
|
33282
|
+
const focusRow = dscodeFocused && rows.length > 0;
|
|
33283
|
+
const searchText = dscodeQuery === "" ? "type to search" : `search: ${dscodeQuery}`;
|
|
33284
|
+
const escape = dscodeQuery === "" ? "esc close" : "esc clears search";
|
|
33285
|
+
if (viewport.maxHeight === 0 || viewport.compact) {
|
|
33286
|
+
const providers = onProviders === void 0 ? "" : " · tab providers";
|
|
33287
|
+
const state = rows.length === 0 ? directory === void 0 && error === void 0 ? "loading…" : error !== void 0 ? "error" : dscodeQuery === "" ? "no models" : "no match"
|
|
33288
|
+
: focusRow ? `❯ ${rows[cursor]?.modelName ?? rows[cursor]?.model ?? ""}` : `${rows.length} ${rows.length === 1 ? "match" : "matches"}`;
|
|
33289
|
+
return (0, import_react.createElement)(Text, { wrap: "truncate-end" }, truncateColumns(`/model · ${searchText} · ${state}${providers} · ${escape}`, viewport.contentColumns));
|
|
33290
|
+
}
|
|
33291
|
+
const visibleStateRows = (directory === void 0 && error === void 0 ? [(0, import_react.createElement)(Text, {
|
|
33292
|
+
key: "loading",
|
|
33293
|
+
dimColor: true,
|
|
33294
|
+
wrap: "truncate-end"
|
|
33295
|
+
}, " loading models…")] : error !== void 0 ? [(0, import_react.createElement)(Text, {
|
|
33296
|
+
key: "error",
|
|
33297
|
+
color: inkColor(getPalette().error),
|
|
33298
|
+
wrap: "truncate-end"
|
|
33299
|
+
}, truncateColumns(` ${singleLineText(error)}`, viewport.contentColumns))] : [...directory?.failures.length === 0 ? [] : [(0, import_react.createElement)(Text, {
|
|
33300
|
+
key: "failures",
|
|
33301
|
+
color: inkColor(getPalette().warn),
|
|
33302
|
+
wrap: "truncate-end"
|
|
33303
|
+
}, truncateColumns(` unavailable providers: ${directory?.failures.join(", ")}`, viewport.contentColumns))], ...rows.length === 0 ? [(0, import_react.createElement)(Text, {
|
|
33304
|
+
key: "empty",
|
|
33305
|
+
dimColor: true,
|
|
33306
|
+
wrap: "truncate-end"
|
|
33307
|
+
}, dscodeQuery === "" ? " no models available" : " no models match the search")] : []]).slice(0, viewport.bodyRows);
|
|
33308
|
+
const rowBudget = Math.max(0, viewport.bodyRows - visibleStateRows.length);
|
|
33309
|
+
const first = selectionWindow(cursor, rows.length, rowBudget);
|
|
33310
|
+
const visible = rowBudget === 0 ? [] : rows.slice(first, first + rowBudget);
|
|
33311
|
+
const count = rows.length === 0 ? "" : focusRow ? ` · ${cursor + 1}/${rows.length}` : ` · ${rows.length} ${rows.length === 1 ? "match" : "matches"}`;
|
|
33312
|
+
return (0, import_react.createElement)(Box, {
|
|
33313
|
+
flexDirection: "column",
|
|
33314
|
+
width: viewport.outerColumns,
|
|
33315
|
+
paddingX: 1,
|
|
33316
|
+
borderStyle: "round",
|
|
33317
|
+
borderColor: inkColor(getPalette().brand)
|
|
33318
|
+
}, (0, import_react.createElement)(Text, {
|
|
33319
|
+
color: inkColor(getPalette().brand),
|
|
33320
|
+
bold: true,
|
|
33321
|
+
wrap: "truncate-end"
|
|
33322
|
+
}, truncateColumns(`/model — select model${count} · ${searchText}`, viewport.contentColumns)), (0, import_react.createElement)(PanelGap, { visible: viewport.gapRows > 0 }), ...visibleStateRows, ...visible.map((row) => {
|
|
33323
|
+
const index = rows.indexOf(row);
|
|
33324
|
+
const focused = focusRow && index === cursor;
|
|
33325
|
+
const capability = row.inputModalities?.includes("image") === true ? " · image" : "";
|
|
33326
|
+
const label = displayText(`${row.providerName} · ${row.modelName}${capability}`);
|
|
33327
|
+
return (0, import_react.createElement)(Text, {
|
|
33328
|
+
key: `${row.provider}/${row.model}`,
|
|
33329
|
+
color: focused ? inkColor(getPalette().brandBright) : inkColor(getPalette().dim),
|
|
33330
|
+
wrap: "truncate-end"
|
|
33331
|
+
}, truncateColumns(`${focused ? "❯ " : " "}${label}`, viewport.contentColumns));
|
|
33332
|
+
}), (0, import_react.createElement)(PanelGap, { visible: viewport.gapRows > 0 }), (0, import_react.createElement)(Text, {
|
|
33333
|
+
dimColor: true,
|
|
33334
|
+
wrap: "truncate-end"
|
|
33335
|
+
}, dim(truncateColumns(`type to search · ↑↓ move · enter ${focusRow ? "select" : "focus first match"}${onProviders === void 0 ? "" : " · tab providers"} · ctrl+r retry · ${escape}`, viewport.contentColumns))));
|
|
33282
33336
|
}
|
|
33283
33337
|
/** Compact provider-state copy; only value-free credential facts cross this boundary. */
|
|
33284
33338
|
function providerStateLabel(row) {
|
|
@@ -34052,6 +34106,154 @@ function ProviderDiscoveryPanel({ target, baseURL, apiKey, configured, discover,
|
|
|
34052
34106
|
}, truncateColumns("↑↓ move · space check · enter adopt · f refetch · esc back", viewport.contentColumns)));
|
|
34053
34107
|
}
|
|
34054
34108
|
/** Bounded destructive-action confirmation for credential or provider removal. */
|
|
34109
|
+
// dscode-compaction-ui-start
|
|
34110
|
+
function dscodeTetrisCells(row, palette, key) {
|
|
34111
|
+
return [...row].map((cell, index) => (0, import_react.createElement)(Text, { key: key + "-" + index, color: inkColor(cell === "@" ? palette.brandBright : cell === "#" ? palette.brandMid : cell === "=" ? palette.warn : palette.dim) }, cell === "." ? " ." : cell === "=" ? "==" : "[]"));
|
|
34112
|
+
}
|
|
34113
|
+
function DscodeCompactionLine({ since, rows, animated = true }) {
|
|
34114
|
+
const columns = useStdout().stdout?.columns ?? 80;
|
|
34115
|
+
const tick = useFrames(animated ? DSCODE_TETRIS_TICK_MS : 1000);
|
|
34116
|
+
const palette = getPalette();
|
|
34117
|
+
const board = dscodeTetrisFrame(animated ? tick : 0);
|
|
34118
|
+
const clock = runClock(since > 0 ? Math.max(0, Date.now() - since) : 0);
|
|
34119
|
+
const room = Math.max(1, columns - 8 - DSCODE_TETRIS_WIDTH * 2);
|
|
34120
|
+
const wall = (key) => (0, import_react.createElement)(Text, { key, color: inkColor(palette.dim) }, "|");
|
|
34121
|
+
const label = (text, color) => (0, import_react.createElement)(Text, { key: "label", color: inkColor(color), wrap: "truncate-end" }, " " + truncateColumns(text, room));
|
|
34122
|
+
if (columns < DSCODE_TETRIS_WIDTH * 2 + 12) return (0, import_react.createElement)(Box, { paddingX: 2 }, (0, import_react.createElement)(Text, { color: inkColor(palette.brandBright), wrap: "truncate-end" }, truncateColumns(dscodeT("compaction.running") + " · " + clock, Math.max(1, columns - 4))));
|
|
34123
|
+
if (rows < 5) return (0, import_react.createElement)(Box, { paddingX: 2 }, wall("left"), ...dscodeTetrisCells(board[board.length - 1], palette, "cell"), wall("right"), label(dscodeT("compaction.running") + " · " + clock, palette.brandBright));
|
|
34124
|
+
return (0, import_react.createElement)(Box, { flexDirection: "column", paddingX: 2 },
|
|
34125
|
+
...board.map((row, y) => (0, import_react.createElement)(Box, { key: y }, wall("left"), ...dscodeTetrisCells(row, palette, "cell"), wall("right"),
|
|
34126
|
+
y === 1 ? label(dscodeT("compaction.running"), palette.brandBright) : y === 2 ? label(clock, palette.dim) : void 0)),
|
|
34127
|
+
(0, import_react.createElement)(Text, { color: inkColor(palette.dim) }, "+" + "-".repeat(DSCODE_TETRIS_WIDTH * 2) + "+"));
|
|
34128
|
+
}
|
|
34129
|
+
function DscodeCompactionConfirmPanel({ preview, confirm, back }) {
|
|
34130
|
+
const stdout = useStdout().stdout;
|
|
34131
|
+
const viewport = panelViewport(stdout?.columns ?? 80, stdout?.rows ?? 30);
|
|
34132
|
+
useStableInput((input, key) => {
|
|
34133
|
+
if (key.escape || input === "n") { back(); return; }
|
|
34134
|
+
if (input === "y") confirm();
|
|
34135
|
+
}, true);
|
|
34136
|
+
const palette = getPalette();
|
|
34137
|
+
const values = { model: singleLineText(preview.label), used: formatTokens(preview.used), threshold: formatTokens(preview.threshold), window: formatTokens(preview.contextWindow), ratio: Math.round(preview.thresholdRatio * 100) + "%" };
|
|
34138
|
+
const title = dscodeT("compaction.confirm.title", values);
|
|
34139
|
+
const hint = dscodeT("compaction.confirm.hint");
|
|
34140
|
+
if (viewport.maxHeight === 0 || viewport.compact) return (0, import_react.createElement)(Text, { wrap: "truncate-end" }, truncateColumns(title + " · " + hint, viewport.contentColumns));
|
|
34141
|
+
const body = [dscodeT("compaction.confirm.usage", values), dscodeT(preview.overflows ? "compaction.confirm.overflow" : "compaction.confirm.next", values)]
|
|
34142
|
+
.map((text, index) => (0, import_react.createElement)(Text, { key: "body" + index, color: index === 0 ? void 0 : inkColor(palette.dim), wrap: "truncate-end" }, truncateColumns(" " + text, viewport.contentColumns)))
|
|
34143
|
+
.slice(0, viewport.bodyRows);
|
|
34144
|
+
return (0, import_react.createElement)(Box, { flexDirection: "column", width: viewport.outerColumns, paddingX: 1, borderStyle: "round", borderColor: inkColor(palette.warn) },
|
|
34145
|
+
(0, import_react.createElement)(Text, { color: inkColor(palette.warn), bold: true, wrap: "truncate-end" }, truncateColumns(title, viewport.contentColumns)),
|
|
34146
|
+
(0, import_react.createElement)(PanelGap, { visible: viewport.gapRows > 0 }), ...body, (0, import_react.createElement)(PanelGap, { visible: viewport.gapRows > 0 }),
|
|
34147
|
+
(0, import_react.createElement)(Text, { color: inkColor(palette.dim), wrap: "truncate-end" }, truncateColumns(hint, viewport.contentColumns)));
|
|
34148
|
+
}
|
|
34149
|
+
// dscode-compaction-ui-end
|
|
34150
|
+
// dscode-openrouter-ui-start
|
|
34151
|
+
async function dscodeOpenRouterSecret(ctx, ref) {
|
|
34152
|
+
const hit = await ctx.get("credentials")?.resolve(ref);
|
|
34153
|
+
return typeof hit?.value === "string" && hit.value.length > 0 ? hit.value : void 0;
|
|
34154
|
+
}
|
|
34155
|
+
async function dscodeManagementKeyStatus(ctx) {
|
|
34156
|
+
const credentials = ctx.get("credentials");
|
|
34157
|
+
if (credentials === void 0) return { state: "unavailable" };
|
|
34158
|
+
try {
|
|
34159
|
+
const facts = await credentials.describe(DSCODE_OPENROUTER_MANAGEMENT_REF);
|
|
34160
|
+
if (facts?.configured) return { state: facts.source === "env" ? "env" : "saved" };
|
|
34161
|
+
return { state: facts?.writable === false ? "readonly" : "missing" };
|
|
34162
|
+
} catch {
|
|
34163
|
+
return { state: "error" };
|
|
34164
|
+
}
|
|
34165
|
+
}
|
|
34166
|
+
async function dscodeSaveManagementKey(ctx, key) {
|
|
34167
|
+
const credentials = ctx.get("credentials");
|
|
34168
|
+
if (typeof credentials?.set !== "function") throw new Error("Credential storage is unavailable.");
|
|
34169
|
+
await dscodeVerifyManagementKey(key);
|
|
34170
|
+
await credentials.set(DSCODE_OPENROUTER_MANAGEMENT_REF, key);
|
|
34171
|
+
}
|
|
34172
|
+
async function dscodeLoadOpenRouterAccountFor(ctx) {
|
|
34173
|
+
const [apiKey, managementKey] = await Promise.all(["OPENROUTER_API_KEY", DSCODE_OPENROUTER_MANAGEMENT_REF].map(ref => dscodeOpenRouterSecret(ctx, ref)));
|
|
34174
|
+
return dscodeLoadOpenRouterAccount({ apiKey, managementKey });
|
|
34175
|
+
}
|
|
34176
|
+
function DscodeManagementKeyPanel({ optional, status, save, done, back }) {
|
|
34177
|
+
const [draft, setDraft] = (0, import_react.useState)("");
|
|
34178
|
+
const [error, setError] = (0, import_react.useState)("");
|
|
34179
|
+
const [busy, setBusy] = (0, import_react.useState)(false);
|
|
34180
|
+
const [state, setState] = (0, import_react.useState)(void 0);
|
|
34181
|
+
const saving = (0, import_react.useRef)(false);
|
|
34182
|
+
(0, import_react.useEffect)(() => {
|
|
34183
|
+
let active = true;
|
|
34184
|
+
Promise.resolve().then(() => status?.()).then(result => { if (active) setState(result?.state ?? "missing"); }, () => { if (active) setState("error"); });
|
|
34185
|
+
return () => { active = false; };
|
|
34186
|
+
}, []);
|
|
34187
|
+
const locked = state === "env" || state === "readonly" || state === "unavailable";
|
|
34188
|
+
useStableInput((input, key) => {
|
|
34189
|
+
if (saving.current) return;
|
|
34190
|
+
if (key.escape || key.ctrl && input === "c") { setDraft(""); back(); return; }
|
|
34191
|
+
if (state === void 0) return;
|
|
34192
|
+
if (key.return) {
|
|
34193
|
+
const raw = draft.trim();
|
|
34194
|
+
if (!raw) { done(false); return; }
|
|
34195
|
+
if (locked) return;
|
|
34196
|
+
if (/[\s\x00-\x1f\x7f-]/.test(raw) || ENV_ASSIGNMENT.test(raw) || hasWrappingQuotes(raw)) {
|
|
34197
|
+
setError("Paste only the management key, without quotes, spaces or an environment-variable name."); return;
|
|
34198
|
+
}
|
|
34199
|
+
saving.current = true; setBusy(true); setError(""); setDraft("");
|
|
34200
|
+
Promise.resolve().then(() => save(raw)).then(() => done(true), reason => {
|
|
34201
|
+
saving.current = false; setBusy(false);
|
|
34202
|
+
setError(reason instanceof Error ? reason.message : String(reason));
|
|
34203
|
+
});
|
|
34204
|
+
return;
|
|
34205
|
+
}
|
|
34206
|
+
if (locked) return;
|
|
34207
|
+
if (key.ctrl && input === "u") { setDraft(""); setError(""); return; }
|
|
34208
|
+
if (key.backspace || key.delete) { setDraft(current => [...current].slice(0, -1).join("")); return; }
|
|
34209
|
+
if (key.ctrl || key.meta || !input) return;
|
|
34210
|
+
setDraft(current => (current + stripPasteMarkers(input)).slice(0, 4096));
|
|
34211
|
+
setError("");
|
|
34212
|
+
});
|
|
34213
|
+
const stateLine = state === "saved" ? "A management key is saved; paste a new one to replace it."
|
|
34214
|
+
: state === "env" ? "OPENROUTER_MANAGEMENT_KEY is set by your environment."
|
|
34215
|
+
: state === "readonly" ? "OPENROUTER_MANAGEMENT_KEY is read-only here."
|
|
34216
|
+
: state === "unavailable" ? "Credential storage is unavailable."
|
|
34217
|
+
: state === "error" ? "Could not read the management key status." : "";
|
|
34218
|
+
return (0, import_react.createElement)(Box, { flexDirection: "column", paddingX: 2 },
|
|
34219
|
+
(0, import_react.createElement)(Text, { bold: true }, "OpenRouter management key" + (optional ? " (optional)" : "")),
|
|
34220
|
+
(0, import_react.createElement)(Text, { dimColor: true }, "Adds every API key's usage and your 30-day spend by model to /openrouter."),
|
|
34221
|
+
(0, import_react.createElement)(Text, { dimColor: true }, "It cannot call models; DSCODE only reads."),
|
|
34222
|
+
(0, import_react.createElement)(Text, { dimColor: true }, "Saved on this Mac in ~/.dscode/credentials.yaml"),
|
|
34223
|
+
stateLine ? (0, import_react.createElement)(Text, { dimColor: true }, stateLine) : void 0,
|
|
34224
|
+
(0, import_react.createElement)(Text, null, busy ? "Checking with OpenRouter…" : state === void 0 ? "Loading…" : locked ? "" : "Management key › " + (draft ? "••••••••" : "paste your key")),
|
|
34225
|
+
error ? (0, import_react.createElement)(Text, { color: "red" }, error) : void 0,
|
|
34226
|
+
(0, import_react.createElement)(Text, { dimColor: true }, locked ? "Enter continue · Esc close" : optional ? "Enter save · Enter on empty skips · Esc skip · Ctrl+U clear" : "Enter save · Esc back · Ctrl+U clear"));
|
|
34227
|
+
}
|
|
34228
|
+
function DscodeOpenRouterPanel({ load, setManagement, back }) {
|
|
34229
|
+
const [account, setAccount] = (0, import_react.useState)(void 0);
|
|
34230
|
+
const [error, setError] = (0, import_react.useState)("");
|
|
34231
|
+
const [epoch, setEpoch] = (0, import_react.useState)(0);
|
|
34232
|
+
const stdout = useStdout().stdout;
|
|
34233
|
+
const columns = stdout?.columns ?? 80, rows = stdout?.rows ?? 30;
|
|
34234
|
+
(0, import_react.useEffect)(() => {
|
|
34235
|
+
let active = true;
|
|
34236
|
+
setAccount(void 0); setError("");
|
|
34237
|
+
Promise.resolve().then(() => load()).then(value => { if (active) setAccount(value); }, reason => { if (active) setError(reason instanceof Error ? reason.message : String(reason)); });
|
|
34238
|
+
return () => { active = false; };
|
|
34239
|
+
}, [epoch]);
|
|
34240
|
+
useStableInput((input, key) => {
|
|
34241
|
+
if (key.escape || input === "q" || key.ctrl && input === "c") { back(); return; }
|
|
34242
|
+
if (input === "r") { setEpoch(value => value + 1); return; }
|
|
34243
|
+
if (input === "m") setManagement();
|
|
34244
|
+
});
|
|
34245
|
+
const palette = getPalette();
|
|
34246
|
+
const width = Math.max(1, columns - 4);
|
|
34247
|
+
const lines = account === void 0
|
|
34248
|
+
? [{ text: error ? "Could not load the OpenRouter account: " + error : "Loading OpenRouter account…", tone: error ? "error" : "dim" }]
|
|
34249
|
+
: dscodeOpenRouterAccountLines(account);
|
|
34250
|
+
const colorOf = tone => tone === "error" ? palette.error : tone === "dim" ? palette.dim : tone === "title" ? palette.brandBright : palette.text;
|
|
34251
|
+
return (0, import_react.createElement)(Box, { flexDirection: "column", paddingX: 2 },
|
|
34252
|
+
(0, import_react.createElement)(Text, { bold: true }, "/openrouter — account"),
|
|
34253
|
+
...lines.slice(0, Math.max(1, rows - 6)).map((line, index) => (0, import_react.createElement)(Text, { key: index, color: inkColor(colorOf(line.tone)), bold: line.tone === "title" || void 0, wrap: "truncate-end" }, truncateColumns(line.text, width))),
|
|
34254
|
+
(0, import_react.createElement)(Text, { dimColor: true }, "r refresh · m management key · esc close"));
|
|
34255
|
+
}
|
|
34256
|
+
// dscode-openrouter-ui-end
|
|
34055
34257
|
function ProviderConfirmPanel({ target, kind, confirm, done, back }) {
|
|
34056
34258
|
const stdout = useStdout().stdout;
|
|
34057
34259
|
const viewport = panelViewport(stdout?.columns ?? 80, stdout?.rows ?? 30);
|
|
@@ -34667,7 +34869,7 @@ function CompletionMenu({ active, mention, index, rows, error }) {
|
|
|
34667
34869
|
* While a modal (approval / question / model panel) owns the keys, the
|
|
34668
34870
|
* box passes every key through untouched.
|
|
34669
34871
|
*/
|
|
34670
|
-
function Input({ effortSurface, ultraPulse, active, frozen, busy, descriptors, skills, dispatch, steer, interrupt, quit, openEmail, emailFill, emailConsumed, openLogin, openProvider, openModel, openEffort, openHelp, openMode, openPermission, openResume, openPlugin, openJobs, openStatusline, openTheme, openLanguage, openHistory, openAgents, openSubagent, openTodos, openDelete, openDiff, reviewChanges, deleteConfirm, confirmDelete, cancelDelete, createSession, forkSession, cancelSessionSwitch, notify, applyEditorKeys, hasNotice, dismissNotice, toggleReasoning, openVerbose, clearView, refresh, loadMentions, inspectImages, prepareImages, inspectFiles, prepareFiles, readClipboardImage, cyclePermission, exportTranscript, renameTitle, copyLastResponse, recallSpace, recordLocal, recordHistory, queued, cancelQueued, historyFill, historyConsumed, animations, applyAnimations, waveTier, waveStyle, maxRows, onEditorRows, onMenuRows, sessionKey }) {
|
|
34872
|
+
function Input({ effortSurface, ultraPulse, active, frozen, busy, descriptors, skills, dispatch, steer, interrupt, quit, openEmail, emailFill, emailConsumed, openLogin, openProvider, openOpenRouter, openModel, openEffort, openHelp, openMode, openPermission, openResume, openPlugin, openJobs, openStatusline, openTheme, openLanguage, openHistory, openAgents, openSubagent, openTodos, openDelete, openDiff, reviewChanges, deleteConfirm, confirmDelete, cancelDelete, createSession, forkSession, cancelSessionSwitch, notify, applyEditorKeys, hasNotice, dismissNotice, toggleReasoning, openVerbose, clearView, refresh, loadMentions, inspectImages, prepareImages, inspectFiles, prepareFiles, readClipboardImage, cyclePermission, exportTranscript, renameTitle, copyLastResponse, recallSpace, recordLocal, recordHistory, queued, cancelQueued, historyFill, historyConsumed, animations, applyAnimations, waveTier, waveStyle, maxRows, onEditorRows, onMenuRows, sessionKey }) {
|
|
34671
34873
|
const columns = useStdout().stdout?.columns ?? 80;
|
|
34672
34874
|
const inputTerminalRows = useStdout().stdout?.rows ?? 30;
|
|
34673
34875
|
const dscodeImeStdout = useStdout().stdout;
|
|
@@ -35210,13 +35412,17 @@ function Input({ effortSurface, ultraPulse, active, frozen, busy, descriptors, s
|
|
|
35210
35412
|
applyEdit(insertText(liveValue, liveCursor, "\n"));
|
|
35211
35413
|
return;
|
|
35212
35414
|
}
|
|
35415
|
+
// dscode-picker-commands-v1: these commands open a picker, so Enter on the menu runs them.
|
|
35416
|
+
let dscodeRunValue;
|
|
35213
35417
|
if (menuActive) {
|
|
35214
|
-
|
|
35418
|
+
const dscodePicked = mentionActive || candidates.length === 0 ? void 0 : candidates[completionIndex % candidates.length];
|
|
35419
|
+
if (dscodePicked !== void 0 && ["/provider","/login","/openrouter"].includes(dscodePicked.label)) dscodeRunValue = dscodePicked.label;
|
|
35420
|
+
else if (!(!mentionActive && candidates.some((candidate) => candidate.label === liveValue))) {
|
|
35215
35421
|
acceptMenuCandidate();
|
|
35216
35422
|
return;
|
|
35217
35423
|
}
|
|
35218
35424
|
}
|
|
35219
|
-
const expandedValue = expandLargePastes(liveValue, pendingPastesRef.current);
|
|
35425
|
+
const expandedValue = expandLargePastes(dscodeRunValue ?? liveValue, pendingPastesRef.current);
|
|
35220
35426
|
const trimmed = expandedValue.trim();
|
|
35221
35427
|
const text = submissionPayload(expandedValue);
|
|
35222
35428
|
if (/^\/email(?:\s|$)/.test(trimmed)) {
|
|
@@ -35235,6 +35441,13 @@ function Input({ effortSurface, ultraPulse, active, frozen, busy, descriptors, s
|
|
|
35235
35441
|
if (busy) { notify("Stop the running turn before /login.", "warning"); return; }
|
|
35236
35442
|
openLogin(dscodeLoginTarget); return;
|
|
35237
35443
|
}
|
|
35444
|
+
if (trimmed === "/openrouter") {
|
|
35445
|
+
valueRef.current = ""; cursorRef.current = 0;
|
|
35446
|
+
setValue(""); setCursor(0); setCompletionIndex(0); setDismissedMenuValue(void 0);
|
|
35447
|
+
recall.current = beginRecall(recallSpace, "");
|
|
35448
|
+
if (busy) { notify("Stop the running turn before /openrouter.", "warning"); return; }
|
|
35449
|
+
openOpenRouter(); return;
|
|
35450
|
+
}
|
|
35238
35451
|
if (trimmed === "/provider" || /^\/provider\s/.test(trimmed)) {
|
|
35239
35452
|
valueRef.current = ""; cursorRef.current = 0;
|
|
35240
35453
|
setValue(""); setCursor(0); setCompletionIndex(0); setDismissedMenuValue(void 0);
|
|
@@ -36170,14 +36383,16 @@ function App(props) {
|
|
|
36170
36383
|
const MENU_RESERVE_ROWS = 5;
|
|
36171
36384
|
const dynamicRows = Math.max(1, terminalRows - 8 - MENU_RESERVE_ROWS - composerGutterRows - (composerRows - 1) - Math.max(0, menuRows - MENU_RESERVE_ROWS));
|
|
36172
36385
|
const streamingActive = view.streaming !== "" || showReasoning && view.streamingReasoning !== "";
|
|
36173
|
-
const
|
|
36386
|
+
const dscodeCompacting = view.dscodeCompactingSince > 0;
|
|
36387
|
+
const dscodeCompactionRows = !dscodeCompacting ? 0 : dynamicRows >= 12 ? 5 : 1;
|
|
36388
|
+
const deepDivingVisible = busy || dscodeCompacting;
|
|
36174
36389
|
const allLiveLines = (0, import_react.useMemo)(() => view.entries.slice(settled).flatMap((entry) => dscodeChatLines(entry, Math.max(1, terminalColumns - 2), showReasoning)), [
|
|
36175
36390
|
view.entries,
|
|
36176
36391
|
settled,
|
|
36177
36392
|
terminalColumns,
|
|
36178
36393
|
showReasoning
|
|
36179
36394
|
]);
|
|
36180
|
-
const liveBudget = busy || streamingActive ? Math.max(1, Math.floor(dynamicRows / 3)) : Math.max(0, dynamicRows - (deepDivingVisible ? 1 : 0));
|
|
36395
|
+
const liveBudget = busy || streamingActive ? Math.max(1, Math.floor((dynamicRows - dscodeCompactionRows) / 3)) : Math.max(0, dynamicRows - (deepDivingVisible ? Math.max(1, dscodeCompactionRows) : 0));
|
|
36181
36396
|
const visibleLiveLines = liveBudget === 0 ? [] : allLiveLines.slice(-liveBudget);
|
|
36182
36397
|
const streamRows = Math.max(1, dynamicRows - visibleLiveLines.length);
|
|
36183
36398
|
const reasoningRows = !showReasoning || view.streamingReasoning === "" || view.streaming !== "" ? 0 : streamRows;
|
|
@@ -36221,6 +36436,14 @@ function App(props) {
|
|
|
36221
36436
|
streamingActive
|
|
36222
36437
|
]);
|
|
36223
36438
|
const sessionHasImages = (0, import_react.useMemo)(() => view.entries.some((entry) => (entry.kind === "user" || entry.kind === "pending") && (entry.images?.length ?? 0) > 0), [view.entries]);
|
|
36439
|
+
const dscodeRequestModel = (row, effortId) => {
|
|
36440
|
+
if (props.dscodeCompactionPreview === void 0 || modelLabel === row.provider + "/" + row.model) { applyModel(row, effortId); return; }
|
|
36441
|
+
Promise.resolve().then(() => props.dscodeCompactionPreview(row)).then((preview) => {
|
|
36442
|
+
if (!preview?.compacts) { applyModel(row, effortId); return; }
|
|
36443
|
+
setEffortFor(void 0); setProviderOpen(false);
|
|
36444
|
+
setProviderAction({ kind: "dscode-compaction", row, effortId, preview }); setModelOpen(true);
|
|
36445
|
+
}, () => applyModel(row, effortId));
|
|
36446
|
+
};
|
|
36224
36447
|
/** Apply one /model pick: record the selection, close the panel, report via notice. */
|
|
36225
36448
|
const applyModel = (row, effortId) => {
|
|
36226
36449
|
try {
|
|
@@ -36257,7 +36480,7 @@ function App(props) {
|
|
|
36257
36480
|
const models = await dscodeWaitForModels(props.loadModels, provider);
|
|
36258
36481
|
const pick = dscodePickModel(models.rows, provider, modelLabel, effortLabel);
|
|
36259
36482
|
if (pick === void 0) { notify(spec.name + " serves no models yet — check /model", "error"); return; }
|
|
36260
|
-
|
|
36483
|
+
dscodeRequestModel(pick.row, pick.effort);
|
|
36261
36484
|
}).catch((error) => notify("provider switch failed: " + (error instanceof Error ? error.message : String(error)), "error"));
|
|
36262
36485
|
};
|
|
36263
36486
|
const reloadModelSurfaces = () => {
|
|
@@ -36302,7 +36525,28 @@ function App(props) {
|
|
|
36302
36525
|
}, [providerDirectory, directory]);
|
|
36303
36526
|
let modelSurface;
|
|
36304
36527
|
if (modelOpen && !approvalPending && !questionPending) {
|
|
36305
|
-
if (providerAction?.kind === "dscode-
|
|
36528
|
+
if (providerAction?.kind === "dscode-compaction") modelSurface = (0, import_react.createElement)(DscodeCompactionConfirmPanel, {
|
|
36529
|
+
preview: providerAction.preview,
|
|
36530
|
+
confirm: () => applyModel(providerAction.row, providerAction.effortId),
|
|
36531
|
+
back: () => setProviderAction(void 0)
|
|
36532
|
+
});
|
|
36533
|
+
else if (providerAction?.kind === "dscode-openrouter") modelSurface = (0, import_react.createElement)(DscodeOpenRouterPanel, {
|
|
36534
|
+
load: () => props.dscodeLoadOpenRouterAccount === void 0 ? Promise.reject(new Error("account data is unavailable in this profile")) : props.dscodeLoadOpenRouterAccount(),
|
|
36535
|
+
setManagement: () => setProviderAction({ kind: "dscode-management-key", then: () => setProviderAction({ kind: "dscode-openrouter" }) }),
|
|
36536
|
+
back: closeModelSurface
|
|
36537
|
+
});
|
|
36538
|
+
else if (providerAction?.kind === "dscode-management-key") modelSurface = (0, import_react.createElement)(DscodeManagementKeyPanel, {
|
|
36539
|
+
optional: providerAction.optional === true,
|
|
36540
|
+
status: props.dscodeManagementKeyStatus,
|
|
36541
|
+
save: (key) => props.dscodeSaveManagementKey === void 0 ? Promise.reject(new Error("credential storage is unavailable")) : props.dscodeSaveManagementKey(key),
|
|
36542
|
+
done: (saved) => {
|
|
36543
|
+
if (saved) notify("OpenRouter management key saved locally; /openrouter now shows every API key and your 30-day spend.");
|
|
36544
|
+
const then = providerAction.then;
|
|
36545
|
+
if (then !== void 0) then(); else closeModelSurface();
|
|
36546
|
+
},
|
|
36547
|
+
back: () => { const then = providerAction.then; if (then !== void 0) then(); else closeModelSurface(); }
|
|
36548
|
+
});
|
|
36549
|
+
else if (providerAction?.kind === "dscode-provider") modelSurface = (0, import_react.createElement)(DscodeProviderPanel, {
|
|
36306
36550
|
current: dscodeProviderOfLabel(modelLabel),
|
|
36307
36551
|
load: props.loadModelProviders,
|
|
36308
36552
|
choose: dscodeSwitchProvider,
|
|
@@ -36313,9 +36557,11 @@ function App(props) {
|
|
|
36313
36557
|
load: async () => { await props.dscodeEnsureProviderRoute?.(providerAction.provider); return props.loadModelProviders(); },
|
|
36314
36558
|
save: props.saveModelProviderCredential,
|
|
36315
36559
|
done: () => {
|
|
36316
|
-
const then = providerAction.then;
|
|
36317
|
-
|
|
36318
|
-
if (then !== void 0) then(); else notify(dscodeProviderSpec(
|
|
36560
|
+
const then = providerAction.then, provider = providerAction.provider;
|
|
36561
|
+
reloadModelSurfaces();
|
|
36562
|
+
const finish = () => { closeModelSurface(); if (then !== void 0) then(); else notify(dscodeProviderSpec(provider).name + " API key saved locally; ready to use."); };
|
|
36563
|
+
if (provider === "openrouter" && props.dscodeSaveManagementKey !== void 0) { setProviderAction({ kind: "dscode-management-key", optional: true, then: finish }); return; }
|
|
36564
|
+
finish();
|
|
36319
36565
|
},
|
|
36320
36566
|
back: closeModelSurface
|
|
36321
36567
|
});
|
|
@@ -36463,7 +36709,7 @@ function App(props) {
|
|
|
36463
36709
|
row: effortFor,
|
|
36464
36710
|
current: effortLabel,
|
|
36465
36711
|
animations,
|
|
36466
|
-
select: (effortId) =>
|
|
36712
|
+
select: (effortId) => dscodeRequestModel(effortFor, effortId),
|
|
36467
36713
|
back: closeModelSurface,
|
|
36468
36714
|
onExit: closeModelSurface
|
|
36469
36715
|
});
|
|
@@ -36477,7 +36723,7 @@ function App(props) {
|
|
|
36477
36723
|
return;
|
|
36478
36724
|
}
|
|
36479
36725
|
const effortId = row.reasoning?.efforts.length === 1 ? row.reasoning.efforts[0].id : void 0;
|
|
36480
|
-
|
|
36726
|
+
dscodeRequestModel(row, effortId);
|
|
36481
36727
|
},
|
|
36482
36728
|
...props.loadModelProviders === void 0 || props.saveModelProviderConfiguration === void 0 ? {} : { onProviders: () => setProviderOpen(true) },
|
|
36483
36729
|
onRetry: reloadModelSurfaces,
|
|
@@ -36512,7 +36758,7 @@ function App(props) {
|
|
|
36512
36758
|
dim: false,
|
|
36513
36759
|
maxRows: auditedAnswerRows,
|
|
36514
36760
|
prefix: " "
|
|
36515
|
-
}, busy ? (0, import_react.createElement)(Caret, { animated: animations }) : void 0) : void 0, void 0) : void 0, transcriptVisible && busy ? (0, import_react.createElement)(DscodeActivityLine, { entries: view.entries, streaming: view.streaming !== "", since: view.busySince, animated: animations }) : void 0, transcriptVisible ? (0, import_react.createElement)(AgentsLine, {
|
|
36761
|
+
}, busy ? (0, import_react.createElement)(Caret, { animated: animations }) : void 0) : void 0, void 0) : void 0, transcriptVisible && dscodeCompacting ? (0, import_react.createElement)(DscodeCompactionLine, { since: view.dscodeCompactingSince, rows: dscodeCompactionRows, animated: animations }) : transcriptVisible && busy ? (0, import_react.createElement)(DscodeActivityLine, { entries: view.entries, streaming: view.streaming !== "", since: view.busySince, animated: animations }) : void 0, transcriptVisible ? (0, import_react.createElement)(AgentsLine, {
|
|
36516
36762
|
rows: agentRows,
|
|
36517
36763
|
total: props.subagents.getTotalSeen()
|
|
36518
36764
|
}) : void 0, todosOpen && !approvalPending && !questionPending ? (0, import_react.createElement)(MemoTodoListPanel, {
|
|
@@ -36672,6 +36918,10 @@ function App(props) {
|
|
|
36672
36918
|
setProviderOpen(false); setEffortFor(void 0);
|
|
36673
36919
|
setProviderAction({ kind: "dscode-key", provider: provider ?? dscodeProviderOfLabel(modelLabel) }); setModelOpen(true);
|
|
36674
36920
|
},
|
|
36921
|
+
openOpenRouter: () => {
|
|
36922
|
+
setProviderOpen(false); setEffortFor(void 0);
|
|
36923
|
+
setProviderAction({ kind: "dscode-openrouter" }); setModelOpen(true);
|
|
36924
|
+
},
|
|
36675
36925
|
openProvider: (provider) => {
|
|
36676
36926
|
if (provider !== void 0) { dscodeSwitchProvider(provider); return; }
|
|
36677
36927
|
setProviderOpen(false); setEffortFor(void 0);
|
|
@@ -39503,6 +39753,14 @@ async function run(ctx, startup, io) {
|
|
|
39503
39753
|
});
|
|
39504
39754
|
return `${row.provider}/${row.model}`;
|
|
39505
39755
|
};
|
|
39756
|
+
const dscodeCompactionPreviewFor = async (row) => {
|
|
39757
|
+
const meter = ctx.get("tokenMeter");
|
|
39758
|
+
const llm = ctx.get("llm");
|
|
39759
|
+
if (active === void 0 || typeof meter?.measure !== "function" || typeof llm?.resolveModelInfo !== "function") return void 0;
|
|
39760
|
+
const used = meter.measure(active.session).totalTokens;
|
|
39761
|
+
const info = await llm.resolveModelInfo(row.provider, row.model);
|
|
39762
|
+
return dscodeCompactionPreview({ used, contextWindow: info?.context?.contextWindow, thresholdRatio: await dscodePricedThresholdRatio(row.provider, row.model), label: row.provider + "/" + row.model });
|
|
39763
|
+
};
|
|
39506
39764
|
/** The /subagent override label, '' when delegated agents follow the current model. */
|
|
39507
39765
|
const subagentModelLabel = () => subagentOverride === void 0 ? "" : modelSelectionLabel(subagentOverride);
|
|
39508
39766
|
/** Apply one /subagent model pick; returns the override label. */
|
|
@@ -39877,8 +40135,11 @@ async function run(ctx, startup, io) {
|
|
|
39877
40135
|
steer,
|
|
39878
40136
|
interrupt,
|
|
39879
40137
|
quit,
|
|
39880
|
-
loadModels: () => loadModelDirectory(ctx),
|
|
40138
|
+
loadModels: () => dscodeMigrateOpenRouter(ctx.get("settings")).then(() => loadModelDirectory(ctx)),
|
|
39881
40139
|
dscodeEnsureProviderRoute: (provider) => dscodeEnsureProviderRoute(ctx.get("settings"), provider),
|
|
40140
|
+
dscodeManagementKeyStatus: () => dscodeManagementKeyStatus(ctx),
|
|
40141
|
+
dscodeSaveManagementKey: (key) => dscodeSaveManagementKey(ctx, key),
|
|
40142
|
+
dscodeLoadOpenRouterAccount: () => dscodeLoadOpenRouterAccountFor(ctx),
|
|
39882
40143
|
loadModelProviders: () => loadProviderSettings(ctx),
|
|
39883
40144
|
subscribeModelProviders: (listener) => subscribeProviderSettings(ctx, listener),
|
|
39884
40145
|
saveModelProviderCredential: (target, key) => saveProviderCredential(ctx, target, key),
|
|
@@ -39902,6 +40163,7 @@ async function run(ctx, startup, io) {
|
|
|
39902
40163
|
cyclePermission: cyclePermission$1,
|
|
39903
40164
|
setPermission: setPermissionAction,
|
|
39904
40165
|
selectModel,
|
|
40166
|
+
dscodeCompactionPreview: dscodeCompactionPreviewFor,
|
|
39905
40167
|
subagentModel: subagentModelLabel(),
|
|
39906
40168
|
setSubagentModel,
|
|
39907
40169
|
clearSubagentModel,
|