@dsh-edge/dsh-edge-agent 0.0.0-stage → 0.1.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 (238) hide show
  1. package/CHANGELOG.md +158 -0
  2. package/LICENSE +21 -0
  3. package/README.md +181 -2
  4. package/config/edge.example.json +179 -0
  5. package/config/privacy-policy.json +202 -0
  6. package/cordis.desktop-safe.patch.yml +129 -0
  7. package/cordis.patch.yml +382 -0
  8. package/cordis.yml +374 -0
  9. package/lib/attestation.d.ts +2 -0
  10. package/lib/attestation.d.ts.map +1 -0
  11. package/lib/attestation.js +2 -0
  12. package/lib/audit-log.d.ts +2 -0
  13. package/lib/audit-log.d.ts.map +1 -0
  14. package/lib/audit-log.js +2 -0
  15. package/lib/client.js +87 -0
  16. package/lib/cloud-llm-adapter.d.ts +2 -0
  17. package/lib/cloud-llm-adapter.d.ts.map +1 -0
  18. package/lib/cloud-llm-adapter.js +2 -0
  19. package/lib/dsh-adapter/attestation.d.ts +42 -0
  20. package/lib/dsh-adapter/attestation.d.ts.map +1 -0
  21. package/lib/dsh-adapter/attestation.js +40 -0
  22. package/lib/dsh-adapter/audit-log.d.ts +139 -0
  23. package/lib/dsh-adapter/audit-log.d.ts.map +1 -0
  24. package/lib/dsh-adapter/audit-log.js +376 -0
  25. package/lib/dsh-adapter/cloud-egress.d.ts +181 -0
  26. package/lib/dsh-adapter/cloud-egress.d.ts.map +1 -0
  27. package/lib/dsh-adapter/cloud-egress.js +257 -0
  28. package/lib/dsh-adapter/cloud-llm-adapter.d.ts +416 -0
  29. package/lib/dsh-adapter/cloud-llm-adapter.d.ts.map +1 -0
  30. package/lib/dsh-adapter/cloud-llm-adapter.js +1472 -0
  31. package/lib/dsh-adapter/contract.d.ts +80 -0
  32. package/lib/dsh-adapter/contract.d.ts.map +1 -0
  33. package/lib/dsh-adapter/contract.js +194 -0
  34. package/lib/dsh-adapter/desktop-cookie-janitor.d.ts +214 -0
  35. package/lib/dsh-adapter/desktop-cookie-janitor.d.ts.map +1 -0
  36. package/lib/dsh-adapter/desktop-cookie-janitor.js +409 -0
  37. package/lib/dsh-adapter/dsh-edge-agent.d.ts +48 -0
  38. package/lib/dsh-adapter/dsh-edge-agent.d.ts.map +1 -0
  39. package/lib/dsh-adapter/dsh-edge-agent.js +64 -0
  40. package/lib/dsh-adapter/edge-config.d.ts +484 -0
  41. package/lib/dsh-adapter/edge-config.d.ts.map +1 -0
  42. package/lib/dsh-adapter/edge-config.js +898 -0
  43. package/lib/dsh-adapter/edge-context-view.d.ts +184 -0
  44. package/lib/dsh-adapter/edge-context-view.d.ts.map +1 -0
  45. package/lib/dsh-adapter/edge-context-view.js +483 -0
  46. package/lib/dsh-adapter/effective-model.d.ts +85 -0
  47. package/lib/dsh-adapter/effective-model.d.ts.map +1 -0
  48. package/lib/dsh-adapter/effective-model.js +171 -0
  49. package/lib/dsh-adapter/etscli-shell-guard.d.ts +244 -0
  50. package/lib/dsh-adapter/etscli-shell-guard.d.ts.map +1 -0
  51. package/lib/dsh-adapter/etscli-shell-guard.js +420 -0
  52. package/lib/dsh-adapter/etscli-tools.d.ts +112 -0
  53. package/lib/dsh-adapter/etscli-tools.d.ts.map +1 -0
  54. package/lib/dsh-adapter/etscli-tools.js +393 -0
  55. package/lib/dsh-adapter/file-logger.d.ts +294 -0
  56. package/lib/dsh-adapter/file-logger.d.ts.map +1 -0
  57. package/lib/dsh-adapter/file-logger.js +564 -0
  58. package/lib/dsh-adapter/function-call-external.d.ts +357 -0
  59. package/lib/dsh-adapter/function-call-external.d.ts.map +1 -0
  60. package/lib/dsh-adapter/function-call-external.js +1005 -0
  61. package/lib/dsh-adapter/host-egress-guard.d.ts +161 -0
  62. package/lib/dsh-adapter/host-egress-guard.d.ts.map +1 -0
  63. package/lib/dsh-adapter/host-egress-guard.js +213 -0
  64. package/lib/dsh-adapter/host-llm-trace.d.ts +198 -0
  65. package/lib/dsh-adapter/host-llm-trace.d.ts.map +1 -0
  66. package/lib/dsh-adapter/host-llm-trace.js +344 -0
  67. package/lib/dsh-adapter/http-api-routes.d.ts +61 -0
  68. package/lib/dsh-adapter/http-api-routes.d.ts.map +1 -0
  69. package/lib/dsh-adapter/http-api-routes.js +79 -0
  70. package/lib/dsh-adapter/http-api-sessions.d.ts +105 -0
  71. package/lib/dsh-adapter/http-api-sessions.d.ts.map +1 -0
  72. package/lib/dsh-adapter/http-api-sessions.js +173 -0
  73. package/lib/dsh-adapter/http-api.d.ts +221 -0
  74. package/lib/dsh-adapter/http-api.d.ts.map +1 -0
  75. package/lib/dsh-adapter/http-api.js +1811 -0
  76. package/lib/dsh-adapter/index.d.ts +62 -0
  77. package/lib/dsh-adapter/index.d.ts.map +1 -0
  78. package/lib/dsh-adapter/index.js +97 -0
  79. package/lib/dsh-adapter/input-guard-messages.d.ts +56 -0
  80. package/lib/dsh-adapter/input-guard-messages.d.ts.map +1 -0
  81. package/lib/dsh-adapter/input-guard-messages.js +136 -0
  82. package/lib/dsh-adapter/input-guard.d.ts +508 -0
  83. package/lib/dsh-adapter/input-guard.d.ts.map +1 -0
  84. package/lib/dsh-adapter/input-guard.js +2174 -0
  85. package/lib/dsh-adapter/intent-prompts.d.ts +77 -0
  86. package/lib/dsh-adapter/intent-prompts.d.ts.map +1 -0
  87. package/lib/dsh-adapter/intent-prompts.js +97 -0
  88. package/lib/dsh-adapter/intent-router.d.ts +710 -0
  89. package/lib/dsh-adapter/intent-router.d.ts.map +1 -0
  90. package/lib/dsh-adapter/intent-router.js +2802 -0
  91. package/lib/dsh-adapter/intent-signals.d.ts +208 -0
  92. package/lib/dsh-adapter/intent-signals.d.ts.map +1 -0
  93. package/lib/dsh-adapter/intent-signals.js +391 -0
  94. package/lib/dsh-adapter/invariant-install.d.ts +16 -0
  95. package/lib/dsh-adapter/invariant-install.d.ts.map +1 -0
  96. package/lib/dsh-adapter/invariant-install.js +15 -0
  97. package/lib/dsh-adapter/invariant.d.ts +16 -0
  98. package/lib/dsh-adapter/invariant.d.ts.map +1 -0
  99. package/lib/dsh-adapter/invariant.js +22 -0
  100. package/lib/dsh-adapter/llm-adapters.d.ts +19 -0
  101. package/lib/dsh-adapter/llm-adapters.d.ts.map +1 -0
  102. package/lib/dsh-adapter/llm-adapters.js +16 -0
  103. package/lib/dsh-adapter/llm-internal-caller.d.ts +92 -0
  104. package/lib/dsh-adapter/llm-internal-caller.d.ts.map +1 -0
  105. package/lib/dsh-adapter/llm-internal-caller.js +100 -0
  106. package/lib/dsh-adapter/llm-max-turns.d.ts +55 -0
  107. package/lib/dsh-adapter/llm-max-turns.d.ts.map +1 -0
  108. package/lib/dsh-adapter/llm-max-turns.js +127 -0
  109. package/lib/dsh-adapter/llm-trace-store.d.ts +131 -0
  110. package/lib/dsh-adapter/llm-trace-store.d.ts.map +1 -0
  111. package/lib/dsh-adapter/llm-trace-store.js +205 -0
  112. package/lib/dsh-adapter/llm-trace.d.ts +450 -0
  113. package/lib/dsh-adapter/llm-trace.d.ts.map +1 -0
  114. package/lib/dsh-adapter/llm-trace.js +463 -0
  115. package/lib/dsh-adapter/local-llm-adapter.d.ts +141 -0
  116. package/lib/dsh-adapter/local-llm-adapter.d.ts.map +1 -0
  117. package/lib/dsh-adapter/local-llm-adapter.js +787 -0
  118. package/lib/dsh-adapter/local-storage.d.ts +96 -0
  119. package/lib/dsh-adapter/local-storage.d.ts.map +1 -0
  120. package/lib/dsh-adapter/local-storage.js +198 -0
  121. package/lib/dsh-adapter/model-router.d.ts +79 -0
  122. package/lib/dsh-adapter/model-router.d.ts.map +1 -0
  123. package/lib/dsh-adapter/model-router.js +107 -0
  124. package/lib/dsh-adapter/ohttp-gateway.d.ts +49 -0
  125. package/lib/dsh-adapter/ohttp-gateway.d.ts.map +1 -0
  126. package/lib/dsh-adapter/ohttp-gateway.js +32 -0
  127. package/lib/dsh-adapter/openai-sse.d.ts +85 -0
  128. package/lib/dsh-adapter/openai-sse.d.ts.map +1 -0
  129. package/lib/dsh-adapter/openai-sse.js +462 -0
  130. package/lib/dsh-adapter/pii-utils.d.ts +96 -0
  131. package/lib/dsh-adapter/pii-utils.d.ts.map +1 -0
  132. package/lib/dsh-adapter/pii-utils.js +324 -0
  133. package/lib/dsh-adapter/plugin-host.d.ts +38 -0
  134. package/lib/dsh-adapter/plugin-host.d.ts.map +1 -0
  135. package/lib/dsh-adapter/plugin-host.js +38 -0
  136. package/lib/dsh-adapter/plugin.d.ts +46 -0
  137. package/lib/dsh-adapter/plugin.d.ts.map +1 -0
  138. package/lib/dsh-adapter/plugin.js +100 -0
  139. package/lib/dsh-adapter/privacy-policy.d.ts +237 -0
  140. package/lib/dsh-adapter/privacy-policy.d.ts.map +1 -0
  141. package/lib/dsh-adapter/privacy-policy.js +391 -0
  142. package/lib/dsh-adapter/prompt-guard.d.ts +152 -0
  143. package/lib/dsh-adapter/prompt-guard.d.ts.map +1 -0
  144. package/lib/dsh-adapter/prompt-guard.js +872 -0
  145. package/lib/dsh-adapter/realm-skill-bridge.d.ts +365 -0
  146. package/lib/dsh-adapter/realm-skill-bridge.d.ts.map +1 -0
  147. package/lib/dsh-adapter/realm-skill-bridge.js +1180 -0
  148. package/lib/dsh-adapter/sanitizer-pipeline.d.ts +140 -0
  149. package/lib/dsh-adapter/sanitizer-pipeline.d.ts.map +1 -0
  150. package/lib/dsh-adapter/sanitizer-pipeline.js +431 -0
  151. package/lib/dsh-adapter/secure-bridge.d.ts +47 -0
  152. package/lib/dsh-adapter/secure-bridge.d.ts.map +1 -0
  153. package/lib/dsh-adapter/secure-bridge.js +35 -0
  154. package/lib/dsh-adapter/session-attribution.d.ts +70 -0
  155. package/lib/dsh-adapter/session-attribution.d.ts.map +1 -0
  156. package/lib/dsh-adapter/session-attribution.js +76 -0
  157. package/lib/dsh-adapter/sessions.d.ts +86 -0
  158. package/lib/dsh-adapter/sessions.d.ts.map +1 -0
  159. package/lib/dsh-adapter/sessions.js +179 -0
  160. package/lib/dsh-adapter/tcm.d.ts +55 -0
  161. package/lib/dsh-adapter/tcm.d.ts.map +1 -0
  162. package/lib/dsh-adapter/tcm.js +94 -0
  163. package/lib/dsh-adapter/td-bus.d.ts +87 -0
  164. package/lib/dsh-adapter/td-bus.d.ts.map +1 -0
  165. package/lib/dsh-adapter/td-bus.js +196 -0
  166. package/lib/dsh-adapter/tool-runner.d.ts +185 -0
  167. package/lib/dsh-adapter/tool-runner.d.ts.map +1 -0
  168. package/lib/dsh-adapter/tool-runner.js +271 -0
  169. package/lib/dsh-adapter/tools.d.ts +118 -0
  170. package/lib/dsh-adapter/tools.d.ts.map +1 -0
  171. package/lib/dsh-adapter/tools.js +292 -0
  172. package/lib/dsh-adapter/types.d.ts +23 -0
  173. package/lib/dsh-adapter/types.d.ts.map +1 -0
  174. package/lib/dsh-adapter/types.js +16 -0
  175. package/lib/dsh-adapter/voice-input.d.ts +30 -0
  176. package/lib/dsh-adapter/voice-input.d.ts.map +1 -0
  177. package/lib/dsh-adapter/voice-input.js +34 -0
  178. package/lib/dsh-adapter/web-search-tavily-bocha.d.ts +152 -0
  179. package/lib/dsh-adapter/web-search-tavily-bocha.d.ts.map +1 -0
  180. package/lib/dsh-adapter/web-search-tavily-bocha.js +289 -0
  181. package/lib/http-api.d.ts +2 -0
  182. package/lib/http-api.d.ts.map +1 -0
  183. package/lib/http-api.js +2 -0
  184. package/lib/index.d.ts +48 -0
  185. package/lib/index.d.ts.map +1 -0
  186. package/lib/index.js +49 -0
  187. package/lib/intent-router.d.ts +2 -0
  188. package/lib/intent-router.d.ts.map +1 -0
  189. package/lib/intent-router.js +2 -0
  190. package/lib/llm-adapters.d.ts +2 -0
  191. package/lib/llm-adapters.d.ts.map +1 -0
  192. package/lib/llm-adapters.js +2 -0
  193. package/lib/local-llm-adapter.d.ts +2 -0
  194. package/lib/local-llm-adapter.d.ts.map +1 -0
  195. package/lib/local-llm-adapter.js +2 -0
  196. package/lib/local-storage.d.ts +2 -0
  197. package/lib/local-storage.d.ts.map +1 -0
  198. package/lib/local-storage.js +2 -0
  199. package/lib/model-router.d.ts +2 -0
  200. package/lib/model-router.d.ts.map +1 -0
  201. package/lib/model-router.js +2 -0
  202. package/lib/ohttp-gateway.d.ts +2 -0
  203. package/lib/ohttp-gateway.d.ts.map +1 -0
  204. package/lib/ohttp-gateway.js +2 -0
  205. package/lib/plugin-host.d.ts +2 -0
  206. package/lib/plugin-host.d.ts.map +1 -0
  207. package/lib/plugin-host.js +2 -0
  208. package/lib/privacy-policy.d.ts +2 -0
  209. package/lib/privacy-policy.d.ts.map +1 -0
  210. package/lib/privacy-policy.js +2 -0
  211. package/lib/prompt-guard.d.ts +2 -0
  212. package/lib/prompt-guard.d.ts.map +1 -0
  213. package/lib/prompt-guard.js +2 -0
  214. package/lib/sanitizer-pipeline.d.ts +2 -0
  215. package/lib/sanitizer-pipeline.d.ts.map +1 -0
  216. package/lib/sanitizer-pipeline.js +2 -0
  217. package/lib/secure-bridge.d.ts +2 -0
  218. package/lib/secure-bridge.d.ts.map +1 -0
  219. package/lib/secure-bridge.js +2 -0
  220. package/lib/sessions.d.ts +2 -0
  221. package/lib/sessions.d.ts.map +1 -0
  222. package/lib/sessions.js +2 -0
  223. package/lib/tcm.d.ts +2 -0
  224. package/lib/tcm.d.ts.map +1 -0
  225. package/lib/tcm.js +2 -0
  226. package/lib/td-bus.d.ts +2 -0
  227. package/lib/td-bus.d.ts.map +1 -0
  228. package/lib/td-bus.js +2 -0
  229. package/lib/tools.d.ts +2 -0
  230. package/lib/tools.d.ts.map +1 -0
  231. package/lib/tools.js +2 -0
  232. package/lib/voice-input.d.ts +2 -0
  233. package/lib/voice-input.d.ts.map +1 -0
  234. package/lib/voice-input.js +2 -0
  235. package/package.json +253 -3
  236. package/presets/agent-preset-edge.json +50 -0
  237. package/presets/edge.desktop-safe.patch.yml +503 -0
  238. package/presets/edge.patch.yml +557 -0
