@te-river/opencode-team-mode 1.5.11 → 1.5.12

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 (89) hide show
  1. package/README.md +129 -53
  2. package/README.zh-CN.md +103 -45
  3. package/dist/agents.d.ts.map +1 -1
  4. package/dist/agents.js +17 -11
  5. package/dist/agents.js.map +1 -1
  6. package/dist/approval-gate.d.ts +54 -16
  7. package/dist/approval-gate.d.ts.map +1 -1
  8. package/dist/approval-gate.js +163 -42
  9. package/dist/approval-gate.js.map +1 -1
  10. package/dist/prompts/lead.d.ts +1 -1
  11. package/dist/prompts/lead.d.ts.map +1 -1
  12. package/dist/prompts/lead.js +22 -3
  13. package/dist/prompts/lead.js.map +1 -1
  14. package/dist/prompts/shared.d.ts +1 -1
  15. package/dist/prompts/shared.d.ts.map +1 -1
  16. package/dist/prompts/shared.js +154 -119
  17. package/dist/prompts/shared.js.map +1 -1
  18. package/dist/prompts/specialists.d.ts +2 -2
  19. package/dist/prompts/specialists.d.ts.map +1 -1
  20. package/dist/prompts/specialists.js +40 -11
  21. package/dist/prompts/specialists.js.map +1 -1
  22. package/dist/tm/args-schema.d.ts +25 -1
  23. package/dist/tm/args-schema.d.ts.map +1 -1
  24. package/dist/tm/args-schema.js +149 -39
  25. package/dist/tm/args-schema.js.map +1 -1
  26. package/dist/tm/browser.d.ts +188 -19
  27. package/dist/tm/browser.d.ts.map +1 -1
  28. package/dist/tm/browser.js +781 -111
  29. package/dist/tm/browser.js.map +1 -1
  30. package/dist/tm/config.d.ts +61 -0
  31. package/dist/tm/config.d.ts.map +1 -1
  32. package/dist/tm/config.js +55 -1
  33. package/dist/tm/config.js.map +1 -1
  34. package/dist/tm/index.d.ts +5 -3
  35. package/dist/tm/index.d.ts.map +1 -1
  36. package/dist/tm/index.js +36 -2
  37. package/dist/tm/index.js.map +1 -1
  38. package/dist/tm/memory.d.ts +88 -10
  39. package/dist/tm/memory.d.ts.map +1 -1
  40. package/dist/tm/memory.js +881 -99
  41. package/dist/tm/memory.js.map +1 -1
  42. package/dist/tm/pipelines.d.ts +26 -3
  43. package/dist/tm/pipelines.d.ts.map +1 -1
  44. package/dist/tm/pipelines.js +167 -11
  45. package/dist/tm/pipelines.js.map +1 -1
  46. package/dist/tm/ptc/budgets.d.ts +22 -1
  47. package/dist/tm/ptc/budgets.d.ts.map +1 -1
  48. package/dist/tm/ptc/budgets.js +87 -8
  49. package/dist/tm/ptc/budgets.js.map +1 -1
  50. package/dist/tm/ptc/contract.d.ts +49 -9
  51. package/dist/tm/ptc/contract.d.ts.map +1 -1
  52. package/dist/tm/ptc/contract.js +41 -3
  53. package/dist/tm/ptc/contract.js.map +1 -1
  54. package/dist/tm/ptc/driver.d.ts +5 -2
  55. package/dist/tm/ptc/driver.d.ts.map +1 -1
  56. package/dist/tm/ptc/driver.js +47 -15
  57. package/dist/tm/ptc/driver.js.map +1 -1
  58. package/dist/tm/ptc/engines.d.ts +15 -4
  59. package/dist/tm/ptc/engines.d.ts.map +1 -1
  60. package/dist/tm/ptc/engines.js +281 -28
  61. package/dist/tm/ptc/engines.js.map +1 -1
  62. package/dist/tm/ptc/index.d.ts +4 -4
  63. package/dist/tm/ptc/index.d.ts.map +1 -1
  64. package/dist/tm/ptc/index.js +2 -2
  65. package/dist/tm/ptc/index.js.map +1 -1
  66. package/dist/tm/ptc/pscan.d.ts +20 -1
  67. package/dist/tm/ptc/pscan.d.ts.map +1 -1
  68. package/dist/tm/ptc/pscan.js +328 -14
  69. package/dist/tm/ptc/pscan.js.map +1 -1
  70. package/dist/tm/ptc/summary.d.ts.map +1 -1
  71. package/dist/tm/ptc/summary.js +23 -1
  72. package/dist/tm/ptc/summary.js.map +1 -1
  73. package/dist/tm/ptc/tool.d.ts +34 -3
  74. package/dist/tm/ptc/tool.d.ts.map +1 -1
  75. package/dist/tm/ptc/tool.js +117 -20
  76. package/dist/tm/ptc/tool.js.map +1 -1
  77. package/dist/tm/search.d.ts +83 -14
  78. package/dist/tm/search.d.ts.map +1 -1
  79. package/dist/tm/search.js +440 -45
  80. package/dist/tm/search.js.map +1 -1
  81. package/dist/tm/shell-bridge.d.ts +14 -1
  82. package/dist/tm/shell-bridge.d.ts.map +1 -1
  83. package/dist/tm/shell-bridge.js +57 -10
  84. package/dist/tm/shell-bridge.js.map +1 -1
  85. package/dist/tm/webfetch.d.ts +25 -7
  86. package/dist/tm/webfetch.d.ts.map +1 -1
  87. package/dist/tm/webfetch.js +88 -14
  88. package/dist/tm/webfetch.js.map +1 -1
  89. package/package.json +5 -2
@@ -8,47 +8,134 @@
8
8
  import { estimateTokens, shouldOffload, shorten } from "../config.js";
