@zenalexa/unicli 0.210.0 → 0.211.2

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.
Files changed (81) hide show
  1. package/AGENTS.md +21 -7
  2. package/README.md +680 -83
  3. package/dist/cli.d.ts.map +1 -1
  4. package/dist/cli.js +5 -0
  5. package/dist/cli.js.map +1 -1
  6. package/dist/commands/agents.d.ts +14 -3
  7. package/dist/commands/agents.d.ts.map +1 -1
  8. package/dist/commands/agents.js +369 -140
  9. package/dist/commands/agents.js.map +1 -1
  10. package/dist/commands/mcp.d.ts +3 -4
  11. package/dist/commands/mcp.d.ts.map +1 -1
  12. package/dist/commands/mcp.js +47 -62
  13. package/dist/commands/mcp.js.map +1 -1
  14. package/dist/commands/schema.d.ts +12 -0
  15. package/dist/commands/schema.d.ts.map +1 -0
  16. package/dist/commands/schema.js +72 -0
  17. package/dist/commands/schema.js.map +1 -0
  18. package/dist/commands/search.d.ts +12 -0
  19. package/dist/commands/search.d.ts.map +1 -0
  20. package/dist/commands/search.js +47 -0
  21. package/dist/commands/search.js.map +1 -0
  22. package/dist/discovery/aliases.d.ts +31 -0
  23. package/dist/discovery/aliases.d.ts.map +1 -0
  24. package/dist/discovery/aliases.js +477 -0
  25. package/dist/discovery/aliases.js.map +1 -0
  26. package/dist/discovery/loader.d.ts.map +1 -1
  27. package/dist/discovery/loader.js +25 -0
  28. package/dist/discovery/loader.js.map +1 -1
  29. package/dist/discovery/search.d.ts +73 -0
  30. package/dist/discovery/search.d.ts.map +1 -0
  31. package/dist/discovery/search.js +355 -0
  32. package/dist/discovery/search.js.map +1 -0
  33. package/dist/manifest-compact.txt +15 -0
  34. package/dist/manifest-search.json +1 -0
  35. package/dist/manifest.json +433 -244
  36. package/dist/mcp/oauth.d.ts +33 -0
  37. package/dist/mcp/oauth.d.ts.map +1 -0
  38. package/dist/mcp/oauth.js +220 -0
  39. package/dist/mcp/oauth.js.map +1 -0
  40. package/dist/mcp/schema.d.ts +65 -0
  41. package/dist/mcp/schema.d.ts.map +1 -0
  42. package/dist/mcp/schema.js +136 -0
  43. package/dist/mcp/schema.js.map +1 -0
  44. package/dist/mcp/server.d.ts +23 -10
  45. package/dist/mcp/server.d.ts.map +1 -1
  46. package/dist/mcp/server.js +350 -182
  47. package/dist/mcp/server.js.map +1 -1
  48. package/dist/mcp/sse-transport.d.ts +34 -0
  49. package/dist/mcp/sse-transport.d.ts.map +1 -0
  50. package/dist/mcp/sse-transport.js +182 -0
  51. package/dist/mcp/sse-transport.js.map +1 -0
  52. package/dist/mcp/streamable-http.d.ts +64 -0
  53. package/dist/mcp/streamable-http.d.ts.map +1 -0
  54. package/dist/mcp/streamable-http.js +312 -0
  55. package/dist/mcp/streamable-http.js.map +1 -0
  56. package/dist/permissions/sensitive-paths.js +2 -2
  57. package/dist/permissions/sensitive-paths.js.map +1 -1
  58. package/package.json +7 -7
  59. package/src/adapters/1688/_site.json +9 -0
  60. package/src/adapters/barchart/_site.json +10 -0
  61. package/src/adapters/jd/_site.json +9 -0
  62. package/src/adapters/linkedin/_site.json +10 -0
  63. package/src/adapters/macos/finder-copy.yaml +40 -0
  64. package/src/adapters/macos/finder-move.yaml +40 -0
  65. package/src/adapters/macos/finder-new-folder.yaml +36 -0
  66. package/src/adapters/macos/safari-history.yaml +23 -0
  67. package/src/adapters/macos/safari-url.yaml +22 -0
  68. package/src/adapters/macos/screen-recording.yaml +32 -0
  69. package/src/adapters/macos/wallpaper.yaml +33 -0
  70. package/src/adapters/reuters/_site.json +9 -0
  71. package/src/adapters/sinablog/_site.json +9 -0
  72. package/src/adapters/smzdm/_site.json +9 -0
  73. package/src/adapters/weixin/_site.json +9 -0
  74. package/src/adapters/1688/manifest.yaml +0 -7
  75. package/src/adapters/barchart/manifest.yaml +0 -8
  76. package/src/adapters/jd/manifest.yaml +0 -7
  77. package/src/adapters/linkedin/manifest.yaml +0 -8
  78. package/src/adapters/reuters/manifest.yaml +0 -7
  79. package/src/adapters/sinablog/manifest.yaml +0 -7
  80. package/src/adapters/smzdm/manifest.yaml +0 -7
  81. package/src/adapters/weixin/manifest.yaml +0 -7
