@moguiyu/dsh-tavily 0.2.0 → 0.2.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.
package/README.md CHANGED
@@ -10,9 +10,10 @@ for key/usage management.
10
10
  - **`tavily_extract` / `tavily_map` / `tavily_crawl`** — read a known URL's content, map a
11
11
  site's links, or crawl a site and return its pages. Same key-rotation/failover as search.
12
12
  - **Settings card** — key list, usage gauge, strategy selector, and the advanced-tool switch.
13
- - **Plugin-config settings card** — the Host registers the `tavily-search` settings namespace
13
+ - **Plugin-config settings card** — the Host installs the `tavily-search` settings section
14
14
  and the card is keyed by it (keyed `settings.plugin.item`), so the Plugins configuration tab
15
- serves the card exactly when this plugin is composed (needs DSH **0.1.0-rc.7 or newer**).
15
+ serves the card exactly when this plugin is composed (needs DSH **0.1.0-rc.7 or newer**,
16
+ including `0.1.2-alpha.x` — both seam generations are detected at runtime).
16
17
  The switch writes the namespace and restarts the row; the choice is mirrored to
17
18
  `~/.dsh/tavily-tool.json`.
18
19
  - **`web_search` is never replaced** — no `ctx.web` provider is registered and
package/lib/client.js CHANGED
@@ -285,8 +285,12 @@ window.__ModuleLoader__.load({
285
285
 
286
286
  const isOff = enabled === false
287
287
 
288
- return react.createElement('div', { style: { border: '1px solid var(--dsw-alias-border-l2)', borderRadius: 10, minWidth: 0, overflow: 'hidden' } },
289
- react.createElement('style', null, '.dts-icon-btn:hover{background:var(--dsw-alias-interactive-bg-hover)}.dts-icon-btn:disabled{opacity:.4;cursor:default}.dts-icon-btn-danger:hover{background:var(--dsw-alias-interactive-bg-hover-danger)}'),
288
+ // Card box mirrors the native plugin-config card (PluginCard.module.css,
289
+ // ui-settings-plugins): bg-layer-3 fill, .5px border-l4, 16px radius,
290
+ // hover/open border lift, and the open state's bg-layer-2 upgrade — so
291
+ // the card sits at the same elevation as native cards in dark mode too.
292
+ return react.createElement('div', { className: expanded ? 'dts-card dts-card-open' : 'dts-card', style: { minWidth: 0 } },
293
+ react.createElement('style', null, '.dts-card{border:.5px solid var(--dsw-alias-border-l4);border-radius:16px;background:var(--dsw-alias-bg-layer-3);transition:border-color .16s,background .16s}.dts-card:hover{border-color:var(--dsw-alias-label-dimmed)}.dts-card-open{background:var(--dsw-alias-bg-layer-2);border-color:var(--dsw-alias-label-dimmed)}.dts-icon-btn:hover{background:var(--dsw-alias-interactive-bg-hover)}.dts-icon-btn:disabled{opacity:.4;cursor:default}.dts-icon-btn-danger:hover{background:var(--dsw-alias-interactive-bg-hover-danger)}'),
290
294
  react.createElement('div', { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', gap: 12, padding: '12px 14px', minHeight: 52, boxSizing: 'border-box' } },
291
295
  react.createElement('button', {
292
296
  type: 'button',
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@moguiyu/dsh-tavily",
3
- "version": "0.2.0",
4
- "description": "Opt-in advanced Tavily model tools for DeepSeek Harness with the Tavily Search settings card (rc.8 plugin management). The built-in web_search is never replaced.",
3
+ "version": "0.2.2",
4
+ "description": "Opt-in advanced Tavily model tools for DeepSeek Harness with the Tavily Search settings card (rc.7/rc.8 and 0.1.2 plugin management). The built-in web_search is never replaced.",
5
5
  "type": "module",
6
6
  "main": "./src/index.js",
7
7
  "exports": {
@@ -53,17 +53,17 @@
53
53
  },
54
54
  "peerDependencies": {
55
55
  "@deepseek-ai/cordis": "^4.0.1",
56
- "@deepseek-ai/dsh-home-paths": "^0.1.0-rc.8",
57
- "@deepseek-ai/dsh-tools": "^0.1.0-rc.8",
58
- "@deepseek-ai/dsh-settings": "^0.1.0-rc.8"
56
+ "@deepseek-ai/dsh-home-paths": "^0.1.0-rc.8 || ^0.1.2-alpha.2",
57
+ "@deepseek-ai/dsh-tools": "^0.1.0-rc.8 || ^0.1.2-alpha.2",
58
+ "@deepseek-ai/dsh-settings": "^0.1.0-rc.8 || ^0.1.2-alpha.2"
59
59
  },
60
60
  "dependencies": {
61
61
  "@deepseek-ai/schemastery": "^3.18.1",
62
- "@moguiyu/dsh-tavily-backend": "^0.1.12",
63
- "@moguiyu/dsh-tool-tavily-search": "^0.2.0"
62
+ "@moguiyu/dsh-tavily-backend": "^0.2.1",
63
+ "@moguiyu/dsh-tool-tavily-search": "^0.2.1"
64
64
  },
65
65
  "devDependencies": {
66
- "@deepseek-ai/dsh-settings": "^0.1.0-rc.8",
67
- "@deepseek-ai/dsh-system-prompt": "^0.1.0-rc.8"
66
+ "@deepseek-ai/dsh-settings": "^0.1.2-alpha.2",
67
+ "@deepseek-ai/dsh-system-prompt": "^0.1.2-alpha.2"
68
68
  }
69
69
  }
package/src/client.js CHANGED
@@ -290,8 +290,12 @@ export function factory(require) {
290
290
 
291
291
  const isOff = enabled === false
292
292
 
293
- return react.createElement('div', { style: { border: '1px solid var(--dsw-alias-border-l2)', borderRadius: 10, minWidth: 0, overflow: 'hidden' } },
294
- react.createElement('style', null, '.dts-icon-btn:hover{background:var(--dsw-alias-interactive-bg-hover)}.dts-icon-btn:disabled{opacity:.4;cursor:default}.dts-icon-btn-danger:hover{background:var(--dsw-alias-interactive-bg-hover-danger)}'),
293
+ // Card box mirrors the native plugin-config card (PluginCard.module.css,
294
+ // ui-settings-plugins): bg-layer-3 fill, .5px border-l4, 16px radius,
295
+ // hover/open border lift, and the open state's bg-layer-2 upgrade — so
296
+ // the card sits at the same elevation as native cards in dark mode too.
297
+ return react.createElement('div', { className: expanded ? 'dts-card dts-card-open' : 'dts-card', style: { minWidth: 0 } },
298
+ react.createElement('style', null, '.dts-card{border:.5px solid var(--dsw-alias-border-l4);border-radius:16px;background:var(--dsw-alias-bg-layer-3);transition:border-color .16s,background .16s}.dts-card:hover{border-color:var(--dsw-alias-label-dimmed)}.dts-card-open{background:var(--dsw-alias-bg-layer-2);border-color:var(--dsw-alias-label-dimmed)}.dts-icon-btn:hover{background:var(--dsw-alias-interactive-bg-hover)}.dts-icon-btn:disabled{opacity:.4;cursor:default}.dts-icon-btn-danger:hover{background:var(--dsw-alias-interactive-bg-hover-danger)}'),
295
299
  react.createElement('div', { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', gap: 12, padding: '12px 14px', minHeight: 52, boxSizing: 'border-box' } },
296
300
  react.createElement('button', {
297
301
  type: 'button',
package/src/index.js CHANGED
@@ -7,8 +7,8 @@
7
7
  * - tool half — `@moguiyu/dsh-tool-tavily-search` {@link installTavilyTool};
8
8
  * - backend half — `@moguiyu/dsh-tavily-backend` {@link installBackend}.
9
9
  *
10
- * This package adds the rc.7 plugin-management seam: the Host registers the
11
- * `tavily-search` settings namespace (the key the Plugins configuration tab
10
+ * This package adds the plugin-management seam: the Host installs the
11
+ * `tavily-search` settings section (the key the Plugins configuration tab
12
12
  * pairs the card against). The switch value lives both in that namespace and
13
13
  * in `~/.dsh/tavily-tool.json`; every write path converges on
14
14
  * `settings.update` (or the state file when no settings service exists),
@@ -20,7 +20,6 @@
20
20
  * search provider and never rewrites `web.searchProvider` — `web_search`
21
21
  * keeps its native provider.
22
22
  */
23
- import { settingsNamespace } from '@deepseek-ai/dsh-settings'
24
23
  import z from '@deepseek-ai/schemastery'
25
24
  import { isToolEnabled, installTavilyTool } from '@moguiyu/dsh-tool-tavily-search'
26
25
  import { installBackend, readToolState, restoreToolState, writeToolState } from '@moguiyu/dsh-tavily-backend'
@@ -35,16 +34,24 @@ export const Config = z.object({
35
34
 
36
35
  /**
37
36
  * Settings namespace owned by this package. It is the join key between the
38
- * Host half and the browser card: the rc.7 Plugins configuration tab serves
39
- * this namespace and dispatches the card registered under the same key.
37
+ * Host half and the browser card: the Plugins configuration tab serves this
38
+ * namespace and dispatches the card registered under the same key. A plain
39
+ * lowercase-hyphenated string, valid on every supported host line: rc.7/rc.8
40
+ * treat the namespace as a branded string (runtime-identical), and 0.1.2
41
+ * validates and brands it on registration (`settingsNamespace()` was
42
+ * removed upstream).
40
43
  */
41
- export const TAVILY_NS = settingsNamespace('tavily-search')
44
+ export const TAVILY_NS = 'tavily-search'
42
45
 
43
46
  export function apply(ctx, config) {
44
47
  // The switch value the current fiber is acting on. Every write path updates
45
48
  // this before the row restart so a watcher re-fired after a restart no-ops.
46
49
  let lastApplied = isToolEnabled(config)
47
- let settingsScope = null
50
+ // Settings seam state: the attached provider (null on hosts without one)
51
+ // and the authoritative switch source — the resolved section while the
52
+ // provider is attached, the composition entry otherwise.
53
+ let settingsProvider = null
54
+ let settingsSource = () => config
48
55
 
49
56
  /** Persist the switch first, then restart this row so the tool (un)registers. */
50
57
  async function applySwitchLocal(enabled) {
@@ -66,39 +73,68 @@ export function apply(ctx, config) {
66
73
  }
67
74
  }
68
75
 
69
- // First-class settings integration (rc.7 plugin management): register the
70
- // `tavily-search` namespace so the Plugins configuration surface serves it
71
- // and pairs this package's card. The row config is the composition base
72
- // layer; the user document overlays it. Runs whether or not the tool is on.
73
- const settings = ctx.get('settings')
74
- if (settings !== undefined && settings !== null && typeof settings.register === 'function') {
76
+ /** Re-judge the switch from a resolved settings value (either seam's shape). */
77
+ function applySwitchValue(value) {
78
+ const nextEnabled = value !== null && typeof value === 'object' && typeof value.enabled === 'boolean'
79
+ ? value.enabled
80
+ : false
81
+ applySwitchLocal(nextEnabled).catch((error) => {
82
+ ctx.logger.warn('tavily-search: applying settings switch failed: %s', error instanceof Error ? error.message : String(error))
83
+ })
84
+ }
85
+
86
+ // First-class settings integration: install the `tavily-search` section so
87
+ // the Plugins configuration surface serves it and pairs this package's
88
+ // card. Runtime-optional on purpose: the row boots (state-file path) even
89
+ // on hosts that never provide a settings service. Two host seams are
90
+ // supported by feature detection, so ONE package version covers both host
91
+ // lines:
92
+ //
93
+ // - 0.1.2 (`installSection`) — the row config is the composition entry
94
+ // (base layer while a provider is attached, fallback value when one
95
+ // detaches); `onChange` re-judges the switch on attach, on detach, and
96
+ // on every committed change.
97
+ // - rc.7/rc.8 (`register`) — the row config is the composition base layer
98
+ // and the scope watcher re-judges the switch on every committed change
99
+ // (`applies: 'restart'`, the 0.2.0 behavior).
100
+ ctx.inject(['settings'], (settingsCtx) => {
101
+ const provider = settingsCtx.settings
75
102
  try {
76
- settingsScope = settings.register(TAVILY_NS, Config, {
77
- base: { enabled: config.enabled },
78
- applies: 'restart',
79
- })
80
- settingsScope.watch((next) => {
81
- const nextEnabled = next !== null && typeof next === 'object' && typeof next.enabled === 'boolean'
82
- ? next.enabled
83
- : false
84
- applySwitchLocal(nextEnabled).catch((error) => {
85
- ctx.logger.warn('tavily-search: applying settings switch failed: %s', error instanceof Error ? error.message : String(error))
103
+ if (typeof provider.installSection === 'function') {
104
+ provider.installSection(ctx, TAVILY_NS, Config, config, {
105
+ setSource: (current) => { settingsSource = current },
106
+ onChange: () => { applySwitchValue(settingsSource()) },
107
+ })
108
+ settingsProvider = provider
109
+ return
110
+ }
111
+ if (typeof provider.register === 'function') {
112
+ const scope = provider.register(TAVILY_NS, Config, {
113
+ base: { enabled: config.enabled },
114
+ applies: 'restart',
86
115
  })
87
- })
116
+ if (scope !== undefined && scope !== null && typeof scope.watch === 'function') {
117
+ scope.watch((next) => { applySwitchValue(next) })
118
+ settingsProvider = provider
119
+ } else {
120
+ ctx.logger.warn('tavily-search: settings scope exposes no watcher; using the state-file path')
121
+ }
122
+ return
123
+ }
124
+ ctx.logger.warn('tavily-search: settings service exposes neither installSection nor register; using the state-file path')
88
125
  } catch (error) {
89
- ctx.logger.warn('tavily-search: settings namespace registration failed: %s', error instanceof Error ? error.message : String(error))
90
- settingsScope = null
126
+ ctx.logger.warn('tavily-search: settings section installation failed: %s', error instanceof Error ? error.message : String(error))
91
127
  }
92
- }
128
+ })
93
129
 
94
130
  installBackend(ctx, {
95
131
  enabled: () => isToolEnabled(config),
96
132
  async applySwitch(enabled) {
97
133
  // Every write converges on one pipeline: the settings namespace when a
98
- // settings service is served (its watcher persists and restarts this
134
+ // settings service is attached (its watcher persists and restarts this
99
135
  // row), or the plain state-file path otherwise.
100
- if (settings !== undefined && settingsScope !== null) {
101
- await settings.update(TAVILY_NS, { enabled })
136
+ if (settingsProvider !== null) {
137
+ await settingsProvider.update(TAVILY_NS, { enabled })
102
138
  } else {
103
139
  await applySwitchLocal(enabled)
104
140
  }