9
9
  import { detectContentType } from "../preview.js";
10
10
  import { tmError } from "../result.js";
11
+ import { askUserForTarget } from "../perm-ask.js";
11
12
  import { BRIDGE_ALLOW } from "./contract.js";
12
13
  import { parsePtcArgs } from "./budgets.js";
13
14
  import { staticPscan } from "./pscan.js";
14
15
  import { runPtc } from "./driver.js";
15
16
  import { renderPtcSummary } from "./summary.js";
16
- // ---------- bridge over the real governed pipelines --------------------------
17
17
  /**
18
- * Real bridge: delegate each call to the corresponding exported pipeline,
19
- * `ctx` passed through untouched, and normalize the pipeline's `unknown`
20
- * result into `PtcCallResult` (TmErrorBody -> ok:false; anything else -> the
21
- * already-governed data). Governance is entirely the pipelines'.
18
+ * Unwrap a web tool's ToolResult back into the PTC `{ok,data}`/`{ok:false,
19
+ * error}` shape. The governed tools return `{output}` strings; a structured
20
+ * error renders with result.ts's pinned `[<tool> 失败 · phase=<phase>]`
21
+ * (optionally ` · line=<n>`) header line — the only machine-readable marker
22
+ * available at this boundary, so it is the split. Anything else (inline
23
+ * text, an offload handle block) is an ok result; a handle's ref is already
24
+ * in the text for the program to feed back through tm.fetch.
22
25
  */
