dsh-cline-pass 0.2.1 → 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.en.md CHANGED
@@ -13,7 +13,7 @@ Connect [Cline Pass](https://cline.bot/cline-pass) subscription models to the [D
13
13
 
14
14
  ## Requirements
15
15
 
16
- - dsh `>= 0.1.2-alpha.3 < 0.2.0`
16
+ - dsh `>= 0.1.2-alpha.3 < 0.3.0`
17
17
  - Node.js `>= 20.3`
18
18
  - A Cline Pass API key
19
19
 
@@ -68,7 +68,25 @@ To override defaults, add a `cline-pass` section to your profile's `$DSH_HOME/pr
68
68
  apiKeyEnv: CLINE_PASS_BACKUP_KEY
69
69
  ```
70
70
 
71
- Common settings include `baseURL`, `knownModels`, `models`, `perModel`, `exposeCatalog`, and `historyLimit`. The default gateway is `https://api.cline.bot/api/v1`. `maxConcurrentRequests` caps how many streams each account keeps open to the gateway at once (default 16); further requests wait for a free slot, and `0` lifts the cap.
71
+ Common settings include `baseURL`, `knownModels`, `models`, `perModel`, `exposeTools`, `exposeCatalog`, and `historyLimit`. The default gateway is `https://api.cline.bot/api/v1`. `maxConcurrentRequests` caps how many streams each account keeps open to the gateway at once (default 16); further requests wait for a free slot, and `0` lifts the cap.
72
+
73
+ ### Management tools
74
+
75
+ The `cline_pass_*` tools are **not registered by default**. Their eight definitions total roughly 5.5k characters of schema and description that ride in every request's tool list, and managing the route is an occasional need, so the default keeps that cost out of every conversation.
76
+
77
+ Turn them on with **Expose the tools (takes effect after a restart)** in **Settings → Cline Pass**, or in the profile configuration:
78
+
79
+ ```yaml
80
+ - id: cline-pass
81
+ config:
82
+ exposeTools: true
83
+ ```
84
+
85
+ **The value is read when the plugin activates, so a change needs a dsh restart** — a tool already registered cannot be pulled back out of a conversation in progress.
86
+
87
+ The provider route and the setup panel are unaffected — the panel is a browser page rather than a tool, and it stays available with the tools off.
88
+
89
+ > A profile upgraded from 0.2.1 or earlier has no `exposeTools` key, so it adopts the new default of `false` and its `cline_pass_*` tools stop being registered. The panel reports this; tick the checkbox and restart to bring them back.
72
90
 
73
91
  ## Upstream channels
74
92
 
package/README.md CHANGED
@@ -13,7 +13,7 @@
13
13
 
14
14
  ## 要求
15
15
 
16
- - dsh `>= 0.1.2-alpha.3`
16
+ - dsh `>= 0.1.2-alpha.3 < 0.3.0`
17
17
  - Node.js `>= 20.3`
18
18
  - Cline Pass API Key
19
19
 
@@ -68,6 +68,24 @@ cline_pass_accounts action=mode mode=roundrobin
68
68
  apiKeyEnv: CLINE_PASS_BACKUP_KEY
69
69
  ```
70
70
 
71
+ ### 管理工具
72
+
73
+ `cline_pass_*` 工具**默认不注册**。8 个工具定义合计约 5.5k 字符,会出现在每次请求的工具列表里,而管理路由只是偶尔需要,所以默认让所有对话都不必付这份开销。
74
+
75
+ 需要时在**设置 → Cline Pass** 中勾选「开启工具注入(重启后生效)」,或在 profile 配置里打开:
76
+
77
+ ```yaml
78
+ - id: cline-pass
79
+ config:
80
+ exposeTools: true
81
+ ```
82
+
83
+ **该值在插件激活时读取,改动后需重启 dsh 才生效** —— 已经注册的工具无法从进行中的对话里撤回。
84
+
85
+ 提供商路由和设置面板不受影响 —— 面板是浏览器页面而非工具,工具关闭时仍然可用。
86
+
87
+ > 从 0.2.1 及更早版本升级的 profile 里没有 `exposeTools` 键,因此会采用新的默认值 `false`:升级后 `cline_pass_*` 工具将不再注册。面板会提示,勾选该复选框并在重启后恢复。
88
+
71
89
  常用设置包括 `baseURL`、`knownModels`、`models`、`perModel`、`exposeCatalog` 和 `historyLimit`。默认网关地址为 `https://api.cline.bot/api/v1`。`maxConcurrentRequests` 限制每个账号同时发往网关的流数,默认 16,超出的请求排队等待空位,设为 `0` 表示不限。
72
90
 
73
91
  ## 上游渠道
package/lib/client.js CHANGED
@@ -240,6 +240,7 @@ window.__ModuleLoader__.load({
240
240
  '.cp-usage-model-cost{font-variant-numeric:tabular-nums;color:var(--dsw-alias-label-primary)}',
241
241
  '.cp-usage-model-tokens{font-variant-numeric:tabular-nums;color:var(--dsw-alias-label-tertiary);min-width:52px;text-align:right}',
242
242
  '.cp-check{width:14px;height:14px;flex:none;cursor:pointer;accent-color:var(--dsw-alias-brand-primary)}',
243
+ '.cp-tools-label{cursor:pointer;gap:8px}',
243
244
  '.cp-model-hidden .cp-mono,.cp-model-hidden .cp-check{opacity:.55}',
244
245
  ].join('')
245
246
 
@@ -336,6 +337,7 @@ window.__ModuleLoader__.load({
336
337
  noHistory: '暂无记录。',
337
338
  busy: '处理中…',
338
339
  settingsUnavailable: '设置服务不可用,改动无法保存。',
340
+ toolsExpose: '开启工具注入(重启后生效)',
339
341
  retry: '重试',
340
342
  }
341
343
  const EN = {
@@ -418,6 +420,7 @@ window.__ModuleLoader__.load({
418
420
  noHistory: 'Nothing recorded.',
419
421
  busy: 'Working…',
420
422
  settingsUnavailable: 'Settings are read-only; changes will not persist.',
423
+ toolsExpose: 'Expose the tools (takes effect after a restart)',
421
424
  retry: 'Retry',
422
425
  }
423
426
 
@@ -697,6 +700,7 @@ window.__ModuleLoader__.load({
697
700
  setAccountEnabled: (name, enabled) => controller.setAccountEnabled(name, enabled),
698
701
  pinModel: (payload) => controller.pinModel(payload),
699
702
  setModelVisible: (model, visible) => controller.setModelVisible(model, visible),
703
+ setToolsExposed: (value) => controller.setToolsExposed(value),
700
704
  setModelsVisibility: (mode) => controller.setModelsVisibility(mode),
701
705
  probeModel: (model) => controller.probeModel(model),
702
706
  validateModel: (model) => controller.validateModel(model),
@@ -872,6 +876,21 @@ window.__ModuleLoader__.load({
872
876
  return result
873
877
  }
874
878
 
879
+ /**
880
+ * Turn the `cline_pass_*` tools on or off.
881
+ *
882
+ * The host reads the setting when the plugin activates, so this cannot
883
+ * change the running plugin: a tool already registered cannot be pulled
884
+ * back out of a conversation's tool list. The host says as much in its
885
+ * reply, and the panel relays it rather than implying the switch already
886
+ * took effect.
887
+ */
888
+ async setToolsExposed(value) {
889
+ const result = await this.run('tools', async () => await this.call('tools.expose', { value }))
890
+ if (result !== undefined) this.applyState(result)
891
+ return result
892
+ }
893
+
875
894
  /**
876
895
  * Show, hide or swap every subscription model at once.
877
896
  *
@@ -1660,6 +1679,7 @@ window.__ModuleLoader__.load({
1660
1679
  setAccountEnabled: props.setAccountEnabled,
1661
1680
  pinModel: props.pinModel,
1662
1681
  setModelVisible: props.setModelVisible,
1682
+ setToolsExposed: props.setToolsExposed,
1663
1683
  setModelsVisibility: props.setModelsVisibility,
1664
1684
  probeModel: props.probeModel,
1665
1685
  validateModel: props.validateModel,
@@ -1713,6 +1733,21 @@ window.__ModuleLoader__.load({
1713
1733
  // Everything below the accounts card reads through the key that card
1714
1734
  // stores, so none of it exists until there is one.
1715
1735
  data === null || !ready ? null : h(ModelsCard, { key: 'models', t, data, disabled, busy: state.busy, actions }),
1736
+ // Route-wide switches last: they are not about one model or account, and
1737
+ // nothing below them depends on their value.
1738
+ data === null ? null : h('div', { key: 'tools', className: 'cp-card' }, [
1739
+ h('label', { key: 'head', className: 'cp-row cp-tools-label' }, [
1740
+ h('input', {
1741
+ key: 'on',
1742
+ type: 'checkbox',
1743
+ className: 'cp-check',
1744
+ checked: data.exposeTools !== false,
1745
+ disabled,
1746
+ onChange: (event) => actions.setToolsExposed(event.target.checked),
1747
+ }),
1748
+ h('span', { key: 'l' }, t('toolsExpose')),
1749
+ ]),
1750
+ ]),
1716
1751
  // Diagnostic detail, so it stays folded away until asked for.
1717
1752
  data === null || !ready ? null : h('details', { key: 'history', className: 'cp-card' }, [
1718
1753
  foldHeader(`${t('history')} · ${total}`),
package/lib/index.js CHANGED
@@ -144,6 +144,24 @@ export const Config = z.object({
144
144
  * waits) instead of opening another stream. `0` lifts the cap.
145
145
  */
146
146
  maxConcurrentRequests: z.number().default(DEFAULT_MAX_CONCURRENT_REQUESTS),
147
+ /**
148
+ * Whether the `cline_pass_*` management tools are registered at all.
149
+ *
150
+ * The eight definitions are ~5.5k characters of schema and description that
151
+ * ride in every request's tool list, and the route itself does not need them:
152
+ * a conversation that never probes, pins or edits the pool pays for them on
153
+ * every turn. Off leaves the provider and the setup panel exactly as they are
154
+ * — the panel is a browser page, not a tool, so it keeps working.
155
+ *
156
+ * Off by default: the cost is paid by every conversation, while the tools are
157
+ * wanted by the few that manage the route. Turning them on is one checkbox.
158
+ * Existing profiles have no `exposeTools` key, so they adopt this default on
159
+ * upgrade and their tools stop being registered — the panel says so, and the
160
+ * checkbox restores them.
161
+ *
162
+ * Read when the plugin activates, so a change needs a restart.
163
+ */
164
+ exposeTools: z.boolean().default(false),
147
165
  exposeCatalog: z.boolean().default(false),
148
166
  historyLimit: z.number().default(100),
149
167
  /**
@@ -543,9 +561,22 @@ export function apply(ctx, config) {
543
561
  await credentials.set(credentialRef(ref), String(value))
544
562
  },
545
563
  refreshCatalog,
564
+ // Read at activation, so this reports the value the running plugin was
565
+ // built with rather than the current config field.
566
+ exposeTools: () => toolsExposed,
546
567
  }
547
568
 
548
- registerTools(ctx, { store, engine, control })
569
+ // The agent-facing management surface. Optional: the eight definitions are
570
+ // ~5.5k characters of tool list on every request, and a conversation that
571
+ // never probes, pins or edits the pool does not need them. `exposeTools:
572
+ // false` drops them while leaving the provider and the setup panel — a
573
+ // browser page rather than a tool — untouched.
574
+ const toolsExposed = config.exposeTools !== false
575
+ if (toolsExposed) {
576
+ registerTools(ctx, { store, engine, control })
577
+ } else {
578
+ ctx.logger?.info('[cline-pass] cline_pass_* tools are not exposed (exposeTools: false); the provider route and the setup panel are unaffected')
579
+ }
549
580
 
550
581
  // The same surface as an ordinary browser page, for users who would rather
551
582
  // click than compose a tool call. Absent in a headless composition.
package/lib/panel.js CHANGED
@@ -139,6 +139,10 @@ export function createPanel({ control, engine, store }) {
139
139
  usage: store.usage(),
140
140
  catalogCount: Number(store.catalog()?.ids?.length ?? 0),
141
141
  historySize: store.historySize(),
142
+ // Whether the `cline_pass_*` tools are registered. Reported, not switched:
143
+ // the value is read when the plugin activates, so a control here could not
144
+ // take effect without a reload.
145
+ exposeTools: control.exposeTools(),
142
146
  }
143
147
  }
144
148
 
@@ -470,6 +474,21 @@ export function createPanel({ control, engine, store }) {
470
474
  }
471
475
  }
472
476
 
477
+ /**
478
+ * Whether the `cline_pass_*` tools are registered.
479
+ *
480
+ * The value is read when the plugin activates, so this writes the setting for
481
+ * the next start rather than changing the running plugin: a tool that is
482
+ * already registered cannot be pulled back out of a conversation's tool list.
483
+ * The response carries `restartRequired` so the panel can say so instead of
484
+ * implying the switch already took effect.
485
+ */
486
+ async function toolsExpose(payload) {
487
+ if (typeof payload?.value !== 'boolean') throw new Error('this action needs a boolean `value`')
488
+ await control.updateConfig({ exposeTools: payload.value })
489
+ return { restartRequired: true, ...(await state()) }
490
+ }
491
+
473
492
  return {
474
493
  state,
475
494
  usage,
@@ -487,6 +506,7 @@ export function createPanel({ control, engine, store }) {
487
506
  'model.test': modelTest,
488
507
  'model.reset': modelReset,
489
508
  'models.refresh': modelsRefresh,
509
+ 'tools.expose': toolsExpose,
490
510
  history,
491
511
  }
492
512
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-cline-pass",
3
- "version": "0.2.1",
3
+ "version": "0.2.2",
4
4
  "description": "Self-contained Cline Pass provider for dsh: register Cline Pass subscription models on the harness LLM seam, enumerate and validate the upstream channels behind each model, pin or exclude them with failover, and drive an account pool. No proxy process and no external cline-pass-switcher install required.",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",
@@ -56,18 +56,18 @@
56
56
  ]
57
57
  },
58
58
  "compatibility": {
59
- "dsh": ">=0.1.2-alpha.3 <0.2.0"
59
+ "dsh": ">=0.1.2-alpha.3 <0.3.0"
60
60
  }
61
61
  },
62
62
  "peerDependencies": {
63
63
  "@deepseek-ai/cordis": "^4.0.2",
64
- "@deepseek-ai/dsh-credentials": ">=0.1.2-alpha.3 <0.2.0",
65
- "@deepseek-ai/dsh-launch-environment": ">=0.1.2-alpha.3 <0.2.0",
66
- "@deepseek-ai/dsh-llm": ">=0.1.2-alpha.3 <0.2.0",
67
- "@deepseek-ai/dsh-settings": ">=0.1.2-alpha.3 <0.2.0",
68
- "@deepseek-ai/dsh-timeout": ">=0.1.2-alpha.3 <0.2.0",
69
- "@deepseek-ai/dsh-tools": ">=0.1.2-alpha.3 <0.2.0",
70
- "@deepseek-ai/dsh-util-values": ">=0.1.2-alpha.3 <0.2.0",
64
+ "@deepseek-ai/dsh-credentials": ">=0.1.2-alpha.3 <0.3.0",
65
+ "@deepseek-ai/dsh-launch-environment": ">=0.1.2-alpha.3 <0.3.0",
66
+ "@deepseek-ai/dsh-llm": ">=0.1.2-alpha.3 <0.3.0",
67
+ "@deepseek-ai/dsh-settings": ">=0.1.2-alpha.3 <0.3.0",
68
+ "@deepseek-ai/dsh-timeout": ">=0.1.2-alpha.3 <0.3.0",
69
+ "@deepseek-ai/dsh-tools": ">=0.1.2-alpha.3 <0.3.0",
70
+ "@deepseek-ai/dsh-util-values": ">=0.1.2-alpha.3 <0.3.0",
71
71
  "@deepseek-ai/schemastery": "^3.18.1"
72
72
  }
73
73
  }