@@ -0,0 +1,73 @@
1
+ /**
2
+ * BM25-based bilingual search engine for command discovery.
3
+ *
4
+ * Replaces the naive `String.includes()` filter with a proper information
5
+ * retrieval algorithm. Designed for ~1000 commands across ~200 sites.
6
+ *
7
+ * Architecture:
8
+ * 1. Build-time: `scripts/build-manifest.js` generates the inverted index
9
+ * and IDF values, shipped as `dist/manifest-search.json`.
10
+ * 2. Runtime: this module loads the index lazily on first search call,
11
+ * then scores queries using BM25 with bilingual keyword expansion.
12
+ *
13
+ * Performance: <10ms for 1000 documents on a cold index load. The inverted
14
+ * index is ~50KB — small enough to hold in memory permanently.
15
+ */
16
+ export interface SearchResult {
17
+ site: string;
18
+ command: string;
19
+ description: string;
20
+ score: number;
21
+ usage: string;
22
+ category: string;
23
+ }
24
+ /** Serialized search index (generated at build time, loaded at runtime). */
25
+ export interface SearchIndex {
26
+ /** Mapping: term → list of document indices that contain this term */
27
+ postings: Record<string, number[]>;
28
+ /** IDF (Inverse Document Frequency) for each term */
29
+ idf: Record<string, number>;
30
+ /** All documents with their metadata */
31
+ documents: Array<{
32
+ id: string;
33
+ site: string;
34
+ command: string;
35
+ description: string;
36
+ terms: string[];
37
+ }>;
38
+ /** Average document length (term count) across the corpus */
39
+ avgDl: number;
40
+ /** Total document count */
41
+ N: number;
42
+ }
43
+ /**
44
+ * Build a search index from a manifest object.
45
+ * Exported for use by the build script.
46
+ */
47
+ export declare function buildIndex(manifest: {
48
+ sites: Record<string, {
49
+ commands: Array<{
50
+ name: string;
51
+ description: string;
52
+ }>;
53
+ }>;
54
+ }): SearchIndex;
55
+ /**
56
+ * Search all commands by natural language query.
57
+ *
58
+ * Algorithm:
59
+ * 1. Tokenize query (bilingual-aware)
60
+ * 2. Expand tokens via alias table
61
+ * 3. Compute BM25 base score for each candidate document
62
+ * 4. Apply boost signals (site match, command match, category match)
63
+ * 5. Return top-K results with usage examples
64
+ *
65
+ * @param query - Natural language query (Chinese or English)
66
+ * @param limit - Maximum results to return (default 5)
67
+ */
68
+ export declare function search(query: string, limit?: number): SearchResult[];
69
+ /**
70
+ * Force-reload the search index (useful after index rebuild).
71
+ */
72
+ export declare function invalidateCache(): void;
73
+ //# sourceMappingURL=search.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../src/discovery/search.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAeH,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CAClB;AAcD,4EAA4E;AAC5E,MAAM,WAAW,WAAW;IAC1B,sEAAsE;IACtE,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IACnC,qDAAqD;IACrD,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5B,wCAAwC;IACxC,SAAS,EAAE,KAAK,CAAC;QACf,EAAE,EAAE,MAAM,CAAC;QACX,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;QAChB,WAAW,EAAE,MAAM,CAAC;QACpB,KAAK,EAAE,MAAM,EAAE,CAAC;KACjB,CAAC,CAAC;IACH,6DAA6D;IAC7D,KAAK,EAAE,MAAM,CAAC;IACd,2BAA2B;IAC3B,CAAC,EAAE,MAAM,CAAC;CACX;AAkFD;;;GAGG;AACH,wBAAgB,UAAU,CAAC,QAAQ,EAAE;IACnC,KAAK,EAAE,MAAM,CACX,MAAM,EACN;QAAE,QAAQ,EAAE,KAAK,CAAC;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,WAAW,EAAE,MAAM,CAAA;SAAE,CAAC,CAAA;KAAE,CAC3D,CAAC;CACH,GAAG,WAAW,CAsDd;AAoID;;;;;;;;;;;;GAYG;AACH,wBAAgB,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,SAAI,GAAG,YAAY,EAAE,CA0G/D;AASD;;GAEG;AACH,wBAAgB,eAAe,IAAI,IAAI,CAEtC"}
@@ -0,0 +1,355 @@
1
+ /**
2
+ * BM25-based bilingual search engine for command discovery.
3
+ *
4
+ * Replaces the naive `String.includes()` filter with a proper information
5
+ * retrieval algorithm. Designed for ~1000 commands across ~200 sites.
6
+ *
7
+ * Architecture:
8
+ * 1. Build-time: `scripts/build-manifest.js` generates the inverted index
9
+ * and IDF values, shipped as `dist/manifest-search.json`.
10
+ * 2. Runtime: this module loads the index lazily on first search call,
11
+ * then scores queries using BM25 with bilingual keyword expansion.
12
+ *
13
+ * Performance: <10ms for 1000 documents on a cold index load. The inverted
14
+ * index is ~50KB — small enough to hold in memory permanently.
15
+ */
16
+ import { readFileSync, existsSync } from "node:fs";
17
+ import { join, dirname } from "node:path";
18
+ import { fileURLToPath } from "node:url";
19
+ import { expandToken, tokenizeQuery, SITE_ALIASES, SITE_CATEGORIES, CATEGORY_ALIASES, } from "./aliases.js";
20
+ // ── BM25 Parameters ─────────────────────────────────────────────────────────
21
+ // Standard BM25 tuning. k1 controls term frequency saturation,
22
+ // b controls document length normalization.
23
+ const K1 = 1.2;
24
+ const B = 0.75;
25
+ // ── Hybrid Scoring ──────────────────────────────────────────────────────────
26
+ // StackOne benchmark (Feb 2026, 2700 test cases, 270 tools) found:
27
+ // Pure BM25 Top-1: 14%
28
+ // BM25+TF-IDF 20/80 blend Top-1: 21%
29
+ // Embedding Top-1: 38%
30
+ // We use the 20/80 blend as the base, with domain-specific boosts on top.
31
+ const ALPHA_BM25 = 0.2;
32
+ const ALPHA_TFIDF = 0.8;
33
+ // ── Score Boost Weights ─────────────────────────────────────────────────────
34
+ // Applied on top of the hybrid BM25+TF-IDF base score.
35
+ const BOOST_SITE_EXACT = 15.0; // Query token exactly matches site name
36
+ const BOOST_SITE_ALIAS = 12.0; // Query token's alias matches site name
37
+ const BOOST_CMD_EXACT = 8.0; // Query token exactly matches command name
38
+ const BOOST_CMD_PARTIAL = 3.0; // Query token is substring of command name
39
+ const BOOST_CATEGORY = 2.0; // Query token matches site's category
40
+ // ── Index Management ────────────────────────────────────────────────────────
41
+ let cachedIndex = null;
42
+ /**
43
+ * Resolve the path to the pre-built search index.
44
+ * Falls back to building one on-the-fly from the manifest if the
45
+ * pre-built index doesn't exist.
46
+ */
47
+ function getIndexPath() {
48
+ const __dirname = dirname(fileURLToPath(import.meta.url));
49
+ return join(__dirname, "..", "..", "dist", "manifest-search.json");
50
+ }
51
+ /**
52
+ * Load or build the search index. Called lazily on first search.
53
+ */
54
+ function loadIndex() {
55
+ if (cachedIndex)
56
+ return cachedIndex;
57
+ const indexPath = getIndexPath();
58
+ if (existsSync(indexPath)) {
59
+ cachedIndex = JSON.parse(readFileSync(indexPath, "utf-8"));
60
+ return cachedIndex;
61
+ }
62
+ // Fallback: build index on-the-fly from manifest.json
63
+ cachedIndex = buildIndexFromManifest();
64
+ return cachedIndex;
65
+ }
66
+ /**
67
+ * Build a search index from the manifest.json file.
68
+ * Used when the pre-built search index doesn't exist (dev mode).
69
+ */
70
+ function buildIndexFromManifest() {
71
+ const __dirname = dirname(fileURLToPath(import.meta.url));
72
+ const manifestPath = join(__dirname, "..", "..", "dist", "manifest.json");
73
+ if (!existsSync(manifestPath)) {
74
+ // No manifest either — return empty index
75
+ return { postings: {}, idf: {}, documents: [], avgDl: 0, N: 0 };
76
+ }
77
+ const manifest = JSON.parse(readFileSync(manifestPath, "utf-8"));
78
+ return buildIndex(manifest);
79
+ }
80
+ /**
81
+ * Build a search index from a manifest object.
82
+ * Exported for use by the build script.
83
+ */
84
+ export function buildIndex(manifest) {
85
+ const documents = [];
86
+ for (const [site, info] of Object.entries(manifest.sites)) {
87
+ for (const cmd of info.commands) {
88
+ const terms = tokenizeDocument(site, cmd.name, cmd.description ?? "");
89
+ documents.push({
90
+ id: `${site}/${cmd.name}`,
91
+ site,
92
+ command: cmd.name,
93
+ description: cmd.description ?? "",
94
+ terms,
95
+ termCount: terms.length,
96
+ });
97
+ }
98
+ }
99
+ const N = documents.length;
100
+ const avgDl = N > 0 ? documents.reduce((sum, d) => sum + d.termCount, 0) / N : 0;
101
+ // Build inverted index
102
+ const postings = {};
103
+ for (let i = 0; i < documents.length; i++) {
104
+ const seen = new Set();
105
+ for (const term of documents[i].terms) {
106
+ if (seen.has(term))
107
+ continue;
108
+ seen.add(term);
109
+ if (!postings[term])
110
+ postings[term] = [];
111
+ postings[term].push(i);
112
+ }
113
+ }
114
+ // Compute IDF for each term
115
+ const idf = {};
116
+ for (const [term, docs] of Object.entries(postings)) {
117
+ // BM25 IDF: log((N - df + 0.5) / (df + 0.5) + 1)
118
+ const df = docs.length;
119
+ idf[term] = Math.log((N - df + 0.5) / (df + 0.5) + 1);
120
+ }
121
+ return {
122
+ postings,
123
+ idf,
124
+ documents: documents.map((d) => ({
125
+ id: d.id,
126
+ site: d.site,
127
+ command: d.command,
128
+ description: d.description,
129
+ terms: d.terms,
130
+ })),
131
+ avgDl,
132
+ N,
133
+ };
134
+ }
135
+ /**
136
+ * Tokenize a document (site + command + description) into search terms.
137
+ * Produces lowercase terms, splits on hyphens and underscores.
138
+ */
139
+ function tokenizeDocument(site, command, description) {
140
+ const terms = [];
141
+ // Site name and its parts
142
+ const siteParts = site.toLowerCase().split(/[-_]/);
143
+ terms.push(site.toLowerCase(), ...siteParts);
144
+ // Command name and its parts
145
+ const cmdParts = command.toLowerCase().split(/[-_]/);
146
+ terms.push(command.toLowerCase(), ...cmdParts);
147
+ // Description words (lowercase, filter short words)
148
+ const descWords = description
149
+ .toLowerCase()
150
+ .replace(/[^a-z0-9\u4e00-\u9fff\s]/g, " ")
151
+ .split(/\s+/)
152
+ .filter((w) => w.length > 1);
153
+ terms.push(...descWords);
154
+ // Category as a term
155
+ const category = SITE_CATEGORIES.get(site);
156
+ if (category)
157
+ terms.push(category);
158
+ return terms;
159
+ }
160
+ // ── BM25 Scoring ────────────────────────────────────────────────────────────
161
+ /**
162
+ * Compute BM25 score for a single document given query terms.
163
+ */
164
+ function bm25Score(docTerms, docLength, queryTerms, index) {
165
+ let score = 0;
166
+ // Count term frequencies in this document
167
+ const tf = new Map();
168
+ for (const term of docTerms) {
169
+ tf.set(term, (tf.get(term) ?? 0) + 1);
170
+ }
171
+ for (const qt of queryTerms) {
172
+ const termIdf = index.idf[qt];
173
+ if (termIdf === undefined)
174
+ continue; // term not in corpus
175
+ const termTf = tf.get(qt) ?? 0;
176
+ if (termTf === 0)
177
+ continue;
178
+ // BM25 TF component: (tf * (k1 + 1)) / (tf + k1 * (1 - b + b * dl/avgdl))
179
+ const numerator = termTf * (K1 + 1);
180
+ const denominator = termTf + K1 * (1 - B + B * (docLength / index.avgDl));
181
+ score += termIdf * (numerator / denominator);
182
+ }
183
+ return score;
184
+ }
185
+ // ── TF-IDF Cosine Similarity ────────────────────────────────────────────────
186
+ /**
187
+ * Compute TF-IDF cosine similarity between a query and a document.
188
+ *
189
+ * TF-IDF for a term t in document d:
190
+ * tf(t,d) = count(t in d) / |d|
191
+ * tfidf(t,d) = tf(t,d) * idf(t)
192
+ *
193
+ * Cosine similarity = dot(query_vec, doc_vec) / (|query_vec| * |doc_vec|)
194
+ */
195
+ function tfidfCosine(docTerms, queryTerms, index) {
196
+ const docLen = docTerms.length;
197
+ if (docLen === 0)
198
+ return 0;
199
+ // Build full doc TF map
200
+ const docTf = new Map();
201
+ for (const term of docTerms) {
202
+ docTf.set(term, (docTf.get(term) ?? 0) + 1);
203
+ }
204
+ // Compute full document norm (all terms, not just query overlap)
205
+ let docNormSq = 0;
206
+ for (const [term, count] of docTf) {
207
+ const idfVal = index.idf[term];
208
+ if (idfVal === undefined)
209
+ continue;
210
+ const w = (count / docLen) * idfVal;
211
+ docNormSq += w * w;
212
+ }
213
+ // Compute query norm and dot product
214
+ let dotProduct = 0;
215
+ let queryNormSq = 0;
216
+ for (const qt of queryTerms) {
217
+ const idfVal = index.idf[qt];
218
+ if (idfVal === undefined)
219
+ continue;
220
+ // Query TF-IDF: binary tf (1) × idf
221
+ const queryWeight = idfVal;
222
+ queryNormSq += queryWeight * queryWeight;
223
+ // Doc TF-IDF: normalized tf × idf
224
+ const rawTf = docTf.get(qt) ?? 0;
225
+ if (rawTf === 0)
226
+ continue;
227
+ const docWeight = (rawTf / docLen) * idfVal;
228
+ dotProduct += queryWeight * docWeight;
229
+ }
230
+ const normProduct = Math.sqrt(queryNormSq) * Math.sqrt(docNormSq);
231
+ if (normProduct === 0)
232
+ return 0;
233
+ return dotProduct / normProduct;
234
+ }
235
+ // ── Main Search Function ────────────────────────────────────────────────────
236
+ /**
237
+ * Search all commands by natural language query.
238
+ *
239
+ * Algorithm:
240
+ * 1. Tokenize query (bilingual-aware)
241
+ * 2. Expand tokens via alias table
242
+ * 3. Compute BM25 base score for each candidate document
243
+ * 4. Apply boost signals (site match, command match, category match)
244
+ * 5. Return top-K results with usage examples
245
+ *
246
+ * @param query - Natural language query (Chinese or English)
247
+ * @param limit - Maximum results to return (default 5)
248
+ */
249
+ export function search(query, limit = 5) {
250
+ const index = loadIndex();
251
+ if (index.N === 0)
252
+ return [];
253
+ // Step 1: Tokenize
254
+ const rawTokens = tokenizeQuery(query);
255
+ // Step 2: Expand via aliases
256
+ const expandedTerms = [];
257
+ const siteHints = []; // Directly matched site names
258
+ const categoryHints = []; // Matched categories
259
+ for (const token of rawTokens) {
260
+ const expanded = expandToken(token);
261
+ expandedTerms.push(...expanded);
262
+ // Check if this token resolves to a site name
263
+ const siteMatch = SITE_ALIASES.get(token) ?? SITE_ALIASES.get(token.toLowerCase());
264
+ if (siteMatch)
265
+ siteHints.push(siteMatch);
266
+ // Check if this token is directly a known site
267
+ if (index.documents.some((d) => d.site === token.toLowerCase())) {
268
+ siteHints.push(token.toLowerCase());
269
+ }
270
+ // Check category alias
271
+ const catMatch = CATEGORY_ALIASES.get(token) ?? CATEGORY_ALIASES.get(token.toLowerCase());
272
+ if (catMatch)
273
+ categoryHints.push(catMatch);
274
+ }
275
+ const queryTerms = [...new Set(expandedTerms.map((t) => t.toLowerCase()))];
276
+ // Step 3: Find candidate documents (union of posting lists)
277
+ const candidateSet = new Set();
278
+ for (const qt of queryTerms) {
279
+ const postings = index.postings[qt];
280
+ if (postings) {
281
+ for (const docIdx of postings) {
282
+ candidateSet.add(docIdx);
283
+ }
284
+ }
285
+ }
286
+ // If site hints exist, also add ALL commands for those sites
287
+ if (siteHints.length > 0) {
288
+ for (let i = 0; i < index.documents.length; i++) {
289
+ if (siteHints.includes(index.documents[i].site)) {
290
+ candidateSet.add(i);
291
+ }
292
+ }
293
+ }
294
+ if (candidateSet.size === 0)
295
+ return [];
296
+ // Step 4: Score candidates using hybrid BM25 + TF-IDF
297
+ const scored = [];
298
+ for (const idx of candidateSet) {
299
+ const doc = index.documents[idx];
300
+ // Hybrid base: alpha-blend BM25 and TF-IDF cosine similarity.
301
+ // BM25 scores are unbounded; cosine is [0,1]. We scale cosine by the
302
+ // average BM25 score across candidates to keep the blend balanced.
303
+ const bm25 = bm25Score(doc.terms, doc.terms.length, queryTerms, index);
304
+ const tfidf = tfidfCosine(doc.terms, queryTerms, index);
305
+ let score = ALPHA_BM25 * bm25 + ALPHA_TFIDF * tfidf * 10;
306
+ // Boost: exact site name match
307
+ if (siteHints.includes(doc.site)) {
308
+ score += BOOST_SITE_EXACT;
309
+ }
310
+ // Boost: alias-resolved site match
311
+ for (const qt of queryTerms) {
312
+ if (qt === doc.site)
313
+ score += BOOST_SITE_ALIAS;
314
+ if (qt === doc.command)
315
+ score += BOOST_CMD_EXACT;
316
+ if (doc.command.includes(qt) && qt.length > 2)
317
+ score += BOOST_CMD_PARTIAL;
318
+ }
319
+ // Boost: category match
320
+ const docCategory = SITE_CATEGORIES.get(doc.site);
321
+ if (docCategory && categoryHints.includes(docCategory)) {
322
+ score += BOOST_CATEGORY;
323
+ }
324
+ if (score > 0)
325
+ scored.push({ idx, score });
326
+ }
327
+ // Step 5: Sort and return top-K
328
+ scored.sort((a, b) => b.score - a.score);
329
+ const topK = scored.slice(0, limit);
330
+ return topK.map(({ idx, score }) => {
331
+ const doc = index.documents[idx];
332
+ const category = SITE_CATEGORIES.get(doc.site) ?? "other";
333
+ return {
334
+ site: doc.site,
335
+ command: doc.command,
336
+ description: doc.description,
337
+ score: Math.round(score * 100) / 100,
338
+ usage: buildUsageExample(doc.site, doc.command),
339
+ category,
340
+ };
341
+ });
342
+ }
343
+ /**
344
+ * Build a usage example string for a command.
345
+ */
346
+ function buildUsageExample(site, command) {
347
+ return `unicli ${site} ${command}`;
348
+ }
349
+ /**
350
+ * Force-reload the search index (useful after index rebuild).
351
+ */
352
+ export function invalidateCache() {
353
+ cachedIndex = null;
354
+ }
355
+ //# sourceMappingURL=search.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search.js","sourceRoot":"","sources":["../../src/discovery/search.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ shopping: 1688(item, search, store), amazon(bestsellers, discussion, movers-shakers, new-releases, offer, product, rankings, search), coupang(add-to-cart, hot, search), dangdang(hot, search), dianping(hot, search), ele(hot, search), jd(hot, item, search), maoyan(hot, search), meituan(hot, search), pinduoduo(hot, search), smzdm(article, hot, search), taobao(hot, search), xianyu(chat, item, search)
2
+ news: 36kr(article, hot, latest, news, search), bbc(news, technology, top, world), bloomberg(businessweek, economics, feeds, industries, main, markets, news, opinions, politics, tech), cnn(technology, top), hackernews(ask, best, comments, item, jobs, new, search, show, top, user), infoq(articles, latest), ithome(hot, latest, news), nytimes(search, top), reuters(article, latest, search, top), techcrunch(latest, search), theverge(latest, search)
3
+ other: adguardhome(add-rule, rules, stats, status, toggle), audacity(convert, effects, info, mix, normalize, spectrogram, split-channels, trim), autoagent(eval-run), aws(s3-ls), az(account), baidu(hot, search), chrome(bookmarks, tabs), claude-code(version), cloudcompare(compare, convert, info, subsample), codex(extract-diff), codex-cli(version), ctrip(hot, search), cua(bench-list, bench-run), cursor(composer), dingtalk(version), discord-app(servers), doctl(droplets), feishu(calendar, docs, send, tasks), flyctl(apps), gcloud(projects), gh(issue, pr, release, repo, run), godot(project-run, scene-export), hermes(sessions-search, skills-list, skills-read), itch-io(popular, search, top), jianyu(search), jimeng(generate, history), jq(format, query), kdenlive(effects, info, render), ke(ershoufang, xiaoqu), krita(batch, convert, export, info), lark(version), lesswrong(comments, curated, frontpage, new, read, sequences, shortform, tag, tags, top, top-month, top-week, top-year, user, user-posts), maimai(search), motion-studio(component-get), mubu(list, search), neonctl(projects), netlify(sites), notion(databases, pages, search), notion-app(search), obs(record-start, record-stop, scenes, screenshot, sources, status, stream-start, stream-stop), obsidian(daily, open, search), ones(enrich-tasks, login, logout, me, my-tasks, resolve-labels, task, task-helpers, tasks, token-info, worklog), opencode(version), openharness(memory-read, skills-list), pexels(curated, search), pscale(databases), quark(ls, search), railway(deploy), renderdoc(capture-list, frame-export), shotcut(effects, info, render), sinablog(article, hot, search, user), sketch(artboards, export, symbols), slack(channels, messages, post, search, send, status, users), slay-the-spire-ii(deck, end-turn, map, play-card, status, use-potion), slock(servers), stagehand(wrap-observe), supabase(projects), threads(hot, search), toutiao(hot, search), unsplash(random, search), vercel(list), vscode(extensions, install-ext, open), wechat-channels(hot, search), weixin(article, download, hot, search), wiremock(create-stub, delete-stub, reset, stubs, verify), wrangler(list), xiaoe(catalog, content, courses, detail, play-url), ycombinator(launches), yollomi(background, edit, face-swap, generate, models, object-remover, remove-bg, restore, try-on, upload, upscale, video), yt-dlp(download, extract-audio, info, search), yuanbao(ask, new, shared), zoom(join, start), zotero(add-note, add-tag, collections, export, items, notes, search, tags)
4
+ audio: apple-podcasts(episodes, search, top), netease-music(hot, playlist, search, top), spotify(now-playing, playlists, search, top-tracks), xiaoyuzhou(episode, podcast, podcast-episodes)
5
+ reference: arxiv(paper, search, trending), chaoxing(assignments, exams), cnki(search), dictionary(examples, search, synonyms), google(news, search, suggest, trends), imdb(box-office, person, reviews, search, title, top, trending), paperreview(feedback, review, submit), wikipedia(random, search, summary, today, trending)
6
+ social: band(bands, mentions, post, posts), bluesky(feeds, followers, following, likes, notifications, post, profile, search, starter-packs, thread, trending, user), douban(book-hot, download, group-hot, marks, movie-hot, new-movies, photos, reviews, search, subject, top250, tv-hot), facebook(add-friend, events, feed, friends, groups, join-group, marketplace, memories, notifications, post, profile, search), hupu(detail, hot, like, mentions, reply, search, unlike), instagram(activity, comment, download, explore, follow, followers, following, highlights, like, note, post, profile, reel, reels, reels-trending, save, saved, search, stories, story, suggested, tags, unfollow, unlike, unsave, user), jike(comment, create, feed, like, notifications, post, repost, search, topic, user), linux-do(categories, category, feed, hot, latest, search, tags, topic, user-posts, user-topics), lobsters(active, hot, newest, search, tag), mastodon(search, timeline, trending, user), reddit(comment, comments, frontpage, hot, new, popular, read, rising, save, saved, search, subreddit, subscribe, top, trending, upvote, upvoted, user, user-comments, user-posts), tieba(hot, posts, read, search), twitter(accept, article, block, bookmark, bookmarks, delete, download, follow, followers, following, hide-reply, like, likes, lists, media, mentions, mute, notifications, pin, post, profile, quotes, reply, reply-dm, retweets, search, spaces, thread, timeline, trending, unblock, unbookmark, unfollow, unmute), v2ex(daily, hot, latest, me, member, node, nodes, notifications, replies, search, topic, user), weibo(comments, feed, hot, me, post, profile, search, timeline, trending, user), xiaohongshu(comments, creator-note-detail, creator-notes, creator-notes-summary, creator-profile, creator-stats, download, feed, follow, hashtag, hot, like, note, notifications, profile, publish, save, search, suggest, trending, unfollow, user), zhihu(answer, answers, article, articles, collections, columns, comment, download, feed, followers, following, hot, me, notifications, pins, question, search, topic, topics, trending, user)
7
+ finance: barchart(flow, greeks, options, quote), binance(hot, kline, ticker), coinbase(prices, rates), eastmoney(fund, hot, market, search), futu(hot, quote), sinafinance(market, news, rolling-news, stock, stock-rank), xueqiu(comments, earnings-date, feed, fund-holdings, fund-snapshot, hot, hot-stock, market, quote, search, stock, watchlist), yahoo-finance(quote, search, trending)
8
+ video: bilibili(coin, comments, download, dynamic, favorites, feed, following, history, hot, later, live, me, ranking, search, subtitle, trending, user-videos), douyin(activities, collections, delete, draft, drafts, hashtag, location, profile, publish, stats, update, user-videos, videos), douyu(hot, search), kuaishou(hot, search), tiktok(comment, explore, follow, following, friends, like, live, notifications, profile, save, search, trending, unfollow, unlike, unsave, user), twitch(games, search, streams, top), youtube(channel, comments, playlist, search, shorts, transcript, trending, video)
9
+ desktop: blender(animation, camera, convert, export, import, info, lighting, materials, objects, render, scene, screenshot, script), comfyui(generate, history, nodes, status), docker(build, images, logs, networks, ps, run, volumes), drawio(export), ffmpeg(compress, concat, convert, extract-audio, gif, normalize, probe, resize, subtitles, thumbnail, trim), freecad(assembly, bom, boolean, check, convert, export-stl, import, info, macro, measure, mesh, properties, render, section, sketch), gimp(adjust, batch, convert, crop, filter, flip, info, layers, merge-layers, resize, rotate, text), imagemagick(compare, composite, convert, identify, montage, resize), inkscape(convert, export, optimize), libreoffice(convert, print), macos(active-app, apps, apps-list, battery, bluetooth, brightness, caffeinate, calendar-create, calendar-list, calendar-today, clipboard, contacts-search, dark-mode, disk-info, disk-usage, do-not-disturb, empty-trash, finder-copy, finder-move, finder-new-folder, finder-recent, finder-selection, finder-tags, lock-screen, mail-send, mail-status, messages-send, music-control, music-now, notes-list, notes-search, notification, notify, open, open-app, photos-search, processes, reminder-create, reminders-complete, reminders-list, safari-history, safari-tabs, safari-url, say, screen-lock, screen-recording, screenshot, shortcuts-list, shortcuts-run, sleep, spotlight, system-info, trash, uptime, volume, wallpaper, wifi, wifi-info), mermaid(render), musescore(convert, export, info, instruments, transpose), pandoc(convert)
10
+ jobs: boss(batchgreet, chatlist, chatmsg, detail, exchange, greet, invite, joblist, mark, recommend, resume, search, send, stats), linkedin(jobs, profile, search, timeline)
11
+ dev: cocoapods(info, search), crates-io(info, search, versions), devto(latest, search, tag, top, user), docker-hub(info, search, tags), gitee(repos, search, trending), github-trending(daily, developers, weekly), gitlab(projects, search, trending), homebrew(info, search), npm(downloads, info, search, versions), npm-trends(compare, trending), producthunt(browse, hot, posts, search, today), pypi(info, search, versions), stackoverflow(bounties, hot, question, search, tags, unanswered)
12
+ ai: deepseek(chat, models), doubao(ask, new, status), doubao-web(ask, detail, history, meeting-summary, meeting-transcript, new, read, send, status), gemini(ask, deep-research, deep-research-result, image, new), grok(ask), hf(datasets, models, spaces, top), huggingface-papers(daily, search), minimax(chat, models, tts), notebooklm(current, get, history, list, note-list, notes-get, open, rpc, shared, source-fulltext, source-get, source-guide, source-list, status, summary), novita(generate, models, status), ollama(generate, list, models, ps), openrouter(models, search), perplexity(ask), replicate(run, search, trending)
13
+ utility: exchangerate(convert, list), ip-info(lookup), qweather(forecast, now), web(read)
14
+ content: medium(article, feed, search, trending, user), pixiv(detail, download, illusts, ranking, search, user), sspai(hot, latest), substack(feed, publication, search, trending), weread(book, highlights, notebooks, notes, ranking, search, shelf), zsxq(dynamics, groups, search, topic, topics)
15
+ games: steam(app-details, new-releases, search, specials, top-sellers, wishlist)