charness 3.2.0 → 3.3.0
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/.env.example +3 -6
- package/DEVELOPMENT.md +15 -0
- package/README.md +111 -38
- package/SETUP.md +121 -16
- package/dist/adapters/adapterEventRouting.d.ts +2 -1
- package/dist/adapters/adapterEventRouting.d.ts.map +1 -1
- package/dist/adapters/adapterEventRouting.js +3 -0
- package/dist/adapters/adapterEventRouting.js.map +1 -1
- package/dist/adapters/adapterNames.d.ts +13 -0
- package/dist/adapters/adapterNames.d.ts.map +1 -1
- package/dist/adapters/adapterNames.js +16 -0
- package/dist/adapters/adapterNames.js.map +1 -1
- package/dist/adapters/backendUnavailableError.d.ts +11 -0
- package/dist/adapters/backendUnavailableError.d.ts.map +1 -0
- package/dist/adapters/backendUnavailableError.js +19 -0
- package/dist/adapters/backendUnavailableError.js.map +1 -0
- package/dist/adapters/claudeCliAdapter.d.ts +29 -6
- package/dist/adapters/claudeCliAdapter.d.ts.map +1 -1
- package/dist/adapters/claudeCliAdapter.js +70 -16
- package/dist/adapters/claudeCliAdapter.js.map +1 -1
- package/dist/adapters/claudeJsonStreamAdapter.d.ts +36 -3
- package/dist/adapters/claudeJsonStreamAdapter.d.ts.map +1 -1
- package/dist/adapters/claudeJsonStreamAdapter.js +93 -30
- package/dist/adapters/claudeJsonStreamAdapter.js.map +1 -1
- package/dist/adapters/createAdapter.d.ts +3 -14
- package/dist/adapters/createAdapter.d.ts.map +1 -1
- package/dist/adapters/createAdapter.js +9 -19
- package/dist/adapters/createAdapter.js.map +1 -1
- package/dist/adapters/openCodeAdapter.d.ts +140 -12
- package/dist/adapters/openCodeAdapter.d.ts.map +1 -1
- package/dist/adapters/openCodeAdapter.js +385 -119
- package/dist/adapters/openCodeAdapter.js.map +1 -1
- package/dist/apiErrorRetry.d.ts +70 -6
- package/dist/apiErrorRetry.d.ts.map +1 -1
- package/dist/apiErrorRetry.js +312 -34
- package/dist/apiErrorRetry.js.map +1 -1
- package/dist/apiRetryKick.d.ts +26 -1
- package/dist/apiRetryKick.d.ts.map +1 -1
- package/dist/apiRetryKick.js +41 -2
- package/dist/apiRetryKick.js.map +1 -1
- package/dist/bot.d.ts +2 -1
- package/dist/bot.d.ts.map +1 -1
- package/dist/bot.js +736 -184
- package/dist/bot.js.map +1 -1
- package/dist/cli/claudeProfiles.d.ts +1 -1
- package/dist/cli/claudeProfiles.js +1 -1
- package/dist/cli/hot.d.ts +7 -1
- package/dist/cli/hot.d.ts.map +1 -1
- package/dist/cli/hot.js +29 -3
- package/dist/cli/hot.js.map +1 -1
- package/dist/configDirFile.d.ts +73 -0
- package/dist/configDirFile.d.ts.map +1 -0
- package/dist/configDirFile.js +216 -0
- package/dist/configDirFile.js.map +1 -0
- package/dist/connectors/telegram/commands/autoContinueLimits.d.ts +2 -2
- package/dist/connectors/telegram/commands/autoContinueLimits.d.ts.map +1 -1
- package/dist/connectors/telegram/commands/autoContinueLimits.js +4 -4
- package/dist/connectors/telegram/commands/autoContinueLimits.js.map +1 -1
- package/dist/connectors/telegram/commands/backendSwitch.d.ts +25 -0
- package/dist/connectors/telegram/commands/backendSwitch.d.ts.map +1 -0
- package/dist/connectors/telegram/commands/backendSwitch.js +104 -0
- package/dist/connectors/telegram/commands/backendSwitch.js.map +1 -0
- package/dist/connectors/telegram/commands/callbackMessage.d.ts +12 -0
- package/dist/connectors/telegram/commands/callbackMessage.d.ts.map +1 -1
- package/dist/connectors/telegram/commands/callbackMessage.js +24 -0
- package/dist/connectors/telegram/commands/callbackMessage.js.map +1 -1
- package/dist/connectors/telegram/commands/callbackToast.d.ts +36 -0
- package/dist/connectors/telegram/commands/callbackToast.d.ts.map +1 -0
- package/dist/connectors/telegram/commands/callbackToast.js +83 -0
- package/dist/connectors/telegram/commands/callbackToast.js.map +1 -0
- package/dist/connectors/telegram/commands/claudeAccounts.d.ts +18 -0
- package/dist/connectors/telegram/commands/claudeAccounts.d.ts.map +1 -1
- package/dist/connectors/telegram/commands/claudeAccounts.js +220 -66
- package/dist/connectors/telegram/commands/claudeAccounts.js.map +1 -1
- package/dist/connectors/telegram/commands/displayModes.d.ts.map +1 -1
- package/dist/connectors/telegram/commands/displayModes.js +4 -2
- package/dist/connectors/telegram/commands/displayModes.js.map +1 -1
- package/dist/connectors/telegram/commands/fallbackChain.d.ts +5 -8
- package/dist/connectors/telegram/commands/fallbackChain.d.ts.map +1 -1
- package/dist/connectors/telegram/commands/fallbackChain.js +183 -193
- package/dist/connectors/telegram/commands/fallbackChain.js.map +1 -1
- package/dist/connectors/telegram/commands/limitsBoard.d.ts +40 -0
- package/dist/connectors/telegram/commands/limitsBoard.d.ts.map +1 -0
- package/dist/connectors/telegram/commands/limitsBoard.js +281 -0
- package/dist/connectors/telegram/commands/limitsBoard.js.map +1 -0
- package/dist/connectors/telegram/commands/modelPage.d.ts +130 -0
- package/dist/connectors/telegram/commands/modelPage.d.ts.map +1 -0
- package/dist/connectors/telegram/commands/modelPage.js +120 -0
- package/dist/connectors/telegram/commands/modelPage.js.map +1 -0
- package/dist/connectors/telegram/commands/modelProviders.d.ts +9 -1
- package/dist/connectors/telegram/commands/modelProviders.d.ts.map +1 -1
- package/dist/connectors/telegram/commands/modelProviders.js +203 -111
- package/dist/connectors/telegram/commands/modelProviders.js.map +1 -1
- package/dist/connectors/telegram/commands/stt.d.ts +32 -0
- package/dist/connectors/telegram/commands/stt.d.ts.map +1 -0
- package/dist/connectors/telegram/commands/stt.js +460 -0
- package/dist/connectors/telegram/commands/stt.js.map +1 -0
- package/dist/effortLevels.d.ts +57 -7
- package/dist/effortLevels.d.ts.map +1 -1
- package/dist/effortLevels.js +65 -9
- package/dist/effortLevels.js.map +1 -1
- package/dist/i18n/de.d.ts.map +1 -1
- package/dist/i18n/de.js +160 -17
- package/dist/i18n/de.js.map +1 -1
- package/dist/i18n/en.d.ts.map +1 -1
- package/dist/i18n/en.js +160 -17
- package/dist/i18n/en.js.map +1 -1
- package/dist/i18n/es.d.ts.map +1 -1
- package/dist/i18n/es.js +160 -17
- package/dist/i18n/es.js.map +1 -1
- package/dist/i18n/fr.d.ts.map +1 -1
- package/dist/i18n/fr.js +160 -17
- package/dist/i18n/fr.js.map +1 -1
- package/dist/i18n/hi.d.ts.map +1 -1
- package/dist/i18n/hi.js +160 -17
- package/dist/i18n/hi.js.map +1 -1
- package/dist/i18n/ja.d.ts.map +1 -1
- package/dist/i18n/ja.js +160 -17
- package/dist/i18n/ja.js.map +1 -1
- package/dist/i18n/ka.d.ts.map +1 -1
- package/dist/i18n/ka.js +160 -17
- package/dist/i18n/ka.js.map +1 -1
- package/dist/i18n/pt.d.ts.map +1 -1
- package/dist/i18n/pt.js +160 -17
- package/dist/i18n/pt.js.map +1 -1
- package/dist/i18n/ru.d.ts.map +1 -1
- package/dist/i18n/ru.js +160 -17
- package/dist/i18n/ru.js.map +1 -1
- package/dist/i18n/uk.d.ts.map +1 -1
- package/dist/i18n/uk.js +160 -17
- package/dist/i18n/uk.js.map +1 -1
- package/dist/i18n/uz.d.ts.map +1 -1
- package/dist/i18n/uz.js +160 -17
- package/dist/i18n/uz.js.map +1 -1
- package/dist/i18n/zh.d.ts.map +1 -1
- package/dist/i18n/zh.js +160 -17
- package/dist/i18n/zh.js.map +1 -1
- package/dist/installManager.d.ts +20 -4
- package/dist/installManager.d.ts.map +1 -1
- package/dist/installManager.js +82 -14
- package/dist/installManager.js.map +1 -1
- package/dist/instanceSettings.d.ts +52 -0
- package/dist/instanceSettings.d.ts.map +1 -0
- package/dist/instanceSettings.js +136 -0
- package/dist/instanceSettings.js.map +1 -0
- package/dist/pinnedStatus.d.ts +7 -1
- package/dist/pinnedStatus.d.ts.map +1 -1
- package/dist/pinnedStatus.js +1 -1
- package/dist/pinnedStatus.js.map +1 -1
- package/dist/requests/requestLedger.d.ts +8 -0
- package/dist/requests/requestLedger.d.ts.map +1 -1
- package/dist/requests/requestLedger.js +19 -1
- package/dist/requests/requestLedger.js.map +1 -1
- package/dist/scheduler/mcpSurface.js +4 -4
- package/dist/scheduler/mcpSurface.js.map +1 -1
- package/dist/shutdown.d.ts +14 -0
- package/dist/shutdown.d.ts.map +1 -1
- package/dist/shutdown.js +16 -0
- package/dist/shutdown.js.map +1 -1
- package/dist/state.d.ts +54 -2
- package/dist/state.d.ts.map +1 -1
- package/dist/state.js +62 -1
- package/dist/state.js.map +1 -1
- package/dist/stt/sttAutoInstall.d.ts +39 -0
- package/dist/stt/sttAutoInstall.d.ts.map +1 -0
- package/dist/stt/sttAutoInstall.js +158 -0
- package/dist/stt/sttAutoInstall.js.map +1 -0
- package/dist/stt/sttChildEnv.d.ts +11 -0
- package/dist/stt/sttChildEnv.d.ts.map +1 -0
- package/dist/stt/sttChildEnv.js +30 -0
- package/dist/stt/sttChildEnv.js.map +1 -0
- package/dist/stt/sttConfigEdit.d.ts +71 -0
- package/dist/stt/sttConfigEdit.d.ts.map +1 -0
- package/dist/stt/sttConfigEdit.js +144 -0
- package/dist/stt/sttConfigEdit.js.map +1 -0
- package/dist/stt/sttInstall.d.ts +147 -0
- package/dist/stt/sttInstall.d.ts.map +1 -0
- package/dist/stt/sttInstall.js +491 -0
- package/dist/stt/sttInstall.js.map +1 -0
- package/dist/stt/sttInstallEntry.d.ts +2 -0
- package/dist/stt/sttInstallEntry.d.ts.map +1 -0
- package/dist/stt/sttInstallEntry.js +31 -0
- package/dist/stt/sttInstallEntry.js.map +1 -0
- package/dist/stt/sttInstallReporter.d.ts +45 -0
- package/dist/stt/sttInstallReporter.d.ts.map +1 -0
- package/dist/stt/sttInstallReporter.js +57 -0
- package/dist/stt/sttInstallReporter.js.map +1 -0
- package/dist/stt/sttRuntime.d.ts +35 -0
- package/dist/stt/sttRuntime.d.ts.map +1 -0
- package/dist/stt/sttRuntime.js +73 -0
- package/dist/stt/sttRuntime.js.map +1 -0
- package/dist/stt/sttScreenPlan.d.ts +193 -0
- package/dist/stt/sttScreenPlan.d.ts.map +1 -0
- package/dist/stt/sttScreenPlan.js +541 -0
- package/dist/stt/sttScreenPlan.js.map +1 -0
- package/dist/stt/sttSettings.d.ts +201 -0
- package/dist/stt/sttSettings.d.ts.map +1 -0
- package/dist/stt/sttSettings.js +387 -0
- package/dist/stt/sttSettings.js.map +1 -0
- package/dist/stt/sttSidecarOwner.d.ts +115 -0
- package/dist/stt/sttSidecarOwner.d.ts.map +1 -0
- package/dist/stt/sttSidecarOwner.js +475 -0
- package/dist/stt/sttSidecarOwner.js.map +1 -0
- package/dist/stt/transcribeChain.d.ts +36 -0
- package/dist/stt/transcribeChain.d.ts.map +1 -0
- package/dist/stt/transcribeChain.js +42 -0
- package/dist/stt/transcribeChain.js.map +1 -0
- package/dist/types.d.ts +77 -4
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/adapterSwitchSessionIds.d.ts +32 -0
- package/dist/utils/adapterSwitchSessionIds.d.ts.map +1 -0
- package/dist/utils/adapterSwitchSessionIds.js +44 -0
- package/dist/utils/adapterSwitchSessionIds.js.map +1 -0
- package/dist/utils/backendSwitchPlan.d.ts +63 -0
- package/dist/utils/backendSwitchPlan.d.ts.map +1 -0
- package/dist/utils/backendSwitchPlan.js +73 -0
- package/dist/utils/backendSwitchPlan.js.map +1 -0
- package/dist/utils/claudeAccountPickerPlan.d.ts +12 -1
- package/dist/utils/claudeAccountPickerPlan.d.ts.map +1 -1
- package/dist/utils/claudeAccountPickerPlan.js +20 -1
- package/dist/utils/claudeAccountPickerPlan.js.map +1 -1
- package/dist/utils/claudeTranscriptContent.d.ts +24 -0
- package/dist/utils/claudeTranscriptContent.d.ts.map +1 -0
- package/dist/utils/claudeTranscriptContent.js +107 -0
- package/dist/utils/claudeTranscriptContent.js.map +1 -0
- package/dist/utils/claudeUsage.d.ts +47 -8
- package/dist/utils/claudeUsage.d.ts.map +1 -1
- package/dist/utils/claudeUsage.js +76 -14
- package/dist/utils/claudeUsage.js.map +1 -1
- package/dist/utils/claudeUsageRefresher.d.ts +8 -1
- package/dist/utils/claudeUsageRefresher.d.ts.map +1 -1
- package/dist/utils/claudeUsageRefresher.js +9 -4
- package/dist/utils/claudeUsageRefresher.js.map +1 -1
- package/dist/utils/effortPickerPlan.d.ts +54 -0
- package/dist/utils/effortPickerPlan.d.ts.map +1 -0
- package/dist/utils/effortPickerPlan.js +56 -0
- package/dist/utils/effortPickerPlan.js.map +1 -0
- package/dist/utils/ensureSessionPlan.d.ts +20 -4
- package/dist/utils/ensureSessionPlan.d.ts.map +1 -1
- package/dist/utils/ensureSessionPlan.js +17 -4
- package/dist/utils/ensureSessionPlan.js.map +1 -1
- package/dist/utils/fallbackBridge.d.ts +6 -2
- package/dist/utils/fallbackBridge.d.ts.map +1 -1
- package/dist/utils/fallbackBridge.js +10 -3
- package/dist/utils/fallbackBridge.js.map +1 -1
- package/dist/utils/fallbackChain.d.ts +36 -0
- package/dist/utils/fallbackChain.d.ts.map +1 -1
- package/dist/utils/fallbackChain.js +65 -1
- package/dist/utils/fallbackChain.js.map +1 -1
- package/dist/utils/fallbackSwitchNotice.d.ts +41 -0
- package/dist/utils/fallbackSwitchNotice.d.ts.map +1 -0
- package/dist/utils/fallbackSwitchNotice.js +75 -0
- package/dist/utils/fallbackSwitchNotice.js.map +1 -0
- package/dist/utils/fileSendService.d.ts +33 -10
- package/dist/utils/fileSendService.d.ts.map +1 -1
- package/dist/utils/fileSendService.js +78 -27
- package/dist/utils/fileSendService.js.map +1 -1
- package/dist/utils/jsonStreamHost.d.ts +39 -0
- package/dist/utils/jsonStreamHost.d.ts.map +1 -1
- package/dist/utils/jsonStreamHost.js +60 -1
- package/dist/utils/jsonStreamHost.js.map +1 -1
- package/dist/utils/limitEpisodeRecovery.d.ts +16 -2
- package/dist/utils/limitEpisodeRecovery.d.ts.map +1 -1
- package/dist/utils/limitEpisodeRecovery.js +44 -3
- package/dist/utils/limitEpisodeRecovery.js.map +1 -1
- package/dist/utils/limitSettings.d.ts +25 -0
- package/dist/utils/limitSettings.d.ts.map +1 -0
- package/dist/utils/limitSettings.js +31 -0
- package/dist/utils/limitSettings.js.map +1 -0
- package/dist/utils/limitsBoardPlan.d.ts +52 -0
- package/dist/utils/limitsBoardPlan.d.ts.map +1 -0
- package/dist/utils/limitsBoardPlan.js +93 -0
- package/dist/utils/limitsBoardPlan.js.map +1 -0
- package/dist/utils/openCodeUsage.d.ts +93 -0
- package/dist/utils/openCodeUsage.d.ts.map +1 -0
- package/dist/utils/openCodeUsage.js +248 -0
- package/dist/utils/openCodeUsage.js.map +1 -0
- package/dist/utils/operatorSwitchPlan.d.ts +61 -0
- package/dist/utils/operatorSwitchPlan.d.ts.map +1 -0
- package/dist/utils/operatorSwitchPlan.js +32 -0
- package/dist/utils/operatorSwitchPlan.js.map +1 -0
- package/dist/utils/promptDelivery.d.ts +40 -0
- package/dist/utils/promptDelivery.d.ts.map +1 -1
- package/dist/utils/promptDelivery.js +31 -0
- package/dist/utils/promptDelivery.js.map +1 -1
- package/dist/utils/recvPreviewRedaction.d.ts +14 -4
- package/dist/utils/recvPreviewRedaction.d.ts.map +1 -1
- package/dist/utils/recvPreviewRedaction.js +19 -7
- package/dist/utils/recvPreviewRedaction.js.map +1 -1
- package/dist/utils/startupReadiness.d.ts +3 -3
- package/dist/utils/startupReadiness.d.ts.map +1 -1
- package/dist/utils/startupReadiness.js +2 -2
- package/dist/utils/startupReadiness.js.map +1 -1
- package/dist/utils/threadStatusReport.d.ts +3 -1
- package/dist/utils/threadStatusReport.d.ts.map +1 -1
- package/dist/utils/threadStatusReport.js +4 -3
- package/dist/utils/threadStatusReport.js.map +1 -1
- package/dist/utils/timezone.d.ts +23 -0
- package/dist/utils/timezone.d.ts.map +1 -1
- package/dist/utils/timezone.js +38 -0
- package/dist/utils/timezone.js.map +1 -1
- package/dist/utils/transcribeAudio.d.ts +25 -12
- package/dist/utils/transcribeAudio.d.ts.map +1 -1
- package/dist/utils/transcribeAudio.js +39 -21
- package/dist/utils/transcribeAudio.js.map +1 -1
- package/dist/utils/usageRefreshBudget.d.ts +9 -0
- package/dist/utils/usageRefreshBudget.d.ts.map +1 -0
- package/dist/utils/usageRefreshBudget.js +27 -0
- package/dist/utils/usageRefreshBudget.js.map +1 -0
- package/examples/.env.example +7 -3
- package/examples/docker-compose.yml +9 -7
- package/package.json +2 -1
- package/stt/gigaam_sidecar.py +800 -0
|
@@ -1,35 +1,28 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.limitsUsageRefreshBudgetMs = void 0;
|
|
4
3
|
exports.createFallbackChain = createFallbackChain;
|
|
5
4
|
/**
|
|
6
|
-
* `/
|
|
7
|
-
* account / provider + model a topic continues on (reorder, include / exclude, remove, add through
|
|
8
|
-
* sub-picker, rebuild a draft, clear — from EVERY topic, one instance-wide list), the two settings that decide
|
|
9
|
-
* limit does (auto switch to a fallback model, wait for the reset and continue — instance defaults in General,
|
|
5
|
+
* `/limits_autoswitch` — the setup of automatic switching on a usage limit, on one screen: the instance-wide priority
|
|
6
|
+
* chain of backend + account / provider + model a topic continues on (reorder, include / exclude, remove, add through
|
|
7
|
+
* a two-step sub-picker, rebuild a draft, clear — from EVERY topic, one instance-wide list), the two settings that decide
|
|
8
|
+
* what a limit does (auto switch to a fallback model, wait for the reset and continue — instance defaults in General,
|
|
10
9
|
* on / off / same-as-General overrides in a topic, chosen in a per-setting sub-menu) — and the «🔁 Switch to …»
|
|
11
|
-
* buttons a usage-limit notice carries. The message text is deliberately short: the
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
10
|
+
* buttons a usage-limit notice carries. The message text is deliberately short: a title, the topic's position and
|
|
11
|
+
* where its settings come from — the list and the settings' values are on the buttons. `/fallback` and
|
|
12
|
+
* `/auto_continue_limits` are hidden aliases of this screen. `/limits` itself is the switch board
|
|
13
|
+
* (`limitsBoard.ts`). See README.md in this folder and `utils/fallbackChain.ts`.
|
|
15
14
|
*/
|
|
16
15
|
const telegraf_1 = require("telegraf");
|
|
17
16
|
const i18n_1 = require("../../../i18n");
|
|
18
|
-
const
|
|
17
|
+
const modelPickerPlan_1 = require("../../../utils/modelPickerPlan");
|
|
19
18
|
const claudeUsage_1 = require("../../../utils/claudeUsage");
|
|
20
|
-
const claudeProfileUsageLines_1 = require("../../../utils/claudeProfileUsageLines");
|
|
21
|
-
const claudeUsageRefresher_1 = require("../../../utils/claudeUsageRefresher");
|
|
22
19
|
const autoContinueOnLimit_1 = require("../../../utils/autoContinueOnLimit");
|
|
20
|
+
const usageRefreshBudget_1 = require("../../../utils/usageRefreshBudget");
|
|
23
21
|
const fallbackChain_1 = require("../../../utils/fallbackChain");
|
|
22
|
+
const limitSettings_1 = require("../../../utils/limitSettings");
|
|
24
23
|
const callbackMessage_1 = require("./callbackMessage");
|
|
25
|
-
|
|
26
|
-
const
|
|
27
|
-
/**
|
|
28
|
-
* How long opening the screen waits for the usage refresh (one poll is ~0.5 s). A slower one — a hung endpoint
|
|
29
|
-
* runs into the fetch's own 15 s timeout — keeps going in the background and the next render shows its result.
|
|
30
|
-
*/
|
|
31
|
-
exports.limitsUsageRefreshBudgetMs = 2_000;
|
|
32
|
-
const settingIds = ['switch', 'wait'];
|
|
24
|
+
const callbackToast_1 = require("./callbackToast");
|
|
25
|
+
const modelPage_1 = require("./modelPage");
|
|
33
26
|
const settingCallbacks = {
|
|
34
27
|
switch: { open: fallbackChain_1.fallbackAutoSwitchOpenCallback, on: fallbackChain_1.fallbackAutoSwitchOnCallback, off: fallbackChain_1.fallbackAutoSwitchOffCallback, same: fallbackChain_1.fallbackAutoSwitchSameCallback },
|
|
35
28
|
wait: { open: fallbackChain_1.fallbackWaitOpenCallback, on: fallbackChain_1.fallbackWaitOnCallback, off: fallbackChain_1.fallbackWaitOffCallback, same: fallbackChain_1.fallbackWaitSameCallback },
|
|
@@ -39,10 +32,14 @@ const settingTextKeys = {
|
|
|
39
32
|
switch: { button: 'limits.switchButton', menuTitle: 'limits.switchMenuTitle' },
|
|
40
33
|
wait: { button: 'limits.waitButton', menuTitle: 'limits.waitMenuTitle' },
|
|
41
34
|
};
|
|
42
|
-
/** @description Build the `/
|
|
35
|
+
/** @description Build the `/limits_autoswitch` feature over its ports: the command (+ the hidden aliases), its buttons, the limit-notice switch button. */
|
|
43
36
|
function createFallbackChain(ports) {
|
|
44
37
|
const { bot, command, getState, replyToThread, editThreadMessage, authoriseContext, withThreadLocale, checkIsGeneral, getInstanceTimezone, refreshClaudeUsage, detectFallbackOptions, getTopicPosition, takeSwitchOffer, applyAutoContinue, getArmedLimitRetryFireAt, } = ports;
|
|
38
|
+
const answerWithWholeText = (0, callbackToast_1.createWholeTextAnswerer)(replyToThread);
|
|
39
|
+
// Both per MESSAGE, keyed by chat + message id (`buildMessageSnapshotKey`): a message id is unique only within one chat.
|
|
45
40
|
const addSnapshots = new Map();
|
|
41
|
+
/** The rung each «add it?» question waits to add; the revision of the list it was asked about rides in its button. */
|
|
42
|
+
const pendingAdds = new Map();
|
|
46
43
|
function getLabelWords() {
|
|
47
44
|
return { claude: (0, i18n_1.t)('fallback.backendClaude'), openCode: (0, i18n_1.t)('fallback.backendOpenCode'), topicModel: (0, i18n_1.t)('fallback.topicModel') };
|
|
48
45
|
}
|
|
@@ -51,15 +48,17 @@ function createFallbackChain(ports) {
|
|
|
51
48
|
return (0, fallbackChain_1.formatFallbackEntryLabel)(entry, getLabelWords());
|
|
52
49
|
}
|
|
53
50
|
/**
|
|
54
|
-
* A rung on its label button:
|
|
55
|
-
*
|
|
56
|
-
* signed in, ❓ not offered any more, 🚫 left out
|
|
57
|
-
*
|
|
51
|
+
* A rung on its label button: `✓ 1. Claude · work · opus` / `3. OpenCode · openai · gpt-6.1 🚫` — the program, then
|
|
52
|
+
* the account or provider and the model when the rung names one (Telegram sizes and truncates the button as it sees
|
|
53
|
+
* fit). The rung's state rides as a suffix (⛔ limited until, 🔒 not signed in, ❓ not offered any more, 🚫 left out
|
|
54
|
+
* of switching) and ✓ at the start marks where the topic runs now. The one place the label is built: a two-row
|
|
55
|
+
* layout (label on its own row) only changes how `buildPicker` assembles the row.
|
|
58
56
|
*/
|
|
59
57
|
function formatRowButtonLabel(index, entry, detection, current, nowMs) {
|
|
58
|
+
const words = getLabelWords();
|
|
60
59
|
const base = entry.backend === 'claude'
|
|
61
|
-
?
|
|
62
|
-
: `${entry.providerId}
|
|
60
|
+
? `${words.claude} · ${entry.profile}${entry.model === null ? '' : ` · ${entry.model}`}`
|
|
61
|
+
: `${words.openCode} · ${entry.providerId} · ${entry.modelId}`;
|
|
63
62
|
const availability = (0, fallbackChain_1.getFallbackEntryAvailability)(entry, detection, nowMs);
|
|
64
63
|
let suffix = '';
|
|
65
64
|
if (availability.status === 'limited')
|
|
@@ -70,9 +69,8 @@ function createFallbackChain(ports) {
|
|
|
70
69
|
suffix += ' ❓';
|
|
71
70
|
if ((0, fallbackChain_1.checkIsFallbackEntryDisabled)(entry))
|
|
72
71
|
suffix += ' 🚫';
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
return `${index + 1}. ${base}${suffix}`;
|
|
72
|
+
const here = current && (0, fallbackChain_1.checkIsSameFallbackAccount)(entry, current) ? '✓ ' : '';
|
|
73
|
+
return `${here}${index + 1}. ${base}${suffix}`;
|
|
76
74
|
}
|
|
77
75
|
/**
|
|
78
76
|
* A rung's detail view, in the message the list sits in: its name and state, then ⬆️ Up / ⬇️ Down (hidden at
|
|
@@ -121,28 +119,7 @@ function createFallbackChain(ports) {
|
|
|
121
119
|
];
|
|
122
120
|
await editThreadMessage(key, messageId, lines.join('\n'), telegraf_1.Markup.inlineKeyboard(rows));
|
|
123
121
|
}
|
|
124
|
-
|
|
125
|
-
function readSetting(id, key, isGeneral) {
|
|
126
|
-
if (id === 'switch') {
|
|
127
|
-
return {
|
|
128
|
-
effective: isGeneral ? getState().getClaudeAutoSwitchOnLimitGlobalDefault() : getState().checkIsClaudeAutoSwitchOnLimitEnabled(key),
|
|
129
|
-
override: isGeneral ? undefined : getState().getClaudeAutoSwitchOnLimitOverride(key),
|
|
130
|
-
generalValue: getState().getClaudeAutoSwitchOnLimitGlobalDefault(),
|
|
131
|
-
};
|
|
132
|
-
}
|
|
133
|
-
return {
|
|
134
|
-
effective: isGeneral ? getState().getAutoContinueOnLimitGlobalDefault() : getState().checkIsAutoContinueOnLimitEnabled(key),
|
|
135
|
-
override: isGeneral ? undefined : getState().getAutoContinueOnLimitOverride(key),
|
|
136
|
-
generalValue: getState().getAutoContinueOnLimitGlobalDefault(),
|
|
137
|
-
};
|
|
138
|
-
}
|
|
139
|
-
function formatState(enabled) {
|
|
140
|
-
return enabled ? (0, i18n_1.t)('autoContinueLimits.on') : (0, i18n_1.t)('autoContinueLimits.off');
|
|
141
|
-
}
|
|
142
|
-
/** Where a topic's setting value comes from: General, or the topic's own override. */
|
|
143
|
-
function formatSettingSource(setting) {
|
|
144
|
-
return setting.override === undefined ? (0, i18n_1.t)('limits.sourceGeneral') : (0, i18n_1.t)('limits.sourceTopic');
|
|
145
|
-
}
|
|
122
|
+
const readSetting = (id, key, isGeneral) => (0, limitSettings_1.readLimitSetting)(getState(), id, key, isGeneral);
|
|
146
123
|
/**
|
|
147
124
|
* One setting's button on the main screen: one full-width button with the setting's name and its effective value
|
|
148
125
|
* (`🔁 Auto switch: ON`). Where a topic's value comes from is in the message text above and in the sub-menu
|
|
@@ -153,7 +130,7 @@ function createFallbackChain(ports) {
|
|
|
153
130
|
function buildSettingRow(id, setting, isGeneral) {
|
|
154
131
|
const callbacks = settingCallbacks[id];
|
|
155
132
|
const tapData = isGeneral ? (setting.effective ? callbacks.off : callbacks.on) : callbacks.open;
|
|
156
|
-
return [telegraf_1.Markup.button.callback((0, i18n_1.t)(settingTextKeys[id].button, { state:
|
|
133
|
+
return [telegraf_1.Markup.button.callback((0, i18n_1.t)(settingTextKeys[id].button, { state: (0, limitSettings_1.formatLimitSettingState)(setting.effective) }), tapData)];
|
|
157
134
|
}
|
|
158
135
|
/**
|
|
159
136
|
* A topic's setting sub-menu, in the message the screen sits in: the setting's name, then ON / OFF / As in
|
|
@@ -168,41 +145,17 @@ function createFallbackChain(ports) {
|
|
|
168
145
|
const callbacks = settingCallbacks[id];
|
|
169
146
|
const mark = (isCurrent) => (isCurrent ? ' ✓' : '');
|
|
170
147
|
const rows = [
|
|
171
|
-
[telegraf_1.Markup.button.callback(`${
|
|
172
|
-
[telegraf_1.Markup.button.callback(`${
|
|
173
|
-
[telegraf_1.Markup.button.callback(`${(0, i18n_1.t)('limits.settingSameButton', { state:
|
|
148
|
+
[telegraf_1.Markup.button.callback(`${(0, limitSettings_1.formatLimitSettingState)(true)}${mark(setting.override === true)}`, callbacks.on)],
|
|
149
|
+
[telegraf_1.Markup.button.callback(`${(0, limitSettings_1.formatLimitSettingState)(false)}${mark(setting.override === false)}`, callbacks.off)],
|
|
150
|
+
[telegraf_1.Markup.button.callback(`${(0, i18n_1.t)('limits.settingSameButton', { state: (0, limitSettings_1.formatLimitSettingState)(setting.generalValue) })}${mark(setting.override === undefined)}`, callbacks.same)],
|
|
174
151
|
buildBackRow(),
|
|
175
152
|
];
|
|
176
153
|
await editThreadMessage(key, messageId, (0, i18n_1.t)(settingTextKeys[id].menuTitle), telegraf_1.Markup.inlineKeyboard(rows));
|
|
177
154
|
}
|
|
178
155
|
/**
|
|
179
|
-
* The
|
|
180
|
-
*
|
|
181
|
-
*
|
|
182
|
-
* one never polled has nothing to show and is left out (no rows → no heading either). OpenCode's limit marks
|
|
183
|
-
* are not repeated here: they are on the rung buttons (`⛔ until`).
|
|
184
|
-
*/
|
|
185
|
-
function formatUsageBlock(detection, nowMs) {
|
|
186
|
-
const timezone = getInstanceTimezone();
|
|
187
|
-
const rows = [];
|
|
188
|
-
for (const profile of detection.claudeProfiles) {
|
|
189
|
-
if (profile.loggedIn === false) {
|
|
190
|
-
rows.push(`• ${profile.name} — ${(0, i18n_1.t)('account.row.loggedOut')}`);
|
|
191
|
-
continue;
|
|
192
|
-
}
|
|
193
|
-
// The first line hangs under a row in `/accounts` (the locale indents it); here it sits after the name.
|
|
194
|
-
const [first, ...rest] = (0, claudeProfileUsageLines_1.formatClaudeProfileUsageLines)(profile, timezone, nowMs);
|
|
195
|
-
if (first === undefined)
|
|
196
|
-
continue;
|
|
197
|
-
rows.push([`• ${profile.name} — ${first.trimStart()}`, ...rest].join('\n'));
|
|
198
|
-
}
|
|
199
|
-
return rows.length === 0 ? '' : [(0, i18n_1.t)('limits.usageHeading'), ...rows].join('\n');
|
|
200
|
-
}
|
|
201
|
-
/**
|
|
202
|
-
* The `/limits` screen. Text: the Claude accounts' usage, then what the topic runs on and where its two
|
|
203
|
-
* settings come from (General: just that these are defaults) and the list's heading — the list itself, its
|
|
204
|
-
* marks and the two settings' values are on the buttons. A topic also gets «skip once» while a limit wait is
|
|
205
|
-
* armed for it.
|
|
156
|
+
* The `/limits_autoswitch` screen. Text: its title, what the topic runs on and where its two settings come from
|
|
157
|
+
* (General: just that these are defaults), then the list's heading — the list itself, its marks and the two
|
|
158
|
+
* settings' values are on the buttons. A topic also gets «skip once» while a limit wait is armed for it.
|
|
206
159
|
*/
|
|
207
160
|
async function buildPicker(key, isGeneral) {
|
|
208
161
|
const chain = getState().getFallbackChain();
|
|
@@ -212,18 +165,13 @@ function createFallbackChain(ports) {
|
|
|
212
165
|
const switchSetting = readSetting('switch', key, isGeneral);
|
|
213
166
|
const waitSetting = readSetting('wait', key, isGeneral);
|
|
214
167
|
const parts = [];
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
parts.push((0, i18n_1.t)('limits.settingsGeneral'));
|
|
220
|
-
}
|
|
221
|
-
else {
|
|
222
|
-
parts.push([
|
|
168
|
+
parts.push(isGeneral
|
|
169
|
+
? [(0, i18n_1.t)('limits.autoswitchTitle'), (0, i18n_1.t)('limits.settingsGeneral')].join('\n')
|
|
170
|
+
: [
|
|
171
|
+
(0, i18n_1.t)('limits.autoswitchTitle'),
|
|
223
172
|
(0, i18n_1.t)('limits.topicRuns', { current: current ? formatEntry(current) : (0, i18n_1.t)('fallback.noAgent') }),
|
|
224
|
-
(0, i18n_1.t)('limits.sourceLine', { switch:
|
|
173
|
+
(0, i18n_1.t)('limits.sourceLine', { switch: (0, limitSettings_1.formatLimitSettingSource)(switchSetting), wait: (0, limitSettings_1.formatLimitSettingSource)(waitSetting) }),
|
|
225
174
|
].join('\n'));
|
|
226
|
-
}
|
|
227
175
|
parts.push(chain.length === 0 ? (0, i18n_1.t)('limits.listNoteEmpty') : (0, i18n_1.t)('limits.listNote'));
|
|
228
176
|
const rows = [];
|
|
229
177
|
const revision = (0, fallbackChain_1.getFallbackChainRevision)(chain);
|
|
@@ -249,7 +197,9 @@ function createFallbackChain(ports) {
|
|
|
249
197
|
async function rerenderPicker(key, messageId, isGeneral) {
|
|
250
198
|
if (messageId === null)
|
|
251
199
|
return;
|
|
252
|
-
|
|
200
|
+
const snapshotKey = (0, callbackMessage_1.buildMessageSnapshotKey)(key, messageId);
|
|
201
|
+
addSnapshots.delete(snapshotKey);
|
|
202
|
+
pendingAdds.delete(snapshotKey);
|
|
253
203
|
const picker = await buildPicker(key, isGeneral);
|
|
254
204
|
await editThreadMessage(key, messageId, picker.text, picker.keyboard);
|
|
255
205
|
}
|
|
@@ -274,7 +224,7 @@ function createFallbackChain(ports) {
|
|
|
274
224
|
await replyToThread(key, (0, i18n_1.t)('fallback.nothingDetected'));
|
|
275
225
|
return;
|
|
276
226
|
}
|
|
277
|
-
addSnapshots.set(messageId, { providers, providerId: null, models: [] });
|
|
227
|
+
addSnapshots.set((0, callbackMessage_1.buildMessageSnapshotKey)(key, messageId), { providers, providerId: null, models: [] });
|
|
278
228
|
rows.push(buildBackRow());
|
|
279
229
|
await editThreadMessage(key, messageId, (0, i18n_1.t)('fallback.pickAccount'), telegraf_1.Markup.inlineKeyboard(rows));
|
|
280
230
|
}
|
|
@@ -285,22 +235,25 @@ function createFallbackChain(ports) {
|
|
|
285
235
|
rows.push(buildBackRow());
|
|
286
236
|
await editThreadMessage(key, messageId, (0, i18n_1.t)('fallback.pickModel', { account: `${getLabelWords().claude} · ${profile}` }), telegraf_1.Markup.inlineKeyboard(rows));
|
|
287
237
|
}
|
|
288
|
-
/** Step 2 for an OpenCode provider: one page of its models (absolute indexes into the snapshot). */
|
|
289
|
-
async function
|
|
290
|
-
const
|
|
291
|
-
const
|
|
292
|
-
const
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
238
|
+
/** Step 2 for an OpenCode provider: one page of its models (absolute indexes into the snapshot), limit marks on the limited ones. */
|
|
239
|
+
async function showAddModelPage(key, messageId, snapshot, page) {
|
|
240
|
+
const providerId = snapshot.providerId ?? '';
|
|
241
|
+
const { openCodeLimits } = await detectFallbackOptions();
|
|
242
|
+
const nowMs = Date.now();
|
|
243
|
+
const { rows } = (0, modelPage_1.buildModelPageButtons)({
|
|
244
|
+
provider: providerId,
|
|
245
|
+
models: snapshot.models,
|
|
246
|
+
page,
|
|
247
|
+
current: null,
|
|
248
|
+
callbacks: {
|
|
249
|
+
buildPage: fallbackChain_1.buildFallbackAddModelPageCallback,
|
|
250
|
+
buildPick: fallbackChain_1.buildFallbackAddModelCallback,
|
|
251
|
+
noop: modelPickerPlan_1.modelPickerNoopCallback,
|
|
252
|
+
back: { label: (0, i18n_1.t)('fallback.backButton'), data: fallbackChain_1.fallbackBackCallback },
|
|
253
|
+
},
|
|
254
|
+
getSuffix: (modelId) => (0, fallbackChain_1.formatOpenCodeModelLimitSuffix)(`${providerId}/${modelId}`, openCodeLimits, getInstanceTimezone(), nowMs),
|
|
255
|
+
});
|
|
256
|
+
await editThreadMessage(key, messageId, (0, i18n_1.t)('fallback.pickModel', { account: `${getLabelWords().openCode} · ${providerId}` }), telegraf_1.Markup.inlineKeyboard(rows));
|
|
304
257
|
}
|
|
305
258
|
/** Append an entry to the chain and RETURN the confirmation (the one write path behind both add steps). */
|
|
306
259
|
async function applyAdd(entry) {
|
|
@@ -311,6 +264,33 @@ function createFallbackChain(ports) {
|
|
|
311
264
|
await getState().setFallbackChain(result.chain);
|
|
312
265
|
return (0, i18n_1.t)('fallback.added', { label: formatEntry(entry) });
|
|
313
266
|
}
|
|
267
|
+
/**
|
|
268
|
+
* The question before a rung of a NEW backend joins automatic switching, in the message the tap came from: the
|
|
269
|
+
* rung, the shared line about the hand-over, ✅ Continue (the revision of the list is baked in) and ✖️ Cancel
|
|
270
|
+
* (`cancelData`: back to the list, or to the rung's detail view). A tap that comes late finds the list changed.
|
|
271
|
+
*/
|
|
272
|
+
async function askAboutNewBackend(key, messageId, questionKey, entry, continueData, cancelData) {
|
|
273
|
+
const text = `${(0, i18n_1.t)(questionKey, { label: formatEntry(entry) })}\n${(0, i18n_1.t)('handover.note')}`;
|
|
274
|
+
await editThreadMessage(key, messageId, text, telegraf_1.Markup.inlineKeyboard([[
|
|
275
|
+
telegraf_1.Markup.button.callback((0, i18n_1.t)('handover.continueButton'), continueData),
|
|
276
|
+
telegraf_1.Markup.button.callback((0, i18n_1.t)('handover.cancelButton'), cancelData),
|
|
277
|
+
]]));
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* An «add» that finished its steps. A rung of a backend the list does not use yet asks first (the question
|
|
281
|
+
* replaces the picker in the same message); any other add goes ahead and the screen is re-rendered.
|
|
282
|
+
*/
|
|
283
|
+
async function takeAdd(ctx, key, isGeneral, messageId, entry) {
|
|
284
|
+
const chain = getState().getFallbackChain();
|
|
285
|
+
if (messageId !== null && (0, fallbackChain_1.addFallbackEntry)(chain, entry).ok && (0, fallbackChain_1.checkIsNewBackendForChain)(chain, entry)) {
|
|
286
|
+
await (0, callbackToast_1.answerCallbackQuerySafely)(ctx);
|
|
287
|
+
pendingAdds.set((0, callbackMessage_1.buildMessageSnapshotKey)(key, messageId), entry);
|
|
288
|
+
await askAboutNewBackend(key, messageId, 'limits.addConfirm', entry, (0, fallbackChain_1.buildFallbackAddConfirmCallback)((0, fallbackChain_1.getFallbackChainRevision)(chain)), fallbackChain_1.fallbackBackCallback);
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
291
|
+
await answerWithWholeText(ctx, key, await applyAdd(entry));
|
|
292
|
+
await rerenderPicker(key, messageId, isGeneral);
|
|
293
|
+
}
|
|
314
294
|
/** Replace the chain with the draft and RETURN the confirmation. */
|
|
315
295
|
async function applyPropose() {
|
|
316
296
|
const chain = (0, fallbackChain_1.proposeFallbackChain)(await detectFallbackOptions(), getState().getFallbackChain());
|
|
@@ -332,55 +312,42 @@ function createFallbackChain(ports) {
|
|
|
332
312
|
const what = (0, i18n_1.t)('limits.whatSwitch');
|
|
333
313
|
if (isGeneral) {
|
|
334
314
|
await getState().setClaudeAutoSwitchOnLimitGlobalDefault(enabled ?? false);
|
|
335
|
-
return (0, i18n_1.t)('limits.setGlobal', { what, state:
|
|
315
|
+
return (0, i18n_1.t)('limits.setGlobal', { what, state: (0, limitSettings_1.formatLimitSettingState)(enabled ?? false) });
|
|
336
316
|
}
|
|
337
317
|
await getState().setClaudeAutoSwitchOnLimitOverride(key, enabled);
|
|
338
318
|
return enabled === null
|
|
339
|
-
? (0, i18n_1.t)('limits.setSame', { what, state:
|
|
340
|
-
: (0, i18n_1.t)('limits.setThisTopic', { what, state:
|
|
319
|
+
? (0, i18n_1.t)('limits.setSame', { what, state: (0, limitSettings_1.formatLimitSettingState)(getState().getClaudeAutoSwitchOnLimitGlobalDefault()) })
|
|
320
|
+
: (0, i18n_1.t)('limits.setThisTopic', { what, state: (0, limitSettings_1.formatLimitSettingState)(enabled) });
|
|
341
321
|
}
|
|
342
322
|
/** The «wait for the reset» twin of {@link applyAutoSwitch}; the write (and the armed-wait cleanup) is `autoContinueLimits.ts`'s. */
|
|
343
323
|
async function applyWait(key, isGeneral, enabled) {
|
|
344
324
|
const what = (0, i18n_1.t)('limits.whatWait');
|
|
345
325
|
await applyAutoContinue(key, isGeneral, isGeneral ? (enabled ?? true) : enabled);
|
|
346
326
|
if (isGeneral)
|
|
347
|
-
return (0, i18n_1.t)('limits.setGlobal', { what, state:
|
|
327
|
+
return (0, i18n_1.t)('limits.setGlobal', { what, state: (0, limitSettings_1.formatLimitSettingState)(enabled ?? true) });
|
|
348
328
|
return enabled === null
|
|
349
|
-
? (0, i18n_1.t)('limits.setSame', { what, state:
|
|
350
|
-
: (0, i18n_1.t)('limits.setThisTopic', { what, state:
|
|
329
|
+
? (0, i18n_1.t)('limits.setSame', { what, state: (0, limitSettings_1.formatLimitSettingState)(getState().getAutoContinueOnLimitGlobalDefault()) })
|
|
330
|
+
: (0, i18n_1.t)('limits.setThisTopic', { what, state: (0, limitSettings_1.formatLimitSettingState)(enabled) });
|
|
351
331
|
}
|
|
352
332
|
// ── the command ──
|
|
353
333
|
function registerFallbackChainCommands() {
|
|
354
|
-
// `/
|
|
334
|
+
// `/limits_autoswitch` — bare: the screen (the chain is edited from every topic). `propose` / `rebuild`
|
|
355
335
|
// drafts the chain, `clear` empties it, `switch|autoswitch on|off|same` and `wait on|off|same` flip the two
|
|
356
|
-
// settings
|
|
357
|
-
// the
|
|
358
|
-
|
|
336
|
+
// settings; `/limits` takes the same verbs (`limitsBoard.ts` hands them to {@link runAutoSwitchCommand}).
|
|
337
|
+
// `/fallback` is the same command under its old name (hidden alias). Not gated on a session: the chain must
|
|
338
|
+
// be settable before any limit hits.
|
|
339
|
+
command(['limits_autoswitch', 'fallback'], async (_ctx, key, parsed) => {
|
|
359
340
|
const [verb = '', value = ''] = parsed.args;
|
|
360
|
-
await
|
|
341
|
+
await runAutoSwitchCommand(key, verb, value);
|
|
361
342
|
});
|
|
362
343
|
}
|
|
363
|
-
/**
|
|
364
|
-
* Refresh the usage snapshots (a snapshot younger than a minute is kept — the `/accounts` freshness), waiting at
|
|
365
|
-
* most {@link limitsUsageRefreshBudgetMs}: the screen is never held by a slow usage endpoint.
|
|
366
|
-
*/
|
|
367
|
-
async function refreshUsageWithinBudget() {
|
|
368
|
-
let timer;
|
|
369
|
-
const budget = new Promise((resolve) => { timer = setTimeout(resolve, exports.limitsUsageRefreshBudgetMs); });
|
|
370
|
-
try {
|
|
371
|
-
await Promise.race([refreshClaudeUsage({ maxAgeMs: claudeUsageRefresher_1.claudeUsageOnDemandMaxAgeMs }), budget]);
|
|
372
|
-
}
|
|
373
|
-
finally {
|
|
374
|
-
clearTimeout(timer);
|
|
375
|
-
}
|
|
376
|
-
}
|
|
377
344
|
/** Open the screen as a fresh message (the `/auto_continue_limits` alias lands here); the usage is refreshed first. */
|
|
378
|
-
async function
|
|
379
|
-
await refreshUsageWithinBudget();
|
|
345
|
+
async function openAutoSwitchView(key) {
|
|
346
|
+
await (0, usageRefreshBudget_1.refreshUsageWithinBudget)(refreshClaudeUsage);
|
|
380
347
|
const picker = await buildPicker(key, checkIsGeneral(key));
|
|
381
348
|
await replyToThread(key, picker.text, picker.keyboard);
|
|
382
349
|
}
|
|
383
|
-
async function
|
|
350
|
+
async function runAutoSwitchCommand(key, verb, value, usageKey = 'limits.autoswitchUsage') {
|
|
384
351
|
const isGeneral = checkIsGeneral(key);
|
|
385
352
|
const word = value.toLowerCase();
|
|
386
353
|
const parseState = () => {
|
|
@@ -394,12 +361,12 @@ function createFallbackChain(ports) {
|
|
|
394
361
|
};
|
|
395
362
|
switch (verb.toLowerCase()) {
|
|
396
363
|
case '':
|
|
397
|
-
await
|
|
364
|
+
await openAutoSwitchView(key);
|
|
398
365
|
return;
|
|
399
366
|
case 'propose':
|
|
400
367
|
case 'rebuild': {
|
|
401
368
|
await replyToThread(key, await applyPropose());
|
|
402
|
-
await
|
|
369
|
+
await openAutoSwitchView(key);
|
|
403
370
|
return;
|
|
404
371
|
}
|
|
405
372
|
case 'clear': {
|
|
@@ -410,7 +377,7 @@ function createFallbackChain(ports) {
|
|
|
410
377
|
case 'autoswitch': {
|
|
411
378
|
const enabled = parseState();
|
|
412
379
|
if (enabled === undefined) {
|
|
413
|
-
await replyToThread(key, (0, i18n_1.t)(
|
|
380
|
+
await replyToThread(key, (0, i18n_1.t)(usageKey));
|
|
414
381
|
return;
|
|
415
382
|
}
|
|
416
383
|
await replyToThread(key, await applyAutoSwitch(key, isGeneral, enabled));
|
|
@@ -419,14 +386,14 @@ function createFallbackChain(ports) {
|
|
|
419
386
|
case 'wait': {
|
|
420
387
|
const enabled = parseState();
|
|
421
388
|
if (enabled === undefined) {
|
|
422
|
-
await replyToThread(key, (0, i18n_1.t)(
|
|
389
|
+
await replyToThread(key, (0, i18n_1.t)(usageKey));
|
|
423
390
|
return;
|
|
424
391
|
}
|
|
425
392
|
await replyToThread(key, await applyWait(key, isGeneral, enabled));
|
|
426
393
|
return;
|
|
427
394
|
}
|
|
428
395
|
default:
|
|
429
|
-
await replyToThread(key, (0, i18n_1.t)(
|
|
396
|
+
await replyToThread(key, (0, i18n_1.t)(usageKey));
|
|
430
397
|
}
|
|
431
398
|
}
|
|
432
399
|
/** The shared tap prologue: authorise, resolve the topic, run under its locale. */
|
|
@@ -438,39 +405,39 @@ function createFallbackChain(ports) {
|
|
|
438
405
|
}
|
|
439
406
|
await withThreadLocale(key, () => run(key, checkIsGeneral(key), (0, callbackMessage_1.getCallbackMessageId)(ctx)));
|
|
440
407
|
}
|
|
441
|
-
/** `answerCbQuery` is capped at 200 characters: a long confirmation goes to the topic instead. */
|
|
442
|
-
async function answerTap(ctx, key, text) {
|
|
443
|
-
if (text.length <= 180) {
|
|
444
|
-
await ctx.answerCbQuery(text);
|
|
445
|
-
return;
|
|
446
|
-
}
|
|
447
|
-
await ctx.answerCbQuery();
|
|
448
|
-
await replyToThread(key, text);
|
|
449
|
-
}
|
|
450
408
|
/** An edit tap: a stale revision only re-renders. */
|
|
451
409
|
function registerEdit(re, edit, confirm,
|
|
452
410
|
/** Where the rung sits after the edit (the detail view follows it); `null` = back to the list. */
|
|
453
|
-
nextIndex
|
|
411
|
+
nextIndex,
|
|
412
|
+
/** An edit that must ask first answers with the data of the question's two buttons; `null` = go ahead. */
|
|
413
|
+
gate) {
|
|
454
414
|
bot.action(re, (ctx) => handleTap(ctx, async (key, isGeneral, messageId) => {
|
|
455
415
|
const chain = getState().getFallbackChain();
|
|
456
|
-
const
|
|
416
|
+
const revision = (0, fallbackChain_1.getFallbackChainRevision)(chain);
|
|
417
|
+
const parsed = (0, fallbackChain_1.parseFallbackEditCallback)(ctx.match[0], re, revision);
|
|
457
418
|
if (parsed === null) {
|
|
458
|
-
await
|
|
419
|
+
await (0, callbackToast_1.answerCallbackQuerySafely)(ctx);
|
|
459
420
|
return;
|
|
460
421
|
}
|
|
461
422
|
if (!parsed.isCurrent) {
|
|
462
|
-
await
|
|
423
|
+
await (0, callbackToast_1.answerCallbackQuerySafely)(ctx, (0, i18n_1.t)('fallback.stale'));
|
|
463
424
|
await rerenderPicker(key, messageId, isGeneral);
|
|
464
425
|
return;
|
|
465
426
|
}
|
|
427
|
+
const question = gate?.(chain, parsed.index, revision);
|
|
428
|
+
if (question && messageId !== null && chain[parsed.index]) {
|
|
429
|
+
await (0, callbackToast_1.answerCallbackQuerySafely)(ctx);
|
|
430
|
+
await askAboutNewBackend(key, messageId, 'limits.enableConfirm', chain[parsed.index], question.continueData, question.cancelData);
|
|
431
|
+
return;
|
|
432
|
+
}
|
|
466
433
|
const result = edit(chain, parsed.index);
|
|
467
434
|
if (!result.ok) {
|
|
468
|
-
await
|
|
435
|
+
await (0, callbackToast_1.answerCallbackQuerySafely)(ctx, (0, i18n_1.t)('fallback.stale'));
|
|
469
436
|
await rerenderPicker(key, messageId, isGeneral);
|
|
470
437
|
return;
|
|
471
438
|
}
|
|
472
439
|
await getState().setFallbackChain(result.chain);
|
|
473
|
-
await
|
|
440
|
+
await answerWithWholeText(ctx, key, confirm(chain, parsed.index));
|
|
474
441
|
const next = nextIndex(parsed.index);
|
|
475
442
|
if (next === null)
|
|
476
443
|
await rerenderPicker(key, messageId, isGeneral);
|
|
@@ -481,106 +448,129 @@ function createFallbackChain(ports) {
|
|
|
481
448
|
function registerFallbackChainCallbacks() {
|
|
482
449
|
registerEdit(fallbackChain_1.fallbackMoveUpCallbackRe, (chain, index) => (0, fallbackChain_1.moveFallbackEntry)(chain, index, -1), () => (0, i18n_1.t)('fallback.moved'), (index) => Math.max(0, index - 1));
|
|
483
450
|
registerEdit(fallbackChain_1.fallbackMoveDownCallbackRe, (chain, index) => (0, fallbackChain_1.moveFallbackEntry)(chain, index, 1), () => (0, i18n_1.t)('fallback.moved'), (index) => index + 1);
|
|
484
|
-
|
|
451
|
+
const confirmToggle = (chain, index) => (0, i18n_1.t)((0, fallbackChain_1.checkIsFallbackEntryDisabled)(chain[index]) ? 'limits.entryEnabled' : 'limits.entryDisabled', { label: formatEntry(chain[index]) });
|
|
452
|
+
// Using a rung that is left out is a question when its backend is not in automatic switching yet.
|
|
453
|
+
registerEdit(fallbackChain_1.fallbackToggleCallbackRe, fallbackChain_1.toggleFallbackEntryDisabled, confirmToggle, (index) => index, (chain, index, revision) => {
|
|
454
|
+
const entry = chain[index];
|
|
455
|
+
if (!entry || !(0, fallbackChain_1.checkIsFallbackEntryDisabled)(entry) || !(0, fallbackChain_1.checkIsNewBackendForChain)(chain.filter((_, i) => i !== index), entry))
|
|
456
|
+
return null;
|
|
457
|
+
return { continueData: (0, fallbackChain_1.buildFallbackToggleConfirmCallback)(index, revision), cancelData: (0, fallbackChain_1.buildFallbackOpenCallback)(index, revision) };
|
|
458
|
+
});
|
|
459
|
+
registerEdit(fallbackChain_1.fallbackToggleConfirmCallbackRe, fallbackChain_1.toggleFallbackEntryDisabled, confirmToggle, (index) => index);
|
|
485
460
|
registerEdit(fallbackChain_1.fallbackRemoveCallbackRe, fallbackChain_1.removeFallbackEntry, (chain, index) => (0, i18n_1.t)('fallback.removed', { label: formatEntry(chain[index]) }), () => null);
|
|
486
461
|
// A rung's button on the list: open its detail view (a stale revision only re-renders the list).
|
|
487
462
|
bot.action(fallbackChain_1.fallbackOpenCallbackRe, (ctx) => handleTap(ctx, async (key, isGeneral, messageId) => {
|
|
488
463
|
const chain = getState().getFallbackChain();
|
|
489
464
|
const parsed = (0, fallbackChain_1.parseFallbackEditCallback)(ctx.match[0], fallbackChain_1.fallbackOpenCallbackRe, (0, fallbackChain_1.getFallbackChainRevision)(chain));
|
|
490
465
|
if (parsed === null) {
|
|
491
|
-
await
|
|
466
|
+
await (0, callbackToast_1.answerCallbackQuerySafely)(ctx);
|
|
492
467
|
return;
|
|
493
468
|
}
|
|
494
469
|
if (!parsed.isCurrent || parsed.index >= chain.length) {
|
|
495
|
-
await
|
|
470
|
+
await (0, callbackToast_1.answerCallbackQuerySafely)(ctx, (0, i18n_1.t)('fallback.stale'));
|
|
496
471
|
await rerenderPicker(key, messageId, isGeneral);
|
|
497
472
|
return;
|
|
498
473
|
}
|
|
499
|
-
await
|
|
474
|
+
await (0, callbackToast_1.answerCallbackQuerySafely)(ctx);
|
|
500
475
|
await renderRungDetail(key, messageId, parsed.index, isGeneral);
|
|
501
476
|
}));
|
|
502
477
|
bot.action(fallbackChain_1.fallbackAddCallback, (ctx) => handleTap(ctx, async (key, _isGeneral, messageId) => {
|
|
503
|
-
await
|
|
478
|
+
await (0, callbackToast_1.answerCallbackQuerySafely)(ctx);
|
|
504
479
|
if (messageId !== null)
|
|
505
480
|
await renderAddAccountStep(key, messageId);
|
|
506
481
|
}));
|
|
507
482
|
bot.action(fallbackChain_1.fallbackAddClaudeCallbackRe, (ctx) => handleTap(ctx, async (key, _isGeneral, messageId) => {
|
|
508
|
-
await
|
|
483
|
+
await (0, callbackToast_1.answerCallbackQuerySafely)(ctx);
|
|
509
484
|
if (messageId !== null)
|
|
510
485
|
await renderAddClaudeModelStep(key, messageId, ctx.match[1]);
|
|
511
486
|
}));
|
|
512
487
|
bot.action(fallbackChain_1.fallbackAddClaudeModelCallbackRe, (ctx) => handleTap(ctx, async (key, isGeneral, messageId) => {
|
|
513
488
|
const model = ctx.match[2] === '-' ? null : ctx.match[2];
|
|
514
|
-
await
|
|
515
|
-
await rerenderPicker(key, messageId, isGeneral);
|
|
489
|
+
await takeAdd(ctx, key, isGeneral, messageId, { backend: 'claude', profile: ctx.match[1], model });
|
|
516
490
|
}));
|
|
517
491
|
bot.action(fallbackChain_1.fallbackAddProviderCallbackRe, (ctx) => handleTap(ctx, async (key, isGeneral, messageId) => {
|
|
518
|
-
const snapshot = messageId === null ? undefined : addSnapshots.get(messageId);
|
|
492
|
+
const snapshot = messageId === null ? undefined : addSnapshots.get((0, callbackMessage_1.buildMessageSnapshotKey)(key, messageId));
|
|
519
493
|
const providerId = snapshot?.providers[Number(ctx.match[1])];
|
|
520
494
|
if (messageId === null || !snapshot || providerId === undefined) {
|
|
521
|
-
await
|
|
495
|
+
await (0, callbackToast_1.answerCallbackQuerySafely)(ctx, (0, i18n_1.t)('fallback.stale'));
|
|
522
496
|
await rerenderPicker(key, messageId, isGeneral);
|
|
523
497
|
return;
|
|
524
498
|
}
|
|
525
|
-
await
|
|
499
|
+
await (0, callbackToast_1.answerCallbackQuerySafely)(ctx);
|
|
526
500
|
const detection = await detectFallbackOptions();
|
|
527
501
|
const models = (0, fallbackChain_1.listOpenCodeModelsOfProvider)(detection.openCodeModels, providerId);
|
|
528
502
|
const next = { ...snapshot, providerId, models };
|
|
529
|
-
addSnapshots.set(messageId, next);
|
|
530
|
-
await
|
|
503
|
+
addSnapshots.set((0, callbackMessage_1.buildMessageSnapshotKey)(key, messageId), next);
|
|
504
|
+
await showAddModelPage(key, messageId, next, 0);
|
|
531
505
|
}));
|
|
532
506
|
bot.action(fallbackChain_1.fallbackAddModelPageCallbackRe, (ctx) => handleTap(ctx, async (key, isGeneral, messageId) => {
|
|
533
|
-
const snapshot = messageId === null ? undefined : addSnapshots.get(messageId);
|
|
507
|
+
const snapshot = messageId === null ? undefined : addSnapshots.get((0, callbackMessage_1.buildMessageSnapshotKey)(key, messageId));
|
|
534
508
|
if (messageId === null || !snapshot || snapshot.providerId === null) {
|
|
535
|
-
await
|
|
509
|
+
await (0, callbackToast_1.answerCallbackQuerySafely)(ctx, (0, i18n_1.t)('fallback.stale'));
|
|
536
510
|
await rerenderPicker(key, messageId, isGeneral);
|
|
537
511
|
return;
|
|
538
512
|
}
|
|
539
|
-
await
|
|
540
|
-
await
|
|
513
|
+
await (0, callbackToast_1.answerCallbackQuerySafely)(ctx);
|
|
514
|
+
await showAddModelPage(key, messageId, snapshot, Number(ctx.match[1]));
|
|
541
515
|
}));
|
|
542
516
|
bot.action(fallbackChain_1.fallbackAddModelCallbackRe, (ctx) => handleTap(ctx, async (key, isGeneral, messageId) => {
|
|
543
|
-
const snapshot = messageId === null ? undefined : addSnapshots.get(messageId);
|
|
517
|
+
const snapshot = messageId === null ? undefined : addSnapshots.get((0, callbackMessage_1.buildMessageSnapshotKey)(key, messageId));
|
|
544
518
|
const modelId = snapshot?.models[Number(ctx.match[1])];
|
|
545
519
|
if (!snapshot || snapshot.providerId === null || modelId === undefined) {
|
|
546
|
-
await
|
|
520
|
+
await (0, callbackToast_1.answerCallbackQuerySafely)(ctx, (0, i18n_1.t)('fallback.stale'));
|
|
521
|
+
await rerenderPicker(key, messageId, isGeneral);
|
|
522
|
+
return;
|
|
523
|
+
}
|
|
524
|
+
await takeAdd(ctx, key, isGeneral, messageId, { backend: 'opencode', providerId: snapshot.providerId, modelId });
|
|
525
|
+
}));
|
|
526
|
+
// «✅ Continue» of the question before a rung of a new backend is added: only while the list is the one the
|
|
527
|
+
// question was asked about; a stale tap re-renders the list and adds nothing.
|
|
528
|
+
bot.action(fallbackChain_1.fallbackAddConfirmCallbackRe, (ctx) => handleTap(ctx, async (key, isGeneral, messageId) => {
|
|
529
|
+
const entry = messageId === null ? undefined : pendingAdds.get((0, callbackMessage_1.buildMessageSnapshotKey)(key, messageId));
|
|
530
|
+
if (!entry || ctx.match[1] !== (0, fallbackChain_1.getFallbackChainRevision)(getState().getFallbackChain())) {
|
|
531
|
+
await (0, callbackToast_1.answerCallbackQuerySafely)(ctx, (0, i18n_1.t)('fallback.stale'));
|
|
547
532
|
await rerenderPicker(key, messageId, isGeneral);
|
|
548
533
|
return;
|
|
549
534
|
}
|
|
550
|
-
|
|
535
|
+
if (messageId !== null)
|
|
536
|
+
pendingAdds.delete((0, callbackMessage_1.buildMessageSnapshotKey)(key, messageId));
|
|
537
|
+
await answerWithWholeText(ctx, key, await applyAdd(entry));
|
|
551
538
|
await rerenderPicker(key, messageId, isGeneral);
|
|
552
539
|
}));
|
|
553
540
|
bot.action(fallbackChain_1.fallbackProposeCallback, (ctx) => handleTap(ctx, async (key, isGeneral, messageId) => {
|
|
554
541
|
if (getState().getFallbackChain().length === 0) {
|
|
555
|
-
await
|
|
542
|
+
await answerWithWholeText(ctx, key, await applyPropose());
|
|
556
543
|
await rerenderPicker(key, messageId, isGeneral);
|
|
557
544
|
return;
|
|
558
545
|
}
|
|
559
|
-
await
|
|
546
|
+
await (0, callbackToast_1.answerCallbackQuerySafely)(ctx);
|
|
560
547
|
if (messageId !== null) {
|
|
561
|
-
|
|
548
|
+
// A draft that holds both backends hands conversations over when a limit moves a topic along it: say so.
|
|
549
|
+
const draft = (0, fallbackChain_1.proposeFallbackChain)(await detectFallbackOptions(), getState().getFallbackChain());
|
|
550
|
+
const text = (0, fallbackChain_1.checkIsMixedFallbackChain)(draft) ? `${(0, i18n_1.t)('limits.rebuildConfirm')}\n${(0, i18n_1.t)('handover.note')}` : (0, i18n_1.t)('limits.rebuildConfirm');
|
|
551
|
+
await editThreadMessage(key, messageId, text, telegraf_1.Markup.inlineKeyboard([
|
|
562
552
|
[telegraf_1.Markup.button.callback((0, i18n_1.t)('fallback.proposeConfirmButton'), fallbackChain_1.fallbackProposeConfirmCallback)],
|
|
563
553
|
buildBackRow(),
|
|
564
554
|
]));
|
|
565
555
|
}
|
|
566
556
|
}));
|
|
567
557
|
bot.action(fallbackChain_1.fallbackProposeConfirmCallback, (ctx) => handleTap(ctx, async (key, isGeneral, messageId) => {
|
|
568
|
-
await
|
|
558
|
+
await answerWithWholeText(ctx, key, await applyPropose());
|
|
569
559
|
await rerenderPicker(key, messageId, isGeneral);
|
|
570
560
|
}));
|
|
571
561
|
bot.action(fallbackChain_1.fallbackClearCallback, (ctx) => handleTap(ctx, async (key, isGeneral, messageId) => {
|
|
572
|
-
await
|
|
562
|
+
await answerWithWholeText(ctx, key, await applyClear());
|
|
573
563
|
await rerenderPicker(key, messageId, isGeneral);
|
|
574
564
|
}));
|
|
575
565
|
bot.action(fallbackChain_1.fallbackBackCallback, (ctx) => handleTap(ctx, async (key, isGeneral, messageId) => {
|
|
576
|
-
await
|
|
566
|
+
await (0, callbackToast_1.answerCallbackQuerySafely)(ctx);
|
|
577
567
|
await rerenderPicker(key, messageId, isGeneral);
|
|
578
568
|
}));
|
|
579
569
|
// A topic's setting button: open its sub-menu. General has no sub-menu (its button flips the value), so a tap
|
|
580
570
|
// that still arrives there only re-renders the screen.
|
|
581
|
-
for (const id of
|
|
571
|
+
for (const id of limitSettings_1.limitSettingIds) {
|
|
582
572
|
bot.action(settingCallbacks[id].open, (ctx) => handleTap(ctx, async (key, isGeneral, messageId) => {
|
|
583
|
-
await
|
|
573
|
+
await (0, callbackToast_1.answerCallbackQuerySafely)(ctx);
|
|
584
574
|
if (isGeneral)
|
|
585
575
|
await rerenderPicker(key, messageId, isGeneral);
|
|
586
576
|
else
|
|
@@ -594,10 +584,10 @@ function createFallbackChain(ports) {
|
|
|
594
584
|
for (const [callback, apply, enabled] of settingTaps) {
|
|
595
585
|
bot.action(callback, (ctx) => handleTap(ctx, async (key, isGeneral, messageId) => {
|
|
596
586
|
if (enabled === null && isGeneral) {
|
|
597
|
-
await
|
|
587
|
+
await (0, callbackToast_1.answerCallbackQuerySafely)(ctx);
|
|
598
588
|
return;
|
|
599
589
|
}
|
|
600
|
-
await
|
|
590
|
+
await answerWithWholeText(ctx, key, await apply(key, isGeneral, enabled));
|
|
601
591
|
await rerenderPicker(key, messageId, isGeneral);
|
|
602
592
|
}));
|
|
603
593
|
}
|
|
@@ -606,19 +596,19 @@ function createFallbackChain(ports) {
|
|
|
606
596
|
bot.action(fallbackChain_1.fallbackSwitchCallbackRe, (ctx) => handleTap(ctx, async (key, _isGeneral, messageId) => {
|
|
607
597
|
const parsed = (0, fallbackChain_1.parseFallbackSwitchCallbackData)(ctx.match[0]);
|
|
608
598
|
if (parsed === null) {
|
|
609
|
-
await
|
|
599
|
+
await (0, callbackToast_1.answerCallbackQuerySafely)(ctx);
|
|
610
600
|
return;
|
|
611
601
|
}
|
|
612
602
|
const confirmation = await takeSwitchOffer(key, parsed.episodeId, parsed.index);
|
|
613
603
|
if (confirmation === null) {
|
|
614
|
-
await
|
|
604
|
+
await (0, callbackToast_1.answerCallbackQuerySafely)(ctx, (0, i18n_1.t)('fallback.switchExpired'));
|
|
615
605
|
return;
|
|
616
606
|
}
|
|
617
|
-
await
|
|
607
|
+
await (0, callbackToast_1.answerCallbackQuerySafely)(ctx);
|
|
618
608
|
if (messageId !== null)
|
|
619
609
|
await editThreadMessage(key, messageId, confirmation);
|
|
620
610
|
}));
|
|
621
611
|
}
|
|
622
|
-
return { registerFallbackChainCommands, registerFallbackChainCallbacks,
|
|
612
|
+
return { registerFallbackChainCommands, registerFallbackChainCallbacks, openAutoSwitchView, runAutoSwitchCommand, applyAutoSwitch, formatFallbackEntry: formatEntry };
|
|
623
613
|
}
|
|
624
614
|
//# sourceMappingURL=fallbackChain.js.map
|