scream-code 0.10.4 → 0.10.6

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/README.md CHANGED
@@ -24,7 +24,7 @@
24
24
 
25
25
  ---
26
26
 
27
- Scream Code is a hassle-free, locally deployable, all-in-one AI Agent assistant. No remote calls, high security — just tell it what you need in natural language (Chinese or English). Vibe coding, write code, search papers, edit files, clean your machine, research, generate reports, search the web... You speak, it acts! Desktop App Download You Can GOOOO!![scream.chat](https://scream.chat/) (There might be a bug.)
27
+ Scream Code is a hassle-free, locally deployable, all-in-one AI Agent assistant. No remote calls, high security — just tell it what you need in natural language (Chinese or English). Vibe coding, write code, search papers, edit files, clean your machine, research, generate reports, search the web... You speak, it acts!
28
28
 
29
29
  ---
30
30
 
@@ -183,18 +183,6 @@ Thanks to these excellent projects for inspiration: pi, pi-tui, gork, kimicli, G
183
183
 
184
184
  ---
185
185
 
186
- ## ⭐ Star History
187
-
188
- <a href="https://www-star-history.com/#LIUTod/scream-code&Date">
189
- <picture>
190
- <source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=LIUTod/scream-code&type=Date&theme=dark" />
191
- <source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=LIUTod/scream-code&type=Date" />
192
- <img alt="Star History Chart" src="https://api.star-history.com/svg?repos=LIUTod/scream-code&type=Date" />
193
- </picture>
194
- </a>
195
-
196
- ---
197
-
198
186
  ## 📄 License
199
187
 
200
188
  [MIT](LICENSE) © [LIUTod](https://github.com/LIUTod)
@@ -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-2lpwWzfy.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-pClOx34t.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";
@@ -81613,6 +81613,71 @@ function formatElapsed$1(ms) {
81613
81613
  return `${Math.floor(totalSeconds / 60)}m${(totalSeconds % 60).toString().padStart(2, "0")}s`;
81614
81614
  }
81615
81615
  //#endregion
81616
+ //#region ../../packages/agent-core/src/agent/injection/mcp-browser-skill.ts
81617
+ const BROWSER_SKILL_GUIDANCE = `\
81618
+ ## Browser Automation (chrome-devtools-mcp)
81619
+
81620
+ You have chrome-devtools-mcp tools available (\`mcp__chrome_devtools__*\`).
81621
+ These give you full control over a Chrome browser instance so you can test,
81622
+ debug, and inspect web pages directly.
81623
+
81624
+ ### Navigation & Pages
81625
+ - \`navigate_page\` — Go to a URL
81626
+ - \`new_page\` / \`close_page\` / \`list_pages\` / \`select_page\` — Manage tabs
81627
+
81628
+ ### Inspecting the Page
81629
+ - \`take_snapshot\` — Full ARIA accessibility tree (best for understanding page structure)
81630
+ - \`take_screenshot\` — Capture visual screenshot (element, viewport, or full page)
81631
+ - \`evaluate_script\` — Execute arbitrary JS in the page (e.g. \`document.title\`, \`window.scrollBy()\`)
81632
+ - \`list_console_messages\` / \`get_console_message\` — Read console logs and errors
81633
+ - \`list_network_requests\` / \`get_network_request\` — Inspect HTTP traffic
81634
+
81635
+ ### Interacting with the Page
81636
+ - \`click\` / \`hover\` / \`press_key\` / \`type_text\` / \`fill\` / \`fill_form\` — Interact with elements
81637
+ - \`drag\` — Drag and drop elements
81638
+ - \`wait_for\` — Wait for text/element to appear before acting
81639
+ - \`upload_file\` — Attach local files to file inputs
81640
+ - \`handle_dialog\` — Accept or dismiss browser dialogs (alert/confirm/prompt)
81641
+
81642
+ ### Performance & Debugging
81643
+ - \`performance_start_trace\` / \`performance_stop_trace\` / \`performance_analyze_insight\` — Record and analyze page load performance
81644
+ - \`lighthouse_audit\` — Run a full Lighthouse audit
81645
+ - \`emulate\` — Emulate device metrics, user agent, or CPU throttling
81646
+
81647
+ ### Usage Pattern
81648
+ 1. \`navigate_page\` to the target URL
81649
+ 2. \`take_snapshot\` to understand the page structure and find element UIDs
81650
+ 3. \`click\` / \`fill\` / \`type_text\` to interact using snapshot UIDs
81651
+ 4. \`take_screenshot\` to verify the visual result
81652
+ 5. \`list_console_messages\` to check for JS errors
81653
+
81654
+ ### When to Use
81655
+ - User asks to test a localhost app → navigate + screenshot + console check
81656
+ - User asks to debug frontend issues → check console errors + network requests
81657
+ - User asks to verify UI changes → screenshot before/after
81658
+ - User asks to test a form flow → fill + click + wait_for + screenshot
81659
+ - User asks to check page performance → performance_start_trace
81660
+ - Do NOT use for simple HTTP data fetching — prefer FetchURL for that.
81661
+
81662
+ ### Notes
81663
+ - Use \`take_snapshot\` before interacting — it provides stable element UIDs for click/fill
81664
+ - \`evaluate_script\` can do anything JS can (scroll, read DOM, trigger events)
81665
+ - Close pages you no longer need with \`close_page\` to manage memory`;
81666
+ const MCP_SERVER_NAME = "chrome-devtools";
81667
+ var McpBrowserSkillInjector = class extends DynamicInjector {
81668
+ injectionVariant = "mcp_browser_skill";
81669
+ constructor(agent) {
81670
+ super(agent);
81671
+ }
81672
+ getInjection() {
81673
+ if (this.injectedAt !== null) return void 0;
81674
+ const mcp = this.agent.mcp;
81675
+ if (!mcp) return void 0;
81676
+ if (!mcp.list().some((e) => e.status === "connected" && e.name === MCP_SERVER_NAME)) return void 0;
81677
+ return BROWSER_SKILL_GUIDANCE;
81678
+ }
81679
+ };
81680
+ //#endregion
81616
81681
  //#region ../../packages/agent-core/src/agent/injection/permission-mode.ts
81617
81682
  const AUTO_MODE_ENTER_REMINDER = [
81618
81683
  "Auto permission mode is active. Tool approvals will be handled automatically while this mode remains enabled.",
@@ -82188,6 +82253,7 @@ var InjectionManager = class {
82188
82253
  this.agent = agent;
82189
82254
  this.injectors = [
82190
82255
  new PluginSessionStartInjector(agent),
82256
+ new McpBrowserSkillInjector(agent),
82191
82257
  new WolfPackModeInjector(agent),
82192
82258
  new PlanModeInjector(agent),
82193
82259
  new PermissionModeInjector(agent),
@@ -122851,7 +122917,7 @@ function optionalBuildString(value) {
122851
122917
  return typeof value === "string" && value.length > 0 ? value : void 0;
122852
122918
  }
122853
122919
  const SCREAM_BUILD_INFO = {
122854
- version: optionalBuildString("0.10.4"),
122920
+ version: optionalBuildString("0.10.6"),
122855
122921
  channel: optionalBuildString(""),
122856
122922
  commit: optionalBuildString(""),
122857
122923
  buildTarget: optionalBuildString("darwin-arm64")
@@ -124398,7 +124464,7 @@ var ApiKeyInputDialogComponent = class extends Container {
124398
124464
  //#endregion
124399
124465
  //#region src/tui/constant/symbols.ts
124400
124466
  const STATUS_BULLET = "■ ";
124401
- const USER_MESSAGE_BULLET = " ";
124467
+ const USER_MESSAGE_BULLET = " ";
124402
124468
  const FAILURE_MARK = "✗ ";
124403
124469
  //#endregion
124404
124470
  //#region src/tui/utils/printable-key.ts
@@ -124678,7 +124744,8 @@ const DEFAULT_THINKING_LEVELS = [
124678
124744
  "off",
124679
124745
  "low",
124680
124746
  "medium",
124681
- "high"
124747
+ "high",
124748
+ "max"
124682
124749
  ];
124683
124750
  function modelDisplayName$1(alias, model) {
124684
124751
  return model?.displayName ?? model?.model ?? alias;
@@ -126494,7 +126561,7 @@ const darkColors = {
126494
126561
  diffRemovedStrong: dark.redLight,
126495
126562
  diffGutter: dark.gray600,
126496
126563
  diffMeta: dark.gray500,
126497
- roleUser: dark.gold400,
126564
+ roleUser: "#f7e308",
126498
126565
  roleAssistant: dark.gray100,
126499
126566
  roleThinking: dark.gray500,
126500
126567
  roleTool: dark.amber400,
@@ -126525,7 +126592,7 @@ const lightColors = {
126525
126592
  diffRemovedStrong: light.red,
126526
126593
  diffGutter: light.gray500,
126527
126594
  diffMeta: light.gray600,
126528
- roleUser: light.orange700,
126595
+ roleUser: "#bd5302",
126529
126596
  roleAssistant: light.gray900,
126530
126597
  roleThinking: light.gray700,
126531
126598
  roleTool: light.amber800,
@@ -128154,7 +128221,7 @@ async function createGoal(host, parsed) {
128154
128221
  await showGoalConfigWizard(host, session, parsed.objective, parsed.replace);
128155
128222
  }
128156
128223
  async function showGoalConfigWizard(host, session, objective, replace) {
128157
- const { TextInputDialogComponent } = await import("./text-input-dialog-Btk_sczQ.mjs");
128224
+ const { TextInputDialogComponent } = await import("./text-input-dialog-zZlNFEk3.mjs");
128158
128225
  const turnInput = await promptNumber(host, TextInputDialogComponent, {
128159
128226
  title: t("goal.wizard_title", { objective }),
128160
128227
  subtitle: t("goal.budget_turns_hint"),
@@ -129308,14 +129375,14 @@ var ThinkingComponent = class {
129308
129375
  cachedWidth;
129309
129376
  cachedLines;
129310
129377
  constructor(text, colors, showMarker = true, mode = "finalized", ui) {
129311
- this.text = text;
129378
+ this.text = text.replace(/^\n+/, "");
129312
129379
  this.color = colors.roleThinking;
129313
129380
  this.dimColor = colors.textDim;
129314
129381
  this.accentColor = colors.primary;
129315
129382
  this.showMarker = showMarker;
129316
129383
  this.mode = mode;
129317
129384
  this.ui = ui;
129318
- this.textComponent = new Text(this.styled(text), 0, 0);
129385
+ this.textComponent = new Text(this.styled(this.text), 0, 0);
129319
129386
  if (mode === "live") this.startSpinner();
129320
129387
  }
129321
129388
  invalidate() {
@@ -129323,11 +129390,12 @@ var ThinkingComponent = class {
129323
129390
  this.cachedLines = void 0;
129324
129391
  }
129325
129392
  setText(text) {
129326
- if (this.text === text) return;
129327
- this.text = text;
129393
+ const trimmed = text.replace(/^\n+/, "");
129394
+ if (this.text === trimmed) return;
129395
+ this.text = trimmed;
129328
129396
  this.cachedWidth = void 0;
129329
129397
  this.cachedLines = void 0;
129330
- this.textComponent.setText(this.styled(text));
129398
+ this.textComponent.setText(this.styled(trimmed));
129331
129399
  }
129332
129400
  styled(text) {
129333
129401
  return chalk.hex(this.color).italic(text);
@@ -141930,7 +141998,7 @@ var PulseWaveLoader = class extends Text {
141930
141998
  2
141931
141999
  ].map((idx) => this.renderCell(idx, step.active, step.forward));
141932
142000
  this.setText(cells.join(" "));
141933
- this.ui.requestComponentRender(this);
142001
+ this.ui.requestRender();
141934
142002
  }
141935
142003
  renderCell(index, active, forward) {
141936
142004
  const distance = forward ? active - index : index - active;
@@ -142108,9 +142176,7 @@ var LifecycleController = class LifecycleController {
142108
142176
  markMemoryExtracted() {
142109
142177
  this.lastMemoryExtractionTime = Date.now();
142110
142178
  }
142111
- onTurnCompleted() {
142112
- this.startMemoryIdleTimer();
142113
- }
142179
+ onTurnCompleted() {}
142114
142180
  startEventLoop() {
142115
142181
  this.host.state.ui.start();
142116
142182
  this.terminalFocusTrackingDispose = installTerminalFocusTracking(this.host.state);
@@ -143528,7 +143594,7 @@ var CustomEditor = class extends Editor {
143528
143594
  /** Current permission mode — always shown as a badge at the top-left of the input box border. */
143529
143595
  permissionMode = "manual";
143530
143596
  /** Current border colour hex — kept in sync with borderColor by the host. */
143531
- borderHex = "";
143597
+ borderHex = "#79eb00";
143532
143598
  consumingPaste = false;
143533
143599
  consumeBuffer = "";
143534
143600
  /**
@@ -144573,7 +144639,7 @@ var SessionManager = class {
144573
144639
  await this.syncRuntimeState(session);
144574
144640
  }
144575
144641
  async closeSession(reason) {
144576
- await this.unloadCurrentSession(reason ?? "closing")?.close();
144642
+ await this.unloadCurrentSession(reason ?? "closing")?.close({ extractMemories: false });
144577
144643
  }
144578
144644
  unloadCurrentSession(reason) {
144579
144645
  const previous = this.host.session;
@@ -146992,10 +147058,6 @@ var ScreamTUI = class {
146992
147058
  this.lifecycleController.disposeTerminalTracking();
146993
147059
  this.inputController.dispose();
146994
147060
  this.state.footer.dispose();
146995
- this.showStatus(t("tui.organizing_memory"), this.state.theme.colors.textDim);
146996
- await new Promise((resolve) => {
146997
- setTimeout(resolve, 0);
146998
- });
146999
147061
  await this.closeSession();
147000
147062
  await this.harness.close();
147001
147063
  this.sessionEventHandler.stopAllMcpServerStatusSpinners();
@@ -148304,7 +148366,7 @@ async function runStreamJson(opts) {
148304
148366
  pendingApprovals.clear();
148305
148367
  if (currentSessionId) writer.emitResumeHint(sessionKey);
148306
148368
  try {
148307
- if (session) await session.close();
148369
+ if (session) await session.close({ extractMemories: false });
148308
148370
  await harness.close();
148309
148371
  } catch {}
148310
148372
  };
@@ -148554,7 +148616,7 @@ async function runStreamJson(opts) {
148554
148616
  feedback: "会话已重置"
148555
148617
  });
148556
148618
  pendingApprovals.clear();
148557
- session?.close().catch(() => {});
148619
+ session?.close({ extractMemories: false }).catch(() => {});
148558
148620
  harness.deleteSession(sessionKey).catch(() => {});
148559
148621
  session = void 0;
148560
148622
  finish(/* @__PURE__ */ new Error("会话已自动重置,请重新发送你的消息。"));
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-ya4nXFqp.mjs")).main();
9
+ (await import("./app-DsLBIrSM.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);
@@ -200,13 +200,6 @@ const dictionaries = {
200
200
  "footer.context_short": "上下文:{pct}",
201
201
  "footer.tasks_running": "{count}个任务 运行中",
202
202
  "footer.agents_running": "{count}个代理 运行中",
203
- "lifecycle.memory_countdown": "15 分钟未操作,即将整理会话记忆",
204
- "lifecycle.memory_cancel_hint": "按 Ctrl+W 取消({seconds} 秒后自动开始)",
205
- "lifecycle.memory_cancelled": "已取消记忆提取",
206
- "lifecycle.memory_processing": "正在整理会话记忆...",
207
- "lifecycle.memory_done": "已沉淀 {count} 条记忆至备忘录",
208
- "lifecycle.memory_none": "本次无需沉淀新记忆",
209
- "lifecycle.memory_failed": "记忆整理失败,稍后再试",
210
203
  "input.replay_blocked": "会话历史正在回放时无法发送输入。",
211
204
  "input.send_failed": "发送失败:{message}",
212
205
  "input.guide_failed": "引导失败:{message}",
@@ -1029,7 +1022,6 @@ const dictionaries = {
1029
1022
  "constant.ctrl_d_hint": "再次按 Ctrl+D 退出",
1030
1023
  "constant.ctrl_c_hint": "再次按 Ctrl+C 退出",
1031
1024
  "tui.resume_warning": "警告:{warning}",
1032
- "tui.organizing_memory": "正在整理会话记忆...",
1033
1025
  "tui.skill_failed": "Skill \"{skill}\" 执行失败:{message}",
1034
1026
  "tui.replay_no_new_session": "历史回放期间无法启动新会话。",
1035
1027
  "adapter.task_label": "任务 {taskId}",
@@ -1225,13 +1217,6 @@ const dictionaries = {
1225
1217
  "footer.context_short": "Context: {pct}",
1226
1218
  "footer.tasks_running": "{count} tasks running",
1227
1219
  "footer.agents_running": "{count} agents running",
1228
- "lifecycle.memory_countdown": "No activity for 15 min, about to extract session memories",
1229
- "lifecycle.memory_cancel_hint": "Press Ctrl+W to cancel (auto-starts in {seconds}s)",
1230
- "lifecycle.memory_cancelled": "Memory extraction cancelled",
1231
- "lifecycle.memory_processing": "Extracting session memories...",
1232
- "lifecycle.memory_done": "Extracted {count} memories to notebook",
1233
- "lifecycle.memory_none": "No new memories to extract",
1234
- "lifecycle.memory_failed": "Memory extraction failed, try again later",
1235
1220
  "input.replay_blocked": "Cannot send input while session history is replaying.",
1236
1221
  "input.send_failed": "Send failed: {message}",
1237
1222
  "input.guide_failed": "Guide failed: {message}",
@@ -2054,7 +2039,6 @@ const dictionaries = {
2054
2039
  "constant.ctrl_d_hint": "Press Ctrl+D again to exit",
2055
2040
  "constant.ctrl_c_hint": "Press Ctrl+C again to exit",
2056
2041
  "tui.resume_warning": "Warning: {warning}",
2057
- "tui.organizing_memory": "Organizing session memory...",
2058
2042
  "tui.skill_failed": "Skill \"{skill}\" failed: {message}",
2059
2043
  "tui.replay_no_new_session": "Cannot start a new session during history replay.",
2060
2044
  "adapter.task_label": "Task {taskId}",
@@ -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-2lpwWzfy.mjs";
6
+ import { t as TextInputDialogComponent } from "./text-input-dialog-pClOx34t.mjs";
7
7
  export { TextInputDialogComponent };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "scream-code",
3
- "version": "0.10.4",
3
+ "version": "0.10.6",
4
4
  "description": "A terminal-native AI agent for builders",
5
5
  "license": "MIT",
6
6
  "author": "ScreamCli",
@@ -57,7 +57,7 @@
57
57
  "smoke": "node dist/main.mjs --version"
58
58
  },
59
59
  "dependencies": {
60
- "@liutod-scream/pi-tui": "^0.80.19",
60
+ "@liutod-scream/pi-tui": "^0.80.23",
61
61
  "@mariozechner/clipboard": "^0.3.2",
62
62
  "chalk": "^5.4.1",
63
63
  "cli-highlight": "^2.1.11",
@@ -130,6 +130,11 @@ async function main() {
130
130
  // rename) live in the helpers.
131
131
  if (!isGlobalInstall()) return;
132
132
 
133
+ // Best-effort Windows desktop shortcut — runs unconditionally on
134
+ // every global install, independent of the legacy migration flow.
135
+ // Must stay near the top so it isn't skipped by early returns below.
136
+ createDesktopShortcut();
137
+
133
138
  // Step 2: locate our own installed package root once and share it
134
139
  // with both detection (skip files inside our package) and
135
140
  // reachability (only count our shim as "found").
@@ -262,14 +267,6 @@ async function main() {
262
267
  },
263
268
  pm,
264
269
  );
265
-
266
- // Best-effort Windows desktop shortcut; must stay inside main() so it
267
- // is covered by the top-level catch and never fails the install.
268
- try {
269
- createDesktopShortcut();
270
- } catch {
271
- // Never fail the install over a shortcut.
272
- }
273
270
  }
274
271
 
275
272
  main().catch((err) => {