scream-code 0.8.3 → 0.8.4

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.
@@ -5,7 +5,7 @@ const __filename = __cjsShimFileURLToPath(import.meta.url);
5
5
  const __dirname = __cjsShimDirname(__filename);
6
6
  import { a as __toESM, i as __require, r as __exportAll, t as __commonJSMin } from "./chunk-apG1qJts.mjs";
7
7
  import "./suppress-sqlite-warning-C2VB0doZ.mjs";
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-DWWVKqBK.mjs";
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-CptHxtUY.mjs";
9
9
  import { createRequire } from "node:module";
10
10
  import { createHash, randomBytes, randomInt, randomUUID } from "node:crypto";
11
11
  import Jn, { access, appendFile, chmod, copyFile, cp, lstat, mkdir, mkdtemp, open, readFile, readdir, realpath, rename, rm, rmdir, stat, unlink, writeFile } from "node:fs/promises";
@@ -56668,6 +56668,22 @@ function createFastEmbedEngine() {
56668
56668
  }
56669
56669
  const denom = Math.sqrt(normA) * Math.sqrt(normB);
56670
56670
  return denom === 0 ? 0 : dot / denom;
56671
+ },
56672
+ async ensureReady() {
56673
+ if (embedder !== null) return true;
56674
+ try {
56675
+ initPromise ??= loadEmbedder();
56676
+ embedder = await initPromise;
56677
+ if (embedder === null) {
56678
+ initPromise = null;
56679
+ return false;
56680
+ }
56681
+ loadFailed = false;
56682
+ return true;
56683
+ } catch {
56684
+ initPromise = null;
56685
+ return false;
56686
+ }
56671
56687
  }
56672
56688
  };
56673
56689
  }
