sweet-search 2.5.5 → 2.5.7

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/scripts/init.js CHANGED
@@ -252,9 +252,26 @@ export function detectProjectRoot(cwd = process.cwd()) {
252
252
  export function ensureDataDir(projectRoot) {
253
253
  const dataDir = join(projectRoot, DATA_DIR_NAME);
254
254
  mkdirSync(dataDir, { recursive: true });
255
+ maybeIgnoreDataDir(projectRoot);
255
256
  return dataDir;
256
257
  }
257
258
 
259
+ // Add `.sweet-search/` to the project's .gitignore so the local index isn't
260
+ // committed — but ONLY if a .gitignore already exists. We never create one for
261
+ // a project that doesn't already use it.
262
+ function maybeIgnoreDataDir(projectRoot) {
263
+ try {
264
+ const gitignorePath = join(projectRoot, '.gitignore');
265
+ if (!existsSync(gitignorePath)) return;
266
+ const content = readFileSync(gitignorePath, 'utf8');
267
+ const already = content.split(/\r?\n/).map((l) => l.trim().replace(/^\//, '').replace(/\/$/, ''))
268
+ .some((l) => l === DATA_DIR_NAME);
269
+ if (already) return;
270
+ const sep = content.length === 0 || content.endsWith('\n') ? '' : '\n';
271
+ writeFileSync(gitignorePath, `${content}${sep}\n# Sweet Search local index\n${DATA_DIR_NAME}/\n`);
272
+ } catch { /* best-effort — never block init on .gitignore */ }
273
+ }
274
+
258
275
  // ---------------------------------------------------------------------------
259
276
  // Init config read/write
260
277
  // ---------------------------------------------------------------------------
@@ -1450,6 +1467,12 @@ export async function runInit(args) {
1450
1467
  return;
1451
1468
  }
1452
1469
 
1470
+ // 0. Animated banner (best-effort; only on an interactive TTY, never in CI/pipes).
1471
+ if (process.stdout.isTTY && !process.env.CI && !process.env.NO_BANNER && !process.env.SWEET_SEARCH_NO_BANNER) {
1472
+ // query:false — init is interactive (readline); avoid any stdin contention with the terminal capability probe.
1473
+ try { const { showBanner } = await import('../core/banner/render-banner.js'); await showBanner({ query: false }); } catch { /* non-fatal */ }
1474
+ }
1475
+
1453
1476
  // 1. Node.js version check
1454
1477
  checkNodeVersion();
1455
1478
 
@@ -1570,11 +1593,10 @@ export async function runInit(args) {
1570
1593
  const skippedOptIns = getSkippedOptInModels(profile);
1571
1594
  let modelResults = new Map();
1572
1595
 
1573
- // Tell the user once which optional models are being skipped. This is
1574
- // NOT an errorthese are opt-in features (e.g. cross-encoder
1575
- // rerankers disabled by default since commit 43a61eb). Without this
1576
- // line, init silently omitting them looks like a missing-model bug.
1577
- if (skippedOptIns.length > 0) {
1596
+ // Opt-in models (e.g. cross-encoder rerankers, disabled by default since
1597
+ // commit 43a61eb) are skipped silently they're optional features, not
1598
+ // missing models. Set DEBUG=1 to see which were skipped and how to enable.
1599
+ if (process.env.DEBUG && skippedOptIns.length > 0) {
1578
1600
  for (const skipped of skippedOptIns) {
1579
1601
  process.stderr.write(
1580
1602
  `[init] Skipping opt-in model "${skipped.key}" — ` +
@@ -2016,7 +2038,7 @@ function runCoremlCascadeBuild(options = {}) {
2016
2038
  ` The CoreML cascade build path currently requires a local clone\n` +
2017
2039
  ` of the sweet-search repository — it is not yet shipped via npm.\n` +
2018
2040
  ` To build the cascade:\n` +
2019
- ` git clone https://github.com/panonitorg/sweet-search\n` +
2041
+ ` git clone https://github.com/mrsladoje/sweet-search\n` +
2020
2042
  ` cd sweet-search\n` +
2021
2043
  ` node scripts/build-coreml-cascade.js\n` +
2022
2044
  ` Then point your install at the managed cache (init detects it).`,
@@ -0,0 +1,34 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * postinstall — print a short "what next" message after install.
4
+ *
5
+ * Deliberately plain text: during `npm install` npm writes its own progress
6
+ * spinner to the terminal CONCURRENTLY with this script, which would interrupt
7
+ * any graphics/animation escape sequence mid-stream and leak its payload as
8
+ * garbage text. So the rich animated banner is reserved for `sweet-search init`
9
+ * and `sweet-search index` (where we own the TTY); install just prints a clean,
10
+ * escape-light pointer. Best-effort; always exits 0 so it can't fail an install.
11
+ */
12
+ import process from 'node:process';
13
+
14
+ function run() {
15
+ const env = process.env;
16
+ if (env.NO_BANNER || env.SWEET_SEARCH_NO_BANNER) return;
17
+ try {
18
+ const c = (n, s) => (process.stdout.isTTY ? `\x1b[${n}m${s}\x1b[0m` : s);
19
+ const lines = [
20
+ '',
21
+ ` ${c('1;38;5;213', 'sweet-search')} installed ${c('2', '— SOTA hybrid code search')}`,
22
+ '',
23
+ ` ${c('1', 'Get started:')}`,
24
+ ` ${c('36', 'sweet-search init')} set up the current project`,
25
+ ` ${c('36', 'sweet-search index')} build the search index`,
26
+ ` ${c('36', 'sweet-search "query"')} search your code`,
27
+ ` ${c('2', '(installed locally? prefix with')} ${c('2;36', 'npx')}${c('2', ', e.g. `npx sweet-search init`)')}`,
28
+ '',
29
+ ];
30
+ process.stdout.write(lines.join('\n') + '\n');
31
+ } catch { /* never break an install */ }
32
+ }
33
+
34
+ run();