scream-code 0.11.7 → 0.11.9
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.
|
@@ -7,7 +7,7 @@ import { i as __require, o as __toESM, r as __exportAll, t as __commonJSMin } fr
|
|
|
7
7
|
import "./suppress-sqlite-warning-C2VB0doZ.mjs";
|
|
8
8
|
import { C as join$1, D as resolve$1, E as relative$1, S as isAbsolute$1, T as parse$7, a as isSupportedFile, b as basename$1, i as ingestFile, r as ingestDirectory, t as multiSearch, w as normalize, x as dirname$2, y as KnowledgeStore } from "./src-BH9W5k24.mjs";
|
|
9
9
|
import { t as require_base64_js } from "./base64-js-DzVmk6Nb.mjs";
|
|
10
|
-
import { a as setLocale, i as getLocale, n as assertScreamHostIdentity, o as t, r as createScreamDefaultHeaders, t as TextInputDialogComponent } from "./text-input-dialog-
|
|
10
|
+
import { a as setLocale, i as getLocale, n as assertScreamHostIdentity, o as t, r as createScreamDefaultHeaders, t as TextInputDialogComponent } from "./text-input-dialog-COl6Uu7m.mjs";
|
|
11
11
|
import { createRequire } from "node:module";
|
|
12
12
|
import { createHash, randomBytes, randomInt, randomUUID } from "node:crypto";
|
|
13
13
|
import * as fs$1 from "node:fs/promises";
|
|
@@ -59888,7 +59888,6 @@ function formatFullSkill(skill) {
|
|
|
59888
59888
|
function formatModelSkill(skill) {
|
|
59889
59889
|
const lines = [`- ${skill.name}: ${truncate$2(skill.description, LISTING_DESC_MAX)}`];
|
|
59890
59890
|
if (typeof skill.metadata.whenToUse === "string" && skill.metadata.whenToUse.length > 0) lines.push(` When to use: ${skill.metadata.whenToUse}`);
|
|
59891
|
-
lines.push(` Path: ${skill.path}`);
|
|
59892
59891
|
return lines;
|
|
59893
59892
|
}
|
|
59894
59893
|
function truncate$2(value, max) {
|
|
@@ -119233,6 +119232,85 @@ function parsePositiveInt(value) {
|
|
|
119233
119232
|
return n;
|
|
119234
119233
|
}
|
|
119235
119234
|
//#endregion
|
|
119235
|
+
//#region ../../packages/agent-core/src/session/provider-balance.ts
|
|
119236
|
+
const fetchers = [{
|
|
119237
|
+
matches: (baseUrl) => {
|
|
119238
|
+
try {
|
|
119239
|
+
return new URL(baseUrl).hostname === "api.deepseek.com";
|
|
119240
|
+
} catch {
|
|
119241
|
+
return false;
|
|
119242
|
+
}
|
|
119243
|
+
},
|
|
119244
|
+
fetch: async (baseUrl, apiKey) => {
|
|
119245
|
+
try {
|
|
119246
|
+
const root = new URL(baseUrl).origin;
|
|
119247
|
+
const res = await fetch(`${root}/user/balance`, {
|
|
119248
|
+
headers: {
|
|
119249
|
+
Accept: "application/json",
|
|
119250
|
+
Authorization: `Bearer ${apiKey}`
|
|
119251
|
+
},
|
|
119252
|
+
signal: AbortSignal.timeout(5e3)
|
|
119253
|
+
});
|
|
119254
|
+
if (!res.ok) return null;
|
|
119255
|
+
const info = (await res.json()).balance_infos?.[0];
|
|
119256
|
+
if (info?.total_balance === void 0) return null;
|
|
119257
|
+
return {
|
|
119258
|
+
currency: info.currency ?? "",
|
|
119259
|
+
totalBalance: info.total_balance
|
|
119260
|
+
};
|
|
119261
|
+
} catch {
|
|
119262
|
+
return null;
|
|
119263
|
+
}
|
|
119264
|
+
}
|
|
119265
|
+
}, {
|
|
119266
|
+
matches: (baseUrl) => {
|
|
119267
|
+
try {
|
|
119268
|
+
return new URL(baseUrl).hostname === "api.moonshot.cn";
|
|
119269
|
+
} catch {
|
|
119270
|
+
return false;
|
|
119271
|
+
}
|
|
119272
|
+
},
|
|
119273
|
+
fetch: async (baseUrl, apiKey) => {
|
|
119274
|
+
try {
|
|
119275
|
+
const root = new URL(baseUrl).origin;
|
|
119276
|
+
const res = await fetch(`${root}/v1/users/me/balance`, {
|
|
119277
|
+
headers: {
|
|
119278
|
+
Accept: "application/json",
|
|
119279
|
+
Authorization: `Bearer ${apiKey}`
|
|
119280
|
+
},
|
|
119281
|
+
signal: AbortSignal.timeout(5e3)
|
|
119282
|
+
});
|
|
119283
|
+
if (!res.ok) return null;
|
|
119284
|
+
const data = await res.json();
|
|
119285
|
+
if (typeof data.data?.available_balance !== "number") return null;
|
|
119286
|
+
return {
|
|
119287
|
+
currency: "CNY",
|
|
119288
|
+
totalBalance: data.data.available_balance.toFixed(2)
|
|
119289
|
+
};
|
|
119290
|
+
} catch {
|
|
119291
|
+
return null;
|
|
119292
|
+
}
|
|
119293
|
+
}
|
|
119294
|
+
}];
|
|
119295
|
+
/**
|
|
119296
|
+
* Look up the balance for the given provider endpoint.
|
|
119297
|
+
* Returns null when the endpoint is not a recognized official vendor or
|
|
119298
|
+
* when the lookup fails — callers render nothing in that case.
|
|
119299
|
+
*/
|
|
119300
|
+
async function fetchProviderBalance(baseUrl, apiKey) {
|
|
119301
|
+
const fetcher = fetchers.find((f) => f.matches(baseUrl));
|
|
119302
|
+
if (!fetcher) return null;
|
|
119303
|
+
return fetcher.fetch(baseUrl, apiKey);
|
|
119304
|
+
}
|
|
119305
|
+
/**
|
|
119306
|
+
* True when the given base URL belongs to a vendor we can query balances
|
|
119307
|
+
* for. Pure local check (no network) — used to skip polling for
|
|
119308
|
+
* unsupported providers.
|
|
119309
|
+
*/
|
|
119310
|
+
function isSupportedBalanceProvider(baseUrl) {
|
|
119311
|
+
return fetchers.some((f) => f.matches(baseUrl));
|
|
119312
|
+
}
|
|
119313
|
+
//#endregion
|
|
119236
119314
|
//#region ../../packages/node-sdk/src/auth.ts
|
|
119237
119315
|
var ScreamAuthFacade = class {
|
|
119238
119316
|
options;
|
|
@@ -120653,7 +120731,7 @@ function optionalBuildString(value) {
|
|
|
120653
120731
|
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
120654
120732
|
}
|
|
120655
120733
|
const SCREAM_BUILD_INFO = {
|
|
120656
|
-
version: optionalBuildString("0.11.
|
|
120734
|
+
version: optionalBuildString("0.11.9"),
|
|
120657
120735
|
channel: optionalBuildString(""),
|
|
120658
120736
|
commit: optionalBuildString(""),
|
|
120659
120737
|
buildTarget: optionalBuildString("darwin-arm64")
|
|
@@ -120918,7 +120996,9 @@ const NotificationsConfigSchema = z.object({
|
|
|
120918
120996
|
const TuiLikePreferencesSchema = z.object({
|
|
120919
120997
|
nickname: z.string().optional(),
|
|
120920
120998
|
tone: z.string().optional(),
|
|
120921
|
-
other: z.string().optional()
|
|
120999
|
+
other: z.string().optional(),
|
|
121000
|
+
/** Explicit prohibitions: things the user does NOT want done. */
|
|
121001
|
+
doNot: z.string().optional()
|
|
120922
121002
|
});
|
|
120923
121003
|
const TuiConfigFileSchema = z.object({
|
|
120924
121004
|
theme: TuiThemeSchema.optional(),
|
|
@@ -121982,14 +122062,16 @@ function buildSkillSlashCommands(skills, builtinCommandNames) {
|
|
|
121982
122062
|
commands.push({
|
|
121983
122063
|
name: commandName,
|
|
121984
122064
|
aliases: [],
|
|
121985
|
-
description: skill.description ?? ""
|
|
122065
|
+
description: skill.description ?? "",
|
|
122066
|
+
source: skill.source
|
|
121986
122067
|
});
|
|
121987
122068
|
if (skill.source === "builtin" && !reservedNames.has(skill.name)) {
|
|
121988
122069
|
commandMap.set(skill.name, skill.name);
|
|
121989
122070
|
commands.push({
|
|
121990
122071
|
name: skill.name,
|
|
121991
122072
|
aliases: [],
|
|
121992
|
-
description: skill.description ?? ""
|
|
122073
|
+
description: skill.description ?? "",
|
|
122074
|
+
source: skill.source
|
|
121993
122075
|
});
|
|
121994
122076
|
}
|
|
121995
122077
|
}
|
|
@@ -123307,7 +123389,7 @@ function mountProfileList(host) {
|
|
|
123307
123389
|
const { subagentModels: bindings, availableModels } = host.state.appState;
|
|
123308
123390
|
const options = getSubagentProfiles().map((profile) => {
|
|
123309
123391
|
const alias = bindings[profile.name];
|
|
123310
|
-
const bindingLabel = alias === void 0 ? t("subagent.follow_main") : modelDisplayName$1(alias, availableModels[alias]);
|
|
123392
|
+
const bindingLabel = alias === void 0 ? t("subagent.follow_main") : availableModels[alias] !== void 0 ? modelDisplayName$1(alias, availableModels[alias]) : t("subagent.stale_binding", { alias });
|
|
123311
123393
|
return {
|
|
123312
123394
|
value: profile.name,
|
|
123313
123395
|
label: `${profile.name} → ${bindingLabel}`,
|
|
@@ -123361,6 +123443,10 @@ async function applyBinding(host, profileName, value) {
|
|
|
123361
123443
|
const configPath = getTuiConfigPath();
|
|
123362
123444
|
try {
|
|
123363
123445
|
const current = await loadTuiConfig(configPath);
|
|
123446
|
+
if (value !== FOLLOW_MAIN && host.state.appState.availableModels[value] === void 0) {
|
|
123447
|
+
host.showError(t("subagent.invalid_alias", { alias: value }));
|
|
123448
|
+
return;
|
|
123449
|
+
}
|
|
123364
123450
|
const updated = { ...current.subagentModels };
|
|
123365
123451
|
if (value === FOLLOW_MAIN) delete updated[profileName];
|
|
123366
123452
|
else updated[profileName] = value;
|
|
@@ -123873,6 +123959,11 @@ function safeUsage(usage) {
|
|
|
123873
123959
|
const CONTEXT_BAR_WIDTH = 10;
|
|
123874
123960
|
const CONTEXT_BAR_FILLED = "▰";
|
|
123875
123961
|
const CONTEXT_BAR_EMPTY = "▱";
|
|
123962
|
+
function currencySymbol(currency) {
|
|
123963
|
+
if (currency === "CNY") return "¥";
|
|
123964
|
+
if (currency === "USD") return "$";
|
|
123965
|
+
return `${currency} `;
|
|
123966
|
+
}
|
|
123876
123967
|
/**
|
|
123877
123968
|
* Half-block progress bar for context usage: `▰▰▰▱▱▱▱▱▱▱` (10 cells).
|
|
123878
123969
|
* Filled cells are rounded from the clamped ratio, so 0% is all-empty and
|
|
@@ -124094,8 +124185,12 @@ var FooterComponent = class {
|
|
|
124094
124185
|
left.push(chalk.hex(colors.primary).bold(goalLabel));
|
|
124095
124186
|
}
|
|
124096
124187
|
const model = shortenModel(modelDisplayName(state));
|
|
124097
|
-
if (model)
|
|
124098
|
-
|
|
124188
|
+
if (model) {
|
|
124189
|
+
if (state.streamingPhase === "thinking") left.push(shimmerText(model, colors));
|
|
124190
|
+
else left.push(chalk.hex(colors.textDim)(model));
|
|
124191
|
+
const balance = state.providerBalance;
|
|
124192
|
+
if (balance !== null && balance !== void 0) left.push(chalk.hex(colors.textDim)(`${currencySymbol(balance.currency)}${balance.totalBalance}`));
|
|
124193
|
+
}
|
|
124099
124194
|
if (this.backgroundBashTaskCount > 0) left.push(chalk.hex(colors.primary)(`[${t("footer.tasks_running", { count: String(this.backgroundBashTaskCount) })}]`));
|
|
124100
124195
|
if (this.backgroundAgentCount > 0) left.push(chalk.hex(colors.primary)(`[${t("footer.agents_running", { count: String(this.backgroundAgentCount) })}]`));
|
|
124101
124196
|
const git = this.gitCache.getStatus();
|
|
@@ -124542,6 +124637,7 @@ function createMarkdownTheme(colors) {
|
|
|
124542
124637
|
quote: (text) => chalk.hex(colors.mdQuote)(text),
|
|
124543
124638
|
quoteBorder: (text) => chalk.hex(colors.mdQuote)(text),
|
|
124544
124639
|
hr: (text) => border(text),
|
|
124640
|
+
tableHeader: (text) => chalk.bold.hex(colors.accent)(text),
|
|
124545
124641
|
listBullet: (text) => chalk.hex(colors.roleAssistant)(text.replace(/^-/, "•")),
|
|
124546
124642
|
bold: (text) => chalk.bold(text),
|
|
124547
124643
|
italic: (text) => chalk.italic(text),
|
|
@@ -124933,6 +125029,99 @@ async function loadManagedUsageReport(host) {
|
|
|
124933
125029
|
} };
|
|
124934
125030
|
}
|
|
124935
125031
|
//#endregion
|
|
125032
|
+
//#region src/tui/api-balance.ts
|
|
125033
|
+
/**
|
|
125034
|
+
* TUI-side provider balance lookup.
|
|
125035
|
+
*
|
|
125036
|
+
* Reads the runtime config.toml (same file the engine consumes), resolves
|
|
125037
|
+
* the plaintext API key (direct value or the provider's ENV_VAR env
|
|
125038
|
+
* reference), and delegates the actual query to the engine's
|
|
125039
|
+
* fetchProviderBalance. Results are cached briefly so footer renders do
|
|
125040
|
+
* not hammer the vendor endpoint.
|
|
125041
|
+
*/
|
|
125042
|
+
const BALANCE_CACHE_MS = 6e4;
|
|
125043
|
+
const cache = /* @__PURE__ */ new Map();
|
|
125044
|
+
/** Monotonic id so an out-of-order lookup can never overwrite a newer one. */
|
|
125045
|
+
let latestRequestId = 0;
|
|
125046
|
+
function resolveApiKey(providerName) {
|
|
125047
|
+
const provider = readConfigFile(join(getDataDir(), "config.toml")).providers?.[providerName];
|
|
125048
|
+
if (!provider) return void 0;
|
|
125049
|
+
const direct = provider.apiKey?.trim();
|
|
125050
|
+
if (direct !== void 0 && direct.length > 0) return direct;
|
|
125051
|
+
const envKey = envKeyForProviderType(provider.type);
|
|
125052
|
+
const stored = envKey !== void 0 ? provider.env?.[envKey]?.trim() : void 0;
|
|
125053
|
+
return stored !== void 0 && stored.length > 0 ? stored : void 0;
|
|
125054
|
+
}
|
|
125055
|
+
function envKeyForProviderType(type) {
|
|
125056
|
+
switch (type) {
|
|
125057
|
+
case "anthropic": return "ANTHROPIC_API_KEY";
|
|
125058
|
+
case "openai":
|
|
125059
|
+
case "openai_responses": return "OPENAI_API_KEY";
|
|
125060
|
+
case "scream": return "SCREAM_API_KEY";
|
|
125061
|
+
case "google-genai": return "GOOGLE_API_KEY";
|
|
125062
|
+
case "vertexai": return "VERTEXAI_API_KEY";
|
|
125063
|
+
default: return;
|
|
125064
|
+
}
|
|
125065
|
+
}
|
|
125066
|
+
async function loadBalance(providerName) {
|
|
125067
|
+
try {
|
|
125068
|
+
const provider = readConfigFile(join(getDataDir(), "config.toml")).providers?.[providerName];
|
|
125069
|
+
if (!provider?.baseUrl) return null;
|
|
125070
|
+
const apiKey = resolveApiKey(providerName);
|
|
125071
|
+
if (apiKey === void 0) return null;
|
|
125072
|
+
return await fetchProviderBalance(provider.baseUrl, apiKey);
|
|
125073
|
+
} catch {
|
|
125074
|
+
return null;
|
|
125075
|
+
}
|
|
125076
|
+
}
|
|
125077
|
+
/**
|
|
125078
|
+
* Look up the balance for the provider that serves the given model
|
|
125079
|
+
* (model names follow the "provider/model" convention). Returns null when
|
|
125080
|
+
* the provider is unknown, unofficial, or the lookup failed — callers
|
|
125081
|
+
* render nothing in that case. Cached for BALANCE_CACHE_MS per provider.
|
|
125082
|
+
*/
|
|
125083
|
+
async function getProviderBalanceForModel(model) {
|
|
125084
|
+
const providerName = model.split("/")[0] ?? "";
|
|
125085
|
+
if (providerName.length === 0) return null;
|
|
125086
|
+
const cached = cache.get(providerName);
|
|
125087
|
+
if (cached !== void 0 && Date.now() - cached.at < BALANCE_CACHE_MS) return cached.balance;
|
|
125088
|
+
const balance = await loadBalance(providerName);
|
|
125089
|
+
cache.set(providerName, {
|
|
125090
|
+
balance,
|
|
125091
|
+
at: Date.now()
|
|
125092
|
+
});
|
|
125093
|
+
return balance;
|
|
125094
|
+
}
|
|
125095
|
+
/**
|
|
125096
|
+
* True when the given model is served by a provider whose balance we can
|
|
125097
|
+
* query. Pure local check (config lookup + hostname match, no network) —
|
|
125098
|
+
* the poller uses it to skip unsupported providers entirely.
|
|
125099
|
+
*/
|
|
125100
|
+
function supportsBalance(model) {
|
|
125101
|
+
const providerName = model.split("/")[0] ?? "";
|
|
125102
|
+
if (providerName.length === 0) return false;
|
|
125103
|
+
try {
|
|
125104
|
+
const baseUrl = readConfigFile(join(getDataDir(), "config.toml")).providers?.[providerName]?.baseUrl;
|
|
125105
|
+
return baseUrl !== void 0 && isSupportedBalanceProvider(baseUrl);
|
|
125106
|
+
} catch {
|
|
125107
|
+
return false;
|
|
125108
|
+
}
|
|
125109
|
+
}
|
|
125110
|
+
/**
|
|
125111
|
+
* Fetch the balance for a model and push it into app state. Fire-and-forget:
|
|
125112
|
+
* failures resolve to null inside getProviderBalanceForModel, so callers
|
|
125113
|
+
* (startup sync and model switches) never await it. A request id guards
|
|
125114
|
+
* against out-of-order resolutions: when the user switches models quickly,
|
|
125115
|
+
* only the latest lookup's result is committed.
|
|
125116
|
+
*/
|
|
125117
|
+
function refreshProviderBalance(model, setAppState) {
|
|
125118
|
+
const requestId = ++latestRequestId;
|
|
125119
|
+
getProviderBalanceForModel(model).then((balance) => {
|
|
125120
|
+
if (requestId !== latestRequestId) return;
|
|
125121
|
+
setAppState({ providerBalance: balance });
|
|
125122
|
+
});
|
|
125123
|
+
}
|
|
125124
|
+
//#endregion
|
|
124936
125125
|
//#region src/tui/commands/config.ts
|
|
124937
125126
|
/**
|
|
124938
125127
|
* Storm Breaker guard for model switches. Returns the (currentTokens,
|
|
@@ -125359,8 +125548,10 @@ async function performModelSwitch(host, alias, thinkingLevel) {
|
|
|
125359
125548
|
}
|
|
125360
125549
|
host.setAppState({
|
|
125361
125550
|
model: effectiveAlias,
|
|
125362
|
-
thinkingLevel: effectiveThinking
|
|
125551
|
+
thinkingLevel: effectiveThinking,
|
|
125552
|
+
providerBalance: null
|
|
125363
125553
|
});
|
|
125554
|
+
refreshProviderBalance(effectiveAlias, (patch) => host.setAppState(patch));
|
|
125364
125555
|
let persisted = false;
|
|
125365
125556
|
try {
|
|
125366
125557
|
persisted = await persistModelSelection(host, alias, thinkingLevel);
|
|
@@ -126195,7 +126386,7 @@ async function guidedGoalSetup(host) {
|
|
|
126195
126386
|
host.showNotice(t("goal.storm_breaker"), t("goal.conflict_loop"));
|
|
126196
126387
|
return;
|
|
126197
126388
|
}
|
|
126198
|
-
const { TextInputDialogComponent } = await import("./text-input-dialog-
|
|
126389
|
+
const { TextInputDialogComponent } = await import("./text-input-dialog-xqTCBHZF.mjs");
|
|
126199
126390
|
const initialDesc = await promptText(host, TextInputDialogComponent, {
|
|
126200
126391
|
title: t("goal.setup_title_initial"),
|
|
126201
126392
|
subtitle: t("goal.setup_desc_hint"),
|
|
@@ -126216,7 +126407,7 @@ async function guidedGoalSetup(host) {
|
|
|
126216
126407
|
await showGoalConfigWizard(host, session, confirmed.trim() || objective, false);
|
|
126217
126408
|
}
|
|
126218
126409
|
async function showGoalConfigWizard(host, session, objective, replace) {
|
|
126219
|
-
const { TextInputDialogComponent } = await import("./text-input-dialog-
|
|
126410
|
+
const { TextInputDialogComponent } = await import("./text-input-dialog-xqTCBHZF.mjs");
|
|
126220
126411
|
const turnInput = await promptNumber(host, TextInputDialogComponent, {
|
|
126221
126412
|
title: t("goal.wizard_title", { objective }),
|
|
126222
126413
|
subtitle: t("goal.budget_turns_hint"),
|
|
@@ -132617,8 +132808,11 @@ function buildRoleAdditionalText(prefs) {
|
|
|
132617
132808
|
if (prefs.nickname !== void 0 && prefs.nickname.trim().length > 0) items.push(`- Nickname: address the user as "${prefs.nickname.trim()}".`);
|
|
132618
132809
|
if (prefs.tone !== void 0 && prefs.tone.trim().length > 0) items.push(`- Tone: respond in ${prefs.tone.trim()} tone.`);
|
|
132619
132810
|
if (prefs.other !== void 0 && prefs.other.trim().length > 0) items.push(`- Other: ${prefs.other.trim()}`);
|
|
132620
|
-
|
|
132621
|
-
|
|
132811
|
+
const doNot = prefs.doNot?.trim();
|
|
132812
|
+
if (items.length === 0 && (doNot === void 0 || doNot.length === 0)) return "";
|
|
132813
|
+
lines.push("", ...items);
|
|
132814
|
+
if (doNot !== void 0 && doNot.length > 0) lines.push("", "## Do NOT (explicit prohibitions — NEVER do these)", doNot);
|
|
132815
|
+
lines.push("", t("like.priority"));
|
|
132622
132816
|
return lines.join("\n");
|
|
132623
132817
|
}
|
|
132624
132818
|
async function getUserPrefsPath() {
|
|
@@ -132626,12 +132820,23 @@ async function getUserPrefsPath() {
|
|
|
132626
132820
|
}
|
|
132627
132821
|
async function persistLikePreferences(host, prefs) {
|
|
132628
132822
|
const configPath = getTuiConfigPath();
|
|
132629
|
-
await
|
|
132630
|
-
|
|
132823
|
+
const current = await loadTuiConfig(configPath);
|
|
132824
|
+
const updated = {
|
|
132825
|
+
...current,
|
|
132631
132826
|
like: prefs
|
|
132632
|
-
}
|
|
132633
|
-
|
|
132634
|
-
|
|
132827
|
+
};
|
|
132828
|
+
try {
|
|
132829
|
+
await saveTuiConfig(updated, configPath);
|
|
132830
|
+
await writeFile(await getUserPrefsPath(), buildRoleAdditionalText(prefs), "utf-8");
|
|
132831
|
+
} catch (error) {
|
|
132832
|
+
try {
|
|
132833
|
+
await saveTuiConfig(current, configPath);
|
|
132834
|
+
} catch {}
|
|
132835
|
+
try {
|
|
132836
|
+
await writeFile(await getUserPrefsPath(), buildRoleAdditionalText(current.like ?? {}), "utf-8");
|
|
132837
|
+
} catch {}
|
|
132838
|
+
throw error;
|
|
132839
|
+
}
|
|
132635
132840
|
host.setAppState({ like: prefs });
|
|
132636
132841
|
}
|
|
132637
132842
|
async function handleLikeCommand(host) {
|
|
@@ -132666,10 +132871,21 @@ async function handleLikeCommand(host) {
|
|
|
132666
132871
|
host.showStatus(t("like.cancelled"), host.state.theme.colors.textDim);
|
|
132667
132872
|
return;
|
|
132668
132873
|
}
|
|
132874
|
+
const doNot = await promptTextInput$1(host, t("like.do_not"), {
|
|
132875
|
+
subtitle: t("like.do_not_hint"),
|
|
132876
|
+
placeholder: t("like.do_not_example"),
|
|
132877
|
+
initialValue: current.doNot,
|
|
132878
|
+
allowEmpty: true
|
|
132879
|
+
});
|
|
132880
|
+
if (doNot === void 0) {
|
|
132881
|
+
host.showStatus(t("like.cancelled"), host.state.theme.colors.textDim);
|
|
132882
|
+
return;
|
|
132883
|
+
}
|
|
132669
132884
|
await persistLikePreferences(host, {
|
|
132670
132885
|
nickname: nickname.trim().length > 0 ? nickname.trim() : void 0,
|
|
132671
132886
|
tone: tone.trim().length > 0 ? tone.trim() : void 0,
|
|
132672
|
-
other: other.trim().length > 0 ? other.trim() : void 0
|
|
132887
|
+
other: other.trim().length > 0 ? other.trim() : void 0,
|
|
132888
|
+
doNot: doNot.trim().length > 0 ? doNot.trim() : void 0
|
|
132673
132889
|
});
|
|
132674
132890
|
host.showStatus(t("like.saved"), host.state.theme.colors.success);
|
|
132675
132891
|
}
|
|
@@ -134681,8 +134897,8 @@ async function handleKnowledgeCommand(host, _args) {
|
|
|
134681
134897
|
switch (status) {
|
|
134682
134898
|
case "ready": return "";
|
|
134683
134899
|
case "downloading": return " · " + t("kw.embedding_downloading");
|
|
134684
|
-
case "failed": return " · " + t("kw.embedding_failed");
|
|
134685
|
-
case "idle": return " · " + t("kw.embedding_not_downloaded");
|
|
134900
|
+
case "failed": return " · " + t("kw.embedding_failed") + t("kw.embedding_data_intact");
|
|
134901
|
+
case "idle": return " · " + t("kw.embedding_not_downloaded") + t("kw.embedding_data_intact");
|
|
134686
134902
|
}
|
|
134687
134903
|
};
|
|
134688
134904
|
const showMenu = () => {
|
|
@@ -141059,7 +141275,7 @@ var InputController = class InputController {
|
|
|
141059
141275
|
this.host = host;
|
|
141060
141276
|
}
|
|
141061
141277
|
setupAutocomplete() {
|
|
141062
|
-
const visible = this.host.getSlashCommands().filter((cmd) => !cmd.name.startsWith("skill:"));
|
|
141278
|
+
const visible = this.host.getSlashCommands().filter((cmd) => !(cmd.name.startsWith("skill:") && cmd.source === "builtin"));
|
|
141063
141279
|
const slashCommands = visible.map((cmd) => cmd);
|
|
141064
141280
|
const { state } = this.host;
|
|
141065
141281
|
const provider = new FileMentionProvider(slashCommands, state.appState.workDir, state.fdPath, state.gitLsFilesCache);
|
|
@@ -142967,8 +143183,10 @@ var SessionManager$1 = class {
|
|
|
142967
143183
|
wallClockBaseAt: Date.now()
|
|
142968
143184
|
} : null,
|
|
142969
143185
|
goalActive: goal?.status === "active",
|
|
142970
|
-
goalContinuationCount: 0
|
|
143186
|
+
goalContinuationCount: 0,
|
|
143187
|
+
providerBalance: null
|
|
142971
143188
|
});
|
|
143189
|
+
refreshProviderBalance(status.model ?? "", (patch) => this.host.setAppState(patch));
|
|
142972
143190
|
}
|
|
142973
143191
|
async activateRuntime() {
|
|
142974
143192
|
const session = this.requireSession();
|
|
@@ -143815,6 +144033,8 @@ var MemoryPickerComponent = class extends Container {
|
|
|
143815
144033
|
searchQuery = "";
|
|
143816
144034
|
isSearching = false;
|
|
143817
144035
|
searchInput = "";
|
|
144036
|
+
/** Memo ids ticked for batch delete (space toggles, a selects all). */
|
|
144037
|
+
selectedIds = /* @__PURE__ */ new Set();
|
|
143818
144038
|
memos;
|
|
143819
144039
|
total;
|
|
143820
144040
|
loading;
|
|
@@ -143843,6 +144063,7 @@ var MemoryPickerComponent = class extends Container {
|
|
|
143843
144063
|
this.memos = result.memos;
|
|
143844
144064
|
this.total = result.total;
|
|
143845
144065
|
this.selectedIndex = 0;
|
|
144066
|
+
this.selectedIds.clear();
|
|
143846
144067
|
} catch {
|
|
143847
144068
|
this.memos = [];
|
|
143848
144069
|
this.total = 0;
|
|
@@ -143874,8 +144095,11 @@ var MemoryPickerComponent = class extends Container {
|
|
|
143874
144095
|
}
|
|
143875
144096
|
if (this.mode === "confirmDelete") {
|
|
143876
144097
|
if (matchesKey(data, Key.enter)) {
|
|
143877
|
-
|
|
143878
|
-
|
|
144098
|
+
if (this.selectedIds.size > 0) this.deleteSelectedAndReload();
|
|
144099
|
+
else {
|
|
144100
|
+
const memo = this.memos[this.selectedIndex];
|
|
144101
|
+
if (memo) this.deleteAndReload(memo.id);
|
|
144102
|
+
}
|
|
143879
144103
|
return;
|
|
143880
144104
|
}
|
|
143881
144105
|
if (matchesKey(data, Key.escape)) {
|
|
@@ -143922,7 +144146,23 @@ var MemoryPickerComponent = class extends Container {
|
|
|
143922
144146
|
return;
|
|
143923
144147
|
}
|
|
143924
144148
|
if (ch === "d" || ch === "D") {
|
|
143925
|
-
if (this.memos.length > 0) this.mode = "confirmDelete";
|
|
144149
|
+
if (this.selectedIds.size > 0 || this.memos.length > 0) this.mode = "confirmDelete";
|
|
144150
|
+
return;
|
|
144151
|
+
}
|
|
144152
|
+
if (ch === " ") {
|
|
144153
|
+
const memo = this.memos[this.selectedIndex];
|
|
144154
|
+
if (memo) {
|
|
144155
|
+
if (this.selectedIds.has(memo.id)) this.selectedIds.delete(memo.id);
|
|
144156
|
+
else this.selectedIds.add(memo.id);
|
|
144157
|
+
this.ui?.requestRender();
|
|
144158
|
+
}
|
|
144159
|
+
return;
|
|
144160
|
+
}
|
|
144161
|
+
if (ch === "a" || ch === "A") {
|
|
144162
|
+
if (this.memos.length === 0) return;
|
|
144163
|
+
if (this.memos.every((memo) => this.selectedIds.has(memo.id))) this.selectedIds.clear();
|
|
144164
|
+
else for (const memo of this.memos) this.selectedIds.add(memo.id);
|
|
144165
|
+
this.ui?.requestRender();
|
|
143926
144166
|
return;
|
|
143927
144167
|
}
|
|
143928
144168
|
if (ch === "/") {
|
|
@@ -143951,6 +144191,15 @@ var MemoryPickerComponent = class extends Container {
|
|
|
143951
144191
|
if (this.selectedIndex >= this.memos.length) this.selectedIndex = Math.max(0, this.memos.length - 1);
|
|
143952
144192
|
this.ui?.requestRender();
|
|
143953
144193
|
}
|
|
144194
|
+
async deleteSelectedAndReload() {
|
|
144195
|
+
const ids = [...this.selectedIds];
|
|
144196
|
+
for (const id of ids) try {
|
|
144197
|
+
await this.store.delete(id);
|
|
144198
|
+
} catch {}
|
|
144199
|
+
await this.loadMemos();
|
|
144200
|
+
this.mode = "list";
|
|
144201
|
+
this.ui?.requestRender();
|
|
144202
|
+
}
|
|
143954
144203
|
render(width) {
|
|
143955
144204
|
const c = this.colors;
|
|
143956
144205
|
const lines = [];
|
|
@@ -143963,7 +144212,7 @@ var MemoryPickerComponent = class extends Container {
|
|
|
143963
144212
|
return lines;
|
|
143964
144213
|
}
|
|
143965
144214
|
const headerLabel = t("memory.notebook_title");
|
|
143966
|
-
const headerHint = this.searchQuery.length > 0 ? t("memory.esc_clear_search") : t("memory.nav_hint");
|
|
144215
|
+
const headerHint = this.searchQuery.length > 0 ? t("memory.esc_clear_search") : this.selectedIds.size > 0 ? t("memory.batch_hint", { count: String(this.selectedIds.size) }) : t("memory.nav_hint");
|
|
143967
144216
|
const labelWidth = visibleWidth(headerLabel);
|
|
143968
144217
|
const shownHint = truncateToWidth(headerHint, Math.max(0, width - labelWidth), ELLIPSIS$1);
|
|
143969
144218
|
lines.push(chalk.hex(c.primary).bold(headerLabel) + chalk.hex(c.textMuted)(shownHint));
|
|
@@ -143984,10 +144233,15 @@ var MemoryPickerComponent = class extends Container {
|
|
|
143984
144233
|
}
|
|
143985
144234
|
if (this.mode === "detail" && this.detailMemo) return this.renderDetail(lines, width, c);
|
|
143986
144235
|
if (this.mode === "confirmDelete") {
|
|
143987
|
-
|
|
143988
|
-
|
|
143989
|
-
lines.push(
|
|
143990
|
-
|
|
144236
|
+
if (this.selectedIds.size > 0) {
|
|
144237
|
+
lines.push(truncateToWidth(chalk.hex(c.warning).bold(t("memory.batch_delete_confirm", { count: String(this.selectedIds.size) })), width, ELLIPSIS$1));
|
|
144238
|
+
lines.push(chalk.hex(c.warning)(t("memory.batch_delete_hint")));
|
|
144239
|
+
} else {
|
|
144240
|
+
const memo = this.memos[this.selectedIndex];
|
|
144241
|
+
if (memo) {
|
|
144242
|
+
lines.push(truncateToWidth(chalk.hex(c.warning).bold(` ${t("memory.deleting")}${memo.userNeed}`), width, ELLIPSIS$1));
|
|
144243
|
+
lines.push(chalk.hex(c.warning)(t("memory.delete_confirm_hint")));
|
|
144244
|
+
}
|
|
143991
144245
|
}
|
|
143992
144246
|
lines.push(chalk.hex(c.primary)("─".repeat(width)));
|
|
143993
144247
|
return lines;
|
|
@@ -144015,6 +144269,7 @@ var MemoryPickerComponent = class extends Container {
|
|
|
144015
144269
|
renderMemoCard(width, memo, isSelected) {
|
|
144016
144270
|
const c = this.colors;
|
|
144017
144271
|
const pointer = isSelected ? "❯" : " ";
|
|
144272
|
+
const check = this.selectedIds.has(memo.id) ? "☑" : "□";
|
|
144018
144273
|
const indent = " ";
|
|
144019
144274
|
const indentWidth = visibleWidth(indent);
|
|
144020
144275
|
const titleColor = isSelected ? c.primary : c.text;
|
|
@@ -144022,10 +144277,12 @@ var MemoryPickerComponent = class extends Container {
|
|
|
144022
144277
|
const trailingParts = [formatRelativeTime$1(memo.recordedAt), sourceLabel(memo.extractionSource)].filter((p) => p.length > 0);
|
|
144023
144278
|
const trailingText = trailingParts.length > 0 ? " " + trailingParts.join(" ") : "";
|
|
144024
144279
|
const trailingWidth = visibleWidth(trailingText);
|
|
144025
|
-
const headerPrefixWidth = visibleWidth(pointer) + 1;
|
|
144280
|
+
const headerPrefixWidth = visibleWidth(pointer) + 1 + visibleWidth(check) + 1;
|
|
144026
144281
|
const titleBudget = Math.max(8, width - headerPrefixWidth - trailingWidth);
|
|
144027
144282
|
const shownTitle = truncateToWidth(singleLine$1(memo.userNeed), titleBudget, ELLIPSIS$1);
|
|
144283
|
+
const checkColor = this.selectedIds.has(memo.id) ? c.primary : c.textDim;
|
|
144028
144284
|
let header = chalk.hex(isSelected ? c.primary : c.textDim)(pointer + " ");
|
|
144285
|
+
header += chalk.hex(checkColor)(check + " ");
|
|
144029
144286
|
header += titleStyle(shownTitle);
|
|
144030
144287
|
if (trailingText.length > 0) header += chalk.hex(c.textDim)(trailingText);
|
|
144031
144288
|
const card = [truncateToWidth(header, width, ELLIPSIS$1)];
|
|
@@ -144162,12 +144419,15 @@ var SessionPickerComponent = class extends Container {
|
|
|
144162
144419
|
onSelect;
|
|
144163
144420
|
onCancel;
|
|
144164
144421
|
onDelete;
|
|
144422
|
+
onDeleteMany;
|
|
144165
144423
|
onStatus;
|
|
144166
144424
|
maxVisibleSessions;
|
|
144167
144425
|
loading;
|
|
144168
144426
|
focused = false;
|
|
144169
144427
|
selectedIndex = 0;
|
|
144170
144428
|
confirmingDelete = false;
|
|
144429
|
+
/** Session ids ticked for batch delete (space toggles, a selects all). */
|
|
144430
|
+
selectedIds = /* @__PURE__ */ new Set();
|
|
144171
144431
|
constructor(opts) {
|
|
144172
144432
|
super();
|
|
144173
144433
|
this.sessions = opts.sessions;
|
|
@@ -144177,6 +144437,7 @@ var SessionPickerComponent = class extends Container {
|
|
|
144177
144437
|
this.onSelect = opts.onSelect;
|
|
144178
144438
|
this.onCancel = opts.onCancel;
|
|
144179
144439
|
this.onDelete = opts.onDelete;
|
|
144440
|
+
this.onDeleteMany = opts.onDeleteMany;
|
|
144180
144441
|
this.onStatus = opts.onStatus;
|
|
144181
144442
|
this.maxVisibleSessions = opts.maxVisibleSessions ?? 4;
|
|
144182
144443
|
}
|
|
@@ -144194,6 +144455,15 @@ var SessionPickerComponent = class extends Container {
|
|
|
144194
144455
|
if (!session) return;
|
|
144195
144456
|
if (this.confirmingDelete) {
|
|
144196
144457
|
this.confirmingDelete = false;
|
|
144458
|
+
if (this.selectedIds.size > 0) {
|
|
144459
|
+
if (this.onDeleteMany === void 0) {
|
|
144460
|
+
this.confirmingDelete = true;
|
|
144461
|
+
this.onStatus(t("session_picker.batch_delete_unavailable"));
|
|
144462
|
+
return;
|
|
144463
|
+
}
|
|
144464
|
+
this.onDeleteMany?.([...this.selectedIds]);
|
|
144465
|
+
return;
|
|
144466
|
+
}
|
|
144197
144467
|
if (session.metadata?.["source"] === "cc-connect") {
|
|
144198
144468
|
this.onStatus(t("session_picker.cc_restricted"));
|
|
144199
144469
|
return;
|
|
@@ -144209,11 +144479,13 @@ var SessionPickerComponent = class extends Container {
|
|
|
144209
144479
|
return;
|
|
144210
144480
|
}
|
|
144211
144481
|
if (matchesKey(data, Key.up)) {
|
|
144482
|
+
if (this.confirmingDelete) return;
|
|
144212
144483
|
this.selectedIndex = Math.max(0, this.selectedIndex - 1);
|
|
144213
144484
|
this.confirmingDelete = false;
|
|
144214
144485
|
return;
|
|
144215
144486
|
}
|
|
144216
144487
|
if (matchesKey(data, Key.down)) {
|
|
144488
|
+
if (this.confirmingDelete) return;
|
|
144217
144489
|
this.selectedIndex = Math.min(this.sessions.length - 1, this.selectedIndex + 1);
|
|
144218
144490
|
this.confirmingDelete = false;
|
|
144219
144491
|
return;
|
|
@@ -144228,6 +144500,26 @@ var SessionPickerComponent = class extends Container {
|
|
|
144228
144500
|
}
|
|
144229
144501
|
if (session.id !== this.currentSessionId) this.confirmingDelete = true;
|
|
144230
144502
|
}
|
|
144503
|
+
if (k === " " && !this.confirmingDelete) {
|
|
144504
|
+
const session = this.sessions[this.selectedIndex];
|
|
144505
|
+
if (!session || session.id === this.currentSessionId) return;
|
|
144506
|
+
if (session.metadata?.["source"] === "cc-connect") {
|
|
144507
|
+
this.onStatus(t("session_picker.cc_restricted"));
|
|
144508
|
+
return;
|
|
144509
|
+
}
|
|
144510
|
+
if (this.selectedIds.has(session.id)) this.selectedIds.delete(session.id);
|
|
144511
|
+
else this.selectedIds.add(session.id);
|
|
144512
|
+
return;
|
|
144513
|
+
}
|
|
144514
|
+
if (k === "a" || k === "A") {
|
|
144515
|
+
if (this.confirmingDelete) return;
|
|
144516
|
+
if (this.sessions.length === 0) return;
|
|
144517
|
+
const selectable = this.sessions.filter((s) => s.id !== this.currentSessionId && s.metadata?.["source"] !== "cc-connect");
|
|
144518
|
+
if (selectable.length === 0) return;
|
|
144519
|
+
if (selectable.every((s) => this.selectedIds.has(s.id))) this.selectedIds.clear();
|
|
144520
|
+
else for (const s of selectable) this.selectedIds.add(s.id);
|
|
144521
|
+
return;
|
|
144522
|
+
}
|
|
144231
144523
|
}
|
|
144232
144524
|
render(width) {
|
|
144233
144525
|
const colors = this.colors;
|
|
@@ -144245,7 +144537,7 @@ var SessionPickerComponent = class extends Container {
|
|
|
144245
144537
|
return lines;
|
|
144246
144538
|
}
|
|
144247
144539
|
const headerLabel = t("session.picker_title");
|
|
144248
|
-
const headerHint = this.confirmingDelete ? t("session.delete_confirm") : t("session.picker_hint");
|
|
144540
|
+
const headerHint = this.confirmingDelete ? this.selectedIds.size > 0 ? t("session_picker.batch_delete_confirm", { count: String(this.selectedIds.size) }) : t("session.delete_confirm") : this.selectedIds.size > 0 ? t("session_picker.batch_hint", { count: String(this.selectedIds.size) }) : t("session.picker_hint");
|
|
144249
144541
|
const labelWidth = visibleWidth(headerLabel);
|
|
144250
144542
|
const shownHint = truncateToWidth(headerHint, Math.max(0, width - labelWidth), ELLIPSIS);
|
|
144251
144543
|
const hintColor = this.confirmingDelete ? colors.warning : colors.textMuted;
|
|
@@ -144271,6 +144563,7 @@ var SessionPickerComponent = class extends Container {
|
|
|
144271
144563
|
renderSessionCard(width, session, isSelected, isCurrent) {
|
|
144272
144564
|
const colors = this.colors;
|
|
144273
144565
|
const pointer = isSelected ? "❯" : " ";
|
|
144566
|
+
const check = this.selectedIds.has(session.id) ? "☑" : "□";
|
|
144274
144567
|
const indent = " ";
|
|
144275
144568
|
const indentWidth = visibleWidth(indent);
|
|
144276
144569
|
const titleColor = isSelected ? colors.primary : colors.text;
|
|
@@ -144284,14 +144577,16 @@ var SessionPickerComponent = class extends Container {
|
|
|
144284
144577
|
});
|
|
144285
144578
|
const trailingParts = [time, badge].filter((p) => p.length > 0);
|
|
144286
144579
|
const trailingWidth = visibleWidth(trailingParts.length > 0 ? " " + trailingParts.join(" ") : "");
|
|
144287
|
-
const headerPrefixWidth = visibleWidth(pointer) + 1;
|
|
144580
|
+
const headerPrefixWidth = visibleWidth(pointer) + 1 + visibleWidth(check) + 1;
|
|
144288
144581
|
const titleBudget = Math.max(8, width - headerPrefixWidth - trailingWidth);
|
|
144289
144582
|
const shownTitle = truncateToWidth(singleLine(titleSource), titleBudget, ELLIPSIS);
|
|
144583
|
+
const checkColor = this.selectedIds.has(session.id) ? colors.primary : colors.textDim;
|
|
144290
144584
|
let header = chalk.hex(isSelected ? colors.primary : colors.textDim)(pointer + " ");
|
|
144585
|
+
header += chalk.hex(checkColor)(check + " ");
|
|
144291
144586
|
header += titleStyle(shownTitle);
|
|
144292
144587
|
if (time.length > 0) header += " " + chalk.hex(colors.textDim)(time);
|
|
144293
144588
|
if (badge.length > 0) header += " " + chalk.hex(colors.success)(badge);
|
|
144294
|
-
const card = [header];
|
|
144589
|
+
const card = [truncateToWidth(header, width)];
|
|
144295
144590
|
const fullId = session.id;
|
|
144296
144591
|
const idWidth = visibleWidth(fullId);
|
|
144297
144592
|
const metaGap = " ";
|
|
@@ -145036,6 +145331,27 @@ var DialogManager = class {
|
|
|
145036
145331
|
}).catch((error) => {
|
|
145037
145332
|
this.host.showError(error instanceof Error ? error.message : String(error));
|
|
145038
145333
|
});
|
|
145334
|
+
},
|
|
145335
|
+
onDeleteMany: (sessionIds) => {
|
|
145336
|
+
const ccIds = new Set(this.host.getSessions().filter((s) => s.metadata?.["source"] === "cc-connect").map((s) => s.id));
|
|
145337
|
+
const deletable = sessionIds.filter((id) => !ccIds.has(id));
|
|
145338
|
+
if (deletable.length === 0) {
|
|
145339
|
+
this.host.showStatus(t("dialog.cc_managed"));
|
|
145340
|
+
return;
|
|
145341
|
+
}
|
|
145342
|
+
(async () => {
|
|
145343
|
+
for (const id of deletable) try {
|
|
145344
|
+
await this.host.deleteSession(id);
|
|
145345
|
+
} catch (error) {
|
|
145346
|
+
this.host.showError(error instanceof Error ? error.message : String(error));
|
|
145347
|
+
break;
|
|
145348
|
+
}
|
|
145349
|
+
await this.host.fetchSessions();
|
|
145350
|
+
if (this.host.getSessions().length === 0) this.hideSessionPicker();
|
|
145351
|
+
else if (this.host.state.activeDialog === "session-picker") this.mountSessionPicker(onCancel);
|
|
145352
|
+
})().catch((error) => {
|
|
145353
|
+
this.host.showError(error instanceof Error ? error.message : String(error));
|
|
145354
|
+
});
|
|
145039
145355
|
}
|
|
145040
145356
|
}));
|
|
145041
145357
|
}
|
|
@@ -145170,6 +145486,7 @@ function createInitialAppState(input) {
|
|
|
145170
145486
|
contextUsage: 0,
|
|
145171
145487
|
contextTokens: 0,
|
|
145172
145488
|
maxContextTokens: 0,
|
|
145489
|
+
providerBalance: null,
|
|
145173
145490
|
isCompacting: false,
|
|
145174
145491
|
lastCompactionFinishedAt: void 0,
|
|
145175
145492
|
autoCompactionCount: 0,
|
|
@@ -145217,6 +145534,8 @@ var ScreamTUI = class {
|
|
|
145217
145534
|
tightModeHandler = null;
|
|
145218
145535
|
reverseRpcDisposers = [];
|
|
145219
145536
|
startupNotice;
|
|
145537
|
+
/** Interval handle for the periodic provider-balance refresh. */
|
|
145538
|
+
balancePollTimer;
|
|
145220
145539
|
updatePrefetched;
|
|
145221
145540
|
sessionManager;
|
|
145222
145541
|
dialogManager;
|
|
@@ -145323,6 +145642,7 @@ var ScreamTUI = class {
|
|
|
145323
145642
|
try {
|
|
145324
145643
|
await this.finishStartup(shouldReplayHistory);
|
|
145325
145644
|
this.lifecycleController.startCcConnectPolling();
|
|
145645
|
+
this.startBalancePolling();
|
|
145326
145646
|
} catch (error) {
|
|
145327
145647
|
this.lifecycleController.disposeTerminalTracking();
|
|
145328
145648
|
this.state.footer.dispose();
|
|
@@ -145357,6 +145677,18 @@ var ScreamTUI = class {
|
|
|
145357
145677
|
this.state.ui.setFocus(this.state.editor);
|
|
145358
145678
|
return shouldReplayHistory;
|
|
145359
145679
|
}
|
|
145680
|
+
/**
|
|
145681
|
+
* Refresh the provider balance badge every 60s, but only for providers
|
|
145682
|
+
* whose balance we can actually query (local hostname check, no network
|
|
145683
|
+
* for unsupported ones). The api-balance layer caches per provider for
|
|
145684
|
+
* 60s, so each tick either serves the cache or performs one real lookup.
|
|
145685
|
+
*/
|
|
145686
|
+
startBalancePolling() {
|
|
145687
|
+
this.balancePollTimer ??= setInterval(() => {
|
|
145688
|
+
const model = this.state.appState.model;
|
|
145689
|
+
if (supportsBalance(model)) refreshProviderBalance(model, (patch) => this.setAppState(patch));
|
|
145690
|
+
}, 6e4);
|
|
145691
|
+
}
|
|
145360
145692
|
async finishStartup(shouldReplayHistory) {
|
|
145361
145693
|
if (this.startupNotice !== void 0) {
|
|
145362
145694
|
this.showStatus(this.startupNotice);
|
|
@@ -145399,6 +145731,10 @@ var ScreamTUI = class {
|
|
|
145399
145731
|
}
|
|
145400
145732
|
setTightMode(false);
|
|
145401
145733
|
this.lifecycleController.stopCcConnectPolling();
|
|
145734
|
+
if (this.balancePollTimer !== void 0) {
|
|
145735
|
+
clearInterval(this.balancePollTimer);
|
|
145736
|
+
this.balancePollTimer = void 0;
|
|
145737
|
+
}
|
|
145402
145738
|
this.lifecycleController.uninstallSignalHandlers();
|
|
145403
145739
|
this.aborted = true;
|
|
145404
145740
|
this.cancelInFlight?.();
|
package/dist/main.mjs
CHANGED
|
@@ -6,7 +6,7 @@ const __dirname = __cjsShimDirname(__filename);
|
|
|
6
6
|
import "./suppress-sqlite-warning-C2VB0doZ.mjs";
|
|
7
7
|
//#region src/main.ts
|
|
8
8
|
try {
|
|
9
|
-
(await import("./app-
|
|
9
|
+
(await import("./app-CTeIrRAX.mjs")).main();
|
|
10
10
|
} catch (error) {
|
|
11
11
|
process.stderr.write(`${error instanceof Error ? error.stack ?? error.message : String(error)}\n`);
|
|
12
12
|
process.exit(1);
|
|
@@ -431,6 +431,9 @@ const dictionaries = {
|
|
|
431
431
|
"like.other": "其他偏好",
|
|
432
432
|
"like.other_hint": "例如:多说例子、先给结论再展开、避免术语等(留空表示不设置)",
|
|
433
433
|
"like.other_example": "例如:请用中文回答,避免缩写",
|
|
434
|
+
"like.do_not": "用户禁止",
|
|
435
|
+
"like.do_not_hint": "用户明确不让做的事。Agent 绝不能做这些。",
|
|
436
|
+
"like.do_not_example": "例如:未经询问绝不修改用户的配置文件",
|
|
434
437
|
"like.cancelled": "已取消 /like 设置",
|
|
435
438
|
"like.saved": "偏好已保存(下次新会话生效)",
|
|
436
439
|
"revoke.streaming": "无法在 streaming 中撤回 — 请先按 Esc 或 Ctrl-C 取消。",
|
|
@@ -470,9 +473,12 @@ const dictionaries = {
|
|
|
470
473
|
"session.loading": "正在加载会话...",
|
|
471
474
|
"session_picker.empty": "未找到会话。按 Escape 关闭。",
|
|
472
475
|
"session_picker.cc_restricted": "CC专属会话不支持切换或删除,请点击或复制下方文件路径进入手动管理",
|
|
476
|
+
"session_picker.batch_delete_confirm": "删除选中的 {count} 个会话?",
|
|
477
|
+
"session_picker.batch_delete_unavailable": "此处不支持批量删除。",
|
|
478
|
+
"session_picker.batch_hint": "[空格] 选择 · [a] 全选 · [d] 删除选中({count})",
|
|
473
479
|
"session.picker_title": "会话 ",
|
|
474
480
|
"session.delete_confirm": "⚠️ 按 Enter 确认删除,Esc 取消",
|
|
475
|
-
"session.picker_hint": "(↑↓ 导航,Enter
|
|
481
|
+
"session.picker_hint": "(↑↓ 导航,Enter 打开,空格 标记,a 全选,d 删除,Esc 取消)",
|
|
476
482
|
"model.nav_model": "↑↓ 模型",
|
|
477
483
|
"model.nav_thinking": "←→ 思考等级",
|
|
478
484
|
"model.nav_page": "PgUp/PgDn 翻页",
|
|
@@ -535,13 +541,16 @@ const dictionaries = {
|
|
|
535
541
|
"memory.search_label": "搜索: ",
|
|
536
542
|
"memory.notebook_title": "记忆备忘录 ",
|
|
537
543
|
"memory.esc_clear_search": "(Esc 清除搜索)",
|
|
538
|
-
"memory.nav_hint": "(↑↓ 导航,Enter
|
|
544
|
+
"memory.nav_hint": "(↑↓ 导航,Enter 查看,空格 标记,a 全选,i 注入,d 删除,/ 搜索,Esc 关闭)",
|
|
539
545
|
"memory.loading": "正在加载...",
|
|
540
546
|
"memory.no_match": "未找到匹配 \"{query}\" 的记忆。",
|
|
541
547
|
"memory.empty": "暂无记忆备忘录。",
|
|
542
548
|
"memory.auto_extract_hint": " 压缩对话或退出会话时,系统会自动提取并保存。",
|
|
543
549
|
"memory.deleting": "删除: ",
|
|
544
550
|
"memory.delete_confirm_hint": " 按 Enter 确认删除,Esc 取消",
|
|
551
|
+
"memory.batch_delete_confirm": "删除选中的 {count} 条记忆?",
|
|
552
|
+
"memory.batch_delete_hint": " 按 Enter 确认批量删除,Esc 取消",
|
|
553
|
+
"memory.batch_hint": "已选 {count} 条 · [空格] 选择 · [a] 全选 · [d] 删除选中",
|
|
545
554
|
"memory.showing_range": "{start}-{end} / {total} 条",
|
|
546
555
|
"memory.id_label": "ID: ",
|
|
547
556
|
"memory.source_label": "来源: ",
|
|
@@ -724,6 +733,8 @@ const dictionaries = {
|
|
|
724
733
|
"subagent.bind_title": "绑定 {profile}",
|
|
725
734
|
"subagent.model_hint": "↑↓ 选择模型 · Enter 确认 · Esc 返回",
|
|
726
735
|
"subagent.save_failed": "保存失败:{msg}",
|
|
736
|
+
"subagent.stale_binding": "{alias}(已失效)",
|
|
737
|
+
"subagent.invalid_alias": "模型别名 {alias} 不存在",
|
|
727
738
|
"kdoctree.no_title": "(无标题)",
|
|
728
739
|
"kdoctree.empty": "(空)",
|
|
729
740
|
"kdoctree.move": "移动",
|
|
@@ -1134,6 +1145,7 @@ const dictionaries = {
|
|
|
1134
1145
|
"kw.embedding_failed": "向量模型加载失败,请返回菜单选择重新下载(建议科学上网)",
|
|
1135
1146
|
"kw.embedding_ready": "向量模型已就绪",
|
|
1136
1147
|
"kw.embedding_not_downloaded": "向量模型未下载(选择「下载向量模型」手动下载)",
|
|
1148
|
+
"kw.embedding_data_intact": " —— 你的知识数据仍然存在,下载模型后即可正常使用",
|
|
1137
1149
|
"kw.embedding_already_installed": "向量模型已安装,无需重新下载"
|
|
1138
1150
|
},
|
|
1139
1151
|
en: {
|
|
@@ -1468,6 +1480,9 @@ const dictionaries = {
|
|
|
1468
1480
|
"like.other": "Other preferences",
|
|
1469
1481
|
"like.other_hint": "e.g. more examples, conclusion first, avoid jargon (leave empty to skip)",
|
|
1470
1482
|
"like.other_example": "e.g. Answer in English, avoid abbreviations",
|
|
1483
|
+
"like.do_not": "User Prohibitions",
|
|
1484
|
+
"like.do_not_hint": "Things the user explicitly does NOT want done. The agent must NEVER do these.",
|
|
1485
|
+
"like.do_not_example": "e.g. Never modify user config files without asking",
|
|
1471
1486
|
"like.cancelled": "/like setup cancelled",
|
|
1472
1487
|
"like.saved": "Preferences saved (takes effect in next session)",
|
|
1473
1488
|
"revoke.streaming": "Cannot revoke during streaming — press Esc or Ctrl-C to cancel first.",
|
|
@@ -1507,9 +1522,12 @@ const dictionaries = {
|
|
|
1507
1522
|
"session.loading": "Loading sessions...",
|
|
1508
1523
|
"session_picker.empty": "No sessions found. Press Escape to close.",
|
|
1509
1524
|
"session_picker.cc_restricted": "CC sessions cannot be switched or deleted. Use the file path below to manage manually",
|
|
1525
|
+
"session_picker.batch_delete_confirm": "Delete {count} selected sessions?",
|
|
1526
|
+
"session_picker.batch_delete_unavailable": "Batch delete is not available here.",
|
|
1527
|
+
"session_picker.batch_hint": "[space] select · [a] all · [d] delete selected ({count})",
|
|
1510
1528
|
"session.picker_title": "Sessions ",
|
|
1511
1529
|
"session.delete_confirm": "⚠️ Press Enter to confirm delete, Esc to cancel",
|
|
1512
|
-
"session.picker_hint": "(↑↓ Navigate, Enter
|
|
1530
|
+
"session.picker_hint": "(↑↓ Navigate, Enter Open, Space Mark, a All, d Delete, Esc Cancel)",
|
|
1513
1531
|
"model.nav_model": "↑↓ Model",
|
|
1514
1532
|
"model.nav_thinking": "←→ Thinking",
|
|
1515
1533
|
"model.nav_page": "PgUp/PgDn Page",
|
|
@@ -1572,13 +1590,16 @@ const dictionaries = {
|
|
|
1572
1590
|
"memory.search_label": "Search: ",
|
|
1573
1591
|
"memory.notebook_title": "Memory Notebook ",
|
|
1574
1592
|
"memory.esc_clear_search": "(Esc clear search)",
|
|
1575
|
-
"memory.nav_hint": "(↑↓ Navigate, Enter View, i Inject, d Delete, / Search, Esc Close)",
|
|
1593
|
+
"memory.nav_hint": "(↑↓ Navigate, Enter View, Space Mark, a All, i Inject, d Delete, / Search, Esc Close)",
|
|
1576
1594
|
"memory.loading": "Loading...",
|
|
1577
1595
|
"memory.no_match": "No memories matching \"{query}\".",
|
|
1578
1596
|
"memory.empty": "No memories yet.",
|
|
1579
1597
|
"memory.auto_extract_hint": " Memories are extracted automatically when compacting or exiting a session.",
|
|
1580
1598
|
"memory.deleting": "Delete: ",
|
|
1581
1599
|
"memory.delete_confirm_hint": " Press Enter to confirm delete, Esc to cancel",
|
|
1600
|
+
"memory.batch_delete_confirm": "Delete {count} selected memos?",
|
|
1601
|
+
"memory.batch_delete_hint": " Press Enter to confirm batch delete, Esc to cancel",
|
|
1602
|
+
"memory.batch_hint": "{count} selected · [space] select · [a] all · [d] delete selected",
|
|
1582
1603
|
"memory.showing_range": "{start}-{end} / {total} items",
|
|
1583
1604
|
"memory.id_label": "ID: ",
|
|
1584
1605
|
"memory.source_label": "Source: ",
|
|
@@ -1761,6 +1782,8 @@ const dictionaries = {
|
|
|
1761
1782
|
"subagent.bind_title": "Bind {profile}",
|
|
1762
1783
|
"subagent.model_hint": "↑↓ Select model · Enter confirm · Esc back",
|
|
1763
1784
|
"subagent.save_failed": "Save failed: {msg}",
|
|
1785
|
+
"subagent.stale_binding": "{alias} (stale)",
|
|
1786
|
+
"subagent.invalid_alias": "Model alias {alias} does not exist",
|
|
1764
1787
|
"kdoctree.no_title": "(untitled)",
|
|
1765
1788
|
"kdoctree.empty": "(empty)",
|
|
1766
1789
|
"kdoctree.move": "Move",
|
|
@@ -2171,6 +2194,7 @@ const dictionaries = {
|
|
|
2171
2194
|
"kw.embedding_failed": "Vector model load failed. Return to the menu and select Download to retry.",
|
|
2172
2195
|
"kw.embedding_ready": "Vector model ready",
|
|
2173
2196
|
"kw.embedding_not_downloaded": "Vector model not downloaded (select Download vector model)",
|
|
2197
|
+
"kw.embedding_data_intact": " — your knowledge data is still there; download the model to use it again",
|
|
2174
2198
|
"kw.embedding_already_installed": "Vector model already installed, no need to re-download"
|
|
2175
2199
|
}
|
|
2176
2200
|
};
|
|
@@ -3,5 +3,5 @@ import { fileURLToPath as __cjsShimFileURLToPath } from 'node:url';
|
|
|
3
3
|
import { dirname as __cjsShimDirname } from 'node:path';
|
|
4
4
|
const __filename = __cjsShimFileURLToPath(import.meta.url);
|
|
5
5
|
const __dirname = __cjsShimDirname(__filename);
|
|
6
|
-
import { t as TextInputDialogComponent } from "./text-input-dialog-
|
|
6
|
+
import { t as TextInputDialogComponent } from "./text-input-dialog-COl6Uu7m.mjs";
|
|
7
7
|
export { TextInputDialogComponent };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "scream-code",
|
|
3
|
-
"version": "0.11.
|
|
3
|
+
"version": "0.11.9",
|
|
4
4
|
"description": "A terminal-native AI agent for builders",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "ScreamCli",
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
"smoke": "node dist/main.mjs --version"
|
|
60
60
|
},
|
|
61
61
|
"dependencies": {
|
|
62
|
-
"@liutod-scream/pi-tui": "^0.80.
|
|
62
|
+
"@liutod-scream/pi-tui": "^0.80.32",
|
|
63
63
|
"@mariozechner/clipboard": "^0.3.2",
|
|
64
64
|
"chalk": "^5.4.1",
|
|
65
65
|
"cli-highlight": "^2.1.11",
|