@goodandready/dsh-tts 0.4.16 → 0.4.18

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/CHANGELOG.md ADDED
@@ -0,0 +1,35 @@
1
+ # Changelog
2
+
3
+ Notable changes to `@goodandready/dsh-tts`.
4
+
5
+ ## 0.4.18
6
+
7
+ ### Fixed
8
+ - **Settings reachable again on the plugin's own page**: the current DSH core
9
+ (0.1.6-alpha.2) renders a plugin's configuration page only for entries registered
10
+ in the plugin-list seat `plugins.item`. `TtsRowConfig` is now registered there too
11
+ (`id: 'dsh-tts'`, order 60, static label); the row seat and the legacy
12
+ `settings.plugin.item` card stay as fallbacks. Sources edited in `lib/client-src`,
13
+ `lib/client.js` rebuilt.
14
+
15
+ ## 0.4.17
16
+
17
+ ### Added
18
+
19
+ - Settings now register into the Plugins page's row seat, `plugins.row.config`,
20
+ keyed `@goodandready/dsh-tts#dsh-tts` (row id as `cordis.patch.yml` declares
21
+ it): the plugin's row on the Plugins page gains a configure control whose page
22
+ is the same settings form (`view: 'page'`), with a one-line state under the row
23
+ title (`view: 'summary'`). The previous seat, `settings.plugin.item`, stays as
24
+ a fallback for older cores, so settings never become unreachable (#127).
25
+
26
+ ### Fixed
27
+
28
+ - The row-seat page renders the settings form **bare**: the host page already
29
+ draws the title, icon and crumb and provides the content padding, so our own
30
+ card chrome would double the border and shift the form out of the content area.
31
+
32
+ ### Tests
33
+
34
+ - `test/row-config-seat.test.mjs` guards the row-seat key, the row id against
35
+ `cordis.patch.yml`, the fallback seats, and the bare view-aware rendering.
@@ -15,6 +15,10 @@ window.__ModuleLoader__.load({
15
15
  ChevronIcon = null
16
16
  }
17
17
  const NS = 'dsh-tts'
18
+ // Plugins page row seat: key = '<package name>#<row id>', row id as cordis.patch.yml declares it.
19
+ const PKG = '@goodandready/dsh-tts'
20
+ const ROW_ID = 'dsh-tts'
21
+ const ROW_CONFIG_KEY = PKG + '#' + ROW_ID
18
22
  const PROVIDERS = [
19
23
  'openai', 'elevenlabs', 'google', 'azure', 'groq', 'deepgram', 'openrouter',
20
24
  'edge', 'piper', 'espeak',
@@ -2,6 +2,7 @@
2
2
  const SET_CSS =
3
3
  '.dts-wrap{display:flex;flex-direction:column;gap:18px;padding:4px 0 24px;max-width:900px}' +
4
4
  '.dts-header{display:flex;flex-direction:column;gap:8px;padding-bottom:14px;border-bottom:1px solid var(--dsw-alias-border-l2)}' +
5
+ '.dts-page{padding:0}' +
5
6
  '.dts-page-title{font-size:20px;font-weight:700;color:var(--dsw-alias-label-primary);display:flex;align-items:center;gap:10px}' +
6
7
  '.dts-page-sub{font-size:13px;color:var(--dsw-alias-label-secondary);line-height:1.5}' +
7
8
  '.dts-block{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:12px;padding:16px 18px;display:flex;flex-direction:column;gap:12px}' +
@@ -118,6 +118,26 @@
118
118
  ))
119
119
  }
120
120
 