23
- export function pipelineBridge(pipelines, ctx) {
26
+ function unwrapToolOutput(tool, output) {
27
+ const m = /^\[(\S+) 失败 · phase=([a-z]+)(?: · line=(-?\d+))?\]\n/.exec(output);
28
+ if (m && m[1] === tool) {
29
+ const phase = m[2];
30
+ const body = { tool, phase, message: output.slice(m[0].length) };
31
+ if (m[3] !== undefined)
32
+ Object.assign(body, { line: Number(m[3]) });
33
+ return { ok: false, error: body };
34
+ }
35
+ return { ok: true, data: output };
36
+ }
37
+ /**
38
+ * Build the OFFICIAL permission request the bridge raises for a bridged web
39
+ * call. The permission name is the tool itself (`tm_search` / `tm_webfetch`),
40
+ * so the host evaluates the CALLER'S own ruleset — exactly as a direct tool
41
+ * call would: `deny` for a non-web role, and for a web-granted role
42
+ * (lead/researcher) the default ruleset is `ask`, so each bridged web call
43
+ * pops a confirmation dialog (store an `allow` rule to skip it) — NOT a
44
+ * silent pass. The patterns carry the target host (webfetch) / engine
45
+ * (search) so any dialog that DOES pop is informative and no-secret.
46
+ */
47
+ export function webBridgeAsk(tool, args) {
48
+ if (tool === "tm_webfetch") {
49
+ const url = typeof args.url === "string" ? args.url : "";
50
+ let host = "";
51
+ try {
52
+ host = url ? new URL(url).hostname : "";
53
+ }
54
+ catch {
55
+ host = "";
56
+ }
57
+ return {
58
+ permission: "tm_webfetch",
59
+ patterns: host ? [host, url] : ["*"],
60
+ metadata: { tool, via: "tm_ptc_run", host },
61
+ };
62
+ }
63
+ const engine = typeof args.engine === "string" ? args.engine : "auto";
64
+ return {
65
+ permission: "tm_search",
66
+ patterns: [`engine:${engine}`],
67
+ metadata: { tool, via: "tm_ptc_run", engine },
68
+ };
69
+ }
70
+ export function pipelineBridge(pipelines, ctx, web) {
24
71
  const pick = (tool) => tool === "tm_read"
25
72
  ? pipelines.tmRead
26
73
  : tool === "tm_grep"
27
74
  ? pipelines.tmGrep
28
75
  : tool === "tm_bash"
29
76
  ? pipelines.tmBash
30
- : pipelines.tmFetch;
77
+ : tool === "tm_fetch"
78
+ ? pipelines.tmFetch
79
+ : tool === "tm_search"
80
+ ? web?.tm_search
81
+ : web?.tm_webfetch;
31
82
  return {
32
83
  async call(tool, args) {
33
84
  if (!BRIDGE_ALLOW.includes(tool)) {
34
85
  return { ok: false, error: tmError(tool, "args", "工具不在桥接白名单内").error };
35
86
  }
36
- const res = await pick(tool)(args ?? {}, ctx);
87
+ const target = pick(tool);
88
+ if (!target) {
89
+ // a web bridge the caller's role / config never enabled
90
+ return {
91
+ ok: false,
92
+ error: tmError(tool, "args", "web 桥未启用(TM_PTC_WEB_BRIDGE=off 或未装配)").error,
93
+ };
94
+ }
95
+ // C2: an ACTIVE role gate for bridged web — BEFORE execute. The bridge
96
+ // invokes the web tool's execute() directly, BYPASSING the host tool
97
+ // dispatch where agents.ts's `tm_search`/`tm_webfetch` = deny would
98
+ // otherwise block a non-web role, and the tools' own ctx.ask only pops
99
+ // for OUT-of-allowlist hosts (every default engine host is seeded). So
100
+ // without this the web bridge was a privilege-escalation path. Raise the
101
+ // SAME ruleset a direct call resolves: ctx.ask with the web permission
102
+ // name + target host/engine. A web-granted role hits the default `ask`
103
+ // rule → a confirmation dialog per call (an `allow` rule skips it); a
104
+ // non-web role's deny rule throws → a permission error step; a
105
+ // rejection or a missing ask bridge is fail-CLOSED.
106
+ if (tool === "tm_search" || tool === "tm_webfetch") {
107
+ const outcome = await askUserForTarget(ctx, webBridgeAsk(tool, args ?? {}));
108
+ if (outcome !== "approved") {
109
+ return {
110
+ ok: false,
111
+ error: tmError(tool, "permission", outcome === "rejected"
112
+ ? `角色无权通过 PTC 桥接使用 ${tool}(ruleset deny / 用户拒绝);web 桥仅授予 lead/researcher。`
113
+ : `无法通过桥接校验 ${tool} 权限(ctx.ask 不可用)——已按最小权限拒绝。`).error,
114
+ };
115
+ }
116
+ }
117
+ const res = typeof target === "function"
118
+ ? await target(args ?? {}, ctx)
119
+ : await target.execute(args ?? {}, ctx);
37
120
  if (res && typeof res === "object" && "error" in res) {
38
121
  return { ok: false, error: res.error };
39
122
  }
123
+ if (tool === "tm_search" || tool === "tm_webfetch") {
124
+ return unwrapToolOutput(tool, String(res?.output ?? res ?? ""));
125
+ }
40
126
  return { ok: true, data: res };
41
127
  },
42
128
  };
43
129
  }
44
130
  // ---------- the tool definition ----------------------------------------------
45
- const PTC_RUN_DESCRIPTION = `Batch orchestration: ONE async program makes N governed tm_* calls with ZERO LLM round-trips — use it INSTEAD of chaining ≥3 tm_read / tm_grep / tm_bash calls toward the same goal (multi-file recon, bulk grep+read aggregation, cross-referencing search results). Only a char-pinned aggregation summary returns to context, so ALWAYS \`return\` the aggregated value at the end of the program: unreturned inline results are discarded (offload handles stay retrievable via tm.fetch).
131
+ const PTC_RUN_DESCRIPTION = `Batch orchestration: ONE async program makes N governed tm_* calls with ZERO LLM round-trips — use it INSTEAD of chaining ≥3 tm_read / tm_grep / tm_bash calls toward the same goal (multi-file recon, bulk grep+read aggregation, cross-referencing search results). Best for READ-ONLY fan-out: reading many files, aggregating many searches, or any parallel read that would otherwise cost one LLM turn per call. Only a char-pinned aggregation summary returns to context, so ALWAYS \`return\` the aggregated value at the end of the program: unreturned inline results are discarded (offload handles stay retrievable via tm.fetch).
46
132
 
47
133
  - Example: \`const out = []; for (const p of ["a.ts", "b.ts", "c.ts"]) { const f = await tm.read({ path: p }); if (f.ok) out.push({ p, head: String(f.data).slice(0, 400) }); } return out;\`
48
- - program: an async function body. Available: \`tm.read(args)\`, \`tm.grep(args)\`, \`tm.bash(args)\`, \`tm.fetch(args)\` — same args as the tm_* four. Each returns \`{ok:true, data}\` (data is already governed: inline text, or an offload handle you can tm.fetch again) or \`{ok:false, error:{tool,phase,line?,message}}\`. \`return\` a value; it is JSON-serialized into the summary (capped 2000 chars, oversized → handle).
49
- - budgets (optional, tighten-only; clamped to TM_PTC_* ceilings): max_calls, max_errors, timeout_ms. Hitting any budget stops the whole run (produced output is NOT lost). Errors are retried at most once and only on idempotent phases (client/execute/store).
50
- - Governance is NOT bypassed: every bridged call runs the full tm_* pipeline (P2 path scope, P3 allowlist, R6, threshold offload + handles, TTL). Status is one of ok | stopped-error-budget | stopped-call-budget | timeout | engine-error.
51
- - Programs containing require/import/process/globalThis/Deno/Bun/fs/net/child_process are rejected before execution (static pre-scan, auxiliary guard).
134
+ - program: an async function body. Available: \`tm.read(args)\`, \`tm.grep(args)\`, \`tm.bash(args)\`, \`tm.fetch(args)\` — same args as the tm_* four — plus the WEB bridges \`await tm.search({ query, engine? })\` and \`await tm.webfetch({ url, fields? })\` (identical args to tm_search / tm_webfetch). Each returns \`{ok:true, data}\` (data is already governed: inline text, or an offload handle you can tm.fetch again) or \`{ok:false, error:{tool,phase,line?,message}}\`. \`return\` a value; it is JSON-serialized into the summary (capped 2000 chars, oversized → handle).
135
+ - Web bridge gating: tm.search / tm.webfetch run the REAL web tools under YOUR calling session's ctx, so the host evaluates them against YOUR agent's ruleset — a role without a web grant gets a \`permission\` error per call (bridged web is not a way around your tool whitelist), and \`TM_PTC_WEB_BRIDGE=off\` disables both. GETs are idempotent, so a transient client/execute/store failure retries once; a permission/args error never does.
136
+ - budgets (optional, tighten-only; clamped to TM_PTC_* ceilings): max_calls, max_errors, timeout_ms. Hitting any budget stops the whole run (produced output is NOT lost). Floors: max_calls 1 / max_errors 1 / timeout_ms 5000 ms; the summary echoes the EFFECTIVE budgets and flags every CLAMPED field (so a silently-narrowed budget is visible, not just the final number). Errors are retried at most once and only on idempotent phases (client/execute/store).
137
+ - Governance is NOT bypassed: every bridged call runs the full tm_* pipeline (P2 path scope, P3 allowlist, R6, threshold offload + handles, TTL). Status is one of ok | stopped-error-budget | stopped-call-budget | timeout | engine-error | program-error (program-error = the program itself threw — no auto-degrade re-run; engine-error = engine fault — auto mode re-runs the WHOLE program on the inline engine).
138
+ - Programs whose EXECUTABLE structure contains require/import/process/globalThis/Deno/Bun/fs/net/child_process are rejected before execution (static pre-scan, an auxiliary guard — NOT a security boundary). The pre-scan STRIPS string / template-literal / comment bodies first, so a grep pattern or log message that merely MENTIONS one of those words is fine — you do NOT need to obfuscate them; only a real \`require(...)\` / \`process.x\` call site is caught.
52
139
  - Engine: TM_PTC_ENGINE=auto|worker|inline (auto tries worker first; on engine failure it re-runs the WHOLE program on inline with a degraded-engine mark — bridged calls are read-only, so a re-run is safe, and the fallback starts with fresh budgets under the same wall-clock deadline).`;
53
140
  /** Build the tm_ptc_run ToolDefinition. Registered in the tool segment
54
141
  * when the agent's whitelist grants tm_ptc_run (M3). `deps.args` is the
@@ -56,7 +143,14 @@ const PTC_RUN_DESCRIPTION = `Batch orchestration: ONE async program makes N gove
56
143
  * descriptor fallback below keeps the tool usable without zod. */
57
144
  export function buildPtcRunTool(deps) {
58
145
  const { cfg, store, nextStepId, ctx, accessToken } = deps;
59
- const baseBridge = deps.bridge ?? (deps.pipelines ? pipelineBridge(deps.pipelines, ctx) : undefined);
146
+ // Per-call bridge factory. The bridge MUST bind the CALLER's execute ctx,
147
+ // not the assembly-time `{ directory }`: tm_search / tm_webfetch run their
148
+ // `ctx.ask` permission probe against the calling agent's session ruleset, so
149
+ // a non-web role's bridged web call is denied by the host exactly as if that
150
+ // agent had called the tool directly. A test-provided `deps.bridge` still
151
+ // wins (the §9 suite injects its own mock).
152
+ const makeBridge = (callCtx) => deps.bridge ??
153
+ (deps.pipelines ? pipelineBridge(deps.pipelines, callCtx ?? ctx, deps.webTools) : undefined);
60
154
  const expireAt = () => Date.now() + cfg.blackboardTtlDays * 24 * 60 * 60 * 1000;
61
155
  return {
62
156
  description: PTC_RUN_DESCRIPTION,
@@ -65,20 +159,23 @@ export function buildPtcRunTool(deps) {
65
159
  label: { descriptor: "label: string (optional, ≤80 chars)" },
66
160
  budgets: { descriptor: "budgets: { max_calls?, max_errors?, timeout_ms? } (optional, tighten-only)" },
67
161
  },
68
- execute: async (rawArgs) => {
162
+ execute: async (rawArgs, callCtx) => {
69
163
  const parsed = parsePtcArgs(rawArgs ?? {}, cfg);
70
164
  if (!parsed.ok) {
71
165
  return { output: `[${parsed.error.error.tool} 失败 · phase=${parsed.error.error.phase}]\n${parsed.error.error.message}` };
72
166
  }
73
- // static pre-scan — reject programs with banned tokens before any
74
- // engine runs.
167
+ // static pre-scan — reject programs with banned tokens in EXECUTABLE
168
+ // structure before any engine runs (string/comment literals are stripped
169
+ // first, so a grep pattern that merely MENTIONS `require` is not caught).
75
170
  const pscan = staticPscan(parsed.args.program);
76
171
  if (pscan.rejected) {
77
172
  return {
78
- output: `[tm_ptc_run 失败 · phase=args]\n程序包含禁止标识符(${pscan.tokens.join(", ")}),已拒绝执行。PTC 桥接仅暴露 tm.read/tm.grep/tm.bash/tm.fetch;require/import/process 等不在桥接白名单内。`,
173
+ output: `[tm_ptc_run 失败 · phase=args]\n程序包含禁止标识符(${pscan.tokens.join(", ")}),已拒绝执行。PTC 桥接仅暴露 tm.read/tm.grep/tm.bash/tm.fetch/tm.search/tm.webfetch(web 两项受 TM_PTC_WEB_BRIDGE 与角色权限门控);require/import/process 等不在桥接白名单内。`,
79
174
  };
80
175
  }
81
- if (!baseBridge) {
176
+ // Re-bind the bridge to THIS call's ctx (role-gated web permission).
177
+ const bridge = makeBridge(callCtx);
178
+ if (!bridge) {
82
179
  return {
83
180
  output: "[tm_ptc_run 失败 · phase=client]\n桥接管线未提供。",
84
181
  };
@@ -117,7 +214,7 @@ export function buildPtcRunTool(deps) {
117
214
  parentStepId,
118
215
  cfg,
119
216
  store,
120
- bridge: baseBridge,
217
+ bridge,
121
218
  ...(deps.engine ? { engine: deps.engine } : {}),
122
219
  });
123
220
  const content = renderPtcSummary(outcome, offloadBlock);
@@ -1 +1 @@
1
- {"version":3,"file":"tool.js","sourceRoot":"","sources":["../../../src/tm/ptc/tool.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"tool.js","sourceRoot":"","sources":["../../../src/tm/ptc/tool.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,OAAO,EAAiB,MAAM,cAAc,CAAA;AACpF,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAA;AAGjD,OAAO,EAAE,OAAO,EAAgB,MAAM,cAAc,CAAA;AACpD,OAAO,EAAE,gBAAgB,EAAqB,MAAM,gBAAgB,CAAA;AAGpE,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAE5C,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAC3C,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AACxC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACpC,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AAyB/C;;;;;;;;GAQG;AACH,SAAS,gBAAgB,CAAC,IAAgB,EAAE,MAAc;IACxD,MAAM,CAAC,GAAG,sDAAsD,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;IAC7E,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;QACvB,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,CAAY,CAAA;QAC7B,MAAM,IAAI,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAA;QAChE,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,SAAS;YAAE,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAA;QACnE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,CAAA;IACnC,CAAC;IACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,CAAA;AACnC,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,YAAY,CAAC,IAAgB,EAAE,IAA6B;IAC1E,IAAI,IAAI,KAAK,aAAa,EAAE,CAAC;QAC3B,MAAM,GAAG,GAAG,OAAO,IAAI,CAAC,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAA;QACxD,IAAI,IAAI,GAAG,EAAE,CAAA;QACb,IAAI,CAAC;YACH,IAAI,GAAG,GAAG,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAA;QACzC,CAAC;QAAC,MAAM,CAAC;YACP,IAAI,GAAG,EAAE,CAAA;QACX,CAAC;QACD,OAAO;YACL,UAAU,EAAE,aAAa;YACzB,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;YACpC,QAAQ,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,YAAY,EAAE,IAAI,EAAE;SAC5C,CAAA;IACH,CAAC;IACD,MAAM,MAAM,GAAG,OAAO,IAAI,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAA;IACrE,OAAO;QACL,UAAU,EAAE,WAAW;QACvB,QAAQ,EAAE,CAAC,UAAU,MAAM,EAAE,CAAC;QAC9B,QAAQ,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,YAAY,EAAE,MAAM,EAAE;KAC9C,CAAA;AACH,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,SAAsB,EAAE,GAAY,EAAE,GAAmB;IACtF,MAAM,IAAI,GAAG,CACX,IAAgB,EAIJ,EAAE,CACd,IAAI,KAAK,SAAS;QAChB,CAAC,CAAC,SAAS,CAAC,MAAM;QAClB,CAAC,CAAC,IAAI,KAAK,SAAS;YAClB,CAAC,CAAC,SAAS,CAAC,MAAM;YAClB,CAAC,CAAC,IAAI,KAAK,SAAS;gBAClB,CAAC,CAAC,SAAS,CAAC,MAAM;gBAClB,CAAC,CAAC,IAAI,KAAK,UAAU;oBACnB,CAAC,CAAC,SAAS,CAAC,OAAO;oBACnB,CAAC,CAAC,IAAI,KAAK,WAAW;wBACpB,CAAC,CAAC,GAAG,EAAE,SAAS;wBAChB,CAAC,CAAC,GAAG,EAAE,WAAW,CAAA;IAC9B,OAAO;QACL,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI;YACnB,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;gBACjC,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC,KAAK,EAAE,CAAA;YACxE,CAAC;YACD,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,CAAA;YACzB,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,wDAAwD;gBACxD,OAAO;oBACL,EAAE,EAAE,KAAK;oBACT,KAAK,EAAE,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,sCAAsC,CAAC,CAAC,KAAK;iBAC3E,CAAA;YACH,CAAC;YACD,wEAAwE;YACxE,qEAAqE;YACrE,oEAAoE;YACpE,uEAAuE;YACvE,wEAAwE;YACxE,0EAA0E;YAC1E,uEAAuE;YACvE,wEAAwE;YACxE,sEAAsE;YACtE,+DAA+D;YAC/D,oDAAoD;YACpD,IAAI,IAAI,KAAK,WAAW,IAAI,IAAI,KAAK,aAAa,EAAE,CAAC;gBACnD,MAAM,OAAO,GAAG,MAAM,gBAAgB,CAAC,GAAG,EAAE,YAAY,CAAC,IAAI,EAAE,IAAI,IAAI,EAAE,CAAC,CAAC,CAAA;gBAC3E,IAAI,OAAO,KAAK,UAAU,EAAE,CAAC;oBAC3B,OAAO;wBACL,EAAE,EAAE,KAAK;wBACT,KAAK,EAAE,OAAO,CACZ,IAAI,EACJ,YAAY,EACZ,OAAO,KAAK,UAAU;4BACpB,CAAC,CAAC,mBAAmB,IAAI,iDAAiD;4BAC1E,CAAC,CAAC,YAAY,IAAI,6BAA6B,CAClD,CAAC,KAAK;qBACR,CAAA;gBACH,CAAC;YACH,CAAC;YACD,MAAM,GAAG,GACP,OAAO,MAAM,KAAK,UAAU;gBAC1B,CAAC,CAAC,MAAM,MAAM,CAAC,IAAI,IAAI,EAAE,EAAE,GAAG,CAAC;gBAC/B,CAAC,CAAC,MAAM,MAAM,CAAC,OAAO,CAAC,IAAI,IAAI,EAAE,EAAE,GAAG,CAAC,CAAA;YAC3C,IAAI,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,OAAO,IAAK,GAA+B,EAAE,CAAC;gBAClF,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAG,GAA+B,CAAC,KAAK,EAAE,CAAA;YACrE,CAAC;YACD,IAAI,IAAI,KAAK,WAAW,IAAI,IAAI,KAAK,aAAa,EAAE,CAAC;gBACnD,OAAO,gBAAgB,CAAC,IAAI,EAAE,MAAM,CAAE,GAA4B,EAAE,MAAM,IAAI,GAAG,IAAI,EAAE,CAAC,CAAC,CAAA;YAC3F,CAAC;YACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,CAAA;QAChC,CAAC;KACF,CAAA;AACH,CAAC;AAED,gFAAgF;AAEhF,MAAM,mBAAmB,GAAG;;;;;;;;8RAQkQ,CAAA;AAE9R;;;mEAGmE;AACnE,MAAM,UAAU,eAAe,CAAC,IAW/B;IACC,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,UAAU,EAAE,GAAG,EAAE,WAAW,EAAE,GAAG,IAAI,CAAA;IACzD,2EAA2E;IAC3E,2EAA2E;IAC3E,6EAA6E;IAC7E,6EAA6E;IAC7E,2EAA2E;IAC3E,4CAA4C;IAC5C,MAAM,UAAU,GAAG,CAAC,OAAgB,EAAyB,EAAE,CAC7D,IAAI,CAAC,MAAM;QACX,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,cAAc,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,IAAI,GAAG,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAA;IAC9F,MAAM,QAAQ,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,GAAG,CAAC,iBAAiB,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAA;IAC/E,OAAO;QACL,WAAW,EAAE,mBAAmB;QAChC,IAAI,EAAE,IAAI,CAAC,IAAI,IAAI;YACjB,OAAO,EAAE,EAAE,UAAU,EAAE,sEAAsE,EAAE;YAC/F,KAAK,EAAE,EAAE,UAAU,EAAE,qCAAqC,EAAE;YAC5D,OAAO,EAAE,EAAE,UAAU,EAAE,4EAA4E,EAAE;SACtG;QACD,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAuB,EAAE;YACvD,MAAM,MAAM,GAAG,YAAY,CAAC,OAAO,IAAI,EAAE,EAAE,GAAG,CAAC,CAAA;YAC/C,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;gBACf,OAAO,EAAE,MAAM,EAAE,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,eAAe,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,MAAM,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,CAAA;YACzH,CAAC;YACD,qEAAqE;YACrE,yEAAyE;YACzE,0EAA0E;YAC1E,MAAM,KAAK,GAAG,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;YAC9C,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;gBACnB,OAAO;oBACL,MAAM,EAAE,2CAA2C,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,+IAA+I;iBAC1N,CAAA;YACH,CAAC;YACD,qEAAqE;YACrE,MAAM,MAAM,GAAG,UAAU,CAAC,OAAO,CAAC,CAAA;YAClC,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,OAAO;oBACL,MAAM,EAAE,0CAA0C;iBACnD,CAAA;YACH,CAAC;YACD,4CAA4C;YAC5C,MAAM,YAAY,GAAG,UAAU,EAAE,CAAA;YACjC,mEAAmE;YACnE,gEAAgE;YAChE,MAAM,YAAY,GAAG,CAAC,IAAY,EAAE,IAAY,EAAU,EAAE;gBAC1D,MAAM,MAAM,GAAG,cAAc,CAAC,IAAI,CAAC,CAAA;gBACnC,IAAI,CAAC;oBACH,MAAM,MAAM,GAAG,KAAK,CAAC,WAAW,CAAC,GAAG,YAAY,IAAI,IAAI,EAAE,EAAE;wBAC1D,IAAI,EAAE,YAAY;wBAClB,OAAO,EAAE,IAAI;wBACb,MAAM;wBACN,WAAW,EAAE,iBAAiB,CAAC,IAAI,CAAC;wBACpC,OAAO,EAAE,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC;wBAC3B,QAAQ,EAAE,QAAQ,EAAE;qBACrB,CAAC,CAAA;oBACF,OAAO;wBACL,QAAQ,MAAM,CAAC,GAAG,EAAE;wBACpB,iBAAiB,WAAW,EAAE;wBAC9B,cAAc,MAAM,CAAC,QAAQ,EAAE;wBAC/B,WAAW,MAAM,EAAE;wBACnB,2DAA2D;qBAC5D,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;gBACd,CAAC;gBAAC,MAAM,CAAC;oBACP,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,CAAA;gBAC5B,CAAC;YACH,CAAC,CAAA;YACD,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC;gBAC3B,OAAO,EAAE,MAAM,CAAC,IAAI,CAAC,OAAO;gBAC5B,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,KAAK;gBACxB,OAAO,EAAE,MAAM,CAAC,IAAI,CAAC,OAAO;gBAC5B,YAAY;gBACZ,GAAG;gBACH,KAAK;gBACL,MAAM;gBACN,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAChD,CAAC,CAAA;YACF,MAAM,OAAO,GAAG,gBAAgB,CAAC,OAAO,EAAE,YAAY,CAAC,CAAA;YACvD,2DAA2D;YAC3D,IAAI,aAAa,CAAC,cAAc,CAAC,OAAO,CAAC,EAAE,GAAG,CAAC,gBAAgB,CAAC,EAAE,CAAC;gBACjE,OAAO;oBACL,MAAM,EACJ,aAAa,cAAc,CAAC,OAAO,CAAC,4BAA4B;wBAChE,YAAY,CAAC,OAAO,EAAE,KAAK,CAAC;wBAC5B,0BAA0B,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE;iBACrD,CAAA;YACH,CAAC;YACD,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAA;QAC5B,CAAC;KACF,CAAA;AACH,CAAC"}
@@ -3,16 +3,27 @@
3
3
  *
4
4
  * One call, one query, clean results: the engine URL is built here, fetched
5
5
  * through the SAME pipeline as tm_webfetch (allowlist, manual redirects,
6
- * 20 s timeout, 2 MB cap) and collapsed into a numbered title+URL hit list
7
- * before governance — the agent never sees raw SERP chrome. Two engines
8
- * return structured JSON (npm registry search, GitHub repo search API) and
9
- * render with versions/stars/descriptions.
6
+ * 20 s timeout, 2 MB cap) and collapsed into a numbered title+URL(+snippet)
7
+ * hit list before governance — the agent never sees raw SERP chrome. The
8
+ * structured engines (npm registry, GitHub repo search, StackExchange
9
+ * question search, HN Algolia, MediaWiki) render with stars/score/tags/
10
+ * snippets.
10
11
  *
11
- * Engine set is chosen for mainland-China reachability without API keys:
12
- * bing CN + international (ensearch=1), sogou, 360 (so.com), baidu,
13
- * bilibili, plus the npm/GitHub data sources. Baidu is the flakiest
14
- * (anti-bot) and stays in the table because it is sometimes the only
15
- * engine indexing CN-specific content — failures name the alternatives.
12
+ * T4 quality upgrade (live benchmark 2026-09-14, CN host): of the HTML
13
+ * SERPs only bing still returns real results — sogou/so/baidu serve
14
+ * anti-bot shells and bing-int (ensearch=1) is 100% dead — so they are
15
+ * REMOVED from the engine table (webfetch's domain whitelist keeps their
16
+ * hosts untouched; users can still fetch those URLs directly). In their
17
+ * place two no-key JSON engines: stackoverflow (api.stackexchange.com,
18
+ * 300 req/day/IP — quota_remaining is tracked and auto-routing degrades to
19
+ * bing once exhausted) and hn (hn.algolia.com).
20
+ *
21
+ * `engine: "auto"` (the new default, TM_SEARCH_DEFAULT_ENGINE) classifies
22
+ * the query, fans out to the matching engine set IN PARALLEL, normalizes
23
+ * every engine's hits to SearchHit, dedupes by host+path and re-ranks
24
+ * with weighted RRF (stackoverflow 0.4 / bing 0.4 / others 0.2) into a
25
+ * top-10 list tagged with its source engine(s). Explicit single-engine
26
+ * calls keep the classic per-engine render.
16
27
  *
17
28
  * tm_webfetch stays the "fetch a KNOWN URL" tool; tm_browser covers
18
29
  * JS-rendered pages. All three share one domain allowlist and one
@@ -23,14 +34,52 @@ import { type TmConfig } from "./config.js";
23
34
  import type { TmPipelines } from "./pipelines.js";
24
35
  export interface SearchEngine {
25
36
  name: string;
26
- /** html engines are extracted via extractSearchHits; json engines have
27
- * a dedicated renderer below. */
28
- kind: "html" | "npm-json" | "github-json" | "wiki-json";
37
+ /** html engines are extracted via extractSearchHits; json engines have a
38
+ * dedicated parser/renderer below. */
39
+ kind: "html" | "npm-json" | "github-json" | "wiki-json" | "so-json" | "hn-json";
29
40
  buildUrl: (encodedQuery: string) => string;
30
41
  /** Hint appended when the engine returns nothing usable. */
31
42
  alt: string;
43
+ /** Transform the RAW query before URL-encoding (CJK phrase protection,
44
+ * GitHub qualifier folding). Identity when absent. */
45
+ prepareQuery?: (query: string) => string;
32
46
  }
33
- /** The engine table — keys are the tm_search `engine` arg values. */
47
+ /**
48
+ * CJK phrase protection: a multi-word Chinese query gets its CORE phrase
49
+ * (the token holding the most CJK chars, ≥2) wrapped in double quotes —
50
+ * CN SERPs otherwise free-match tokens across pages and drown the result
51
+ * list in tangential hits. Single-word queries and already-quoted queries
52
+ * pass through untouched (never fabricate a phrase boundary, never fight
53
+ * the user's own quoting). Applied to bing via prepareQuery; JSON query
54
+ * APIs are skipped because they treat quotes literally.
55
+ */
56
+ export declare function protectCjkPhrase(query: string): string;
57
+ export declare function foldGithubQualifiers(query: string): {
58
+ q: string;
59
+ qualifiers: string[];
60
+ };
61
+ export type QueryClass = "error-code" | "dev-ecosystem" | "cjk" | "general";
62
+ export declare function classifyQuery(query: string): QueryClass;
63
+ export declare const AUTO_ENGINE_KEY = "auto";
64
+ /** Mutable SO quota state (per process). api.stackexchange answers every
65
+ * payload with quota_remaining/quota_max; hitting 0 flips `exhausted`
66
+ * and engine:"auto" swaps the SO leg for bing until the process restarts
67
+ * (the daily quota rolls over on the server, not here). */
68
+ export declare const SO_QUOTA: {
69
+ max: number;
70
+ remaining: number | null;
71
+ exhausted: boolean;
72
+ };
73
+ export declare function resetSoQuota(): void;
74
+ /** Resolve the auto route set for a query (exported for tests + PTC). */
75
+ export declare function resolveAutoRoutes(query: string): {
76
+ routes: string[];
77
+ queryClass: QueryClass;
78
+ notes: string[];
79
+ };
80
+ /** The engine table — keys are the tm_search `engine` arg values. The
81
+ * dead CN SERPs (sogou/so/baidu/bing-int) are GONE, not even manually
82
+ * selectable (2026-09-14 benchmark: anti-bot shells / 100% empty). */
34
83
  export declare const SEARCH_ENGINES: Record<string, SearchEngine>;
35
84
  export declare const SEARCH_ENGINE_NAMES: string[];
36
85
  /** npm registry search JSON → numbered package list (name@version — desc). */
@@ -40,9 +89,28 @@ export declare function renderGithubResults(query: string, body: string): string
40
89
  /** MediaWiki search API JSON (moegirl) → numbered entry list with
41
90
  * tag-stripped snippets and direct article URLs. */
42
91
  export declare function renderWikiResults(query: string, body: string): string | null;
43
- /** Collapse an HTML SERP into the compact hit list; null when the engine
92
+ /** StackExchange search JSON → numbered question list; the per-hit snippet
93
+ * is SYNTHESIZED from the engine's own metadata (score/answers/tags —
94
+ * search/advanced carries no body text). The quota footer reflects the
95
+ * tracked quota_remaining. */
96
+ export declare function renderSoResults(query: string, body: string): string | null;
97
+ /** HN Algolia story search JSON → numbered post list; the per-hit snippet
98
+ * is the engine's own points/comments/date metadata. */
99
+ export declare function renderHnResults(query: string, body: string): string | null;
100
+ /** Collapse an HTML SERP into the compact hit list; [] when the engine
44
101
  * gave nothing extractable (anti-bot shell / markup change). */
45
102
  export declare function extractHtmlResults(html: string): SearchHit[];
103
+ /** host+path identity across engines (query/fragment/trailing-slash/www
104
+ * ignored) — the fusion dedupe key. */
105
+ export declare function dedupeKey(url: string): string;
106
+ interface FusionGroup {
107
+ engine: string;
108
+ hits: SearchHit[];
109
+ }
110
+ /** Reciprocal Rank Fusion over the routed engines' hit lists: normalize →
111
+ * host+path dedupe → score = Σ weight/(k+rank) → top-10, every hit tagged
112
+ * with its contributing engine(s). */
113
+ export declare function fuseRrf(groups: FusionGroup[], max?: number): SearchHit[];
46
114
  /** Build the tm_search ToolDefinition over the SHARED main pipelines
47
115
  * instance. `fetchImpl` is injectable for tests. */
48
116
  export declare function buildTmSearchTool(deps: {
@@ -55,4 +123,5 @@ export declare function buildTmSearchTool(deps: {
55
123
  args: Record<string, unknown>;
56
124
  execute: (rawArgs: Record<string, unknown>, ctx: unknown) => Promise<import("../types.js").ToolResult>;
57
125
  };
126
+ export {};
58
127
  //# sourceMappingURL=search.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../src/tm/search.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAkE,KAAK,SAAS,EAAE,KAAK,SAAS,EAAE,MAAM,eAAe,CAAA;AAE9H,OAAO,EAAW,KAAK,QAAQ,EAAE,MAAM,aAAa,CAAA;AAGpD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAEjD,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ;sCACkC;IAClC,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,aAAa,GAAG,WAAW,CAAA;IACvD,QAAQ,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,MAAM,CAAA;IAC1C,4DAA4D;IAC5D,GAAG,EAAE,MAAM,CAAA;CACZ;AAED,qEAAqE;AACrE,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAuDvD,CAAA;AAED,eAAO,MAAM,mBAAmB,UAA8B,CAAA;AAI9D,8EAA8E;AAC9E,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAmB3E;AAED,2EAA2E;AAC3E,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAsB9E;AAED;qDACqD;AACrD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CA2B5E;AAED;iEACiE;AACjE,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,EAAE,CAE5D;AAUD;sDACsD;AACtD,wBAAgB,iBAAiB,CAAC,IAAI,EAAE;IACtC,SAAS,EAAE,WAAW,CAAA;IACtB,GAAG,EAAE,QAAQ,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC9B,SAAS,CAAC,EAAE,SAAS,CAAA;CACtB,GAAG;IACF,WAAW,EAAE,MAAM,CAAA;IACnB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC7B,OAAO,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC,OAAO,aAAa,EAAE,UAAU,CAAC,CAAA;CACvG,CA8FA"}
1
+ {"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../src/tm/search.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH,OAAO,EAML,KAAK,SAAS,EACd,KAAK,SAAS,EACf,MAAM,eAAe,CAAA;AAEtB,OAAO,EAAW,KAAK,QAAQ,EAAE,MAAM,aAAa,CAAA;AAGpD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAEjD,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ;2CACuC;IACvC,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,aAAa,GAAG,WAAW,GAAG,SAAS,GAAG,SAAS,CAAA;IAC/E,QAAQ,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,MAAM,CAAA;IAC1C,4DAA4D;IAC5D,GAAG,EAAE,MAAM,CAAA;IACX;4DACwD;IACxD,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAA;CACzC;AAID;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAkBtD;AAQD,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,EAAE,CAAA;CAAE,CASvF;AAID,MAAM,MAAM,UAAU,GAAG,YAAY,GAAG,eAAe,GAAG,KAAK,GAAG,SAAS,CAAA;AAe3E,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,CAKvD;AASD,eAAO,MAAM,eAAe,SAAS,CAAA;AAQrC;;;4DAG4D;AAC5D,eAAO,MAAM,QAAQ,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,SAAS,EAAE,OAAO,CAAA;CAIjF,CAAA;AAED,wBAAgB,YAAY,IAAI,IAAI,CAInC;AAED,yEAAyE;AACzE,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG;IAAE,MAAM,EAAE,MAAM,EAAE,CAAC;IAAC,UAAU,EAAE,UAAU,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAA;CAAE,CAU9G;AAID;;uEAEuE;AACvE,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CA8CvD,CAAA;AAED,eAAO,MAAM,mBAAmB,UAA8B,CAAA;AA0F9D,8EAA8E;AAC9E,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAmB3E;AAED,2EAA2E;AAC3E,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAsB9E;AAED;qDACqD;AACrD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CA2B5E;AAED;;;+BAG+B;AAC/B,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAa1E;AAED;yDACyD;AACzD,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAW1E;AAED;iEACiE;AACjE,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,EAAE,CAE5D;AAsED;wCACwC;AACxC,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAS7C;AAED,UAAU,WAAW;IACnB,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,SAAS,EAAE,CAAA;CAClB;AAED;;uCAEuC;AACvC,wBAAgB,OAAO,CAAC,MAAM,EAAE,WAAW,EAAE,EAAE,GAAG,SAAkB,GAAG,SAAS,EAAE,CA+BjF;AA6BD;sDACsD;AACtD,wBAAgB,iBAAiB,CAAC,IAAI,EAAE;IACtC,SAAS,EAAE,WAAW,CAAA;IACtB,GAAG,EAAE,QAAQ,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC9B,SAAS,CAAC,EAAE,SAAS,CAAA;CACtB,GAAG;IACF,WAAW,EAAE,MAAM,CAAA;IACnB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC7B,OAAO,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC,OAAO,aAAa,EAAE,UAAU,CAAC,CAAA;CACvG,CA8JA"}