@@ -58216,7 +58232,7 @@ var KnowledgeLookupTool = class {
58216
58232
  const llm = { generate: async (systemPrompt, userPrompt) => {
58217
58233
  return this.agent.generateText(systemPrompt, userPrompt);
58218
58234
  } };
58219
- const { multiSearchWithTrace } = await import("./src-BChzuWm-.mjs");
58235
+ const { multiSearchWithTrace } = await import("./src-DhT3eU2C.mjs");
58220
58236
  const { results, trace } = await multiSearchWithTrace(store, llm, query, { topK });
58221
58237
  if (results.length === 0) return {
58222
58238
  isError: false,
@@ -122253,7 +122269,7 @@ function optionalBuildString(value) {
122253
122269
  return typeof value === "string" && value.length > 0 ? value : void 0;
122254
122270
  }
122255
122271
  const SCREAM_BUILD_INFO = {
122256
- version: optionalBuildString("0.8.3"),
122272
+ version: optionalBuildString("0.8.4"),
122257
122273
  channel: optionalBuildString(""),
122258
122274
  commit: optionalBuildString(""),
122259
122275
  buildTarget: optionalBuildString("darwin-arm64")
@@ -134014,6 +134030,19 @@ async function handleIngest(host) {
134014
134030
  }
134015
134031
  const store = await getKnowledgeStore();
134016
134032
  const llm = makeLlmCaller(host);
134033
+ const checkSpinner = host.showProgressSpinner("检查向量模型...");
134034
+ if (!(await store.ensureEmbeddingReady()).ok) {
134035
+ checkSpinner.stop({
134036
+ ok: false,
134037
+ label: "向量模型下载失败"
134038
+ });
134039
+ host.showNotice("向量模型下载失败", "知识库需要中文向量模型 bge-small-zh-v1.5(约 95MB)才能进行语义检索。\n\n可能原因:\n• 网络不通,无法下载模型文件\n• onnxruntime native binding 加载失败\n\n请检查网络后重试。");
134040
+ return;
134041
+ }
134042
+ checkSpinner.stop({
134043
+ ok: true,
134044
+ label: "向量模型就绪"
134045
+ });
134017
134046
  const spinner = host.showProgressSpinner("开始摄入...");
134018
134047
  try {
134019
134048
  if (stats.isDirectory()) {
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-Dpd7ZDc_.mjs")).main();
9
+ (await import("./app-DYDC5U75.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);
@@ -243,6 +243,22 @@ var KnowledgeStore = class {
243
243
  return this.embeddingEngine;
244
244
  }
245
245
  /**
246
+ * Proactively load the embedding model (downloads on first call).
247
+ * Call before ingestion so the user gets a clear download prompt instead
248
+ * of a mid-ingest failure.
249
+ */
250
+ async ensureEmbeddingReady() {
251
+ if (this.embeddingEngine === void 0) return {
252
+ ok: false,
253
+ reason: "engine not set"
254
+ };
255
+ const ok = await this.embeddingEngine.ensureReady();
256
+ return {
257
+ ok,
258
+ reason: ok ? void 0 : "fastembed init failed"
259
+ };
260
+ }
261
+ /**
246
262
  * Begin a write transaction. Use commitTransaction / rollbackTransaction
247
263
  * to close it. Used by ingest to keep chunks/events/entities/edges atomic —
248
264
  * a mid-ingest failure leaves no partial rows.
@@ -1441,9 +1457,9 @@ async function ingestFile(store, llm, filePath, onProgress) {
1441
1457
  if (engine === void 0 || !engine.available) {
1442
1458
  onProgress?.({
1443
1459
  stage: "error",
1444
- message: "embedding engine unavailable"
1460
+ message: "向量模型未就绪"
1445
1461
  });
1446
- throw new Error("embedding engine unavailable — knowledge base requires fastembed");
1462
+ throw new Error("向量模型未就绪,请检查网络后重试");
1447
1463
  }
1448
1464
  const existing = await store.findSourceByFilePath(filePath);
1449
1465
  if (existing !== void 0) {
@@ -1451,7 +1467,7 @@ async function ingestFile(store, llm, filePath, onProgress) {
1451
1467
  stage: "error",
1452
1468
  message: `文件已摄入:${existing.name}(source id=${existing.id})`
1453
1469
  });
1454
- throw new Error(`file already ingested: ${filePath} (source ${existing.id})`);
1470
+ throw new Error(`文件已摄入过: ${filePath} (source ${existing.id})`);
1455
1471
  }
1456
1472
  onProgress?.({
1457
1473
  stage: "chunking",
@@ -1464,7 +1480,7 @@ async function ingestFile(store, llm, filePath, onProgress) {
1464
1480
  stage: "error",
1465
1481
  message: "文件无有效内容"
1466
1482
  });
1467
- throw new Error("file has no content to ingest");
1483
+ throw new Error("文件无有效内容可摄入");
1468
1484
  }
1469
1485
  store.beginTransaction();
1470
1486
  try {
@@ -1489,9 +1505,9 @@ async function ingestFile(store, llm, filePath, onProgress) {
1489
1505
  if (chunkEmbeddings === null) {
1490
1506
  onProgress?.({
1491
1507
  stage: "error",
1492
- message: "chunk embedding failed"
1508
+ message: "chunk 向量嵌入失败"
1493
1509
  });
1494
- throw new Error("chunk embedding failed");
1510
+ throw new Error("chunk 向量嵌入失败");
1495
1511
  }
1496
1512
  const chunks = [];
1497
1513
  for (let i = 0; i < sections.length; i++) {
@@ -1540,9 +1556,9 @@ async function ingestFile(store, llm, filePath, onProgress) {
1540
1556
  if (titleEmbeddings === null || contentEmbeddings === null) {
1541
1557
  onProgress?.({
1542
1558
  stage: "error",
1543
- message: "event embedding failed"
1559
+ message: "event 向量嵌入失败"
1544
1560
  });
1545
- throw new Error("event embedding failed");
1561
+ throw new Error("event 向量嵌入失败");
1546
1562
  }
1547
1563
  const events = [];
1548
1564
  for (let i = 0; i < extractedEvents.length; i++) {
@@ -1583,9 +1599,9 @@ async function ingestFile(store, llm, filePath, onProgress) {
1583
1599
  if (uniqueEntities.length > 0 && entityEmbeddings === null) {
1584
1600
  onProgress?.({
1585
1601
  stage: "error",
1586
- message: "entity embedding failed"
1602
+ message: "entity 向量嵌入失败"
1587
1603
  });
1588
- throw new Error("entity embedding failed");
1604
+ throw new Error("entity 向量嵌入失败");
1589
1605
  }
1590
1606
  const entityIdByEntityKey = /* @__PURE__ */ new Map();
1591
1607
  for (let i = 0; i < uniqueEntities.length; i++) {
@@ -1620,9 +1636,9 @@ async function ingestFile(store, llm, filePath, onProgress) {
1620
1636
  if (relationPairs.length > 0 && relationEmbeddings === null) {
1621
1637
  onProgress?.({
1622
1638
  stage: "error",
1623
- message: "relation embedding failed"
1639
+ message: "relation 向量嵌入失败"
1624
1640
  });
1625
- throw new Error("relation embedding failed");
1641
+ throw new Error("relation 向量嵌入失败");
1626
1642
  }
1627
1643
  for (let i = 0; i < relationPairs.length; i++) {
1628
1644
  const pair = relationPairs[i];
@@ -1668,7 +1684,7 @@ async function collectSupportedFiles(dirPath) {
1668
1684
  }
1669
1685
  async function ingestDirectory(store, llm, dirPath, onProgress) {
1670
1686
  const files = await collectSupportedFiles(dirPath);
1671
- if (files.length === 0) throw new Error(`no supported files (.md, .markdown, .txt) found in ${dirPath}`);
1687
+ if (files.length === 0) throw new Error(`目录下没有支持的文件 (.md, .markdown, .txt): ${dirPath}`);
1672
1688
  const errors = [];
1673
1689
  let succeeded = 0;
1674
1690
  let totalChunks = 0;
@@ -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 { n as multiSearchWithTrace } from "./src-DWWVKqBK.mjs";
6
+ import { n as multiSearchWithTrace } from "./src-CptHxtUY.mjs";
7
7
  export { multiSearchWithTrace };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "scream-code",
3
- "version": "0.8.3",
3
+ "version": "0.8.4",
4
4
  "description": "A terminal-native AI agent for builders",
5
5
  "license": "MIT",
6
6
  "author": "ScreamCli",