tianshu-harness 3.23.0
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/LICENSE +189 -0
- package/README.en.md +1066 -0
- package/README.ja.md +1214 -0
- package/README.ko.md +1216 -0
- package/README.md +309 -0
- package/completions/rivet.bash +118 -0
- package/completions/rivet.fish +110 -0
- package/completions/rivet.ps1 +230 -0
- package/completions/rivet.zsh +187 -0
- package/dist/account-OAEKORZE.js +47 -0
- package/dist/account-login-V6FOLHJR.js +65 -0
- package/dist/account-status-KHNPPAFL.js +23 -0
- package/dist/agent/worker-process/child.js +407 -0
- package/dist/browser-cli-FLNY5ZHI.js +19 -0
- package/dist/browser-readiness-LWVGSBD5.js +12 -0
- package/dist/build-backends-5KXKR2S4.js +13 -0
- package/dist/build-options-66Y4ZE7C.js +9 -0
- package/dist/bundled-skills/brainstorming/SKILL.md +139 -0
- package/dist/bundled-skills/visual-acceptance/SKILL.md +64 -0
- package/dist/chain-7MAMFXZ3.js +10 -0
- package/dist/checkpoint-MND4DUIX.js +33 -0
- package/dist/chunk-2E6CK2RC.js +392 -0
- package/dist/chunk-2EBWGAXD.js +51 -0
- package/dist/chunk-2HDP7RMR.js +119 -0
- package/dist/chunk-2HKD2UFM.js +1000 -0
- package/dist/chunk-2VYRLULP.js +51 -0
- package/dist/chunk-2XN7PM4N.js +125 -0
- package/dist/chunk-35H7GVNR.js +66 -0
- package/dist/chunk-3C3R7JXY.js +77 -0
- package/dist/chunk-3VGD2FXB.js +118 -0
- package/dist/chunk-424AP7FM.js +534 -0
- package/dist/chunk-4J5TZGOE.js +3707 -0
- package/dist/chunk-4QJ3Y5JM.js +898 -0
- package/dist/chunk-4U2ET7ZY.js +1326 -0
- package/dist/chunk-4XPFLICE.js +876 -0
- package/dist/chunk-5B2OCU5P.js +31707 -0
- package/dist/chunk-5GGOGLSN.js +73 -0
- package/dist/chunk-5JRZPLI6.js +251 -0
- package/dist/chunk-5TQ3JYBU.js +397 -0
- package/dist/chunk-66JPZSGX.js +55 -0
- package/dist/chunk-6HSVXHCZ.js +764 -0
- package/dist/chunk-6S5FPUS7.js +21 -0
- package/dist/chunk-722LQO64.js +131 -0
- package/dist/chunk-73NJ7IT7.js +354 -0
- package/dist/chunk-7FW3I7WC.js +95 -0
- package/dist/chunk-7KUCBNLB.js +173 -0
- package/dist/chunk-7RDOV3DF.js +201 -0
- package/dist/chunk-A5MNH4ER.js +79 -0
- package/dist/chunk-ADIVZ2D5.js +15 -0
- package/dist/chunk-AE3P3F6W.js +366 -0
- package/dist/chunk-AERM3VGP.js +280 -0
- package/dist/chunk-AEWHC4WM.js +246 -0
- package/dist/chunk-AOVQ7VIF.js +169 -0
- package/dist/chunk-AOYHP3WI.js +12411 -0
- package/dist/chunk-B3YEBABJ.js +7160 -0
- package/dist/chunk-BCQXEZPJ.js +154 -0
- package/dist/chunk-BKTQAYO2.js +418 -0
- package/dist/chunk-BSECIPAQ.js +80 -0
- package/dist/chunk-BUIMGNDD.js +52 -0
- package/dist/chunk-BXHV3GSB.js +10320 -0
- package/dist/chunk-C6ZVZCPP.js +139 -0
- package/dist/chunk-CEZNQVWM.js +82 -0
- package/dist/chunk-CGFZGR7G.js +1492 -0
- package/dist/chunk-CGOADM2X.js +337 -0
- package/dist/chunk-CI4R6P2B.js +24 -0
- package/dist/chunk-D2TCGRSX.js +73 -0
- package/dist/chunk-D4PTYFOG.js +154 -0
- package/dist/chunk-D54ZWG4T.js +717 -0
- package/dist/chunk-DEBI37QB.js +145 -0
- package/dist/chunk-DWROHPXP.js +1051 -0
- package/dist/chunk-DZ6UOJ5D.js +92 -0
- package/dist/chunk-EBJTVRQN.js +81 -0
- package/dist/chunk-EGEI2RQA.js +1167 -0
- package/dist/chunk-EHHUASO5.js +1305 -0
- package/dist/chunk-EPKTIOED.js +41 -0
- package/dist/chunk-ER5JW2QZ.js +5681 -0
- package/dist/chunk-ETHFACAB.js +315 -0
- package/dist/chunk-EXUE5W2F.js +112 -0
- package/dist/chunk-EXXICUIW.js +73 -0
- package/dist/chunk-FFQSZJOO.js +169 -0
- package/dist/chunk-FHFKPGDO.js +85 -0
- package/dist/chunk-FW3QKMFX.js +158 -0
- package/dist/chunk-GD4ZNZ7W.js +30 -0
- package/dist/chunk-GHVMWF2I.js +581 -0
- package/dist/chunk-GMKAXSYQ.js +297 -0
- package/dist/chunk-HBVF6BWO.js +325 -0
- package/dist/chunk-HV4YGVMS.js +379 -0
- package/dist/chunk-ILBCKAV6.js +89 -0
- package/dist/chunk-J4U4AW46.js +440 -0
- package/dist/chunk-J6ESSM47.js +1791 -0
- package/dist/chunk-JBZHIC6T.js +2309 -0
- package/dist/chunk-JCFWOULR.js +245 -0
- package/dist/chunk-JRF5L6OD.js +131 -0
- package/dist/chunk-JSS75KCG.js +2014 -0
- package/dist/chunk-JSXWIWWJ.js +225 -0
- package/dist/chunk-JYV7I2QH.js +98 -0
- package/dist/chunk-KIOXTQQL.js +1596 -0
- package/dist/chunk-KWVTXT5B.js +89 -0
- package/dist/chunk-KX22RD6R.js +33 -0
- package/dist/chunk-LA6IPTGH.js +709 -0
- package/dist/chunk-LH5VCGLB.js +1796 -0
- package/dist/chunk-LQQ6XJ2Y.js +269 -0
- package/dist/chunk-MJQ55WZZ.js +65 -0
- package/dist/chunk-ML3UKMH3.js +40 -0
- package/dist/chunk-MOZPLHSU.js +5526 -0
- package/dist/chunk-NGEWJ4DF.js +89 -0
- package/dist/chunk-NH6VIOAR.js +211 -0
- package/dist/chunk-O5VZQKCB.js +26106 -0
- package/dist/chunk-OHSV42QB.js +748 -0
- package/dist/chunk-OO3TAHO5.js +4070 -0
- package/dist/chunk-OTNHSAGN.js +38282 -0
- package/dist/chunk-OUWAC7AQ.js +442 -0
- package/dist/chunk-OXMIV4WE.js +270 -0
- package/dist/chunk-P5KJURUR.js +229 -0
- package/dist/chunk-P6GJOVO6.js +307 -0
- package/dist/chunk-QARAGUXX.js +23 -0
- package/dist/chunk-R43HJCDX.js +2711 -0
- package/dist/chunk-RAXBAWRN.js +210 -0
- package/dist/chunk-RK3JHWPT.js +39 -0
- package/dist/chunk-RWA23GMM.js +24 -0
- package/dist/chunk-S4K4L6IM.js +179 -0
- package/dist/chunk-SAXK6LVF.js +124 -0
- package/dist/chunk-SEPGEJNK.js +1607 -0
- package/dist/chunk-SUJERP5I.js +285 -0
- package/dist/chunk-T3ED6BY2.js +913 -0
- package/dist/chunk-THKDVSEC.js +90 -0
- package/dist/chunk-TI4GSEL5.js +52 -0
- package/dist/chunk-TPI73L57.js +164 -0
- package/dist/chunk-TVHW77C7.js +338 -0
- package/dist/chunk-TWNHOSDT.js +1073 -0
- package/dist/chunk-UFMN76QD.js +347 -0
- package/dist/chunk-UHGLFRZE.js +205 -0
- package/dist/chunk-UTZYPKBF.js +15231 -0
- package/dist/chunk-UXNLELW6.js +25 -0
- package/dist/chunk-UXXS53EA.js +166 -0
- package/dist/chunk-V5DHFGI7.js +171 -0
- package/dist/chunk-V5YIPMHV.js +2353 -0
- package/dist/chunk-WMUWEO2C.js +754 -0
- package/dist/chunk-WOE3D7JM.js +945 -0
- package/dist/chunk-X2IK5LVR.js +2592 -0
- package/dist/chunk-XU2YXCDL.js +459 -0
- package/dist/chunk-YJG5HIX5.js +203 -0
- package/dist/chunk-Z3QE7TZM.js +72 -0
- package/dist/chunk-Z5Z3JHJY.js +64 -0
- package/dist/chunk-ZDIFBJFT.js +168 -0
- package/dist/chunk-ZGGCEXDC.js +176 -0
- package/dist/chunk-ZMZCZNKU.js +263 -0
- package/dist/chunk-ZNC5T65N.js +17 -0
- package/dist/chunk-ZO3I3A7O.js +308 -0
- package/dist/chunk-ZQKXBUB7.js +217 -0
- package/dist/chunk-ZTRINFM2.js +78 -0
- package/dist/chunk-ZU7JZCVP.js +193 -0
- package/dist/chunk-ZZAWNALS.js +350 -0
- package/dist/cli/entry.js +54 -0
- package/dist/connector-L5QQTR6Y.js +26 -0
- package/dist/context-62DC6EC3.js +31 -0
- package/dist/council-convene-NJWPNBDU.js +46 -0
- package/dist/create-agent-config-ODSQWNVC.js +55 -0
- package/dist/default-registry-2PU3BTAU.js +68 -0
- package/dist/deliver-task-KONV4C4M.js +57 -0
- package/dist/delivery-gate-v2-F2YVMVGK.js +27 -0
- package/dist/domain-knowledge-store-DDZ3F4J7.js +11 -0
- package/dist/fetch-core-ZPPYDSZH.js +14 -0
- package/dist/galaxy-K72BBDQN.js +91 -0
- package/dist/goal-criteria-SCALAU2D.js +141 -0
- package/dist/goal-persist-XWY2GDQX.js +19 -0
- package/dist/goal-tracker-FXMJ2GVK.js +11 -0
- package/dist/headless-LSB6I7PT.js +162 -0
- package/dist/headless-coordinator-VDPDMVUT.js +90 -0
- package/dist/inject-U55SMB6A.js +39 -0
- package/dist/login-flow-CD4ZGXOC.js +59 -0
- package/dist/logs-cli-SQVYFMMN.js +283 -0
- package/dist/loop-ULZYBDA3.js +76 -0
- package/dist/main.js +4064 -0
- package/dist/manager-ROZBCWPA.js +171 -0
- package/dist/manager-Z7XFFUOM.js +10670 -0
- package/dist/meridian-indexer-ZIW363L7.js +21 -0
- package/dist/native-resolver-PN34UIVV.js +13 -0
- package/dist/node_modules/better-sqlite3/lib/database.js +90 -0
- package/dist/node_modules/better-sqlite3/lib/index.js +3 -0
- package/dist/node_modules/better-sqlite3/lib/methods/aggregate.js +43 -0
- package/dist/node_modules/better-sqlite3/lib/methods/backup.js +67 -0
- package/dist/node_modules/better-sqlite3/lib/methods/function.js +31 -0
- package/dist/node_modules/better-sqlite3/lib/methods/inspect.js +7 -0
- package/dist/node_modules/better-sqlite3/lib/methods/pragma.js +12 -0
- package/dist/node_modules/better-sqlite3/lib/methods/serialize.js +16 -0
- package/dist/node_modules/better-sqlite3/lib/methods/table.js +189 -0
- package/dist/node_modules/better-sqlite3/lib/methods/transaction.js +78 -0
- package/dist/node_modules/better-sqlite3/lib/methods/wrappers.js +54 -0
- package/dist/node_modules/better-sqlite3/lib/sqlite-error.js +20 -0
- package/dist/node_modules/better-sqlite3/lib/util.js +12 -0
- package/dist/node_modules/better-sqlite3/package.json +59 -0
- package/dist/ownership-ledger-E3WIEKPL.js +9 -0
- package/dist/package.json +3 -0
- package/dist/path-grants-XRRXHXG7.js +40 -0
- package/dist/paths-LVV5IMQN.js +49 -0
- package/dist/plan-fact-anchors-LMVQZCW5.js +13 -0
- package/dist/plan-store-ODLTTPFB.js +17 -0
- package/dist/plan-templates-5FPFBOL6.js +109 -0
- package/dist/plugin-loader-ZZKX7ZE6.js +22 -0
- package/dist/prefix-budget-62OV5HQC.js +13 -0
- package/dist/project-trust-5WS5MOMU.js +31 -0
- package/dist/provider-cli-ALDQXIT7.js +37 -0
- package/dist/providers-XQYTAVPK.js +11 -0
- package/dist/proxy-resolver-V2Y6534D.js +15 -0
- package/dist/recovery-cli-KPGY6FY3.js +106 -0
- package/dist/review-discipline-MNSYCST5.js +55 -0
- package/dist/review-router-BVQZW3MX.js +18 -0
- package/dist/seed-capsules/seed-capsule-attack-methodology.md +62 -0
- package/dist/seed-capsules/seed-capsule-changgeng.md +31 -0
- package/dist/seed-capsules/seed-capsule-design-aesthetics.md +38 -0
- package/dist/seed-capsules/seed-capsule-diagnostic-ladder.md +54 -0
- package/dist/seed-capsules/seed-capsule-fu.md +39 -0
- package/dist/seed-capsules/seed-capsule-huagai.md +73 -0
- package/dist/seed-capsules/seed-capsule-kaiyang.md +65 -0
- package/dist/seed-capsules/seed-capsule-knowledge-work.md +40 -0
- package/dist/seed-capsules/seed-capsule-tanlang.md +47 -0
- package/dist/seed-capsules/seed-capsule-tianfu.md +23 -0
- package/dist/seed-capsules/seed-capsule-tianliang.md +63 -0
- package/dist/seed-capsules/seed-capsule-tianquan.md +32 -0
- package/dist/seed-capsules/seed-capsule-tianxuan-ccr.md +22 -0
- package/dist/seed-capsules/seed-capsule-tianxuan.md +64 -0
- package/dist/seed-capsules/seed-capsule-yaoguang.md +87 -0
- package/dist/serve-X2R2UTLF.js +170 -0
- package/dist/serve-agent-KHSU6RVV.js +965 -0
- package/dist/session-persist-HUUC772H.js +37 -0
- package/dist/session-registry-6XUD5C4Y.js +15 -0
- package/dist/skill-loader-CK3RMO47.js +48 -0
- package/dist/skills/cli-harness-sop.md +207 -0
- package/dist/spawn-git-4HFU65AH.js +29 -0
- package/dist/sse-EYUTBWUK.js +512 -0
- package/dist/starflow-NOFBMPFU.js +30 -0
- package/dist/streamableHttp-V67CNJMO.js +447 -0
- package/dist/task-contract-6XHBNJQK.js +32 -0
- package/dist/task-ledger-3K4TJIER.js +9 -0
- package/dist/team-orchestrate-S6NHZP7X.js +64 -0
- package/dist/title-extract-QX4XGCYN.js +50 -0
- package/dist/todo-QDXGRZZP.js +31 -0
- package/dist/todo-store-V3TTO5AH.js +12 -0
- package/dist/tool-preset-LU5BYEDZ.js +23 -0
- package/dist/tool-tiers-GD742YBN.js +23 -0
- package/dist/turndown.es-OI55K6C3.js +17373 -0
- package/dist/verification-attribution-EKG4CNUV.js +13 -0
- package/dist/volatile-git-MBTST7RA.js +15 -0
- package/dist/wave-checkpoint-XLIIHXQA.js +30 -0
- package/dist/web-cli-DUG4I35O.js +233 -0
- package/dist/web-search-3IK542AA.js +34 -0
- package/dist/workers/cpu-worker.js +45 -0
- package/dist/workflow-runner-HX7UBAYG.js +297 -0
- package/dist/worktree-baseline-O5NCU6M2.js +9 -0
- package/package.json +122 -0
- package/scripts/check-mobile-env.mjs +76 -0
- package/scripts/fetch-native-sqlite.js +392 -0
- package/scripts/prune-installed-wasms.js +45 -0
- package/scripts/tree-sitter-wasm-keep.js +40 -0
|
@@ -0,0 +1,440 @@
|
|
|
1
|
+
#!/usr/bin/env -S node --expose-gc --max-old-space-size=4096
|
|
2
|
+
import { createRequire as __rivetCreateRequire } from 'node:module'; const require = __rivetCreateRequire(import.meta.url);
|
|
3
|
+
import {
|
|
4
|
+
resolveProxyForUrl
|
|
5
|
+
} from "./chunk-2HDP7RMR.js";
|
|
6
|
+
import {
|
|
7
|
+
require_undici
|
|
8
|
+
} from "./chunk-O5VZQKCB.js";
|
|
9
|
+
import {
|
|
10
|
+
__toESM,
|
|
11
|
+
init_esm_shims
|
|
12
|
+
} from "./chunk-5GGOGLSN.js";
|
|
13
|
+
|
|
14
|
+
// src/tools/web-search/build-backends.ts
|
|
15
|
+
init_esm_shims();
|
|
16
|
+
|
|
17
|
+
// src/tools/web-search/duckduckgo.ts
|
|
18
|
+
init_esm_shims();
|
|
19
|
+
function parseDuckDuckGoResults(html, maxCount) {
|
|
20
|
+
const results = [];
|
|
21
|
+
const titleBlocks = html.split('<h2 class="result__title">');
|
|
22
|
+
for (let i = 1; i < titleBlocks.length && results.length < maxCount; i++) {
|
|
23
|
+
const block = titleBlocks[i];
|
|
24
|
+
const linkMatch = block.match(/<a[^>]+class="result__a"[^>]+href="([^"]+)"[^>]*>([\s\S]*?)<\/a>/i);
|
|
25
|
+
if (!linkMatch) continue;
|
|
26
|
+
const url = decodeHtmlEntities(linkMatch[1]);
|
|
27
|
+
const title = decodeHtmlEntities(stripHtml(linkMatch[2])).trim();
|
|
28
|
+
if (!title || !url) continue;
|
|
29
|
+
const snippetMatch = block.match(/<a[^>]+class="result__snippet"[^>]*>([\s\S]*?)<\/a>/i);
|
|
30
|
+
const snippet = snippetMatch ? decodeHtmlEntities(stripHtml(snippetMatch[1])).trim() : "";
|
|
31
|
+
const actualUrl = extractActualUrl(url);
|
|
32
|
+
results.push({ title, url: actualUrl, snippet });
|
|
33
|
+
}
|
|
34
|
+
return results;
|
|
35
|
+
}
|
|
36
|
+
function stripHtml(text) {
|
|
37
|
+
return text.replace(/<[^>]+>/g, "").trim();
|
|
38
|
+
}
|
|
39
|
+
function decodeHtmlEntities(text) {
|
|
40
|
+
return text.replace(/&(#x[0-9a-fA-F]+|#\d+|amp|lt|gt|quot|apos|#39|nbsp|ensp|emsp|thinsp|rsaquo|lsaquo);/g, (m, e) => {
|
|
41
|
+
switch (e) {
|
|
42
|
+
case "amp":
|
|
43
|
+
return "&";
|
|
44
|
+
case "lt":
|
|
45
|
+
return "<";
|
|
46
|
+
case "gt":
|
|
47
|
+
return ">";
|
|
48
|
+
case "quot":
|
|
49
|
+
return '"';
|
|
50
|
+
case "apos":
|
|
51
|
+
case "#39":
|
|
52
|
+
return "'";
|
|
53
|
+
case "nbsp":
|
|
54
|
+
return "\xA0";
|
|
55
|
+
case "ensp":
|
|
56
|
+
return "\u2002";
|
|
57
|
+
case "emsp":
|
|
58
|
+
return "\u2003";
|
|
59
|
+
case "thinsp":
|
|
60
|
+
return "\u2009";
|
|
61
|
+
case "rsaquo":
|
|
62
|
+
return "\u203A";
|
|
63
|
+
case "lsaquo":
|
|
64
|
+
return "\u2039";
|
|
65
|
+
}
|
|
66
|
+
const code = e[1] === "x" || e[1] === "X" ? parseInt(e.slice(2), 16) : parseInt(e.slice(1), 10);
|
|
67
|
+
return Number.isFinite(code) && code > 0 ? String.fromCodePoint(code) : m;
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
function extractActualUrl(ddgUrl) {
|
|
71
|
+
try {
|
|
72
|
+
const parsed = new URL(ddgUrl.replace(/^\/\//, "https://"));
|
|
73
|
+
const uddg = parsed.searchParams.get("uddg");
|
|
74
|
+
if (uddg) {
|
|
75
|
+
const decoded = decodeURIComponent(uddg);
|
|
76
|
+
return /^https?:\/\//i.test(decoded) ? decoded : ddgUrl;
|
|
77
|
+
}
|
|
78
|
+
const u = parsed.searchParams.get("u");
|
|
79
|
+
if (u) {
|
|
80
|
+
const decoded = decodeURIComponent(u);
|
|
81
|
+
return /^https?:\/\//i.test(decoded) ? decoded : ddgUrl;
|
|
82
|
+
}
|
|
83
|
+
} catch {
|
|
84
|
+
}
|
|
85
|
+
return ddgUrl;
|
|
86
|
+
}
|
|
87
|
+
var DuckDuckGoBackend = class {
|
|
88
|
+
constructor(fetchImpl) {
|
|
89
|
+
this.fetchImpl = fetchImpl;
|
|
90
|
+
}
|
|
91
|
+
fetchImpl;
|
|
92
|
+
name = "duckduckgo";
|
|
93
|
+
isAvailable() {
|
|
94
|
+
return true;
|
|
95
|
+
}
|
|
96
|
+
async search(query, count, signal) {
|
|
97
|
+
const url = `https://html.duckduckgo.com/html/?q=${encodeURIComponent(query)}`;
|
|
98
|
+
const response = await this.fetchImpl(url, {
|
|
99
|
+
signal,
|
|
100
|
+
headers: { "User-Agent": "terminal-coding-agent/1.0" },
|
|
101
|
+
redirect: "manual"
|
|
102
|
+
});
|
|
103
|
+
if (!response.ok) {
|
|
104
|
+
throw new Error(`HTTP ${response.status}`);
|
|
105
|
+
}
|
|
106
|
+
const html = await response.text();
|
|
107
|
+
return parseDuckDuckGoResults(html, count);
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
// src/tools/web-search/bing.ts
|
|
112
|
+
init_esm_shims();
|
|
113
|
+
var BING_ENDPOINT = "https://cn.bing.com/search";
|
|
114
|
+
var BING_UA = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36";
|
|
115
|
+
function parseBingResults(html, maxCount) {
|
|
116
|
+
const results = [];
|
|
117
|
+
const blocks = html.split('<li class="b_algo');
|
|
118
|
+
for (let i = 1; i < blocks.length && results.length < maxCount; i++) {
|
|
119
|
+
const block = blocks[i];
|
|
120
|
+
const linkMatch = extractTitleLink(block);
|
|
121
|
+
if (!linkMatch) continue;
|
|
122
|
+
const rawUrl = decodeHtmlEntities(linkMatch.url);
|
|
123
|
+
const url = decodeCkAUrl(rawUrl);
|
|
124
|
+
const title = decodeHtmlEntities(stripHtml2(linkMatch.title)).replace(/\s+/g, " ").trim();
|
|
125
|
+
if (!title || !url || !/^https?:\/\//i.test(url)) continue;
|
|
126
|
+
const snippetMatch = block.match(/<p[^>]+class="b_lineclamp\d"[^>]*>([\s\S]*?)<\/p>/i);
|
|
127
|
+
const snippet = snippetMatch ? decodeHtmlEntities(stripHtml2(snippetMatch[1])).replace(/\s+/g, " ").trim() : "";
|
|
128
|
+
results.push({ title, url, snippet });
|
|
129
|
+
}
|
|
130
|
+
return results;
|
|
131
|
+
}
|
|
132
|
+
function extractTitleLink(block) {
|
|
133
|
+
const h2 = block.match(/<h2[^>]*>([\s\S]*?)<\/h2>/i);
|
|
134
|
+
if (h2) {
|
|
135
|
+
const m2 = h2[1].match(/<a[^>]+href="([^"]+)"[^>]*>([\s\S]*?)<\/a>/i);
|
|
136
|
+
if (m2) return { url: m2[1], title: m2[2] };
|
|
137
|
+
}
|
|
138
|
+
const head = block.slice(0, 4096);
|
|
139
|
+
const anchorRe = /<a[^>]+href="([^"]+)"[^>]*>([\s\S]*?)<\/a>/gi;
|
|
140
|
+
let m;
|
|
141
|
+
while ((m = anchorRe.exec(head)) !== null) {
|
|
142
|
+
const href = m[1];
|
|
143
|
+
if (!/^https?:\/\//i.test(href)) continue;
|
|
144
|
+
if (isBingInternalUrl(href)) continue;
|
|
145
|
+
return { url: href, title: m[2] };
|
|
146
|
+
}
|
|
147
|
+
return void 0;
|
|
148
|
+
}
|
|
149
|
+
function isBingInternalUrl(url) {
|
|
150
|
+
try {
|
|
151
|
+
const host = new URL(url).hostname.toLowerCase();
|
|
152
|
+
return host.endsWith(".bing.com") || host.endsWith(".microsoft.com") || host === "go.microsoft.com" || host === "r.bing.com";
|
|
153
|
+
} catch {
|
|
154
|
+
return false;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
function stripHtml2(text) {
|
|
158
|
+
return text.replace(/<[^>]+>/g, "");
|
|
159
|
+
}
|
|
160
|
+
function decodeCkAUrl(rawUrl) {
|
|
161
|
+
if (!rawUrl.includes("/ck/a")) return rawUrl;
|
|
162
|
+
try {
|
|
163
|
+
const parsed = new URL(rawUrl);
|
|
164
|
+
const u = parsed.searchParams.get("u");
|
|
165
|
+
if (!u) return rawUrl;
|
|
166
|
+
const b64 = u.slice(2).replace(/-/g, "+").replace(/_/g, "/");
|
|
167
|
+
const padded = b64 + "===".slice((b64.length + 3) % 4);
|
|
168
|
+
const decoded = Buffer.from(padded, "base64").toString("utf8");
|
|
169
|
+
return /^https?:\/\//i.test(decoded) ? decoded : rawUrl;
|
|
170
|
+
} catch {
|
|
171
|
+
return rawUrl;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
var BingBackend = class {
|
|
175
|
+
constructor(fetchImpl) {
|
|
176
|
+
this.fetchImpl = fetchImpl;
|
|
177
|
+
}
|
|
178
|
+
fetchImpl;
|
|
179
|
+
name = "bing";
|
|
180
|
+
isAvailable() {
|
|
181
|
+
return true;
|
|
182
|
+
}
|
|
183
|
+
async search(query, count, signal) {
|
|
184
|
+
const url = `${BING_ENDPOINT}?q=${encodeURIComponent(query)}`;
|
|
185
|
+
const response = await this.fetchImpl(url, {
|
|
186
|
+
signal,
|
|
187
|
+
headers: {
|
|
188
|
+
"User-Agent": BING_UA,
|
|
189
|
+
"Accept-Language": "zh-CN,zh;q=0.9,en;q=0.5"
|
|
190
|
+
},
|
|
191
|
+
redirect: "manual"
|
|
192
|
+
});
|
|
193
|
+
if (!response.ok) {
|
|
194
|
+
throw new Error(`HTTP ${response.status}`);
|
|
195
|
+
}
|
|
196
|
+
const html = await response.text();
|
|
197
|
+
return parseBingResults(html, count);
|
|
198
|
+
}
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
// src/tools/web-search/brave.ts
|
|
202
|
+
init_esm_shims();
|
|
203
|
+
var BRAVE_ENDPOINT = "https://api.search.brave.com/res/v1/web/search";
|
|
204
|
+
var BraveBackend = class {
|
|
205
|
+
constructor(fetchImpl, apiKey, region) {
|
|
206
|
+
this.fetchImpl = fetchImpl;
|
|
207
|
+
this.apiKey = apiKey;
|
|
208
|
+
this.region = region;
|
|
209
|
+
}
|
|
210
|
+
fetchImpl;
|
|
211
|
+
apiKey;
|
|
212
|
+
region;
|
|
213
|
+
name = "brave";
|
|
214
|
+
isAvailable() {
|
|
215
|
+
return typeof this.apiKey === "string" && this.apiKey.length > 0;
|
|
216
|
+
}
|
|
217
|
+
async search(query, count, signal) {
|
|
218
|
+
const params = new URLSearchParams({ q: query, count: String(count) });
|
|
219
|
+
if (this.region) params.set("country", this.region);
|
|
220
|
+
const response = await this.fetchImpl(`${BRAVE_ENDPOINT}?${params.toString()}`, {
|
|
221
|
+
signal,
|
|
222
|
+
headers: {
|
|
223
|
+
Accept: "application/json",
|
|
224
|
+
"Accept-Encoding": "gzip",
|
|
225
|
+
"X-Subscription-Token": this.apiKey ?? ""
|
|
226
|
+
}
|
|
227
|
+
});
|
|
228
|
+
if (!response.ok) {
|
|
229
|
+
throw new Error(`HTTP ${response.status}`);
|
|
230
|
+
}
|
|
231
|
+
const data = await response.json();
|
|
232
|
+
const raw = data.web?.results ?? [];
|
|
233
|
+
const results = [];
|
|
234
|
+
for (const r of raw) {
|
|
235
|
+
if (!r.url || !r.title) continue;
|
|
236
|
+
results.push({ title: r.title, url: r.url, snippet: r.description ?? "" });
|
|
237
|
+
if (results.length >= count) break;
|
|
238
|
+
}
|
|
239
|
+
return results;
|
|
240
|
+
}
|
|
241
|
+
};
|
|
242
|
+
|
|
243
|
+
// src/tools/web-search/tavily.ts
|
|
244
|
+
init_esm_shims();
|
|
245
|
+
var TAVILY_ENDPOINT = "https://api.tavily.com/search";
|
|
246
|
+
var TavilyBackend = class {
|
|
247
|
+
constructor(fetchImpl, apiKey) {
|
|
248
|
+
this.fetchImpl = fetchImpl;
|
|
249
|
+
this.apiKey = apiKey;
|
|
250
|
+
}
|
|
251
|
+
fetchImpl;
|
|
252
|
+
apiKey;
|
|
253
|
+
name = "tavily";
|
|
254
|
+
isAvailable() {
|
|
255
|
+
return typeof this.apiKey === "string" && this.apiKey.length > 0;
|
|
256
|
+
}
|
|
257
|
+
async search(query, count, signal) {
|
|
258
|
+
const response = await this.fetchImpl(TAVILY_ENDPOINT, {
|
|
259
|
+
signal,
|
|
260
|
+
method: "POST",
|
|
261
|
+
headers: {
|
|
262
|
+
Accept: "application/json",
|
|
263
|
+
"Content-Type": "application/json",
|
|
264
|
+
Authorization: `Bearer ${this.apiKey ?? ""}`
|
|
265
|
+
},
|
|
266
|
+
body: JSON.stringify({ query, max_results: count })
|
|
267
|
+
});
|
|
268
|
+
if (!response.ok) {
|
|
269
|
+
throw new Error(`HTTP ${response.status}`);
|
|
270
|
+
}
|
|
271
|
+
const data = await response.json();
|
|
272
|
+
const raw = data.results ?? [];
|
|
273
|
+
const results = [];
|
|
274
|
+
for (const r of raw) {
|
|
275
|
+
if (!r.url || !r.title) continue;
|
|
276
|
+
results.push({ title: r.title, url: r.url, snippet: r.content ?? "" });
|
|
277
|
+
if (results.length >= count) break;
|
|
278
|
+
}
|
|
279
|
+
return results;
|
|
280
|
+
}
|
|
281
|
+
};
|
|
282
|
+
|
|
283
|
+
// src/tools/web-search/bocha.ts
|
|
284
|
+
init_esm_shims();
|
|
285
|
+
var BOCHA_ENDPOINT = "https://api.bochaai.com/v1/web-search";
|
|
286
|
+
var BochaBackend = class {
|
|
287
|
+
constructor(fetchImpl, apiKey) {
|
|
288
|
+
this.fetchImpl = fetchImpl;
|
|
289
|
+
this.apiKey = apiKey;
|
|
290
|
+
}
|
|
291
|
+
fetchImpl;
|
|
292
|
+
apiKey;
|
|
293
|
+
name = "bocha";
|
|
294
|
+
isAvailable() {
|
|
295
|
+
return typeof this.apiKey === "string" && this.apiKey.length > 0;
|
|
296
|
+
}
|
|
297
|
+
async search(query, count, signal) {
|
|
298
|
+
const response = await this.fetchImpl(BOCHA_ENDPOINT, {
|
|
299
|
+
signal,
|
|
300
|
+
method: "POST",
|
|
301
|
+
headers: {
|
|
302
|
+
Accept: "application/json",
|
|
303
|
+
"Content-Type": "application/json",
|
|
304
|
+
Authorization: `Bearer ${this.apiKey ?? ""}`
|
|
305
|
+
},
|
|
306
|
+
body: JSON.stringify({ query, count, summary: true })
|
|
307
|
+
});
|
|
308
|
+
if (!response.ok) {
|
|
309
|
+
throw new Error(`HTTP ${response.status}`);
|
|
310
|
+
}
|
|
311
|
+
const data = await response.json();
|
|
312
|
+
if (data.code && data.code !== 200) {
|
|
313
|
+
throw new Error(`bocha ${data.code}: ${data.msg ?? "unknown error"}`);
|
|
314
|
+
}
|
|
315
|
+
const raw = data.data?.webPages?.value ?? [];
|
|
316
|
+
const results = [];
|
|
317
|
+
for (const r of raw) {
|
|
318
|
+
if (!r.url || !r.name) continue;
|
|
319
|
+
const snippet = r.summary || r.snippet || "";
|
|
320
|
+
const result = { title: r.name, url: r.url, snippet };
|
|
321
|
+
if (r.siteName) result.siteName = r.siteName;
|
|
322
|
+
if (r.datePublished) result.publishedAt = r.datePublished;
|
|
323
|
+
results.push(result);
|
|
324
|
+
if (results.length >= count) break;
|
|
325
|
+
}
|
|
326
|
+
return results;
|
|
327
|
+
}
|
|
328
|
+
};
|
|
329
|
+
|
|
330
|
+
// src/tools/web-search/proxy-fetch.ts
|
|
331
|
+
init_esm_shims();
|
|
332
|
+
var import_undici = __toESM(require_undici(), 1);
|
|
333
|
+
|
|
334
|
+
// src/tools/web-search/bounded-fetch.ts
|
|
335
|
+
init_esm_shims();
|
|
336
|
+
var DEFAULT_MAX_SEARCH_BYTES = 8 * 1024 * 1024;
|
|
337
|
+
function boundedSearchFetch(fetchImpl, maxBytes = DEFAULT_MAX_SEARCH_BYTES) {
|
|
338
|
+
return async (url, init) => {
|
|
339
|
+
const res = await fetchImpl(url, init);
|
|
340
|
+
if (!res.body) return res;
|
|
341
|
+
const reader = res.body.getReader();
|
|
342
|
+
const chunks = [];
|
|
343
|
+
let total = 0;
|
|
344
|
+
try {
|
|
345
|
+
for (; ; ) {
|
|
346
|
+
const { done, value } = await reader.read();
|
|
347
|
+
if (done) break;
|
|
348
|
+
if (value && value.byteLength > 0) {
|
|
349
|
+
total += value.byteLength;
|
|
350
|
+
if (total > maxBytes) {
|
|
351
|
+
await reader.cancel().catch(() => {
|
|
352
|
+
});
|
|
353
|
+
throw new Error(`search response body exceeded ${maxBytes}-byte cap`);
|
|
354
|
+
}
|
|
355
|
+
chunks.push(Buffer.from(value));
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
} finally {
|
|
359
|
+
try {
|
|
360
|
+
reader.releaseLock();
|
|
361
|
+
} catch {
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
const headers = new Headers(res.headers);
|
|
365
|
+
headers.delete("content-encoding");
|
|
366
|
+
headers.delete("content-length");
|
|
367
|
+
return new Response(Buffer.concat(chunks, total), {
|
|
368
|
+
status: res.status,
|
|
369
|
+
statusText: res.statusText,
|
|
370
|
+
headers
|
|
371
|
+
});
|
|
372
|
+
};
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
// src/tools/web-search/proxy-fetch.ts
|
|
376
|
+
function createProxyAwareFetch(proxyOpts, fetchImpl = import_undici.fetch) {
|
|
377
|
+
const bounded = boundedSearchFetch(fetchImpl);
|
|
378
|
+
return async (url, init) => {
|
|
379
|
+
const proxyUrl = resolveProxyForUrl(url, proxyOpts);
|
|
380
|
+
if (!proxyUrl) return bounded(url, init);
|
|
381
|
+
const merged = { ...init };
|
|
382
|
+
merged.dispatcher = new import_undici.ProxyAgent({ uri: proxyUrl });
|
|
383
|
+
return bounded(url, merged);
|
|
384
|
+
};
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
// src/tools/web-search/build-backends.ts
|
|
388
|
+
function resolveSearchKey(config, env, backend) {
|
|
389
|
+
const s = config.search;
|
|
390
|
+
const inlineKey = s[`${backend}ApiKey`];
|
|
391
|
+
if (typeof inlineKey === "string" && inlineKey.length > 0) return inlineKey;
|
|
392
|
+
const envName = s[`${backend}ApiKeyEnv`];
|
|
393
|
+
if (typeof envName === "string" && envName.length > 0) {
|
|
394
|
+
const v = env[envName];
|
|
395
|
+
if (v) return v;
|
|
396
|
+
}
|
|
397
|
+
return env[`${backend.toUpperCase()}_API_KEY`];
|
|
398
|
+
}
|
|
399
|
+
function buildSearchBackends(config, deps = {}) {
|
|
400
|
+
const fetchImpl = deps.fetch ?? createProxyAwareFetch(deps.proxy);
|
|
401
|
+
const env = deps.env ?? process.env;
|
|
402
|
+
const backends = [];
|
|
403
|
+
for (const name of config.search.backends) {
|
|
404
|
+
switch (name) {
|
|
405
|
+
case "bing":
|
|
406
|
+
backends.push(new BingBackend(fetchImpl));
|
|
407
|
+
break;
|
|
408
|
+
case "duckduckgo":
|
|
409
|
+
backends.push(new DuckDuckGoBackend(fetchImpl));
|
|
410
|
+
break;
|
|
411
|
+
case "brave":
|
|
412
|
+
backends.push(new BraveBackend(fetchImpl, resolveSearchKey(config, env, "brave"), config.search.region));
|
|
413
|
+
break;
|
|
414
|
+
case "tavily":
|
|
415
|
+
backends.push(new TavilyBackend(fetchImpl, resolveSearchKey(config, env, "tavily")));
|
|
416
|
+
break;
|
|
417
|
+
case "bocha":
|
|
418
|
+
backends.push(new BochaBackend(fetchImpl, resolveSearchKey(config, env, "bocha")));
|
|
419
|
+
break;
|
|
420
|
+
default:
|
|
421
|
+
break;
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
if (backends.length === 0) {
|
|
425
|
+
backends.push(new DuckDuckGoBackend(fetchImpl));
|
|
426
|
+
}
|
|
427
|
+
return backends;
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
export {
|
|
431
|
+
parseDuckDuckGoResults,
|
|
432
|
+
decodeHtmlEntities,
|
|
433
|
+
DuckDuckGoBackend,
|
|
434
|
+
createProxyAwareFetch,
|
|
435
|
+
BingBackend,
|
|
436
|
+
BraveBackend,
|
|
437
|
+
TavilyBackend,
|
|
438
|
+
resolveSearchKey,
|
|
439
|
+
buildSearchBackends
|
|
440
|
+
};
|