@goodandready/dsh-clinebot 0.4.5 → 0.4.7

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 CHANGED
@@ -5,6 +5,23 @@ All notable changes to `@goodandready/dsh-clinebot` will be documented in this f
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.4.7] - 2026-09-27
9
+
10
+ ### Fixed & Cleaned
11
+ - **Unused Imports Elimination (#121)**: Pruned dead imports across `lib/index.js` (`resolveKeyValue`, `smokeChat`, `fetchUsageLimits`, `checkRegisteredInPiAi`, `buildStatus`), `lib/config.js` (`getDefaultModelIds`), and `lib/routes/settings.js` (`isTrustedSettingsRequest`).
12
+ - **Design Contract Synchronization (#122)**: Updated `docs/design/DESIGN.md` Section 2.1 and Section 12.2 to accurately reflect DSH 0.1.7 settings architecture (`inject = ['webServer', 'credentials']`, direct `settingsApi` adapter, `docs/plans/` exclusion).
13
+ - **Peer Dependencies Alignment (#123)**: Removed obsolete `@deepseek-ai/dsh-settings` from `peerDependencies` in `package.json`, eliminating pnpm peer dependency installation warnings.
14
+ - **Repository Hygiene & Service Plans Exclusion (#124)**: Untracked internal implementation plan `docs/plans/13-issues-refactor-plan.md` and added `docs/plans/` to `.gitignore`.
15
+ - **Root Artifact Cleanup (#125)**: Removed stale packed `.tgz` archives from DEV root, ensuring clean workspace.
16
+
17
+ ## [0.4.6] - 2026-09-25
18
+
19
+ ### Fixed
20
+ - **Obsolete Settings Service Dependency Removal (#119)**: Removed ` settings` from `inject` and eradicated legacy `ctx.inject([settings], ...)` and `sctx.settings.register(...)` calls, adapting to DSH 0.1.7 kernel architecture where the Cordis `settings` service was removed.
21
+ - **Config Reader Export (#119)**: Exported `configReader(config)` returning `() => config` to provide standard DSH configuration introspection.
22
+ - **Defensive SettingsForms Adapter (#119)**: Implemented lightweight `settingsApi` adapter providing `get()`, `replace()`, `update()`, and `watch()` without declaring `settings` in `inject`, accessing `ctx?.get?.(settings)` defensively.
23
+ - **Failover & Settings Regression Tests (#119)**: Added 5 strict DoD regression tests verifying `inject`, absence of `settings.register`, proxy property safety, config reader, and strict proxy boot.
24
+
8
25
  ## [0.4.5] - 2026-09-25
9
26
 
10
27
  ### Fixed
package/lib/config.js CHANGED
@@ -9,7 +9,6 @@ import {
9
9
  import {
10
10
  DEFAULT_MODEL_ID,
11
11
  getAllModels,
12
- getDefaultModelIds,
13
12
  getActiveModelIds,
14
13
  } from './models.js'
15
14
 
package/lib/index.js CHANGED
@@ -5,17 +5,12 @@ import {
5
5
  recordSessionRequest,
6
6
  resetSessionStats,
7
7
  rotateToNextAccount,
8
- resolveKeyValue,
9
- smokeChat,
10
- fetchUsageLimits,
11
8
  isQuotaExceededError,
12
9
  } from './cline-client.js'
13
10
  import { PROVIDER_ID } from './models.js'
14
11
  import {
15
- checkRegisteredInPiAi,
16
12
  upsertPiAiProvider,
17
13
  removePiAiProvider,
18
- buildStatus,
19
14
  autoDiscoverPlanModels,
20
15
  resolveActiveAccountKey,
21
16
  } from './provider-sync.js'
@@ -26,7 +21,11 @@ import { registerAuthRoutes } from './routes/auth.js'
26
21
  import { registerSlashCommand } from './slash-command.js'
27
22
 
28
23
  export const name = '@goodandready/dsh-clinebot'
29
- export const inject = ['settings', 'webServer', 'credentials']
24
+ export const inject = ['webServer', 'credentials']
25
+
26
+ export function configReader(config) {
27
+ return () => config
28
+ }
30
29
 
31
30
  export { NS, LLM_PI_AI_NS, Config, sessionStats, recordSessionRequest, resetSessionStats, rotateToNextAccount }
32
31
 
@@ -56,66 +55,51 @@ export function apply(ctx, config) {
56
55
  autoDiscoverPlanModels(ctx, { live, getSettingsApi: () => settingsApi, syncProviderState })
57
56
  }
58
57
 
59
- const createSettingsAdapter = (svc) => {
60
- if (!svc) return undefined
61
- if (typeof svc.replace === 'function' || typeof svc.update === 'function' || typeof svc.write === 'function') {
62
- const getRevision = () => {
63
- try {
64
- return svc.describe?.().find((row) => row.ns === NS)?.revision
65
- } catch {
66
- return undefined
67
- }
68
- }
69
- return {
70
- get: () => live(),
71
- replace: async (next) => {
72
- const parsed = Config(structuredClone(plainConfig(next)))
73
- currentConfig = parsed
74
- const payload = volatileConfig(parsed)
75
- if (typeof svc.replace === 'function') {
76
- await svc.replace(NS, payload, getRevision())
77
- } else if (typeof svc.update === 'function') {
78
- await svc.update(NS, payload, getRevision())
79
- }
80
- return parsed
81
- },
82
- update: async (patch) => {
83
- const merged = Config({ ...publicConfig(live()), ...plainConfig(patch) })
84
- currentConfig = merged
85
- const payload = volatileConfig(merged)
86
- if (typeof svc.update === 'function') {
87
- await svc.update(NS, payload, getRevision())
88
- } else if (typeof svc.replace === 'function') {
89
- await svc.replace(NS, payload, getRevision())
90
- }
91
- return merged
92
- },
93
- watch: (cb) => {
94
- if (typeof svc.watch === 'function') return svc.watch(cb)
95
- return () => {}
96
- },
97
- }
58
+ const getRevision = (svc) => {
59
+ try {
60
+ return svc?.describe?.().find((row) => row.ns === NS)?.revision
61
+ } catch {
62
+ return undefined
98
63
  }
99
- return undefined
100
64
  }
101
65
 
102
- if (typeof ctx.inject === 'function') {
103
- ctx.inject(['settings'], (sctx) => {
104
- if (typeof sctx.settings?.register === 'function') {
105
- const scope = sctx.settings.register(NS, Config, { base: config })
106
- settingsApi = scope
107
- getConfig = () => (scope?.get?.() ?? config) ?? config
108
- sctx.effect(() => scope.watch((next) => {
109
- syncProviderState(live())
110
- }), 'dsh-clinebot: settings')
111
- } else {
112
- settingsApi = createSettingsAdapter(sctx.settings)
66
+ settingsApi = {
67
+ get: () => live(),
68
+ replace: async (next) => {
69
+ const parsed = Config(structuredClone(plainConfig(next)))
70
+ currentConfig = parsed
71
+ const svc = ctx?.get?.('settings')
72
+ if (svc) {
73
+ const payload = volatileConfig(parsed)
74
+ if (typeof svc.replace === 'function') {
75
+ await svc.replace(NS, payload, getRevision(svc))
76
+ } else if (typeof svc.update === 'function') {
77
+ await svc.update(NS, payload, getRevision(svc))
78
+ }
113
79
  }
114
- sctx.effect(() => () => {
115
- getConfig = () => config
116
- settingsApi = undefined
117
- })
118
- })
80
+ await syncProviderState(live())
81
+ return parsed
82
+ },
83
+ update: async (patch) => {
84
+ const merged = Config({ ...publicConfig(live()), ...plainConfig(patch) })
85
+ currentConfig = merged
86
+ const svc = ctx?.get?.('settings')
87
+ if (svc) {
88
+ const payload = volatileConfig(merged)
89
+ if (typeof svc.update === 'function') {
90
+ await svc.update(NS, payload, getRevision(svc))
91
+ } else if (typeof svc.replace === 'function') {
92
+ await svc.replace(NS, payload, getRevision(svc))
93
+ }
94
+ }
95
+ await syncProviderState(live())
96
+ return merged
97
+ },
98
+ watch: (cb) => {
99
+ const svc = ctx?.get?.('settings')
100
+ if (typeof svc?.watch === 'function') return svc.watch(cb)
101
+ return () => {}
102
+ },
119
103
  }
120
104
 
121
105
  syncProviderState(live())
@@ -1,5 +1,5 @@
1
1
  import { writeJson, readBody } from '../http.js'
2
- import { isTrustedSettingsRequest, assertTrustedSettingsRequest } from '../access.js'
2
+ import { assertTrustedSettingsRequest } from '../access.js'
3
3
  import { publicConfig, plainConfig, Config } from '../config.js'
4
4
  import { buildStatus } from '../provider-sync.js'
5
5
  import { saveCredentialKey, smokeChat, DEFAULT_API_KEY_ENV } from '../cline-client.js'
@@ -22,6 +22,7 @@ import {
22
22
  } from './cline-client.js'
23
23
 
24
24
  export function registerSlashCommand(ctx, { live, getSettingsApi, syncProviderState }) {
25
+ if (typeof ctx.inject !== 'function') return
25
26
  ctx.inject(['commands'], (cmdCtx) => {
26
27
  const commands = cmdCtx.commands
27
28
  if (typeof commands?.register !== 'function') return
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@goodandready/dsh-clinebot",
3
- "version": "0.4.5",
3
+ "version": "0.4.7",
4
4
  "description": "DeepSeek Harness companion for ClineBot / ClinePass: dynamic subscription models sync, quota exhaustion warnings, session metrics, dedicated settings page, live usage limits, and /cline slash-command.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -61,7 +61,6 @@
61
61
  "@deepseek-ai/cordis": "^4.0.1",
62
62
  "@deepseek-ai/dsh-credentials": "^0.1.0-rc.6",
63
63
  "@deepseek-ai/dsh-host-webserver": "^0.1.0-rc.6",
64
- "@deepseek-ai/dsh-settings": "^0.1.0-rc.6",
65
64
  "@deepseek-ai/schemastery": "^3.18.1"
66
65
  },
67
66
  "devDependencies": {