@@ -0,0 +1,152 @@
1
+ /**
2
+ * web-search-tavily-bocha — Phase 5 (§7.82) 3-tier fallback search provider.
3
+ *
4
+ * Provider chain (resolved per call, on `ctx.web.search`):
5
+ * 1. Tavily — primary (English/global, AI-tuned results, `tavilyApiKey`)
6
+ * 2. 博查 AI — secondary (Chinese search optimization, `bochaApiKey`)
7
+ * 3. DeepSeek — tertiary (re-imports `@deepseek-ai/dsh-web-search-deepseek`,
8
+ * uses native `web_search_20250305` server tool on Anthropic
9
+ * Messages; final backstop when both Tavily and Bocha fail
10
+ * or when neither key is set and only DEEPSEEK_API_KEY is present)
11
+ *
12
+ * Configuration (.env-managed via §7.75 .env.sh source chain — bare names,
13
+ * no DSH_/XDG_/DYLD_/BASH_FUNC_ prefix to bypass dsh-app-boot blacklist):
14
+ * - TAVILY_API_KEY (Tier 1) — bare name, lives in repo .env
15
+ * - BOCHA_API_KEY (Tier 2) — bare name, lives in repo .env
16
+ * - DEEPSEEK_API_KEY (Tier 3 fallback, already required for cloud-llm)
17
+ * - DEEPSEEK_BASE_URL (optional, default https://api.deepseek.com/anthropic/v1)
18
+ *
19
+ * Where the keys come from (§7.102, 2026-10-21): config/edge.json
20
+ * `secrets.tavilyApiKey` / `secrets.bochaApiKey` / `secrets.deepseekApiKey`.
21
+ * The old flow was: repo .env → install.sh `source .env.sh` → process.env
22
+ * → this read. That chain is gone — the desktop GUI never sourced it, so
23
+ * the desktop build had no search keys at all. The env names below stay
24
+ * honoured as a per-process override.
25
+ *
26
+ * Why bare names (NOT DSH_EDGE_* prefix)? DSH dsh-app-boot 0.1.2-rc.1's
27
+ * BOOTSTRAP_PREFIXES = ["DSH_", "XDG_", "DYLD_", "BASH_FUNC_"] rejects any
28
+ * DSH_-prefixed KEY in .env files when dsh itself parses them
29
+ * (dsh-app-boot/lib/index.js:933-1015). Bare names stay compatible with
30
+ * that launcher behaviour for the env override path.
31
+ *
32
+ * Cordis integration: registers as a single search provider with id
33
+ * `tavily-bocha-fallback` in `ctx.web`. `available()` returns true iff at
34
+ * least one tier has its key configured — when both Tavily and Bocha keys
35
+ * are missing but DEEPSEEK_API_KEY is set, the aggregator still registers
36
+ * (Tier-3 DeepSeek only), avoiding the seam's `WEB_PROVIDER_UNAVAILABLE`.
37
+ *
38
+ * Fallback semantics mirror lingguard's `internal/tools/web.go` (Tavily →
39
+ * 博查) but extend to a 3rd tier for resilience: any exception from a tier
40
+ * (HTTP non-2xx, malformed JSON, AbortError) is logged and the next tier
41
+ * takes over. Final WebError `WEB_PROVIDER_UNAVAILABLE` only fires when ALL
42
+ * three tiers fail or are unavailable.
43
+ */
44
+ import { type WebSearchProvider, type WebSearchRequest, type WebSearchResult } from '@deepseek-ai/dsh-web';
45
+ import { DeepSeekSearchProvider } from '@deepseek-ai/dsh-web-search-deepseek';
46
+ import type { Context } from '@deepseek-ai/cordis';
47
+ import Schema from '@deepseek-ai/schemastery';
48
+ /** Stable id for `ctx.web.searchProviderId` selection and audit messages. */
49
+ export declare const TAVILY_BOCHA_PROVIDER_ID = "tavily-bocha-fallback";
50
+ /**
51
+ * Cordis plugin name — must match the `id:` row in `cordis.patch.yml`.
52
+ */
53
+ export declare const name = "web-search-tavily-bocha";
54
+ /** Inject `web` (seam) so `ctx.web.registerSearchProvider` is available. */
55
+ export declare const inject: string[];
56
+ /**
57
+ * Config schema. The aggregator is fully env-driven (§7.82: TAVILY_API_KEY
58
+ * / BOCHA_API_KEY / DEEPSEEK_API_KEY — bare names per §7.75), so the schema is
59
+ * intentionally minimal — provided only to satisfy the `verify:plugin-spec`
60
+ * battery. Future Phase 5 work (per-provider rate-limit split, domain
61
+ * whitelist, SafeSearch) can add fields here without touching `apply()`.
62
+ */
63
+ export interface Config {
64
+ /** Reserved for future tuning knobs. No-op in v0.1.x. */
65
+ reserved: Record<string, unknown>;
66
+ }
67
+ export declare const Config: Schema<Config>;
68
+ /**
69
+ * Aggregator provider: Tier-1 Tavily → Tier-2 Bocha → Tier-3 DeepSeek.
70
+ * Implements the `WebSearchProvider` interface from `@deepseek-ai/dsh-web`.
71
+ */
72
+ export declare class TavilyBochaFallbackProvider implements WebSearchProvider {
73
+ private readonly tavilyKey;
74
+ private readonly bochaKey;
75
+ private readonly dsKey;
76
+ private readonly deepseek;
77
+ /**
78
+ * §7.107 (2026-10-24): per-tier switches. `config/edge.json` has always
79
+ * declared `webSearch.tavilyEnabled` / `bochaEnabled` — and NOTHING read
80
+ * them: the tiers were gated purely on "is the key present". An operator
81
+ * who wanted DeepSeek Search as the backend had no way to say so; every
82
+ * search burned two 401 round-trips on the way down the chain to it.
83
+ * §7.182 (2026-11-11, owner ruling): the shipped default is **OFF** for
84
+ * both tiers ⇒ out of the box only the DeepSeek tier is on the chain.
85
+ * An unset switch therefore means DISABLED (opt-in, not opt-out).
86
+ */
87
+ private readonly tiers;
88
+ readonly id = "tavily-bocha-fallback";
89
+ constructor(tavilyKey: string | undefined, bochaKey: string | undefined, dsKey: string | undefined, deepseek: DeepSeekSearchProvider,
90
+ /**
91
+ * §7.107 (2026-10-24): per-tier switches. `config/edge.json` has always
92
+ * declared `webSearch.tavilyEnabled` / `bochaEnabled` — and NOTHING read
93
+ * them: the tiers were gated purely on "is the key present". An operator
94
+ * who wanted DeepSeek Search as the backend had no way to say so; every
95
+ * search burned two 401 round-trips on the way down the chain to it.
96
+ * §7.182 (2026-11-11, owner ruling): the shipped default is **OFF** for
97
+ * both tiers ⇒ out of the box only the DeepSeek tier is on the chain.
98
+ * An unset switch therefore means DISABLED (opt-in, not opt-out).
99
+ */
100
+ tiers?: {
101
+ tavilyEnabled?: boolean;
102
+ bochaEnabled?: boolean;
103
+ });
104
+ private get tavilyEnabled();
105
+ private get bochaEnabled();
106
+ /**
107
+ * Cheap local availability check; no network calls. Returns true iff any
108
+ * tier can serve — at least one of Tavily/Bocha/DeepSeek key set.
109
+ *
110
+ * We deliberately do NOT delegate to `this.deepseek.available()` because
111
+ * upstream's check returns true whenever a `resolveApiKey` thunk is
112
+ * defined, regardless of whether the resolved key string is empty.
113
+ * Our caller may legitimately invoke us with `dsKey=undefined` (Tiers 1/2
114
+ * only config), so we must check the key string ourselves.
115
+ *
116
+ * When ALL three are unavailable, `ctx.web` will filter us out and the
117
+ * seam will throw `WEB_PROVIDER_UNAVAILABLE` only if no other provider
118
+ * is registered as a fallback. (We always register this row, so an
119
+ * absent-key env is a no-op rather than an error.)
120
+ */
121
+ available(): boolean;
122
+ search(request: WebSearchRequest, signal?: AbortSignal): Promise<WebSearchResult>;
123
+ private searchTavily;
124
+ private searchBocha;
125
+ }
126
+ /**
127
+ * The dsh loader passes the parent Cordis `ctx` here; `inject: ['web']`
128
+ * guarantees `ctx.web` is non-null. We register one aggregator provider
129
+ * whose id is `tavily-bocha-fallback`.
130
+ *
131
+ * The Tier-3 DeepSeek provider is constructed (not registered) so we can
132
+ * invoke its `search()` directly inside our Tier-3 fallback path. The
133
+ * upstream `web-search-deepseek` plugin row is kept enabled in
134
+ * `cordis.patch.yml` so its `registerSearchProvider('deepseek-official')`
135
+ * also fires — but DSH's seam then sees TWO registered search providers
136
+ * (ours + deepseek-official) and would throw `WEB_PROVIDER_AMBIGUOUS`.
137
+ *
138
+ * To avoid that, the cordis.patch.yml disables `web-search-deepseek` when
139
+ * `web-search-tavily-bocha` is enabled; the Tier-3 fallback inside the
140
+ * aggregator reaches the same DeepSeek HTTP endpoint by holding a private
141
+ * `DeepSeekSearchProvider` instance, so we never lose the backstop.
142
+ *
143
+ * @param ctx - Cordis context with `ctx.web` available per `inject`.
144
+ */
145
+ export declare function apply(ctx: Context, _config: Config): Promise<void>;
146
+ declare const _default: {
147
+ name: string;
148
+ inject: string[];
149
+ apply: typeof apply;
150
+ };
151
+ export default _default;
152
+ //# sourceMappingURL=web-search-tavily-bocha.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"web-search-tavily-bocha.d.ts","sourceRoot":"","sources":["../../src/dsh-adapter/web-search-tavily-bocha.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AAEH,OAAO,EAAY,KAAK,iBAAiB,EAAE,KAAK,gBAAgB,EAAE,KAAK,eAAe,EAAE,MAAM,sBAAsB,CAAA;AACpH,OAAO,EAAE,sBAAsB,EAAE,MAAM,sCAAsC,CAAA;AAC7E,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,MAAM,MAAM,0BAA0B,CAAA;AAW7C,6EAA6E;AAC7E,eAAO,MAAM,wBAAwB,0BAA0B,CAAA;AAE/D;;GAEG;AACH,eAAO,MAAM,IAAI,4BAA4B,CAAA;AAE7C,4EAA4E;AAC5E,eAAO,MAAM,MAAM,UAAU,CAAA;AAE7B;;;;;;GAMG;AACH,MAAM,WAAW,MAAM;IACrB,yDAAyD;IACzD,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAClC;AAED,eAAO,MAAM,MAAM,EAAE,MAAM,CAAC,MAAM,CAEhC,CAAA;AAEF;;;GAGG;AACH,qBAAa,2BAA4B,YAAW,iBAAiB;IAIjE,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB;;;;;;;;;OASG;IACH,OAAO,CAAC,QAAQ,CAAC,KAAK;IAjBxB,QAAQ,CAAC,EAAE,2BAA2B;gBAGnB,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,QAAQ,EAAE,MAAM,GAAG,SAAS,EAC5B,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,QAAQ,EAAE,sBAAsB;IACjD;;;;;;;;;OASG;IACc,KAAK,GAAE;QAAE,aAAa,CAAC,EAAE,OAAO,CAAC;QAAC,YAAY,CAAC,EAAE,OAAO,CAAA;KAAO;IAGlF,OAAO,KAAK,aAAa,GAGxB;IAED,OAAO,KAAK,YAAY,GAGvB;IAED;;;;;;;;;;;;;;OAcG;IACH,SAAS,IAAI,OAAO;IAId,MAAM,CAAC,OAAO,EAAE,gBAAgB,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,eAAe,CAAC;YA+CzE,YAAY;YAwCZ,WAAW;CA8D1B;AAGD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAsCxE;;;;;;AAED,wBAAsC"}
@@ -0,0 +1,289 @@
1
+ /**
2
+ * web-search-tavily-bocha — Phase 5 (§7.82) 3-tier fallback search provider.
3
+ *
4
+ * Provider chain (resolved per call, on `ctx.web.search`):
5
+ * 1. Tavily — primary (English/global, AI-tuned results, `tavilyApiKey`)
6
+ * 2. 博查 AI — secondary (Chinese search optimization, `bochaApiKey`)
7
+ * 3. DeepSeek — tertiary (re-imports `@deepseek-ai/dsh-web-search-deepseek`,
8
+ * uses native `web_search_20250305` server tool on Anthropic
9
+ * Messages; final backstop when both Tavily and Bocha fail
10
+ * or when neither key is set and only DEEPSEEK_API_KEY is present)
11
+ *
12
+ * Configuration (.env-managed via §7.75 .env.sh source chain — bare names,
13
+ * no DSH_/XDG_/DYLD_/BASH_FUNC_ prefix to bypass dsh-app-boot blacklist):
14
+ * - TAVILY_API_KEY (Tier 1) — bare name, lives in repo .env
15
+ * - BOCHA_API_KEY (Tier 2) — bare name, lives in repo .env
16
+ * - DEEPSEEK_API_KEY (Tier 3 fallback, already required for cloud-llm)
17
+ * - DEEPSEEK_BASE_URL (optional, default https://api.deepseek.com/anthropic/v1)
18
+ *
19
+ * Where the keys come from (§7.102, 2026-10-21): config/edge.json
20
+ * `secrets.tavilyApiKey` / `secrets.bochaApiKey` / `secrets.deepseekApiKey`.
21
+ * The old flow was: repo .env → install.sh `source .env.sh` → process.env
22
+ * → this read. That chain is gone — the desktop GUI never sourced it, so
23
+ * the desktop build had no search keys at all. The env names below stay
24
+ * honoured as a per-process override.
25
+ *
26
+ * Why bare names (NOT DSH_EDGE_* prefix)? DSH dsh-app-boot 0.1.2-rc.1's
27
+ * BOOTSTRAP_PREFIXES = ["DSH_", "XDG_", "DYLD_", "BASH_FUNC_"] rejects any
28
+ * DSH_-prefixed KEY in .env files when dsh itself parses them
29
+ * (dsh-app-boot/lib/index.js:933-1015). Bare names stay compatible with
30
+ * that launcher behaviour for the env override path.
31
+ *
32
+ * Cordis integration: registers as a single search provider with id
33
+ * `tavily-bocha-fallback` in `ctx.web`. `available()` returns true iff at
34
+ * least one tier has its key configured — when both Tavily and Bocha keys
35
+ * are missing but DEEPSEEK_API_KEY is set, the aggregator still registers
36
+ * (Tier-3 DeepSeek only), avoiding the seam's `WEB_PROVIDER_UNAVAILABLE`.
37
+ *
38
+ * Fallback semantics mirror lingguard's `internal/tools/web.go` (Tavily →
39
+ * 博查) but extend to a 3rd tier for resilience: any exception from a tier
40
+ * (HTTP non-2xx, malformed JSON, AbortError) is logged and the next tier
41
+ * takes over. Final WebError `WEB_PROVIDER_UNAVAILABLE` only fires when ALL
42
+ * three tiers fail or are unavailable.
43
+ */
44
+ import { WebError } from '@deepseek-ai/dsh-web';
45
+ import { DeepSeekSearchProvider } from '@deepseek-ai/dsh-web-search-deepseek';
46
+ import Schema from '@deepseek-ai/schemastery';
47
+ import { loadEdgeConfig } from './edge-config.js';
48
+ // ── Endpoints (fixed; these are the only authoritative hosts for each provider) ─────
49
+ const TAVILY_ENDPOINT = 'https://api.tavily.com/search';
50
+ // 博查 AI web-search endpoint (§7.82.2 修正域名 —— 旧 `api.bocha.cn` 是误传,
51
+ // 官方开放平台 docs https://open.bochaai.com 明确指向 `api.bochaai.com`;
52
+ // 旧域名持任何 key 都会 403 quota 错误,实际是路由不可达伪装成 quota)。
53
+ const BOCHA_ENDPOINT = 'https://api.bochaai.com/v1/web-search';
54
+ const DEEPSEEK_DEFAULT_BASE_URL = 'https://api.deepseek.com/anthropic/v1';
55
+ /** Stable id for `ctx.web.searchProviderId` selection and audit messages. */
56
+ export const TAVILY_BOCHA_PROVIDER_ID = 'tavily-bocha-fallback';
57
+ /**
58
+ * Cordis plugin name — must match the `id:` row in `cordis.patch.yml`.
59
+ */
60
+ export const name = 'web-search-tavily-bocha';
61
+ /** Inject `web` (seam) so `ctx.web.registerSearchProvider` is available. */
62
+ export const inject = ['web'];
63
+ export const Config = Schema.object({
64
+ reserved: Schema.dict(Schema.any()).default({}),
65
+ });
66
+ /**
67
+ * Aggregator provider: Tier-1 Tavily → Tier-2 Bocha → Tier-3 DeepSeek.
68
+ * Implements the `WebSearchProvider` interface from `@deepseek-ai/dsh-web`.
69
+ */
70
+ export class TavilyBochaFallbackProvider {
71
+ tavilyKey;
72
+ bochaKey;
73
+ dsKey;
74
+ deepseek;
75
+ tiers;
76
+ id = TAVILY_BOCHA_PROVIDER_ID;
77
+ constructor(tavilyKey, bochaKey, dsKey, deepseek,
78
+ /**
79
+ * §7.107 (2026-10-24): per-tier switches. `config/edge.json` has always
80
+ * declared `webSearch.tavilyEnabled` / `bochaEnabled` — and NOTHING read
81
+ * them: the tiers were gated purely on "is the key present". An operator
82
+ * who wanted DeepSeek Search as the backend had no way to say so; every
83
+ * search burned two 401 round-trips on the way down the chain to it.
84
+ * §7.182 (2026-11-11, owner ruling): the shipped default is **OFF** for
85
+ * both tiers ⇒ out of the box only the DeepSeek tier is on the chain.
86
+ * An unset switch therefore means DISABLED (opt-in, not opt-out).
87
+ */
88
+ tiers = {}) {
89
+ this.tavilyKey = tavilyKey;
90
+ this.bochaKey = bochaKey;
91
+ this.dsKey = dsKey;
92
+ this.deepseek = deepseek;
93
+ this.tiers = tiers;
94
+ }
95
+ get tavilyEnabled() {
96
+ // §7.182: unset = disabled (the shipped default is off).
97
+ return this.tiers.tavilyEnabled === true;
98
+ }
99
+ get bochaEnabled() {
100
+ // §7.182: unset = disabled (the shipped default is off).
101
+ return this.tiers.bochaEnabled === true;
102
+ }
103
+ /**
104
+ * Cheap local availability check; no network calls. Returns true iff any
105
+ * tier can serve — at least one of Tavily/Bocha/DeepSeek key set.
106
+ *
107
+ * We deliberately do NOT delegate to `this.deepseek.available()` because
108
+ * upstream's check returns true whenever a `resolveApiKey` thunk is
109
+ * defined, regardless of whether the resolved key string is empty.
110
+ * Our caller may legitimately invoke us with `dsKey=undefined` (Tiers 1/2
111
+ * only config), so we must check the key string ourselves.
112
+ *
113
+ * When ALL three are unavailable, `ctx.web` will filter us out and the
114
+ * seam will throw `WEB_PROVIDER_UNAVAILABLE` only if no other provider
115
+ * is registered as a fallback. (We always register this row, so an
116
+ * absent-key env is a no-op rather than an error.)
117
+ */
118
+ available() {
119
+ return Boolean((this.tavilyEnabled && this.tavilyKey) || (this.bochaEnabled && this.bochaKey) || this.dsKey);
120
+ }
121
+ async search(request, signal) {
122
+ // Tier 1 — Tavily
123
+ if (this.tavilyEnabled && this.tavilyKey) {
124
+ try {
125
+ return await this.searchTavily(request, signal);
126
+ }
127
+ catch (err) {
128
+ // Tier 1 failed; fall through to Tier 2. We log but do not throw —
129
+ // this is the explicit lingguard-style "fail-down" contract.
130
+ console.warn(`[web-search-tavily-bocha] Tavily failed, falling through to 博查: ` +
131
+ (err instanceof Error ? err.message : String(err)));
132
+ }
133
+ }
134
+ // Tier 2 — 博查 AI
135
+ if (this.bochaEnabled && this.bochaKey) {
136
+ try {
137
+ return await this.searchBocha(request, signal);
138
+ }
139
+ catch (err) {
140
+ console.warn(`[web-search-tavily-bocha] 博查 failed, falling through to DeepSeek: ` +
141
+ (err instanceof Error ? err.message : String(err)));
142
+ }
143
+ }
144
+ // Tier 3 — DeepSeek (imported provider; uses native server-tool search).
145
+ // We gate on `this.dsKey` directly rather than `this.deepseek.available()`
146
+ // because upstream's available() returns true whenever a `resolveApiKey`
147
+ // thunk is defined, even when it resolves to an empty string.
148
+ if (this.dsKey) {
149
+ return await this.deepseek.search(request, signal);
150
+ }
151
+ // All tiers failed or unavailable.
152
+ throw new WebError('all web search providers failed or none configured ' +
153
+ '(set TAVILY_API_KEY / BOCHA_API_KEY / DEEPSEEK_API_KEY in .env)', 'WEB_PROVIDER_UNAVAILABLE');
154
+ }
155
+ // ── Tier 1: Tavily ───────────────────────────────────────────────────────
156
+ // API: https://docs.tavily.com/docs/rest-api/api-reference#endpoint-search
157
+ // Body: { api_key, query, max_results, search_depth, include_answer }
158
+ // 200 OK response: { answer?: string, results: [{ title, url, content, score }] }
159
+ async searchTavily(req, signal) {
160
+ const r = await fetch(TAVILY_ENDPOINT, {
161
+ method: 'POST',
162
+ headers: { 'Content-Type': 'application/json' },
163
+ body: JSON.stringify({
164
+ api_key: this.tavilyKey,
165
+ query: req.query,
166
+ max_results: req.maxResults ?? 5,
167
+ search_depth: 'basic',
168
+ include_answer: true,
169
+ }),
170
+ signal,
171
+ });
172
+ if (!r.ok) {
173
+ const body = await r.text().catch(() => '');
174
+ throw new Error(`Tavily HTTP ${r.status}: ${body.slice(0, 200)}`);
175
+ }
176
+ const json = (await r.json());
177
+ const sources = (json.results ?? [])
178
+ .filter((it) => it.url)
179
+ .map((it) => ({
180
+ url: it.url,
181
+ ...(it.title ? { title: it.title } : {}),
182
+ ...(it.content ? { snippet: it.content } : {}),
183
+ }));
184
+ return {
185
+ ...(json.answer ? { content: json.answer } : {}),
186
+ sources,
187
+ truncated: false,
188
+ };
189
+ }
190
+ // ── Tier 2: 博查 AI ────────────────────────────────────────────────────────
191
+ // API: https://open.bochaai.com(§7.82.2 修正:旧 feishu docx 链接已迁移,权威 spec 在开放平台)
192
+ // Body: { query, count, summary, freshness } —— 4 个字段,无额外必填
193
+ // 200 OK response: { code: 200, msg: null, log_id, data: { _type, queryContext, webPages: { webSearchUrl, totalEstimatedMatches, value: [...] }, images?, videos? } }
194
+ // 错误 response: { code: 4xx, msg: '...', log_id } —— 无 data 字段
195
+ async searchBocha(req, signal) {
196
+ const r = await fetch(BOCHA_ENDPOINT, {
197
+ method: 'POST',
198
+ headers: {
199
+ 'Content-Type': 'application/json',
200
+ Authorization: `Bearer ${this.bochaKey}`,
201
+ },
202
+ body: JSON.stringify({
203
+ query: req.query,
204
+ count: req.maxResults ?? 5,
205
+ summary: true,
206
+ freshness: 'noLimit',
207
+ }),
208
+ signal,
209
+ });
210
+ if (!r.ok) {
211
+ const body = await r.text().catch(() => '');
212
+ throw new Error(`博查 HTTP ${r.status}: ${body.slice(0, 200)}`);
213
+ }
214
+ const json = (await r.json());
215
+ if (json.code !== 200) {
216
+ throw new Error(`博查 API code ${json.code}: ${json.msg ?? 'unknown error'} (log_id=${json.log_id ?? 'n/a'})`);
217
+ }
218
+ const pages = json.data?.webPages?.value ?? [];
219
+ const sources = pages
220
+ .filter((it) => it.url)
221
+ .map((it) => ({
222
+ url: it.url,
223
+ ...(it.name ? { title: it.name } : {}),
224
+ ...(it.summary ? { snippet: it.summary } : it.snippet ? { snippet: it.snippet } : {}),
225
+ ...(it.datePublished ? { datePublished: it.datePublished } : {}),
226
+ }));
227
+ return {
228
+ ...(json.data?.summary ? { content: json.data.summary } : {}),
229
+ sources,
230
+ truncated: false,
231
+ };
232
+ }
233
+ }
234
+ // ── Cordis plugin entry point ───────────────────────────────────────────
235
+ /**
236
+ * The dsh loader passes the parent Cordis `ctx` here; `inject: ['web']`
237
+ * guarantees `ctx.web` is non-null. We register one aggregator provider
238
+ * whose id is `tavily-bocha-fallback`.
239
+ *
240
+ * The Tier-3 DeepSeek provider is constructed (not registered) so we can
241
+ * invoke its `search()` directly inside our Tier-3 fallback path. The
242
+ * upstream `web-search-deepseek` plugin row is kept enabled in
243
+ * `cordis.patch.yml` so its `registerSearchProvider('deepseek-official')`
244
+ * also fires — but DSH's seam then sees TWO registered search providers
245
+ * (ours + deepseek-official) and would throw `WEB_PROVIDER_AMBIGUOUS`.
246
+ *
247
+ * To avoid that, the cordis.patch.yml disables `web-search-deepseek` when
248
+ * `web-search-tavily-bocha` is enabled; the Tier-3 fallback inside the
249
+ * aggregator reaches the same DeepSeek HTTP endpoint by holding a private
250
+ * `DeepSeekSearchProvider` instance, so we never lose the backstop.
251
+ *
252
+ * @param ctx - Cordis context with `ctx.web` available per `inject`.
253
+ */
254
+ export async function apply(ctx, _config) {
255
+ // §7.102 (2026-10-21): the search keys come from config/edge.json
256
+ // (secrets.tavilyApiKey / secrets.bochaApiKey / secrets.deepseekApiKey).
257
+ // The old flow was: repo .env → install.sh `source .env.sh` → process.env
258
+ // → this read. That chain is gone — the desktop GUI never sourced it.
259
+ // Env names stay honoured as a per-process override.
260
+ const cfg = loadEdgeConfig(true);
261
+ const secrets = cfg.secrets ?? {};
262
+ const tavilyKey = (secrets.tavilyApiKey ?? process.env.TAVILY_API_KEY)?.trim() || undefined;
263
+ const bochaKey = (secrets.bochaApiKey ?? process.env.BOCHA_API_KEY)?.trim() || undefined;
264
+ const dsKey = (secrets.deepseekApiKey ?? process.env.DEEPSEEK_API_KEY)?.trim() || undefined;
265
+ const dsBaseURL = process.env.DEEPSEEK_BASE_URL?.trim() || DEEPSEEK_DEFAULT_BASE_URL;
266
+ // Construct upstream DeepSeek provider for Tier-3 fallback. We bypass its
267
+ // settings-section / credential-ref machinery because we read env vars
268
+ // ourselves (consistent with `local-llm-adapter` pattern). The provider
269
+ // class is stateless across calls — re-reading env on each `search()`.
270
+ const dsProvider = new DeepSeekSearchProvider(() => ({
271
+ resolveApiKey: async () => dsKey,
272
+ baseURL: dsBaseURL,
273
+ model: 'deepseek-v4-flash',
274
+ apiVersion: '2023-06-01',
275
+ maxTokens: 4096,
276
+ maxUses: 5,
277
+ }));
278
+ const provider = new TavilyBochaFallbackProvider(tavilyKey, bochaKey, dsKey, dsProvider, {
279
+ // §7.107: the per-tier switches, finally read. §7.182: default =
280
+ // disabled ⇒ an unset config keeps only the DeepSeek tier on the chain.
281
+ tavilyEnabled: cfg.webSearch?.tavilyEnabled,
282
+ bochaEnabled: cfg.webSearch?.bochaEnabled,
283
+ });
284
+ // The `web` seam is registered by `@deepseek-ai/dsh-tool-web` upstream;
285
+ // it's not part of the stock `Context` interface, so cast narrowly.
286
+ const webCtx = ctx;
287
+ webCtx.web.registerSearchProvider(provider);
288
+ }
289
+ export default { name, inject, apply };
@@ -0,0 +1,2 @@
1
+ export * from './dsh-adapter/http-api.js';
2
+ //# sourceMappingURL=http-api.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-api.d.ts","sourceRoot":"","sources":["../src/http-api.ts"],"names":[],"mappings":"AACA,cAAc,2BAA2B,CAAA"}
@@ -0,0 +1,2 @@
1
+ // @module dsh-edge-agent/http-api
2
+ export * from './dsh-adapter/http-api.js';
package/lib/index.d.ts ADDED
@@ -0,0 +1,48 @@
1
+ /**
2
+ * dsh-edge-agent — package root (flat layout, matching dsh-context's pattern).
3
+ *
4
+ * The aggregate plugin (`name='dsh-edge-agent'`) that cordis 0.2.1-rc.2
5
+ * mounts when the patch row uses the bare package name lives in
6
+ * `./dsh-adapter/dsh-edge-agent.ts` so the adapter boundary holds:
7
+ * `verify-adapter-boundary` only allows `@deepseek-ai/*` imports under
8
+ * `src/dsh-adapter/`. This file stays as a thin re-export shell — it must
9
+ * NOT import upstream packages directly, only re-export sub-plugin modules
10
+ * and the aggregate bootstrap.
11
+ *
12
+ * For `cordis require('@scope/pkg')` to resolve to the aggregate plugin,
13
+ * `package.json#main` → `lib/index.js` (this file compiled) AND the
14
+ * `lib/` directory must hold `index.js` flat (no dotted `lib/types/` prefix).
15
+ * The dotted layout silently misroutes cordis to `lib/types/<name>.js`,
16
+ * which would cause the whole bundle to never mount — flat layout is
17
+ * mandatory (see docs/dev-notes/cordis-rc021-patch-loader.md).
18
+ *
19
+ * Sub-plugin re-exports preserve the public API: a consumer can still do
20
+ * `import { auditLog } from '@scope/pkg/audit-log'`
21
+ * because every adapter subpath is `export *`-ed here.
22
+ */
23
+ export { name, inject, Config, apply, type Config as AggregatorConfig, } from './dsh-adapter/dsh-edge-agent.js';
24
+ export * from './dsh-adapter/tcm.js';
25
+ export * from './dsh-adapter/local-storage.js';
26
+ export * from './dsh-adapter/sessions.js';
27
+ export * from './dsh-adapter/audit-log.js';
28
+ export * from './dsh-adapter/privacy-policy.js';
29
+ export * from './dsh-adapter/tools.js';
30
+ export * from './dsh-adapter/realm-skill-bridge.js';
31
+ export * from './dsh-adapter/prompt-guard.js';
32
+ export * from './dsh-adapter/intent-router.js';
33
+ export * from './dsh-adapter/model-router.js';
34
+ export * from './dsh-adapter/local-llm-adapter.js';
35
+ export * from './dsh-adapter/cloud-llm-adapter.js';
36
+ export * from './dsh-adapter/sanitizer-pipeline.js';
37
+ export * from './dsh-adapter/ohttp-gateway.js';
38
+ export * from './dsh-adapter/secure-bridge.js';
39
+ export * from './dsh-adapter/attestation.js';
40
+ export * from './dsh-adapter/td-bus.js';
41
+ export * from './dsh-adapter/voice-input.js';
42
+ export * from './dsh-adapter/plugin-host.js';
43
+ export { name as httpApiName, inject as httpApiInject, Config as HttpApiConfig, HttpApiServiceImpl, apply as httpApiApply } from './dsh-adapter/http-api.js';
44
+ export type { HttpApiService } from './dsh-adapter/http-api.js';
45
+ export * from './dsh-adapter/llm-adapters.js';
46
+ export * from './dsh-adapter/edge-context-view.js';
47
+ export * from './dsh-adapter/desktop-cookie-janitor.js';
48
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EACL,IAAI,EACJ,MAAM,EACN,MAAM,EACN,KAAK,EACL,KAAK,MAAM,IAAI,gBAAgB,GAChC,MAAM,iCAAiC,CAAA;AAKxC,cAAc,sBAAsB,CAAA;AACpC,cAAc,gCAAgC,CAAA;AAC9C,cAAc,2BAA2B,CAAA;AACzC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,iCAAiC,CAAA;AAC/C,cAAc,wBAAwB,CAAA;AACtC,cAAc,qCAAqC,CAAA;AACnD,cAAc,+BAA+B,CAAA;AAC7C,cAAc,gCAAgC,CAAA;AAC9C,cAAc,+BAA+B,CAAA;AAC7C,cAAc,oCAAoC,CAAA;AAClD,cAAc,oCAAoC,CAAA;AAClD,cAAc,qCAAqC,CAAA;AACnD,cAAc,gCAAgC,CAAA;AAC9C,cAAc,gCAAgC,CAAA;AAC9C,cAAc,8BAA8B,CAAA;AAC5C,cAAc,yBAAyB,CAAA;AACvC,cAAc,8BAA8B,CAAA;AAC5C,cAAc,8BAA8B,CAAA;AAC5C,OAAO,EAAE,IAAI,IAAI,WAAW,EAAE,MAAM,IAAI,aAAa,EAAE,MAAM,IAAI,aAAa,EAAE,kBAAkB,EAAE,KAAK,IAAI,YAAY,EAAE,MAAM,2BAA2B,CAAA;AAC5J,YAAY,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAA;AAC/D,cAAc,+BAA+B,CAAA;AAC7C,cAAc,oCAAoC,CAAA;AAClD,cAAc,yCAAyC,CAAA"}
package/lib/index.js ADDED
@@ -0,0 +1,49 @@
1
+ /**
2
+ * dsh-edge-agent — package root (flat layout, matching dsh-context's pattern).
3
+ *
4
+ * The aggregate plugin (`name='dsh-edge-agent'`) that cordis 0.2.1-rc.2
5
+ * mounts when the patch row uses the bare package name lives in
6
+ * `./dsh-adapter/dsh-edge-agent.ts` so the adapter boundary holds:
7
+ * `verify-adapter-boundary` only allows `@deepseek-ai/*` imports under
8
+ * `src/dsh-adapter/`. This file stays as a thin re-export shell — it must
9
+ * NOT import upstream packages directly, only re-export sub-plugin modules
10
+ * and the aggregate bootstrap.
11
+ *
12
+ * For `cordis require('@scope/pkg')` to resolve to the aggregate plugin,
13
+ * `package.json#main` → `lib/index.js` (this file compiled) AND the
14
+ * `lib/` directory must hold `index.js` flat (no dotted `lib/types/` prefix).
15
+ * The dotted layout silently misroutes cordis to `lib/types/<name>.js`,
16
+ * which would cause the whole bundle to never mount — flat layout is
17
+ * mandatory (see docs/dev-notes/cordis-rc021-patch-loader.md).
18
+ *
19
+ * Sub-plugin re-exports preserve the public API: a consumer can still do
20
+ * `import { auditLog } from '@scope/pkg/audit-log'`
21
+ * because every adapter subpath is `export *`-ed here.
22
+ */
23
+ export { name, inject, Config, apply, } from './dsh-adapter/dsh-edge-agent.js';
24
+ // Convenience: re-export the canonical subpath plugins so that consumers
25
+ // who `import '@dsh-edge/dsh-edge-agent'` can also
26
+ // pull individual cordis rows out of the same module.
27
+ export * from './dsh-adapter/tcm.js';
28
+ export * from './dsh-adapter/local-storage.js';
29
+ export * from './dsh-adapter/sessions.js';
30
+ export * from './dsh-adapter/audit-log.js';
31
+ export * from './dsh-adapter/privacy-policy.js';
32
+ export * from './dsh-adapter/tools.js';
33
+ export * from './dsh-adapter/realm-skill-bridge.js';
34
+ export * from './dsh-adapter/prompt-guard.js';
35
+ export * from './dsh-adapter/intent-router.js';
36
+ export * from './dsh-adapter/model-router.js';
37
+ export * from './dsh-adapter/local-llm-adapter.js';
38
+ export * from './dsh-adapter/cloud-llm-adapter.js';
39
+ export * from './dsh-adapter/sanitizer-pipeline.js';
40
+ export * from './dsh-adapter/ohttp-gateway.js';
41
+ export * from './dsh-adapter/secure-bridge.js';
42
+ export * from './dsh-adapter/attestation.js';
43
+ export * from './dsh-adapter/td-bus.js';
44
+ export * from './dsh-adapter/voice-input.js';
45
+ export * from './dsh-adapter/plugin-host.js';
46
+ export { name as httpApiName, inject as httpApiInject, Config as HttpApiConfig, HttpApiServiceImpl, apply as httpApiApply } from './dsh-adapter/http-api.js';
47
+ export * from './dsh-adapter/llm-adapters.js';
48
+ export * from './dsh-adapter/edge-context-view.js';
49
+ export * from './dsh-adapter/desktop-cookie-janitor.js';
@@ -0,0 +1,2 @@
1
+ export * from './dsh-adapter/intent-router.js';
2
+ //# sourceMappingURL=intent-router.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"intent-router.d.ts","sourceRoot":"","sources":["../src/intent-router.ts"],"names":[],"mappings":"AACA,cAAc,gCAAgC,CAAA"}
@@ -0,0 +1,2 @@
1
+ // @module dsh-edge-agent/intent-router
2
+ export * from './dsh-adapter/intent-router.js';
@@ -0,0 +1,2 @@
1
+ export * from './dsh-adapter/llm-adapters.js';
2
+ //# sourceMappingURL=llm-adapters.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"llm-adapters.d.ts","sourceRoot":"","sources":["../src/llm-adapters.ts"],"names":[],"mappings":"AACA,cAAc,+BAA+B,CAAA"}
@@ -0,0 +1,2 @@
1
+ // @module dsh-edge-agent/llm-adapters
2
+ export * from './dsh-adapter/llm-adapters.js';
@@ -0,0 +1,2 @@
1
+ export * from './dsh-adapter/local-llm-adapter.js';
2
+ //# sourceMappingURL=local-llm-adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local-llm-adapter.d.ts","sourceRoot":"","sources":["../src/local-llm-adapter.ts"],"names":[],"mappings":"AACA,cAAc,oCAAoC,CAAA"}
@@ -0,0 +1,2 @@
1
+ // @module dsh-edge-agent/local-llm-adapter
2
+ export * from './dsh-adapter/local-llm-adapter.js';
@@ -0,0 +1,2 @@
1
+ export * from './dsh-adapter/local-storage.js';
2
+ //# sourceMappingURL=local-storage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local-storage.d.ts","sourceRoot":"","sources":["../src/local-storage.ts"],"names":[],"mappings":"AACA,cAAc,gCAAgC,CAAA"}
@@ -0,0 +1,2 @@
1
+ // @module dsh-edge-agent/local-storage
2
+ export * from './dsh-adapter/local-storage.js';
@@ -0,0 +1,2 @@
1
+ export * from './dsh-adapter/model-router.js';
2
+ //# sourceMappingURL=model-router.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model-router.d.ts","sourceRoot":"","sources":["../src/model-router.ts"],"names":[],"mappings":"AACA,cAAc,+BAA+B,CAAA"}
@@ -0,0 +1,2 @@
1
+ // @module dsh-edge-agent/model-router
2
+ export * from './dsh-adapter/model-router.js';
@@ -0,0 +1,2 @@
1
+ export * from './dsh-adapter/ohttp-gateway.js';
2
+ //# sourceMappingURL=ohttp-gateway.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ohttp-gateway.d.ts","sourceRoot":"","sources":["../src/ohttp-gateway.ts"],"names":[],"mappings":"AACA,cAAc,gCAAgC,CAAA"}
@@ -0,0 +1,2 @@
1
+ // @module dsh-edge-agent/ohttp-gateway
2
+ export * from './dsh-adapter/ohttp-gateway.js';
@@ -0,0 +1,2 @@
1
+ export * from './dsh-adapter/plugin-host.js';
2
+ //# sourceMappingURL=plugin-host.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin-host.d.ts","sourceRoot":"","sources":["../src/plugin-host.ts"],"names":[],"mappings":"AACA,cAAc,8BAA8B,CAAA"}
@@ -0,0 +1,2 @@
1
+ // @module dsh-edge-agent/plugin-host
2
+ export * from './dsh-adapter/plugin-host.js';