scream-code 0.11.8 → 0.11.10

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-DYHGTG6m.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-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";
@@ -59422,6 +59422,27 @@ const USER_GENERIC_DIRS = [".agents/skills"];
59422
59422
  const PROJECT_BRAND_DIRS = [".scream-code/skills"];
59423
59423
  const PROJECT_GENERIC_DIRS = [".agents/skills"];
59424
59424
  const MAX_SKILL_SCAN_DEPTH = 8;
59425
+ /**
59426
+ * Common documentation files shipped inside downloaded skill/plugin bundles
59427
+ * are not skills; matched (case-insensitively) against top-level flat .md
59428
+ * entries so e.g. README.md does not surface as a /skill:README entry.
59429
+ */
59430
+ const DOCUMENTATION_MARKDOWN_LOWER = new Set([
59431
+ "readme.md",
59432
+ "changelog.md",
59433
+ "changes.md",
59434
+ "history.md",
59435
+ "license.md",
59436
+ "copying.md",
59437
+ "authors.md",
59438
+ "notice.md",
59439
+ "contributing.md",
59440
+ "security.md",
59441
+ "code_of_conduct.md",
59442
+ "architecture.md",
59443
+ "design.md",
59444
+ "notes.md"
59445
+ ]);
59425
59446
  async function resolveSkillRoots(options) {
59426
59447
  const isDir = options.isDir ?? defaultIsDir;
59427
59448
  const realpath = options.realpath ?? ((p) => promises.realpath(p).then((r) => r.replaceAll("\\", "/")));
@@ -59495,6 +59516,7 @@ async function discoverSkills(options) {
59495
59516
  for (const entry of entries) {
59496
59517
  if (!entry.endsWith(".md")) continue;
59497
59518
  if (entry === "SKILL.md") continue;
59519
+ if (DOCUMENTATION_MARKDOWN_LOWER.has(entry.toLowerCase())) continue;
59498
59520
  const skillName = entry.slice(0, -3);
59499
59521
  if (directorySkills.has(skillName)) {
59500
59522
  warn(`Ignoring flat skill ${join$1(dirPath, entry)} because ${join$1(dirPath, skillName, "SKILL.md")} exists with the same name`);
@@ -59888,7 +59910,6 @@ function formatFullSkill(skill) {
59888
59910
  function formatModelSkill(skill) {
59889
59911
  const lines = [`- ${skill.name}: ${truncate$2(skill.description, LISTING_DESC_MAX)}`];
59890
59912
  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
59913
  return lines;
59893
59914
  }
59894
59915
  function truncate$2(value, max) {
@@ -119303,6 +119324,14 @@ async function fetchProviderBalance(baseUrl, apiKey) {
119303
119324
  if (!fetcher) return null;
119304
119325
  return fetcher.fetch(baseUrl, apiKey);
119305
119326
  }
119327
+ /**
119328
+ * True when the given base URL belongs to a vendor we can query balances
119329
+ * for. Pure local check (no network) — used to skip polling for
119330
+ * unsupported providers.
119331
+ */
119332
+ function isSupportedBalanceProvider(baseUrl) {
119333
+ return fetchers.some((f) => f.matches(baseUrl));
119334
+ }
119306
119335
  //#endregion
119307
119336
  //#region ../../packages/node-sdk/src/auth.ts
119308
119337
  var ScreamAuthFacade = class {
@@ -120724,7 +120753,7 @@ function optionalBuildString(value) {
120724
120753
  return typeof value === "string" && value.length > 0 ? value : void 0;
120725
120754
  }
120726
120755
  const SCREAM_BUILD_INFO = {
120727
- version: optionalBuildString("0.11.8"),
120756
+ version: optionalBuildString("0.11.10"),
120728
120757
  channel: optionalBuildString(""),
120729
120758
  commit: optionalBuildString(""),
120730
120759
  buildTarget: optionalBuildString("darwin-arm64")
@@ -122055,14 +122084,16 @@ function buildSkillSlashCommands(skills, builtinCommandNames) {
122055
122084
  commands.push({
122056
122085
  name: commandName,
122057
122086
  aliases: [],
122058
- description: skill.description ?? ""
122087
+ description: skill.description ?? "",
122088
+ source: skill.source
122059
122089
  });
122060
122090
  if (skill.source === "builtin" && !reservedNames.has(skill.name)) {
122061
122091
  commandMap.set(skill.name, skill.name);
122062
122092
  commands.push({
122063
122093
  name: skill.name,
122064
122094
  aliases: [],
122065
- description: skill.description ?? ""
122095
+ description: skill.description ?? "",
122096
+ source: skill.source
122066
122097
  });
122067
122098
  }
122068
122099
  }
@@ -124628,7 +124659,7 @@ function createMarkdownTheme(colors) {
124628
124659
  quote: (text) => chalk.hex(colors.mdQuote)(text),
124629
124660
  quoteBorder: (text) => chalk.hex(colors.mdQuote)(text),
124630
124661
  hr: (text) => border(text),
124631
- tableHeader: (text) => chalk.bold.hex(colors.accent)(text),
124662
+ tableHeader: (text) => chalk.bold.hex(colors.fusionPlanMode)(text),
124632
124663
  listBullet: (text) => chalk.hex(colors.roleAssistant)(text.replace(/^-/, "•")),
124633
124664
  bold: (text) => chalk.bold(text),
124634
124665
  italic: (text) => chalk.italic(text),
@@ -125084,6 +125115,21 @@ async function getProviderBalanceForModel(model) {
125084
125115
  return balance;
125085
125116
  }
125086
125117
  /**
125118
+ * True when the given model is served by a provider whose balance we can
125119
+ * query. Pure local check (config lookup + hostname match, no network) —
125120
+ * the poller uses it to skip unsupported providers entirely.
125121
+ */
125122
+ function supportsBalance(model) {
125123
+ const providerName = model.split("/")[0] ?? "";
125124
+ if (providerName.length === 0) return false;
125125
+ try {
125126
+ const baseUrl = readConfigFile(join(getDataDir(), "config.toml")).providers?.[providerName]?.baseUrl;
125127
+ return baseUrl !== void 0 && isSupportedBalanceProvider(baseUrl);
125128
+ } catch {
125129
+ return false;
125130
+ }
125131
+ }
125132
+ /**
125087
125133
  * Fetch the balance for a model and push it into app state. Fire-and-forget:
125088
125134
  * failures resolve to null inside getProviderBalanceForModel, so callers
125089
125135
  * (startup sync and model switches) never await it. A request id guards
@@ -126362,7 +126408,7 @@ async function guidedGoalSetup(host) {
126362
126408
  host.showNotice(t("goal.storm_breaker"), t("goal.conflict_loop"));
126363
126409
  return;
126364
126410
  }
126365
- const { TextInputDialogComponent } = await import("./text-input-dialog-DX3hKoBF.mjs");
126411
+ const { TextInputDialogComponent } = await import("./text-input-dialog-xqTCBHZF.mjs");
126366
126412
  const initialDesc = await promptText(host, TextInputDialogComponent, {
126367
126413
  title: t("goal.setup_title_initial"),
126368
126414
  subtitle: t("goal.setup_desc_hint"),
@@ -126383,7 +126429,7 @@ async function guidedGoalSetup(host) {
126383
126429
  await showGoalConfigWizard(host, session, confirmed.trim() || objective, false);
126384
126430
  }
126385
126431
  async function showGoalConfigWizard(host, session, objective, replace) {
126386
- const { TextInputDialogComponent } = await import("./text-input-dialog-DX3hKoBF.mjs");
126432
+ const { TextInputDialogComponent } = await import("./text-input-dialog-xqTCBHZF.mjs");
126387
126433
  const turnInput = await promptNumber(host, TextInputDialogComponent, {
126388
126434
  title: t("goal.wizard_title", { objective }),
126389
126435
  subtitle: t("goal.budget_turns_hint"),
@@ -134873,8 +134919,8 @@ async function handleKnowledgeCommand(host, _args) {
134873
134919
  switch (status) {
134874
134920
  case "ready": return "";
134875
134921
  case "downloading": return " · " + t("kw.embedding_downloading");
134876
- case "failed": return " · " + t("kw.embedding_failed");
134877
- case "idle": return " · " + t("kw.embedding_not_downloaded");
134922
+ case "failed": return " · " + t("kw.embedding_failed") + t("kw.embedding_data_intact");
134923
+ case "idle": return " · " + t("kw.embedding_not_downloaded") + t("kw.embedding_data_intact");
134878
134924
  }
134879
134925
  };
134880
134926
  const showMenu = () => {
@@ -140894,9 +140940,11 @@ var FileMentionProvider = class {
140894
140940
  const desc = ac.description ?? "";
140895
140941
  const resolvedDesc = desc ? t(desc) : "";
140896
140942
  const aliases = cmd.aliases;
140943
+ const aliasStr = aliases && aliases.length > 0 ? ` (${aliases.join(", ")})` : "";
140944
+ const shortDesc = resolvedDesc ? truncateToWidth(resolvedDesc, 60, "…") : "";
140897
140945
  return {
140898
140946
  value: name,
140899
- label: `/${name}${aliases && aliases.length > 0 ? ` (${aliases.join(", ")})` : ""}${resolvedDesc ? ` — ${resolvedDesc}` : ""}`
140947
+ label: `/${name}${aliasStr}${shortDesc ? ` — ${shortDesc}` : ""}`
140900
140948
  };
140901
140949
  });
140902
140950
  this.inner = new CombinedAutocompleteProvider(slashCommands, workDir, fdPath);
@@ -141251,7 +141299,7 @@ var InputController = class InputController {
141251
141299
  this.host = host;
141252
141300
  }
141253
141301
  setupAutocomplete() {
141254
- const visible = this.host.getSlashCommands().filter((cmd) => !cmd.name.startsWith("skill:"));
141302
+ const visible = this.host.getSlashCommands().filter((cmd) => !(cmd.name.startsWith("skill:") && cmd.source === "builtin"));
141255
141303
  const slashCommands = visible.map((cmd) => cmd);
141256
141304
  const { state } = this.host;
141257
141305
  const provider = new FileMentionProvider(slashCommands, state.appState.workDir, state.fdPath, state.gitLsFilesCache);
@@ -145510,6 +145558,8 @@ var ScreamTUI = class {
145510
145558
  tightModeHandler = null;
145511
145559
  reverseRpcDisposers = [];
145512
145560
  startupNotice;
145561
+ /** Interval handle for the periodic provider-balance refresh. */
145562
+ balancePollTimer;
145513
145563
  updatePrefetched;
145514
145564
  sessionManager;
145515
145565
  dialogManager;
@@ -145616,6 +145666,7 @@ var ScreamTUI = class {
145616
145666
  try {
145617
145667
  await this.finishStartup(shouldReplayHistory);
145618
145668
  this.lifecycleController.startCcConnectPolling();
145669
+ this.startBalancePolling();
145619
145670
  } catch (error) {
145620
145671
  this.lifecycleController.disposeTerminalTracking();
145621
145672
  this.state.footer.dispose();
@@ -145650,6 +145701,18 @@ var ScreamTUI = class {
145650
145701
  this.state.ui.setFocus(this.state.editor);
145651
145702
  return shouldReplayHistory;
145652
145703
  }
145704
+ /**
145705
+ * Refresh the provider balance badge every 60s, but only for providers
145706
+ * whose balance we can actually query (local hostname check, no network
145707
+ * for unsupported ones). The api-balance layer caches per provider for
145708
+ * 60s, so each tick either serves the cache or performs one real lookup.
145709
+ */
145710
+ startBalancePolling() {
145711
+ this.balancePollTimer ??= setInterval(() => {
145712
+ const model = this.state.appState.model;
145713
+ if (supportsBalance(model)) refreshProviderBalance(model, (patch) => this.setAppState(patch));
145714
+ }, 6e4);
145715
+ }
145653
145716
  async finishStartup(shouldReplayHistory) {
145654
145717
  if (this.startupNotice !== void 0) {
145655
145718
  this.showStatus(this.startupNotice);
@@ -145692,6 +145755,10 @@ var ScreamTUI = class {
145692
145755
  }
145693
145756
  setTightMode(false);
145694
145757
  this.lifecycleController.stopCcConnectPolling();
145758
+ if (this.balancePollTimer !== void 0) {
145759
+ clearInterval(this.balancePollTimer);
145760
+ this.balancePollTimer = void 0;
145761
+ }
145695
145762
  this.lifecycleController.uninstallSignalHandlers();
145696
145763
  this.aborted = true;
145697
145764
  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-zSNn5qdo.mjs")).main();
9
+ (await import("./app-T1SUMT1T.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);
@@ -1145,6 +1145,7 @@ const dictionaries = {
1145
1145
  "kw.embedding_failed": "向量模型加载失败,请返回菜单选择重新下载(建议科学上网)",
1146
1146
  "kw.embedding_ready": "向量模型已就绪",
1147
1147
  "kw.embedding_not_downloaded": "向量模型未下载(选择「下载向量模型」手动下载)",
1148
+ "kw.embedding_data_intact": " —— 你的知识数据仍然存在,下载模型后即可正常使用",
1148
1149
  "kw.embedding_already_installed": "向量模型已安装,无需重新下载"
1149
1150
  },
1150
1151
  en: {
@@ -2193,6 +2194,7 @@ const dictionaries = {
2193
2194
  "kw.embedding_failed": "Vector model load failed. Return to the menu and select Download to retry.",
2194
2195
  "kw.embedding_ready": "Vector model ready",
2195
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",
2196
2198
  "kw.embedding_already_installed": "Vector model already installed, no need to re-download"
2197
2199
  }
2198
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-DYHGTG6m.mjs";
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.8",
3
+ "version": "0.11.10",
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.32",
62
+ "@liutod-scream/pi-tui": "^0.80.34",
63
63
  "@mariozechner/clipboard": "^0.3.2",
64
64
  "chalk": "^5.4.1",
65
65
  "cli-highlight": "^2.1.11",