@goodandready/dsh-ollama-cloud-provider 0.0.0-stage → 0.1.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/CHANGELOG.md +52 -0
- package/LICENSE +21 -0
- package/NOTICE +15 -0
- package/README.md +232 -2
- package/README.ru.md +131 -0
- package/README.zh.md +131 -0
- package/cordis.patch.yml +11 -0
- package/lib/client.js +2656 -0
- package/lib/index.d.ts +452 -0
- package/lib/index.js +4651 -0
- package/media/visual-verification.png +0 -0
- package/package.json +119 -4
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.1.2 — 2026-10-21
|
|
4
|
+
|
|
5
|
+
- Test connection falls back to the reasoning text when a thinking model returns
|
|
6
|
+
no content, and uses a 64-token budget (#17).
|
|
7
|
+
- Production acceptance of 0.1.1 confirmed chat, catalog and balance; the probe
|
|
8
|
+
is the only follow-up defect.
|
|
9
|
+
|
|
10
|
+
## 0.1.1 — 2026-10-21
|
|
11
|
+
|
|
12
|
+
Audit fixes (Gitea #1–#15):
|
|
13
|
+
|
|
14
|
+
- A transient transport/timeout/server failure no longer cools down the only
|
|
15
|
+
configured account; the harness retry policy can recover. Credential and quota
|
|
16
|
+
rejections still cool the key (#1).
|
|
17
|
+
- Removed the unimplemented `toolUpdate: 'addition-only'` declaration so the
|
|
18
|
+
model always receives the full tool list (#2).
|
|
19
|
+
- `/dsh-ollama/key` and `/key/clear` only accept this plugin's credential
|
|
20
|
+
references (`apiKeyEnv`, configured account refs and `OLLAMA_*`) (#3).
|
|
21
|
+
- The sidebar quota card honors `showSidebarQuota`, stays unmounted while the
|
|
22
|
+
setting is off and stops polling `/state` (#4).
|
|
23
|
+
- The injected stylesheet carries `data-dsh-plugin` so neighbouring plugin
|
|
24
|
+
cleanup cannot strip it (#5).
|
|
25
|
+
- Analytics uses the shared `estimateCost` implementation and applies
|
|
26
|
+
`priceOverrides` (#7).
|
|
27
|
+
- Empty catch blocks report through `bestEffortFailed` at debug level (#8).
|
|
28
|
+
- Removed unused modules and exports (`quota-runway`, `requireImages`,
|
|
29
|
+
`clearAnalyticsCache`, `PLUGIN_PROVIDERS`, `showUrlFor`) (#9).
|
|
30
|
+
- Heatmap and theme values no longer hardcode colors (#10).
|
|
31
|
+
- Test-connection requests disable thinking and use a 32-token budget (#11).
|
|
32
|
+
- The request log is flushed on shutdown (#12).
|
|
33
|
+
- Architecture documentation moved to `docs/design/ARCHITECTURE.md`; the
|
|
34
|
+
design contract lives in `docs/design/DESIGN.md` (#13).
|
|
35
|
+
- Added wiring, analytics, route-guard and adapter regression tests (#14).
|
|
36
|
+
- Account rows show the 7-day spend without a meaningless percentage (#15).
|
|
37
|
+
|
|
38
|
+
## 0.1.0
|
|
39
|
+
|
|
40
|
+
Initial release.
|
|
41
|
+
|
|
42
|
+
- Registers the `ollama-cloud` provider route for DeepSeek Harness.
|
|
43
|
+
- Native `/api/chat` transport (NDJSON) with thinking, tool calls, images and usage counters.
|
|
44
|
+
- OpenAI-compatible `/v1/chat/completions` transport selectable per model.
|
|
45
|
+
- Live model catalog from `/v1/models` enriched with `/api/tags` capabilities, plus an offline snapshot.
|
|
46
|
+
- Balance from `/api/balance` (credits and legacy percentage windows) and spend from `/api/usage`
|
|
47
|
+
with 24-hour, 7-day and 30-day windows and per-model groups.
|
|
48
|
+
- Multi-account rotation before the first streamed token, persistent cooldowns, sticky sessions and
|
|
49
|
+
model → account glob rules.
|
|
50
|
+
- Price estimates including off-peak rates and per-model overrides.
|
|
51
|
+
- Settings page, sidebar quota card, quota/analytics panel with a request heatmap, `/ollama` command,
|
|
52
|
+
TUI settings section and one-click plugin update.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 dsh-opencode-provider contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/NOTICE
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
dsh-ollama-cloud-provider
|
|
2
|
+
Copyright (c) 2026 GooDAnDReaDY
|
|
3
|
+
|
|
4
|
+
This product is MIT-licensed (see LICENSE).
|
|
5
|
+
|
|
6
|
+
Third-party references and attribution:
|
|
7
|
+
|
|
8
|
+
- The plugin structure, cordis lifecycle wiring, HTTP route guards, request log, analytics reader,
|
|
9
|
+
quota runway and generic client widgets were adapted from the author's own
|
|
10
|
+
`@goodandready/dsh-opencode-provider` (MIT).
|
|
11
|
+
- The feature set was informed by `@goodandready/dsh-clinebot` (MIT) and
|
|
12
|
+
`@mars-sea/dsh-commandcode-provider` (MIT). No vendor code from those packages is bundled.
|
|
13
|
+
- DeepSeek Harness packages (`@deepseek-ai/*`) are host-owned peer dependencies and are not bundled.
|
|
14
|
+
- Ollama Cloud API facts were verified against the public documentation and live endpoints on
|
|
15
|
+
2026-10-21. Ollama is a trademark of its respective owner; this plugin is unofficial.
|
package/README.md
CHANGED
|
@@ -1,3 +1,233 @@
|
|
|
1
|
-
#
|
|
1
|
+
# 📦 @goodandready/dsh-ollama-cloud-provider
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
<div align="center">
|
|
4
|
+
|
|
5
|
+
<h3>Ollama Cloud LLM Provider for DeepSeek Harness</h3>
|
|
6
|
+
|
|
7
|
+
<p>
|
|
8
|
+
<a href="https://www.npmjs.com/package/@goodandready/dsh-ollama-cloud-provider"><img src="https://img.shields.io/npm/v/@goodandready/dsh-ollama-cloud-provider?style=for-the-badge&color=crimson&logo=npm" alt="npm version"></a>
|
|
9
|
+
</p>
|
|
10
|
+
|
|
11
|
+
</div>
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
Ollama Cloud provider plugin for [DeepSeek Harness](https://deepseek-harness.github.io/deepseek-harness/) (dsh).
|
|
16
|
+
|
|
17
|
+
It registers one native LLM route, `ollama-cloud`, served by `https://ollama.com`, with two wire protocols:
|
|
18
|
+
|
|
19
|
+
| Transport | Endpoint | When |
|
|
20
|
+
|---|---|---|
|
|
21
|
+
| `native` (default) | `POST /api/chat` | thinking, tool calls, usage counters |
|
|
22
|
+
| `openai-chat` | `POST /v1/chat/completions` | OpenAI-compatible deployments and fallback |
|
|
23
|
+
|
|
24
|
+
Requests resolve the key per call, so a changed credential reaches the next request without a restart.
|
|
25
|
+
|
|
26
|
+
## Architecture
|
|
27
|
+
|
|
28
|
+
```mermaid
|
|
29
|
+
graph LR
|
|
30
|
+
subgraph DSH["DeepSeek Harness Core"]
|
|
31
|
+
Agent["DSH Agent / Chat"]
|
|
32
|
+
Creds["Credentials / launch env"]
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
subgraph Plugin["dsh-ollama-cloud-provider"]
|
|
36
|
+
Router{"Route: ollama-cloud"}
|
|
37
|
+
Pool["Account pool<br/>rotation, cooldowns, sticky"]
|
|
38
|
+
Catalog["Live catalog<br/>/v1/models + /api/tags"]
|
|
39
|
+
Usage["Balance & usage<br/>/api/balance + /api/usage"]
|
|
40
|
+
|
|
41
|
+
subgraph Transports["Wire protocols"]
|
|
42
|
+
T1["Native /api/chat (NDJSON)"]
|
|
43
|
+
T2["OpenAI /v1/chat/completions (SSE)"]
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
subgraph Ollama["Ollama Cloud"]
|
|
48
|
+
Chat["ollama.com/api/chat"]
|
|
49
|
+
OpenAI["ollama.com/v1/chat/completions"]
|
|
50
|
+
Billing["/api/balance, /api/usage"]
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
Agent --> Router
|
|
54
|
+
Creds -.-> Pool
|
|
55
|
+
Router --> Pool
|
|
56
|
+
Pool --> Transports
|
|
57
|
+
T1 --> Chat
|
|
58
|
+
T2 --> OpenAI
|
|
59
|
+
Catalog --> Router
|
|
60
|
+
Usage --> Billing
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Features
|
|
64
|
+
|
|
65
|
+
- **Two wire transports** chosen per model: the native Ollama API (NDJSON) and the OpenAI-compatible gateway (SSE).
|
|
66
|
+
- **Text, thinking, tool calls, images, usage and finish reasons** on both transports.
|
|
67
|
+
- **Live catalog** from `GET /v1/models`, enriched with capability flags from `GET /api/tags`.
|
|
68
|
+
- **Accurate limits** for the dsh picker: context window, input modalities, reasoning levels and their default, tool support, and API visibility.
|
|
69
|
+
- **Balance and usage** from the official `/api/balance` and `/api/usage` endpoints: included credits, purchased credits, 24-hour / 7-day / 30-day spend, and spend by model.
|
|
70
|
+
- **Multi-account rotation** before any content is streamed: 401/403/429 and quota rejections mark a key and retry with the next one. Cooldowns persist across restarts.
|
|
71
|
+
- **Sticky accounts** per conversation, plus model → account glob rules.
|
|
72
|
+
- **Price estimates** from the published Ollama pricing table, including off-peak rates, with per-model overrides.
|
|
73
|
+
- **Browser UI**:
|
|
74
|
+
- **Settings → Ollama Cloud**: key, balance, accounts, rules, model allowlist, per-model transport, connection settings.
|
|
75
|
+
- **Sidebar quota card** (off by default, and it does not poll `/state` while disabled): a ring with the highest used window and rows with remaining credits or legacy windows.
|
|
76
|
+
- **Center quota panel**: spend windows, spend by model, accounts, routing trace, usage analytics and a request heatmap.
|
|
77
|
+
- **`/ollama` command** for status, usage, balance, accounts, models, rules and `test [model]`.
|
|
78
|
+
- **TUI settings section** for terminal profiles.
|
|
79
|
+
- **One-click plugin update** in Settings → Ollama Cloud.
|
|
80
|
+
|
|
81
|
+
## Install
|
|
82
|
+
|
|
83
|
+
Build and pack first:
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
npm install
|
|
87
|
+
npm run build
|
|
88
|
+
npm pack
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Install the packed tarball into a profile:
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
dsh plugin --profile web add /absolute/path/to/goodandready-dsh-ollama-cloud-provider-0.1.0.tgz
|
|
95
|
+
# DSH Desktop:
|
|
96
|
+
dsh plugin --profile desktop add /absolute/path/to/goodandready-dsh-ollama-cloud-provider-0.1.0.tgz
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Restart dsh (or DSH Desktop), then pick **Ollama Cloud** in the model picker.
|
|
100
|
+
|
|
101
|
+
> **Use the tarball, not the directory.** On dsh 0.2.1-rc.2 the Desktop CLI aliases a local
|
|
102
|
+
> directory passed to `dsh plugin add` and overwrites the target's `package.json`.
|
|
103
|
+
|
|
104
|
+
## Configure
|
|
105
|
+
|
|
106
|
+
```yaml
|
|
107
|
+
- id: llm-ollama-cloud
|
|
108
|
+
name: "@goodandready/dsh-ollama-cloud-provider"
|
|
109
|
+
config:
|
|
110
|
+
apiKeyEnv: OLLAMA_API_KEY # default
|
|
111
|
+
# apiKey: ... # composition only, never commit
|
|
112
|
+
transport: native # native | openai-chat
|
|
113
|
+
requestTimeoutMs: 300000
|
|
114
|
+
streamIdleTimeoutMs: 300000
|
|
115
|
+
visibleModels: []
|
|
116
|
+
modelTransports: {}
|
|
117
|
+
# contextWindowOverrides: { "gpt-oss:120b": 131072 }
|
|
118
|
+
# maxOutputTokens: 32768
|
|
119
|
+
accounts:
|
|
120
|
+
- label: Work
|
|
121
|
+
apiKeyEnv: OLLAMA_API_KEY_2
|
|
122
|
+
activeAccount: '' # label or credential name to pin
|
|
123
|
+
stickySession: true
|
|
124
|
+
showSidebarQuota: false
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Every field except `apiKey` is volatile and appears in dsh settings.
|
|
128
|
+
|
|
129
|
+
### Keys
|
|
130
|
+
|
|
131
|
+
1. `config.apiKey` (composition only, `role('secret')`).
|
|
132
|
+
2. The dsh credential seam under `apiKeyEnv` (default `OLLAMA_API_KEY`).
|
|
133
|
+
3. The launch environment (process, project `.env`, `$DSH_HOME/.env`).
|
|
134
|
+
|
|
135
|
+
Create a key at <https://ollama.com/settings/keys>. Keys do not expire; `x-api-key` is **not** accepted, only `Authorization: Bearer`.
|
|
136
|
+
|
|
137
|
+
### Accounts and rotation
|
|
138
|
+
|
|
139
|
+
Add a second account in **Settings → Ollama Cloud → Accounts**: give it a name and a credential reference (for example `OLLAMA_API_KEY_2`), paste its key, then Save. The default account always serves first unless `activeAccount` pins another one.
|
|
140
|
+
|
|
141
|
+
Rotation happens **before any content is streamed**. When the serving key is rejected with an invalid credential, a rate limit or an exhausted quota, the adapter marks that key and retries the same request with the next usable account. A request that already started streaming is not replayed. Cooldowns are stored in `~/.dsh/storages/dsh-ollama/cooldowns.json` keyed by a SHA-256 fingerprint — raw keys are never written.
|
|
142
|
+
|
|
143
|
+
### Model → account rules
|
|
144
|
+
|
|
145
|
+
Pin a model to a preferred account with a glob. The first matching rule wins; `*` and `?` are supported and matching is case-insensitive. Other accounts remain fallbacks.
|
|
146
|
+
|
|
147
|
+
```yaml
|
|
148
|
+
modelAccountRules:
|
|
149
|
+
- pattern: "*flash*"
|
|
150
|
+
account: "Work"
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## Balance and usage
|
|
154
|
+
|
|
155
|
+
The plugin uses the documented cloud endpoints:
|
|
156
|
+
|
|
157
|
+
- `GET /api/balance` → `included.balance_usd` / `included.allowance_usd` / `included.period` and `purchased.balance_usd`. Legacy accounts return `included.session.remaining_percent` and `included.weekly.remaining_percent`; both formats are displayed.
|
|
158
|
+
- `GET /api/usage?range=24h|7d|30d&group_by=model` → totals and per-model groups with request count, USD, input, cached input and output tokens.
|
|
159
|
+
|
|
160
|
+
`/api/usage` is limited to **10 requests per minute per user**, so the reader caches each range (balance 60 s, usage 120 s, failures 30 s) and never polls in the background. Quota failures are fail-open: chat never depends on them.
|
|
161
|
+
|
|
162
|
+
## Settings page
|
|
163
|
+
|
|
164
|
+
Open **Settings → Ollama Cloud**:
|
|
165
|
+
|
|
166
|
+
- **Key** — status, paste a key, clear it, run **Test connection** against a chosen model. The probe disables thinking so the reply is visible.
|
|
167
|
+
- **Balance and usage** — credit bar or legacy windows, spend windows, warning at 80 % and exhausted at 95 %.
|
|
168
|
+
- **Accounts** — extra keys, per-account spend, pin, remove, set a key.
|
|
169
|
+
- **Model → account rules** — glob rules.
|
|
170
|
+
- **Routing** — sticky session per conversation.
|
|
171
|
+
- **Models** — search, refresh the live catalog, hide models, override the wire transport per model, see price, context and capabilities.
|
|
172
|
+
- **Connection** — native and OpenAI bases, usage and balance endpoints, transport, timeouts, output cap and context override.
|
|
173
|
+
- **Sidebar** — show or hide the quota card.
|
|
174
|
+
- **Plugin update** — current/latest version and **Update now**.
|
|
175
|
+
|
|
176
|
+
The Host serves `/dsh-ollama/state`, `/health`, `/analytics`, `/usage`, `/balance`, `/config`, `/key`, `/key/clear`, `/refresh`, `/models/refresh`, `/test` and `/update`. Writes require JSON, are refused for cross-origin requests, and are restricted to loopback (`127.0.0.1` / `::1`).
|
|
177
|
+
|
|
178
|
+
## Command
|
|
179
|
+
|
|
180
|
+
```
|
|
181
|
+
/ollama status # provider, accounts, quota and model count
|
|
182
|
+
/ollama usage # 7-day spend windows and spend by model
|
|
183
|
+
/ollama balance # included and purchased credits
|
|
184
|
+
/ollama accounts # labels, source, active/cooling, 7-day spend
|
|
185
|
+
/ollama models # ids, price, context, capabilities
|
|
186
|
+
/ollama rules # model → account rules
|
|
187
|
+
/ollama test [model] # minimal real request, default gpt-oss:120b
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
## Verified API facts
|
|
191
|
+
|
|
192
|
+
Checked live on 2026-10-21:
|
|
193
|
+
|
|
194
|
+
- `GET https://ollama.com/v1/models` is public and returns `data[]` plus a non-standard `models[]` array carrying `context_window`, `max_context_window`, `input_modalities`, `supported_reasoning_levels`, `default_reasoning_level`, `visibility` and `supported_in_api`.
|
|
195
|
+
- `GET https://ollama.com/api/tags` is public and is the only per-model source of `capabilities` (`completion`, `tools`, `thinking`, `vision`).
|
|
196
|
+
- The live catalog returned 23 cloud models.
|
|
197
|
+
- Native `/api/chat` streams NDJSON and reports `prompt_eval_count`, `prompt_eval_cached_count`, `eval_count` and `done_reason` in the final line.
|
|
198
|
+
- OpenAI `/v1/chat/completions` supports streaming, tools, vision, `reasoning_effort` and `stream_options.include_usage`.
|
|
199
|
+
- Anthropic compatibility (`/v1/messages`) exists but is partial; this plugin does not use it.
|
|
200
|
+
|
|
201
|
+
## Development
|
|
202
|
+
|
|
203
|
+
```bash
|
|
204
|
+
npm run typecheck
|
|
205
|
+
npm test
|
|
206
|
+
npm run build
|
|
207
|
+
npm run check # typecheck + tests + build
|
|
208
|
+
npm run release # check + packed tarball
|
|
209
|
+
node scripts/probe.mjs
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
`scripts/probe.mjs` is read-only against the public catalog; with `OLLAMA_API_KEY` set it also probes chat, balance and usage and prints the raw shapes.
|
|
213
|
+
|
|
214
|
+
## Visual verification
|
|
215
|
+
|
|
216
|
+
The Ollama Cloud settings page in DSH Desktop (dark theme): configured
|
|
217
|
+
credential, balance and usage, and the connection probe.
|
|
218
|
+
|
|
219
|
+

|
|
220
|
+
|
|
221
|
+
## Limitations
|
|
222
|
+
|
|
223
|
+
- **Cloud only.** Local `http://localhost:11434` is not registered as a route.
|
|
224
|
+
- Embeddings are not exposed: no cloud model in the live catalog advertises the `embedding` capability.
|
|
225
|
+
- File attachments are forwarded as deterministic handle text, not inline bytes.
|
|
226
|
+
- The usage endpoint is limited to 10 requests per minute; caches and the UI account for that.
|
|
227
|
+
- Cost values are estimates from the published table (including off-peak rates); the gateway is the authority.
|
|
228
|
+
- Automatic update requires the DSH CLI entry in the runtime.
|
|
229
|
+
- The UI requires a web profile; the TUI keeps the `/ollama` command and the model route.
|
|
230
|
+
|
|
231
|
+
## License
|
|
232
|
+
|
|
233
|
+
MIT © [GooDAnDReaDY](https://github.com/GooDAnDReaDY). See [LICENSE](./LICENSE) and [NOTICE](./NOTICE).
|
package/README.ru.md
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# 📦 @goodandready/dsh-ollama-cloud-provider
|
|
2
|
+
|
|
3
|
+
Провайдер **Ollama Cloud** для DeepSeek Harness (dsh).
|
|
4
|
+
|
|
5
|
+
Плагин регистрирует один маршрут `ollama-cloud` (`https://ollama.com`) и два протокола:
|
|
6
|
+
|
|
7
|
+
| Транспорт | Endpoint | Когда используется |
|
|
8
|
+
|---|---|---|
|
|
9
|
+
| `native` (по умолчанию) | `POST /api/chat` | thinking, вызовы инструментов, счётчики usage |
|
|
10
|
+
| `openai-chat` | `POST /v1/chat/completions` | OpenAI-совместимые развёртывания и запасной путь |
|
|
11
|
+
|
|
12
|
+
Ключ разрешается на каждый запрос, поэтому смена credential применяется без перезапуска.
|
|
13
|
+
|
|
14
|
+
## Возможности
|
|
15
|
+
|
|
16
|
+
- Два транспорта, выбираемые по модели.
|
|
17
|
+
- Текст, reasoning/thinking, tool calls, изображения, usage и finish reasons.
|
|
18
|
+
- Живой каталог из `GET /v1/models`, дополненный `capabilities` из `GET /api/tags`.
|
|
19
|
+
- Точные метаданные для picker: контекст, модальности, уровни reasoning и уровень по умолчанию, поддержка инструментов, видимость в API.
|
|
20
|
+
- Баланс и расход из официальных `/api/balance` и `/api/usage`: включённые и купленные кредиты, расход за 24 часа / 7 дней / 30 дней, расход по моделям.
|
|
21
|
+
- Мультиаккаунт с ротацией **до первого токена** на 401/403/429 и исчерпанную квоту; cooldown'ы сохраняются между перезапусками.
|
|
22
|
+
- Липкий аккаунт на диалог и правила `модель → аккаунт` по glob.
|
|
23
|
+
- Оценка стоимости по published-тарифу Ollama, включая off-peak, с ручными overrides.
|
|
24
|
+
- UI: страница **Настройки → Ollama Cloud**, карточка квоты в сайдбаре (по умолчанию выключена и не опрашивает `/state`, пока выключена), панель с расходом, аналитикой и heatmap.
|
|
25
|
+
- Команда `/ollama`, секция TUI и обновление плагина в один клик.
|
|
26
|
+
|
|
27
|
+
## Установка
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
npm install
|
|
31
|
+
npm run build
|
|
32
|
+
npm pack
|
|
33
|
+
dsh plugin --profile web add /absolute/path/to/goodandready-dsh-ollama-cloud-provider-0.1.0.tgz
|
|
34
|
+
# DSH Desktop:
|
|
35
|
+
dsh plugin --profile desktop add /absolute/path/to/goodandready-dsh-ollama-cloud-provider-0.1.0.tgz
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
После установки перезапустите dsh и выберите **Ollama Cloud** в списке моделей.
|
|
39
|
+
|
|
40
|
+
## Настройка
|
|
41
|
+
|
|
42
|
+
```yaml
|
|
43
|
+
- id: llm-ollama-cloud
|
|
44
|
+
name: "@goodandready/dsh-ollama-cloud-provider"
|
|
45
|
+
config:
|
|
46
|
+
apiKeyEnv: OLLAMA_API_KEY
|
|
47
|
+
transport: native # native | openai-chat
|
|
48
|
+
requestTimeoutMs: 300000
|
|
49
|
+
streamIdleTimeoutMs: 300000
|
|
50
|
+
visibleModels: []
|
|
51
|
+
accounts:
|
|
52
|
+
- label: Work
|
|
53
|
+
apiKeyEnv: OLLAMA_API_KEY_2
|
|
54
|
+
activeAccount: ''
|
|
55
|
+
stickySession: true
|
|
56
|
+
showSidebarQuota: false
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Все поля, кроме `apiKey`, доступны в настройках DSH.
|
|
60
|
+
|
|
61
|
+
### Ключи
|
|
62
|
+
|
|
63
|
+
1. `config.apiKey` — только в composition, `role('secret')`.
|
|
64
|
+
2. Credential-сервис по имени `apiKeyEnv` (по умолчанию `OLLAMA_API_KEY`).
|
|
65
|
+
3. Переменные окружения запуска.
|
|
66
|
+
|
|
67
|
+
Ключ создаётся на <https://ollama.com/settings/keys>, не истекает. Принимается только `Authorization: Bearer`; `x-api-key` cloud отклоняет.
|
|
68
|
+
|
|
69
|
+
### Аккаунты и ротация
|
|
70
|
+
|
|
71
|
+
Дополнительный аккаунт добавляется в **Настройки → Ollama Cloud → Аккаунты**: имя + ссылка на credential (например `OLLAMA_API_KEY_2`), затем ключ и «Сохранить». Ротация происходит до стриминга: отклонённый ключ получает cooldown, запрос повторяется следующим ключом. Cooldown'ы лежат в `~/.dsh/storages/dsh-ollama/cooldowns.json` и хранятся по SHA-256 fingerprint — сырые ключи не пишутся.
|
|
72
|
+
|
|
73
|
+
### Правила модель → аккаунт
|
|
74
|
+
|
|
75
|
+
```yaml
|
|
76
|
+
modelAccountRules:
|
|
77
|
+
- pattern: "*flash*"
|
|
78
|
+
account: "Work"
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Первый совпавший glob ставит аккаунт первым; остальные остаются fallback.
|
|
82
|
+
|
|
83
|
+
## Баланс и расход
|
|
84
|
+
|
|
85
|
+
- `GET /api/balance` — новый формат (`included.balance_usd`, `allowance_usd`, `period`, `purchased.balance_usd`) и legacy-формат (`session` / `weekly` с `remaining_percent`). Поддерживаются оба.
|
|
86
|
+
- `GET /api/usage?range=24h|7d|30d&group_by=model` — totals и группы по моделям.
|
|
87
|
+
|
|
88
|
+
У `/api/usage` лимит **10 запросов в минуту на пользователя**, поэтому баланс кэшируется на 60 с, usage — на 120 с, ошибки — на 30 с. Фонового опроса нет. Недоступность квот не блокирует чат.
|
|
89
|
+
|
|
90
|
+
## Команда
|
|
91
|
+
|
|
92
|
+
```
|
|
93
|
+
/ollama status
|
|
94
|
+
/ollama usage
|
|
95
|
+
/ollama balance
|
|
96
|
+
/ollama accounts
|
|
97
|
+
/ollama models
|
|
98
|
+
/ollama rules
|
|
99
|
+
/ollama test [model]
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## Проверенные факты API (2026-10-21)
|
|
103
|
+
|
|
104
|
+
- `GET https://ollama.com/v1/models` публичный и, кроме стандартного `data[]`, отдаёт нестандартный `models[]` с контекстом, модальностями, уровнями reasoning, `visibility` и `supported_in_api`.
|
|
105
|
+
- `GET https://ollama.com/api/tags` публичный и единственный источник `capabilities` по моделям.
|
|
106
|
+
- Live-каталог вернул 23 облачные модели.
|
|
107
|
+
- Нативный `/api/chat` — NDJSON, счётчики и `done_reason` в финальной строке.
|
|
108
|
+
- OpenAI `/v1/chat/completions` поддерживает стриминг, tools, vision, `reasoning_effort` и `include_usage`.
|
|
109
|
+
- Anthropic-совместимость (`/v1/messages`) частичная и плагином не используется.
|
|
110
|
+
|
|
111
|
+
## Разработка
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
npm run typecheck
|
|
115
|
+
npm test
|
|
116
|
+
npm run build
|
|
117
|
+
npm run check
|
|
118
|
+
node scripts/probe.mjs
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## Ограничения
|
|
122
|
+
|
|
123
|
+
- Только Ollama Cloud; локальный `http://localhost:11434` не регистрируется.
|
|
124
|
+
- Embeddings не поддерживаются: ни одна облачная модель не объявляет capability `embedding`.
|
|
125
|
+
- Файловые вложения передаются текстовыми handle-заглушками, не байтами.
|
|
126
|
+
- Стоимость — оценка по опубликованному тарифу; финальным авторитетом остаётся gateway.
|
|
127
|
+
- UI требует web-профиль; в TUI остаются команда `/ollama` и маршрут модели.
|
|
128
|
+
|
|
129
|
+
## Лицензия
|
|
130
|
+
|
|
131
|
+
MIT © [GooDAnDReaDY](https://github.com/GooDAnDReaDY). См. [LICENSE](./LICENSE) и [NOTICE](./NOTICE).
|
package/README.zh.md
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# 📦 @goodandready/dsh-ollama-cloud-provider
|
|
2
|
+
|
|
3
|
+
DeepSeek Harness(dsh)的 **Ollama Cloud** 模型提供方插件。
|
|
4
|
+
|
|
5
|
+
插件注册一个路由 `ollama-cloud`(`https://ollama.com`),支持两种传输协议:
|
|
6
|
+
|
|
7
|
+
| 传输 | 端点 | 用途 |
|
|
8
|
+
|---|---|---|
|
|
9
|
+
| `native`(默认) | `POST /api/chat` | thinking、工具调用、usage 计数 |
|
|
10
|
+
| `openai-chat` | `POST /v1/chat/completions` | OpenAI 兼容部署与回退 |
|
|
11
|
+
|
|
12
|
+
密钥在每次请求时解析,更换凭据无需重启。
|
|
13
|
+
|
|
14
|
+
## 功能
|
|
15
|
+
|
|
16
|
+
- 按模型选择两种传输协议。
|
|
17
|
+
- 文本、thinking、工具调用、图像、usage 和结束原因。
|
|
18
|
+
- 从 `GET /v1/models` 读取实时模型目录,并用 `GET /api/tags` 的 `capabilities` 补充能力。
|
|
19
|
+
- 模型选择器中的准确元数据:上下文窗口、输入模态、推理等级及默认值、工具支持、API 可见性。
|
|
20
|
+
- 从官方 `/api/balance` 和 `/api/usage` 读取余额与用量:包含额度、购买额度、24 小时 / 7 天 / 30 天支出、按模型支出。
|
|
21
|
+
- 多账号轮换在**首个 token 之前**完成:401/403/429 与配额耗尽会标记密钥并切换到下一个。冷却状态重启后保留。
|
|
22
|
+
- 每个会话的粘性账号,以及 `模型 → 账号` 的 glob 规则。
|
|
23
|
+
- 按 Ollama 公开价目表估算费用,包含 off-peak 价格,并支持按模型覆盖。
|
|
24
|
+
- 浏览器界面:**设置 → Ollama Cloud**、侧边栏配额卡片(默认关闭,关闭时不会轮询 `/state`)、含用量分析、热力图和路由记录的中央面板。
|
|
25
|
+
- `/ollama` 命令、TUI 设置区、一键插件更新。
|
|
26
|
+
|
|
27
|
+
## 安装
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
npm install
|
|
31
|
+
npm run build
|
|
32
|
+
npm pack
|
|
33
|
+
dsh plugin --profile web add /absolute/path/to/goodandready-dsh-ollama-cloud-provider-0.1.0.tgz
|
|
34
|
+
# DSH Desktop:
|
|
35
|
+
dsh plugin --profile desktop add /absolute/path/to/goodandready-dsh-ollama-cloud-provider-0.1.0.tgz
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
重启 dsh,然后在模型列表中选择 **Ollama Cloud**。
|
|
39
|
+
|
|
40
|
+
## 配置
|
|
41
|
+
|
|
42
|
+
```yaml
|
|
43
|
+
- id: llm-ollama-cloud
|
|
44
|
+
name: "@goodandready/dsh-ollama-cloud-provider"
|
|
45
|
+
config:
|
|
46
|
+
apiKeyEnv: OLLAMA_API_KEY
|
|
47
|
+
transport: native # native | openai-chat
|
|
48
|
+
requestTimeoutMs: 300000
|
|
49
|
+
streamIdleTimeoutMs: 300000
|
|
50
|
+
visibleModels: []
|
|
51
|
+
accounts:
|
|
52
|
+
- label: Work
|
|
53
|
+
apiKeyEnv: OLLAMA_API_KEY_2
|
|
54
|
+
activeAccount: ''
|
|
55
|
+
stickySession: true
|
|
56
|
+
showSidebarQuota: false
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
除 `apiKey` 外的所有字段都是 volatile,可直接在 dsh 设置中编辑。
|
|
60
|
+
|
|
61
|
+
### 密钥
|
|
62
|
+
|
|
63
|
+
1. `config.apiKey`:仅用于 composition,`role('secret')`。
|
|
64
|
+
2. dsh 凭据服务中的 `apiKeyEnv`(默认 `OLLAMA_API_KEY`)。
|
|
65
|
+
3. 启动环境变量。
|
|
66
|
+
|
|
67
|
+
在 <https://ollama.com/settings/keys> 创建密钥,密钥不会过期。云端只接受 `Authorization: Bearer`,不接受 `x-api-key`。
|
|
68
|
+
|
|
69
|
+
### 账号与轮换
|
|
70
|
+
|
|
71
|
+
在 **设置 → Ollama Cloud → 账号** 中添加账号:填写名称与凭据引用(如 `OLLAMA_API_KEY_2`),粘贴密钥并保存。轮换发生在流式输出之前;被拒绝的密钥进入冷却,请求由下一个可用密钥继续。冷却信息保存在 `~/.dsh/storages/dsh-ollama/cooldowns.json`,仅使用 SHA-256 指纹,不写入原始密钥。
|
|
72
|
+
|
|
73
|
+
### 模型 → 账号规则
|
|
74
|
+
|
|
75
|
+
```yaml
|
|
76
|
+
modelAccountRules:
|
|
77
|
+
- pattern: "*flash*"
|
|
78
|
+
account: "Work"
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
第一个匹配的 glob 优先使用指定账号,其余账号仍作后备。
|
|
82
|
+
|
|
83
|
+
## 余额与用量
|
|
84
|
+
|
|
85
|
+
- `GET /api/balance`:新格式(`included.balance_usd`、`allowance_usd`、`period`、`purchased.balance_usd`)与旧格式(`session` / `weekly` 的 `remaining_percent`)均支持。
|
|
86
|
+
- `GET /api/usage?range=24h|7d|30d&group_by=model`:总计与按模型分组。
|
|
87
|
+
|
|
88
|
+
`/api/usage` 限制为**每位用户每分钟 10 次请求**,因此余额缓存 60 秒、用量缓存 120 秒、失败缓存 30 秒,不做后台轮询。配额不可用不影响聊天。
|
|
89
|
+
|
|
90
|
+
## 命令
|
|
91
|
+
|
|
92
|
+
```
|
|
93
|
+
/ollama status
|
|
94
|
+
/ollama usage
|
|
95
|
+
/ollama balance
|
|
96
|
+
/ollama accounts
|
|
97
|
+
/ollama models
|
|
98
|
+
/ollama rules
|
|
99
|
+
/ollama test [model]
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## 已验证的 API 事实(2026-10-21)
|
|
103
|
+
|
|
104
|
+
- `GET https://ollama.com/v1/models` 公开,除标准 `data[]` 外还返回非标准 `models[]`,包含上下文、模态、推理等级、`visibility` 和 `supported_in_api`。
|
|
105
|
+
- `GET https://ollama.com/api/tags` 公开,是按模型获取 `capabilities` 的唯一来源。
|
|
106
|
+
- 实时目录返回 23 个云端模型。
|
|
107
|
+
- 原生 `/api/chat` 使用 NDJSON,最后一行包含计数与 `done_reason`。
|
|
108
|
+
- OpenAI `/v1/chat/completions` 支持流式、工具、图像、`reasoning_effort` 与 `include_usage`。
|
|
109
|
+
- Anthropic 兼容接口(`/v1/messages`)仅部分支持,本插件未使用。
|
|
110
|
+
|
|
111
|
+
## 开发
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
npm run typecheck
|
|
115
|
+
npm test
|
|
116
|
+
npm run build
|
|
117
|
+
npm run check
|
|
118
|
+
node scripts/probe.mjs
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## 限制
|
|
122
|
+
|
|
123
|
+
- 仅支持 Ollama Cloud;不注册本地 `http://localhost:11434`。
|
|
124
|
+
- 不支持 embeddings:实时目录中没有模型声明 `embedding` 能力。
|
|
125
|
+
- 文件附件以确定的文本句柄传递,而不是内联字节。
|
|
126
|
+
- 费用为公开价目表的估算值,最终以网关为准。
|
|
127
|
+
- UI 需要 web profile;TUI 保留 `/ollama` 命令与模型路由。
|
|
128
|
+
|
|
129
|
+
## 许可证
|
|
130
|
+
|
|
131
|
+
MIT © [GooDAnDReaDY](https://github.com/GooDAnDReaDY)。参见 [LICENSE](./LICENSE) 与 [NOTICE](./NOTICE)。
|
package/cordis.patch.yml
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# dsh-ollama-cloud-provider bundle layer.
|
|
2
|
+
# Registers the `ollama-cloud` provider route. All fields are optional —
|
|
3
|
+
# schema defaults apply.
|
|
4
|
+
#
|
|
5
|
+
# `name` must be the FULL package specifier as installed in the profile's
|
|
6
|
+
# node_modules. Quote it: an unquoted YAML scalar starting with `@` fails.
|
|
7
|
+
- insert:
|
|
8
|
+
- id: llm-ollama-cloud
|
|
9
|
+
name: "@goodandready/dsh-ollama-cloud-provider"
|
|
10
|
+
config:
|
|
11
|
+
apiKeyEnv: OLLAMA_API_KEY
|