@moguiyu/dsh-tavily 0.2.0 → 0.2.1

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 (3) hide show
  1. package/README.md +3 -2
  2. package/package.json +9 -9
  3. package/src/index.js +66 -30
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/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.1",
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/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
  }