121
+ /**
122
+ * Plugins page row seat (`plugins.row.config`, current core).
123
+ *
124
+ * The host page draws the title, icon and crumb and provides the content
125
+ * padding, so the page view renders the settings form bare: our own card
126
+ * chrome would double the border and shift the form out of the content
127
+ * area. The summary view feeds the one-liner under the row title.
128
+ */
129
+ function TtsRowConfig(props) {
130
+ const t = (props && props.t) || ((key) => key)
131
+ if (props && props.view === 'summary') {
132
+ return React.createElement('div', { className: 'dts-sub' }, t('subtitle'))
133
+ }
134
+ return React.createElement('div', { className: 'dts-page' },
135
+ React.createElement(ErrorBoundary, null,
136
+ React.createElement(TtsSection, Object.assign({}, props, { ctx: props && props.ctx })),
137
+ ),
138
+ )
139
+ }
140
+
121
141
  function registerSettings(ctx) {
122
142
  // Dictionary packages may also register languages for other namespaces.
123
143
  // Core throws on duplicate namespace+language; an unguarded call used to
@@ -137,9 +157,44 @@
137
157
  // The sidebar draws the section label, not our component: props.t never
138
158
  // reaches it, so bind the translator to the namespace ourselves.
139
159
  const t = ctx.locale.bind(NS)
140
- // Primary settings home is the plugin-settings tab card. The tab looks up
141
- // a slot by entryKey equal to the namespace name: key must equal NS or
142
- // the card never appears, with no log error.
160
+ // Current core: settings live on the plugin's own row on the Plugins page
161
+ // (`plugins.row.config`). Key = '<package name>#<row id>'; the row gains a
162
+ // configure control that asks for view:'summary' and view:'page'.
163
+ try {
164
+ ctx.slots.inject('plugins.row.config', () => ctx.slots.register(
165
+ {
166
+ name: 'plugins.row.config',
167
+ key: ROW_CONFIG_KEY,
168
+ locale: NS,
169
+ inject: () => ({ ctx: ctx }),
170
+ },
171
+ TtsRowConfig,
172
+ ))
173
+ } catch (rowSeatUnavailable) {
174
+ console.warn('[dsh-tts] row seat plugins.row.config not available:', rowSeatUnavailable && rowSeatUnavailable.message)
175
+ }
176
+ // Plugin-list seat (`plugins.item`): the seat the current core (0.1.6-alpha.2)
177
+ // renders as the plugin's own page with its configuration. The label is a static
178
+ // string on purpose — it is resolved while the page renders, and a locale lookup
179
+ // there would take the whole client batch down with it.
180
+ try {
181
+ ctx.slots.inject('plugins.item', () => ctx.slots.register(
182
+ {
183
+ name: 'plugins.item',
184
+ id: ROW_ID,
185
+ order: 60,
186
+ label: () => 'Text to Speech',
187
+ locale: NS,
188
+ inject: () => ({ ctx: ctx }),
189
+ },
190
+ TtsRowConfig,
191
+ ))
192
+ } catch (itemSeatUnavailable) {
193
+ console.warn('[dsh-tts] list seat plugins.item not available:', itemSeatUnavailable && itemSeatUnavailable.message)
194
+ }
195
+ // Fallback for hosts that render the older plugin-settings tab card. The tab
196
+ // looks up a slot by entryKey equal to the namespace name: key must equal NS
197
+ // or the card never appears, with no log error.
143
198
  ctx.slots.inject('settings.plugin.item', () => ctx.slots.register(
144
199
  {
145
200
  name: 'settings.plugin.item',
package/lib/client.js CHANGED
@@ -15,6 +15,10 @@ window.__ModuleLoader__.load({
15
15
  ChevronIcon = null
16
16
  }
17
17
  const NS = 'dsh-tts'
18
+ // Plugins page row seat: key = '<package name>#<row id>', row id as cordis.patch.yml declares it.
19
+ const PKG = '@goodandready/dsh-tts'
20
+ const ROW_ID = 'dsh-tts'
21
+ const ROW_CONFIG_KEY = PKG + '#' + ROW_ID
18
22
  const PROVIDERS = [
19
23
  'openai', 'elevenlabs', 'google', 'azure', 'groq', 'deepgram', 'openrouter',
20
24
  'edge', 'piper', 'espeak',
@@ -87,6 +91,7 @@ window.__ModuleLoader__.load({
87
91
  const SET_CSS =
88
92
  '.dts-wrap{display:flex;flex-direction:column;gap:18px;padding:4px 0 24px;max-width:900px}' +
89
93
  '.dts-header{display:flex;flex-direction:column;gap:8px;padding-bottom:14px;border-bottom:1px solid var(--dsw-alias-border-l2)}' +
94
+ '.dts-page{padding:0}' +
90
95
  '.dts-page-title{font-size:20px;font-weight:700;color:var(--dsw-alias-label-primary);display:flex;align-items:center;gap:10px}' +
91
96
  '.dts-page-sub{font-size:13px;color:var(--dsw-alias-label-secondary);line-height:1.5}' +
92
97
  '.dts-block{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:12px;padding:16px 18px;display:flex;flex-direction:column;gap:12px}' +
@@ -1876,6 +1881,26 @@ async function pollPending() {
1876
1881
  ))
1877
1882
  }
1878
1883
 
1884
+ /**
1885
+ * Plugins page row seat (`plugins.row.config`, current core).
1886
+ *
1887
+ * The host page draws the title, icon and crumb and provides the content
1888
+ * padding, so the page view renders the settings form bare: our own card
1889
+ * chrome would double the border and shift the form out of the content
1890
+ * area. The summary view feeds the one-liner under the row title.
1891
+ */
1892
+ function TtsRowConfig(props) {
1893
+ const t = (props && props.t) || ((key) => key)
1894
+ if (props && props.view === 'summary') {
1895
+ return React.createElement('div', { className: 'dts-sub' }, t('subtitle'))
1896
+ }
1897
+ return React.createElement('div', { className: 'dts-page' },
1898
+ React.createElement(ErrorBoundary, null,
1899
+ React.createElement(TtsSection, Object.assign({}, props, { ctx: props && props.ctx })),
1900
+ ),
1901
+ )
1902
+ }
1903
+
1879
1904
  function registerSettings(ctx) {
1880
1905
  // Dictionary packages may also register languages for other namespaces.
1881
1906
  // Core throws on duplicate namespace+language; an unguarded call used to
@@ -1895,9 +1920,44 @@ async function pollPending() {
1895
1920
  // The sidebar draws the section label, not our component: props.t never
1896
1921
  // reaches it, so bind the translator to the namespace ourselves.
1897
1922
  const t = ctx.locale.bind(NS)
1898
- // Primary settings home is the plugin-settings tab card. The tab looks up
1899
- // a slot by entryKey equal to the namespace name: key must equal NS or
1900
- // the card never appears, with no log error.
1923
+ // Current core: settings live on the plugin's own row on the Plugins page
1924
+ // (`plugins.row.config`). Key = '<package name>#<row id>'; the row gains a
1925
+ // configure control that asks for view:'summary' and view:'page'.
1926
+ try {
1927
+ ctx.slots.inject('plugins.row.config', () => ctx.slots.register(
1928
+ {
1929
+ name: 'plugins.row.config',
1930
+ key: ROW_CONFIG_KEY,
1931
+ locale: NS,
1932
+ inject: () => ({ ctx: ctx }),
1933
+ },
1934
+ TtsRowConfig,
1935
+ ))
1936
+ } catch (rowSeatUnavailable) {
1937
+ console.warn('[dsh-tts] row seat plugins.row.config not available:', rowSeatUnavailable && rowSeatUnavailable.message)
1938
+ }
1939
+ // Plugin-list seat (`plugins.item`): the seat the current core (0.1.6-alpha.2)
1940
+ // renders as the plugin's own page with its configuration. The label is a static
1941
+ // string on purpose — it is resolved while the page renders, and a locale lookup
1942
+ // there would take the whole client batch down with it.
1943
+ try {
1944
+ ctx.slots.inject('plugins.item', () => ctx.slots.register(
1945
+ {
1946
+ name: 'plugins.item',
1947
+ id: ROW_ID,
1948
+ order: 60,
1949
+ label: () => 'Text to Speech',
1950
+ locale: NS,
1951
+ inject: () => ({ ctx: ctx }),
1952
+ },
1953
+ TtsRowConfig,
1954
+ ))
1955
+ } catch (itemSeatUnavailable) {
1956
+ console.warn('[dsh-tts] list seat plugins.item not available:', itemSeatUnavailable && itemSeatUnavailable.message)
1957
+ }
1958
+ // Fallback for hosts that render the older plugin-settings tab card. The tab
1959
+ // looks up a slot by entryKey equal to the namespace name: key must equal NS
1960
+ // or the card never appears, with no log error.
1901
1961
  ctx.slots.inject('settings.plugin.item', () => ctx.slots.register(
1902
1962
  {
1903
1963
  name: 'settings.plugin.item',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@goodandready/dsh-tts",
3
- "version": "0.4.16",
3
+ "version": "0.4.18",
4
4
  "description": "Text-to-speech for DeepSeek Harness: speak agent replies in the Web UI with a provider fallback chain (OpenAI, ElevenLabs, Google, Azure, Groq, Deepgram, OpenRouter, Edge, Piper, eSpeak).",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -15,6 +15,7 @@
15
15
  "lib/",
16
16
  "scripts/",
17
17
  "cordis.patch.yml",
18
+ "CHANGELOG.md",
18
19
  "README.md",
19
20
  "LICENSE",
20
21
  "README.ru.md",