opencode-qoder-bridge 0.1.7 → 0.1.9
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 +67 -1
- package/README.md +111 -38
- package/SECURITY.md +3 -2
- package/bin/statusline.mjs +30 -6
- package/bin/usage.mjs +7 -6
- package/dist/async-utils.d.ts +8 -0
- package/dist/async-utils.d.ts.map +1 -0
- package/dist/async-utils.js +27 -0
- package/dist/async-utils.js.map +1 -0
- package/dist/auth.d.ts +4 -2
- package/dist/auth.d.ts.map +1 -1
- package/dist/auth.js +28 -8
- package/dist/auth.js.map +1 -1
- package/dist/cost.d.ts +2 -1
- package/dist/cost.d.ts.map +1 -1
- package/dist/cost.js +163 -63
- package/dist/cost.js.map +1 -1
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +6 -3
- package/dist/errors.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +156 -46
- package/dist/index.js.map +1 -1
- package/dist/language-model.d.ts +22 -0
- package/dist/language-model.d.ts.map +1 -1
- package/dist/language-model.js +934 -186
- package/dist/language-model.js.map +1 -1
- package/dist/logger.d.ts +1 -0
- package/dist/logger.d.ts.map +1 -1
- package/dist/logger.js +35 -5
- package/dist/logger.js.map +1 -1
- package/dist/mcp-bridge.d.ts.map +1 -1
- package/dist/mcp-bridge.js +71 -7
- package/dist/mcp-bridge.js.map +1 -1
- package/dist/models.d.ts +8 -1
- package/dist/models.d.ts.map +1 -1
- package/dist/models.js +157 -46
- package/dist/models.js.map +1 -1
- package/dist/prompt-builder.d.ts.map +1 -1
- package/dist/prompt-builder.js +241 -43
- package/dist/prompt-builder.js.map +1 -1
- package/dist/sdk-auth.d.ts +3 -3
- package/dist/sdk-auth.d.ts.map +1 -1
- package/dist/sdk-auth.js +13 -9
- package/dist/sdk-auth.js.map +1 -1
- package/dist/sdk-session.d.ts.map +1 -1
- package/dist/sdk-session.js +26 -2
- package/dist/sdk-session.js.map +1 -1
- package/dist/session-store.d.ts +14 -3
- package/dist/session-store.d.ts.map +1 -1
- package/dist/session-store.js +451 -46
- package/dist/session-store.js.map +1 -1
- package/dist/state-dir.d.ts.map +1 -1
- package/dist/state-dir.js +2 -1
- package/dist/state-dir.js.map +1 -1
- package/dist/tool-normalizer.d.ts.map +1 -1
- package/dist/tool-normalizer.js +11 -2
- package/dist/tool-normalizer.js.map +1 -1
- package/dist/tui-register.d.ts.map +1 -1
- package/dist/tui-register.js +88 -37
- package/dist/tui-register.js.map +1 -1
- package/dist/tui.d.ts.map +1 -1
- package/dist/tui.js +42 -17
- package/dist/tui.js.map +1 -1
- package/dist/types.d.ts +14 -4
- package/dist/types.d.ts.map +1 -1
- package/dist/usage.d.ts.map +1 -1
- package/dist/usage.js +55 -30
- package/dist/usage.js.map +1 -1
- package/package.json +12 -4
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,68 @@ All notable changes to this project are documented here. The format follows
|
|
|
4
4
|
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and releases use
|
|
5
5
|
[Semantic Versioning](https://semver.org/).
|
|
6
6
|
|
|
7
|
+
## [0.1.9] - 2026-08-30
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- Updated `@qoder-ai/qoder-agent-sdk` to `1.0.30` (paired with `qodercli` 1.1.35).
|
|
12
|
+
- **Plan Mode Integration**: Added `planMode?: boolean` provider option to run in planning mode independently from tool permissions. Registered new `/qoder_plan_mode` tool.
|
|
13
|
+
- **Outbound Proxy Routing**: Added `proxy?: string` provider option for direct qodercli HTTP/HTTPS/SOCKS5 proxy routing without mutating environment variables, with automatic fallback to `HTTPS_PROXY` / `HTTP_PROXY`.
|
|
14
|
+
- **Skill Evolution**: Added `evolution?: EvolutionOptions` provider option to enable autonomous turn-completion skill analysis and recommendations.
|
|
15
|
+
- **Dynamic Live Model Catalog Updates**: Ingests real-time `available_models_update` stream events to synchronize model availability and persistent cache without restarting OpenCode.
|
|
16
|
+
- **Artifacts Tracking**: Ingests `artifacts_update` events during chat turns and surfaces artifact change metadata in `providerMetadata.qoder.artifacts`.
|
|
17
|
+
- **Sessions Tool**: Added `qoder_sessions` tool using SDK's `listSessions()` to inspect recent sessions, titles, and git branches.
|
|
18
|
+
|
|
19
|
+
### Fixed
|
|
20
|
+
|
|
21
|
+
- **Runtime Package Boundary**: Moved the runtime-used `@opencode-ai/plugin`
|
|
22
|
+
helper into production dependencies and verified root/provider imports from a
|
|
23
|
+
dev-omitted packed install.
|
|
24
|
+
- **Workspace-Aware Session Safety**: Scoped persisted session mappings by
|
|
25
|
+
workspace, serialized same-key turns, delayed mapping writes until a
|
|
26
|
+
successful turn, and added bounded cross-process state locking.
|
|
27
|
+
- **Catalog, Usage, and Stream Hardening**: Made live model snapshots
|
|
28
|
+
authoritative, bounded discovery/usage requests, closed abort and duplicate
|
|
29
|
+
event races, sanitized malformed SDK usage/metadata, and surfaced typed
|
|
30
|
+
authentication/result failures.
|
|
31
|
+
- **Persistent State and Input Bounds**: Hardened atomic state/config writes,
|
|
32
|
+
model/session cache validation, prompt/image limits, MCP URL/command input,
|
|
33
|
+
and finite cost/statusline accounting.
|
|
34
|
+
- **Unknown Model Transparency**: Unknown requested model IDs are now forwarded
|
|
35
|
+
unchanged to Qoder while the default catalog entry is used only for prompt
|
|
36
|
+
sizing metadata; the bridge no longer silently selects `auto`.
|
|
37
|
+
- **Ephemeral Session Privacy**: Explicitly disables SDK transcript persistence
|
|
38
|
+
for non-persistent turns and auxiliary usage/model discovery queries.
|
|
39
|
+
- **Stream and Boundary Hardening**: Added bounded turn timeouts, abort-aware
|
|
40
|
+
generation failures, bounded query cleanup, malformed-stream rejection,
|
|
41
|
+
replay UUID guards, tool ownership deny rules, diagnostic redaction, and
|
|
42
|
+
stricter MCP URL/command validation.
|
|
43
|
+
- **Release Artifact Safety**: Added a `prepack` rebuild hook, executable usage
|
|
44
|
+
CLI permissions, and a public `./errors` export for the typed error API.
|
|
45
|
+
- **Session Store Concurrency Race Condition**: Added an async mutex queue (`withLock`) to serialize concurrent `ensureQoderSession` and `deleteQoderSession` operations, preventing dropped session records under parallel turns.
|
|
46
|
+
- **Tool Continuation History Trimming**: Fixed a critical bug in `trimToBudget` where the active user prompt was dropped during continuation turns with large assistant/tool outputs, preventing prompts from falling back to `"Hello"`.
|
|
47
|
+
- **Data URL Parsing Hardening**: Added bounded-length and round-trip base64 validation with early rejection of oversized image attachments, preventing avoidable CPU and memory pressure from malformed multi-megabyte inputs.
|
|
48
|
+
- **Stream Controller Abort Safety & Listener Cleanup**: Added `safeEnqueue` and `safeClose` to prevent uncaught `Invalid state: Controller is already closed` exceptions when streams are aborted or cancelled, and cleaned up `abortSignal` event listeners in `language-model.ts` and `sdk-session.ts` to prevent memory leaks on shared signals.
|
|
49
|
+
- **`doGenerate` Provider Metadata**: Fixed `doGenerate` discarding `providerMetadata` (`totalCostUSD`, `contextUsageRatio`, `planMode`, `artifacts`), ensuring parity with `doStream`.
|
|
50
|
+
- **Coalesced Model Cache Writes**: Implemented a coalesced cache write queue in `models.ts` to prevent simultaneous file write contention and eliminate orphaned `.tmp` files under rapid streaming catalog updates.
|
|
51
|
+
- **Atomic File Cleanup & All-Session Reset**: Added `try...finally` temporary file unlinking in `session-store.ts` and `models.ts` to guarantee zero dangling `.tmp` files, and exported `clearAllSessions()` to support full session resets.
|
|
52
|
+
- **Tool Schema & Error Boundaries**: Upgraded plugin tools with `tool()` and `tool.schema` from `@opencode-ai/plugin`, added `key` (and `"all"`) to `qoder_session_reset`, added `dir` and `limit` filtering to `qoder_sessions`, and wrapped tool executions in error boundaries.
|
|
53
|
+
- **Tool Normalization & Path Aliases**: Added `execute_command`, `executecommand`, `run_command`, and `runcommand` mapping to `bash`, added `cmd` alias for command, and added `path` alias for `filePath` across read, write, edit, delete, view, and apply_diff.
|
|
54
|
+
- **MCP Bridge Argument Flexibility**: Converted numeric and boolean arguments in `mcp-bridge` stdio configs without dropping the argument list.
|
|
55
|
+
- **Prompt Serialization Hardening**: Added non-image file attachment serialization in `prompt-builder` so attached text files are preserved, and safely guarded missing `toolCallId` / `toolName`.
|
|
56
|
+
- **TUI & CLI Hardening**: Guarded `latest.model?.providerID` in `tui.ts` against undefined model objects, guarded against non-finite costs (`NaN`) in sidebar and statusline, and trimmed PAT whitespace in `hasQoderPAT()`.
|
|
57
|
+
- **Stress Test Suite**: Added `test/stress.test.mjs` verifying concurrency, massive conversations (1,000 messages), stream aborts, and prototype pollution protection.
|
|
58
|
+
- **CI-Safe Live Stress Coverage**: Made the Qoder-backed stream-abort stress probe opt-in with `QODER_STRESS_E2E=1`, keeping the normal test suite credential-free while preserving live stress coverage when explicitly enabled.
|
|
59
|
+
|
|
60
|
+
## [0.1.8] - 2026-08-26
|
|
61
|
+
|
|
62
|
+
### Fixed
|
|
63
|
+
|
|
64
|
+
- Allow authenticated sessions to use the Qoder Agent SDK's bundled Worker
|
|
65
|
+
runtime when a separately installed `qodercli` executable is unavailable.
|
|
66
|
+
- Updated authentication and usage guidance to distinguish missing credentials
|
|
67
|
+
from an optional local CLI installation.
|
|
68
|
+
|
|
7
69
|
## [0.1.5] - 2026-08-22
|
|
8
70
|
|
|
9
71
|
### Fixed
|
|
@@ -69,7 +131,9 @@ All notable changes to this project are documented here. The format follows
|
|
|
69
131
|
session.
|
|
70
132
|
- The `models.json` cache is written atomically with mode 0600 instead of a
|
|
71
133
|
direct partial-write-prone write.
|
|
72
|
-
- Unknown model IDs
|
|
134
|
+
- Unknown model IDs previously fell back to the default model with a debug log
|
|
135
|
+
entry; current releases preserve the requested ID and let Qoder report model
|
|
136
|
+
availability explicitly.
|
|
73
137
|
|
|
74
138
|
## [0.1.3] - 2026-08-20
|
|
75
139
|
|
|
@@ -145,3 +209,5 @@ also verified with an in-process MCP transport.
|
|
|
145
209
|
[0.1.3]: https://github.com/naoufalelbani/opencode-qoder-bridge/compare/v0.1.2...v0.1.3
|
|
146
210
|
[0.1.4]: https://github.com/naoufalelbani/opencode-qoder-bridge/compare/v0.1.3...v0.1.4
|
|
147
211
|
[0.1.5]: https://github.com/naoufalelbani/opencode-qoder-bridge/compare/v0.1.4...v0.1.5
|
|
212
|
+
[0.1.8]: https://github.com/naoufalelbani/opencode-qoder-bridge/compare/v0.1.7...v0.1.8
|
|
213
|
+
[0.1.9]: https://github.com/naoufalelbani/opencode-qoder-bridge/compare/v0.1.8...v0.1.9
|
package/README.md
CHANGED
|
@@ -119,37 +119,23 @@ The ledger accumulates across sessions. Delete `~/.config/opencode-qoder-bridge/
|
|
|
119
119
|
|
|
120
120
|
The bridge discovers the available catalog at startup through the SDK's
|
|
121
121
|
`getAvailableModels()` API. Availability is account-, region-, rollout-, and
|
|
122
|
-
SDK-version-dependent. A
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
|
131
|
-
|
|
132
|
-
| `
|
|
133
|
-
| `
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
| `qmodel_38max` | Qwen3.8-Max | 0.25x | ✓ | ✓ | 180K | 32K |
|
|
140
|
-
| `qmodel_latest` | Qwen3.7-Max | 0.10x promo | ✓ | ✗ | 1M | 32K |
|
|
141
|
-
| `qmodel` | Qwen3.7-Plus | 0.04x promo | ✓ | ✗ | 1M | 32K |
|
|
142
|
-
| `kmodel_latest` | Kimi-K3 | 0.80x | ✓ | ✗ | 180K | 32K |
|
|
143
|
-
| `kmodel` | Kimi-K2.7-Code | 0.30x | ✓ | ✗ | 256K | 32K |
|
|
144
|
-
| `gm51model` | GLM-5.2 | 0.50x promo | ✓ | ✓ | 1M | 32K |
|
|
145
|
-
| `dmodel` | DeepSeek-V4-Pro | 0.50x | ✓ | ✓ | 1M | 32K |
|
|
146
|
-
| `dfmodel` | DeepSeek-V4-Flash | 0.10x | ✓ | ✓ | 1M | 32K |
|
|
147
|
-
| `mmodel` | MiniMax-M3 | 0.20x | ✓ | ✗ | 1M | 32K |
|
|
148
|
-
|
|
149
|
-
This table is a snapshot, not a hard-coded allowlist. Qoder can vary model
|
|
150
|
-
availability by account, plan, CLI version, or staged rollout. Promotional
|
|
151
|
-
multipliers are time-dependent; the SDK's current `priceFactor` is
|
|
152
|
-
authoritative. Restart OpenCode to refresh the bridge's in-process model cache.
|
|
122
|
+
SDK-version-dependent. A permanent allowlist is intentionally not embedded
|
|
123
|
+
here because the catalog is account- and scene-dependent.
|
|
124
|
+
|
|
125
|
+
The following is the current model snapshot returned by `qodercli --list-models`
|
|
126
|
+
on 2026-08-30:
|
|
127
|
+
|
|
128
|
+
| Model |
|
|
129
|
+
|-------|
|
|
130
|
+
| `Qwen3.8-Max` |
|
|
131
|
+
| `Qwen3.8-Flash` |
|
|
132
|
+
| `Qwen3.7-Max` |
|
|
133
|
+
| `Qwen3.7-Plus` |
|
|
134
|
+
|
|
135
|
+
This is an account-, region-, plan-, CLI-version-, and rollout-dependent
|
|
136
|
+
snapshot. The CLI command reports display names only; the bridge's SDK catalog
|
|
137
|
+
is authoritative for model IDs, capabilities, context limits, and pricing.
|
|
138
|
+
Run `qodercli --list-models` and restart OpenCode to refresh the local view.
|
|
153
139
|
|
|
154
140
|
Run `opencode models qoder` to inspect the models currently registered with
|
|
155
141
|
OpenCode. The `qoder_models` tool also exposes capabilities, context limits,
|
|
@@ -172,7 +158,13 @@ Bridge opencode MCP servers into the SDK by passing provider options:
|
|
|
172
158
|
}
|
|
173
159
|
```
|
|
174
160
|
|
|
161
|
+
Flag names may be written with or without the leading `--`.
|
|
162
|
+
|
|
175
163
|
`config.mcp` servers are bridged into the SDK's `mcpServers` automatically.
|
|
164
|
+
Chat turns have a 30-minute bridge timeout by default; set `options.timeoutMs`
|
|
165
|
+
to a positive value to use a shorter or longer bounded timeout (up to 24 hours).
|
|
166
|
+
Values in `options.env` override inherited process variables rather than
|
|
167
|
+
replacing the complete child environment.
|
|
176
168
|
|
|
177
169
|
### Persistent sessions and permissions
|
|
178
170
|
|
|
@@ -194,9 +186,15 @@ Session persistence is opt-in. Give a provider configuration a stable
|
|
|
194
186
|
|
|
195
187
|
Mappings are stored in
|
|
196
188
|
`~/.config/opencode-qoder-bridge/sessions.json` with restrictive file
|
|
197
|
-
permissions
|
|
198
|
-
|
|
199
|
-
|
|
189
|
+
permissions and are scoped to the configured working directory. The plugin
|
|
190
|
+
uses OpenCode's project directory when available; set `options.cwd` when
|
|
191
|
+
loading the provider directly. Use the `qoder_session_reset` tool to forget
|
|
192
|
+
the mapping. A new session is created automatically if the mapping does not
|
|
193
|
+
exist; existing sessions are resumed through the Qoder SDK.
|
|
194
|
+
|
|
195
|
+
Qoder-native and bridged MCP tools remain provider-owned. If OpenCode supplies
|
|
196
|
+
a function with a colliding native name, the bridge derives a Qoder deny rule
|
|
197
|
+
to avoid executing the same operation in both runtimes.
|
|
200
198
|
|
|
201
199
|
The bridge uses the SDK's safer permission policy by default. To explicitly
|
|
202
200
|
allow all Qoder tools in a trusted local environment, configure for example:
|
|
@@ -218,22 +216,97 @@ Available permission modes are `default`, `acceptEdits`, and
|
|
|
218
216
|
`bypassPermissions`. Only explicitly configure `bypassPermissions` when the
|
|
219
217
|
host environment is trusted.
|
|
220
218
|
|
|
219
|
+
Image inputs may reference `file://`, `~/`, or absolute local paths. Only pass
|
|
220
|
+
paths from trusted callers: the bridge bounds image size but does not sandbox
|
|
221
|
+
or restrict readable local files to the project directory. A current turn is
|
|
222
|
+
limited to 64 images and 40 MiB of decoded image data; excess attachments are
|
|
223
|
+
reported as omitted text.
|
|
224
|
+
|
|
225
|
+
### Plan Mode
|
|
226
|
+
|
|
227
|
+
Plan Mode instructs Qoder to analyze and plan changes without modifying files
|
|
228
|
+
or running action tools. It operates independently from tool permissions,
|
|
229
|
+
preserving your configured `permissionMode`:
|
|
230
|
+
|
|
231
|
+
```json
|
|
232
|
+
{
|
|
233
|
+
"provider": {
|
|
234
|
+
"qoder": {
|
|
235
|
+
"options": {
|
|
236
|
+
"planMode": true
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
Run `/qoder_plan_mode` in OpenCode for quick guidance.
|
|
244
|
+
|
|
245
|
+
### Proxy & Network Routing
|
|
246
|
+
|
|
247
|
+
Pass an outbound proxy URL directly to the Qoder runtime without mutating host
|
|
248
|
+
environment variables (supports `http://`, `https://`, `socks5://`, and `socks://`):
|
|
249
|
+
|
|
250
|
+
```json
|
|
251
|
+
{
|
|
252
|
+
"provider": {
|
|
253
|
+
"qoder": {
|
|
254
|
+
"options": {
|
|
255
|
+
"proxy": "http://127.0.0.1:8888"
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
If `proxy` is omitted, the bridge automatically falls back to `HTTPS_PROXY` or
|
|
263
|
+
`HTTP_PROXY` from your environment.
|
|
264
|
+
|
|
265
|
+
### Skill Evolution
|
|
266
|
+
|
|
267
|
+
Enable autonomous turn-completion skill analysis and recommendations:
|
|
268
|
+
|
|
269
|
+
```json
|
|
270
|
+
{
|
|
271
|
+
"provider": {
|
|
272
|
+
"qoder": {
|
|
273
|
+
"options": {
|
|
274
|
+
"evolution": {
|
|
275
|
+
"skill": { "mode": "native" }
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
### Available Tools
|
|
284
|
+
|
|
285
|
+
The plugin registers several built-in OpenCode tools:
|
|
286
|
+
|
|
287
|
+
- `qoder_usage` — Live account balance, quota percentages, and local cost ledger totals.
|
|
288
|
+
- `qoder_models` — List known Qoder models, context limits, vision/reasoning flags, and multipliers.
|
|
289
|
+
- `qoder_sessions` — List recent Qoder sessions, session IDs, branches, and timestamps via SDK `listSessions()`.
|
|
290
|
+
- `qoder_session_reset` — Forget the persisted Qoder session mapping for the active project.
|
|
291
|
+
- `qoder_plan_mode` — View Plan Mode status and configuration guidance.
|
|
292
|
+
|
|
221
293
|
## Troubleshooting
|
|
222
294
|
|
|
223
295
|
| Problem | Solution |
|
|
224
296
|
|---------|----------|
|
|
225
297
|
| Auth prompt at startup | Run `qoder login`, then restart opencode |
|
|
226
|
-
| `qodercli not found` |
|
|
298
|
+
| `qodercli not found` | Authenticate with `qoder login` or set `QODER_PERSONAL_ACCESS_TOKEN`; the SDK can use its bundled runtime, while an installed CLI is preferred when available |
|
|
227
299
|
| Model not found | Verify the model ID matches the table above |
|
|
228
|
-
| Missing models in the model list | Run `/qoder_models`; the bridge refreshes the live catalog at
|
|
300
|
+
| Missing models in the model list | Run `/qoder_models`; the bridge refreshes the live catalog at startup and falls back to the last cached catalog plus the built-ins (`lite`, `auto`, `performance`) when offline. If your account serves models in a different Qoder scene, set `QODER_SCENE` before launching opencode |
|
|
229
301
|
|
|
230
302
|
### How model discovery works
|
|
231
303
|
|
|
232
304
|
At startup the bridge immediately exposes cached/built-in models, then
|
|
233
305
|
refreshes the live catalog from Qoder (`fetchStrategy: "live"` — the CLI
|
|
234
306
|
re-queries the server and falls back to its local cache if the server returns
|
|
235
|
-
nothing).
|
|
236
|
-
|
|
307
|
+
nothing). Each successful catalog snapshot replaces previously discovered
|
|
308
|
+
dynamic IDs, so retired models do not remain selectable. A failed refresh
|
|
309
|
+
keeps the last known catalog and the built-ins.
|
|
237
310
|
|
|
238
311
|
## Development
|
|
239
312
|
|
package/SECURITY.md
CHANGED
|
@@ -19,6 +19,7 @@ keep OpenCode, the Qoder CLI, and package dependencies current.
|
|
|
19
19
|
## Credential handling
|
|
20
20
|
|
|
21
21
|
This plugin does not distribute Qoder credentials. Authentication remains with
|
|
22
|
-
the
|
|
22
|
+
the Qoder Agent SDK. Use a personal access token or local Qoder sign-in as
|
|
23
|
+
documented by the SDK; its bundled Worker runtime can be used without a
|
|
24
|
+
separately installed Qoder CLI. Never include files from `~/.qoder/`, npm
|
|
23
25
|
tokens, prompts containing secrets, or local usage ledgers in a report.
|
|
24
|
-
|
package/bin/statusline.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { readFileSync } from "node:fs";
|
|
2
|
+
import { lstatSync, readFileSync } from "node:fs";
|
|
3
3
|
import { homedir } from "node:os";
|
|
4
4
|
import { join } from "node:path";
|
|
5
5
|
|
|
@@ -8,20 +8,41 @@ import { join } from "node:path";
|
|
|
8
8
|
function resolveStateDir(env = process.env) {
|
|
9
9
|
const override = env.QODER_BRIDGE_STATE_DIR?.trim();
|
|
10
10
|
if (override) return join(override);
|
|
11
|
-
const configHome = env.XDG_CONFIG_HOME?.trim()
|
|
11
|
+
const configHome = env.XDG_CONFIG_HOME?.trim()
|
|
12
|
+
|| (process.platform === "win32" ? env.APPDATA?.trim() : undefined);
|
|
12
13
|
return join(configHome || join(homedir(), ".config"), "opencode-qoder-bridge");
|
|
13
14
|
}
|
|
14
15
|
|
|
15
16
|
const STATE_FILE = join(resolveStateDir(), "usage.json");
|
|
17
|
+
const MAX_STATE_BYTES = 1_000_000;
|
|
16
18
|
|
|
17
19
|
function fmt(usd) {
|
|
18
|
-
|
|
20
|
+
const n = typeof usd === "number" && Number.isFinite(usd) ? usd : 0;
|
|
21
|
+
return `$${n.toFixed(4)}`;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function count(value) {
|
|
25
|
+
return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : 0;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function add(left, right) {
|
|
29
|
+
const total = left + right;
|
|
30
|
+
return Number.isFinite(total) ? total : Number.MAX_SAFE_INTEGER;
|
|
19
31
|
}
|
|
20
32
|
|
|
21
33
|
function main() {
|
|
22
34
|
let state = null;
|
|
23
35
|
try {
|
|
36
|
+
const info = lstatSync(STATE_FILE);
|
|
37
|
+
if (!info.isFile() || info.isSymbolicLink() || info.size > MAX_STATE_BYTES) {
|
|
38
|
+
process.stdout.write("qoder: no usage yet");
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
24
41
|
state = JSON.parse(readFileSync(STATE_FILE, "utf8"));
|
|
42
|
+
if (!state || typeof state !== "object" || Array.isArray(state)) {
|
|
43
|
+
process.stdout.write("qoder: no usage yet");
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
25
46
|
} catch {
|
|
26
47
|
process.stdout.write("qoder: no usage yet");
|
|
27
48
|
return;
|
|
@@ -29,12 +50,15 @@ function main() {
|
|
|
29
50
|
|
|
30
51
|
const parts = [
|
|
31
52
|
`cost ${fmt(state.totalCostUsd)}`,
|
|
32
|
-
`turns ${state.turnCount
|
|
33
|
-
`tok ${(state.totalInputTokens
|
|
53
|
+
`turns ${count(state.turnCount)}`,
|
|
54
|
+
`tok ${add(count(state.totalInputTokens), count(state.totalOutputTokens))}`,
|
|
34
55
|
];
|
|
35
56
|
|
|
36
57
|
const last = Array.isArray(state.recent) ? state.recent.at(-1) : null;
|
|
37
|
-
if (last?.model
|
|
58
|
+
if (typeof last?.model === "string" && last.model) {
|
|
59
|
+
const model = last.model.replace(/[\u0000-\u001f\u007f]/g, " ").slice(0, 256);
|
|
60
|
+
parts.push(`last ${model}`);
|
|
61
|
+
}
|
|
38
62
|
|
|
39
63
|
process.stdout.write(`qoder: ${parts.join(" · ")}`);
|
|
40
64
|
}
|
package/bin/usage.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { getLiveUsage, formatUsageReport } from "../dist/usage.js";
|
|
3
3
|
import { summarize, formatCost } from "../dist/cost.js";
|
|
4
|
+
import { describeError } from "../dist/logger.js";
|
|
4
5
|
|
|
5
6
|
async function main() {
|
|
6
7
|
const lines = [];
|
|
@@ -8,17 +9,17 @@ async function main() {
|
|
|
8
9
|
lines.push(
|
|
9
10
|
live
|
|
10
11
|
? formatUsageReport(live)
|
|
11
|
-
: "Live Qoder usage unavailable (not logged in or Qoder
|
|
12
|
+
: "Live Qoder usage unavailable (not logged in or Qoder runtime unavailable).",
|
|
12
13
|
);
|
|
13
14
|
|
|
14
15
|
const summary = summarize();
|
|
15
16
|
lines.push("");
|
|
16
17
|
lines.push("Local Usage Ledger");
|
|
17
|
-
lines.push(` Reference cost: ${formatCost(summary
|
|
18
|
-
lines.push(` Turns: ${summary
|
|
19
|
-
lines.push(` Tokens: ${summary
|
|
18
|
+
lines.push(` Reference cost: ${formatCost(summary?.totalCostUsd ?? 0)}`);
|
|
19
|
+
lines.push(` Turns: ${summary?.turnCount ?? 0}`);
|
|
20
|
+
lines.push(` Tokens: ${summary?.totalInputTokens ?? 0} in / ${summary?.totalOutputTokens ?? 0} out`);
|
|
20
21
|
|
|
21
|
-
const models = Object.entries(summary
|
|
22
|
+
const models = Object.entries(summary?.byModel ?? {});
|
|
22
23
|
if (models.length > 0) {
|
|
23
24
|
lines.push(" By model:");
|
|
24
25
|
for (const [name, bucket] of models) {
|
|
@@ -30,6 +31,6 @@ async function main() {
|
|
|
30
31
|
}
|
|
31
32
|
|
|
32
33
|
main().catch((error) => {
|
|
33
|
-
process.stderr.write(`Unable to read Qoder usage: ${
|
|
34
|
+
process.stderr.write(`Unable to read Qoder usage: ${describeError(error)}\n`);
|
|
34
35
|
process.exitCode = 1;
|
|
35
36
|
});
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/** Race SDK operations against a host-side deadline. Aborting the SDK is
|
|
2
|
+
* still the caller's responsibility; this helper guarantees the bridge does
|
|
3
|
+
* not wait forever for a non-cooperative promise. */
|
|
4
|
+
export declare function withTimeout<T>(operation: PromiseLike<T>, timeoutMs: number, message: string): Promise<T>;
|
|
5
|
+
export declare function closeAsyncIterator(iterator: {
|
|
6
|
+
return?: (value?: void | PromiseLike<void>) => PromiseLike<unknown> | unknown;
|
|
7
|
+
}, timeoutMs: number): Promise<void>;
|
|
8
|
+
//# sourceMappingURL=async-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"async-utils.d.ts","sourceRoot":"","sources":["../src/async-utils.ts"],"names":[],"mappings":"AAAA;;qDAEqD;AACrD,wBAAgB,WAAW,CAAC,CAAC,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CASxG;AAED,wBAAsB,kBAAkB,CACtC,QAAQ,EAAE;IAAE,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,IAAI,GAAG,WAAW,CAAC,IAAI,CAAC,KAAK,WAAW,CAAC,OAAO,CAAC,GAAG,OAAO,CAAA;CAAE,EAC3F,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC,CAQf"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/** Race SDK operations against a host-side deadline. Aborting the SDK is
|
|
2
|
+
* still the caller's responsibility; this helper guarantees the bridge does
|
|
3
|
+
* not wait forever for a non-cooperative promise. */
|
|
4
|
+
export function withTimeout(operation, timeoutMs, message) {
|
|
5
|
+
let timer;
|
|
6
|
+
const timeout = new Promise((_, reject) => {
|
|
7
|
+
timer = setTimeout(() => reject(new Error(message)), timeoutMs);
|
|
8
|
+
if (typeof timer.unref === "function")
|
|
9
|
+
timer.unref();
|
|
10
|
+
});
|
|
11
|
+
return Promise.race([Promise.resolve(operation), timeout]).finally(() => {
|
|
12
|
+
if (timer)
|
|
13
|
+
clearTimeout(timer);
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
export async function closeAsyncIterator(iterator, timeoutMs) {
|
|
17
|
+
if (typeof iterator.return !== "function")
|
|
18
|
+
return;
|
|
19
|
+
const closing = Promise.resolve().then(() => iterator.return?.(undefined)).then(() => undefined);
|
|
20
|
+
try {
|
|
21
|
+
await withTimeout(closing, timeoutMs, "SDK iterator cleanup timed out");
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
// Cleanup is best effort; the request's primary error remains authoritative.
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=async-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"async-utils.js","sourceRoot":"","sources":["../src/async-utils.ts"],"names":[],"mappings":"AAAA;;qDAEqD;AACrD,MAAM,UAAU,WAAW,CAAI,SAAyB,EAAE,SAAiB,EAAE,OAAe;IAC1F,IAAI,KAAgD,CAAC;IACrD,MAAM,OAAO,GAAG,IAAI,OAAO,CAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE;QAC/C,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;QAChE,IAAI,OAAO,KAAK,CAAC,KAAK,KAAK,UAAU;YAAE,KAAK,CAAC,KAAK,EAAE,CAAC;IACvD,CAAC,CAAC,CAAC;IACH,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE;QACtE,IAAI,KAAK;YAAE,YAAY,CAAC,KAAK,CAAC,CAAC;IACjC,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,QAA2F,EAC3F,SAAiB;IAEjB,IAAI,OAAO,QAAQ,CAAC,MAAM,KAAK,UAAU;QAAE,OAAO;IAClD,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;IACjG,IAAI,CAAC;QACH,MAAM,WAAW,CAAC,OAAO,EAAE,SAAS,EAAE,gCAAgC,CAAC,CAAC;IAC1E,CAAC;IAAC,MAAM,CAAC;QACP,6EAA6E;IAC/E,CAAC;AACH,CAAC"}
|
package/dist/auth.d.ts
CHANGED
|
@@ -4,7 +4,9 @@ export declare function isAuthenticated(): boolean;
|
|
|
4
4
|
* 1. PATH
|
|
5
5
|
* 2. ~/.qoder/local/qodercli
|
|
6
6
|
* 3. ~/.qoder/bin/qodercli/qodercli-<version> (latest)
|
|
7
|
-
* Returns null when
|
|
7
|
+
* Returns null when no separately installed CLI is found. The Qoder SDK can
|
|
8
|
+
* still run through its bundled Worker runtime when credentials are present.
|
|
8
9
|
*/
|
|
9
|
-
export declare function findQoderCLI(): string | null;
|
|
10
|
+
export declare function findQoderCLI(force?: boolean): string | null;
|
|
11
|
+
export declare function resetCachedCliPath(): void;
|
|
10
12
|
//# sourceMappingURL=auth.d.ts.map
|
package/dist/auth.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AASA,wBAAgB,eAAe,IAAI,OAAO,CAEzC;AAuBD
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AASA,wBAAgB,eAAe,IAAI,OAAO,CAEzC;AAuBD;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,KAAK,UAAQ,GAAG,MAAM,GAAG,IAAI,CAIzD;AAED,wBAAgB,kBAAkB,IAAI,IAAI,CAEzC"}
|
package/dist/auth.js
CHANGED
|
@@ -35,14 +35,18 @@ let cachedCliPath;
|
|
|
35
35
|
* 1. PATH
|
|
36
36
|
* 2. ~/.qoder/local/qodercli
|
|
37
37
|
* 3. ~/.qoder/bin/qodercli/qodercli-<version> (latest)
|
|
38
|
-
* Returns null when
|
|
38
|
+
* Returns null when no separately installed CLI is found. The Qoder SDK can
|
|
39
|
+
* still run through its bundled Worker runtime when credentials are present.
|
|
39
40
|
*/
|
|
40
|
-
export function findQoderCLI() {
|
|
41
|
-
if (cachedCliPath !== undefined)
|
|
41
|
+
export function findQoderCLI(force = false) {
|
|
42
|
+
if (!force && cachedCliPath !== undefined)
|
|
42
43
|
return cachedCliPath;
|
|
43
44
|
cachedCliPath = resolveCli();
|
|
44
45
|
return cachedCliPath;
|
|
45
46
|
}
|
|
47
|
+
export function resetCachedCliPath() {
|
|
48
|
+
cachedCliPath = undefined;
|
|
49
|
+
}
|
|
46
50
|
function resolveCli() {
|
|
47
51
|
const exe = process.platform === "win32" ? "qodercli.exe" : "qodercli";
|
|
48
52
|
for (const dir of (process.env.PATH ?? "").split(delimiter)) {
|
|
@@ -57,12 +61,12 @@ function resolveCli() {
|
|
|
57
61
|
return local;
|
|
58
62
|
const binDir = join(homedir(), ".qoder", "bin", "qodercli");
|
|
59
63
|
try {
|
|
60
|
-
const
|
|
64
|
+
const versions = readdirSync(binDir)
|
|
61
65
|
.filter((f) => f.startsWith("qodercli-"))
|
|
62
|
-
.sort()
|
|
63
|
-
.
|
|
64
|
-
|
|
65
|
-
const p = join(binDir,
|
|
66
|
+
.sort(compareCliVersions)
|
|
67
|
+
.reverse();
|
|
68
|
+
for (const version of versions) {
|
|
69
|
+
const p = join(binDir, version);
|
|
66
70
|
if (isExecutableFile(p))
|
|
67
71
|
return p;
|
|
68
72
|
}
|
|
@@ -72,4 +76,20 @@ function resolveCli() {
|
|
|
72
76
|
}
|
|
73
77
|
return null;
|
|
74
78
|
}
|
|
79
|
+
function compareCliVersions(left, right) {
|
|
80
|
+
const leftParts = left.slice("qodercli-".length).split(/[.-]/);
|
|
81
|
+
const rightParts = right.slice("qodercli-".length).split(/[.-]/);
|
|
82
|
+
const length = Math.max(leftParts.length, rightParts.length);
|
|
83
|
+
for (let i = 0; i < length; i++) {
|
|
84
|
+
const a = leftParts[i] ?? "";
|
|
85
|
+
const b = rightParts[i] ?? "";
|
|
86
|
+
const aNumber = /^\d+$/.test(a) ? Number(a) : NaN;
|
|
87
|
+
const bNumber = /^\d+$/.test(b) ? Number(b) : NaN;
|
|
88
|
+
if (Number.isFinite(aNumber) && Number.isFinite(bNumber) && aNumber !== bNumber)
|
|
89
|
+
return aNumber - bNumber;
|
|
90
|
+
if (a !== b)
|
|
91
|
+
return a.localeCompare(b);
|
|
92
|
+
}
|
|
93
|
+
return left.localeCompare(right);
|
|
94
|
+
}
|
|
75
95
|
//# sourceMappingURL=auth.js.map
|
package/dist/auth.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACvE,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAE5C,MAAM,UAAU,GAAG;IACjB,IAAI,CAAC,OAAO,EAAE,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,CAAC;IAC9C,IAAI,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,CAAC;CAC3C,CAAC;AAEF,MAAM,UAAU,eAAe;IAC7B,OAAO,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;AAClD,CAAC;AAED,SAAS,aAAa,CAAC,CAAS;IAC9B,IAAI,CAAC;QACH,OAAO,QAAQ,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;IAC9B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,SAAS,gBAAgB,CAAC,CAAS;IACjC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IACpC,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO;QAAE,OAAO,IAAI,CAAC;IAC9C,IAAI,CAAC;QACH,UAAU,CAAC,CAAC,EAAE,SAAS,CAAC,IAAI,CAAC,CAAC;QAC9B,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,IAAI,aAAwC,CAAC;AAE7C
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACvE,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAE5C,MAAM,UAAU,GAAG;IACjB,IAAI,CAAC,OAAO,EAAE,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,CAAC;IAC9C,IAAI,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,CAAC;CAC3C,CAAC;AAEF,MAAM,UAAU,eAAe;IAC7B,OAAO,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;AAClD,CAAC;AAED,SAAS,aAAa,CAAC,CAAS;IAC9B,IAAI,CAAC;QACH,OAAO,QAAQ,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;IAC9B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,SAAS,gBAAgB,CAAC,CAAS;IACjC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IACpC,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO;QAAE,OAAO,IAAI,CAAC;IAC9C,IAAI,CAAC;QACH,UAAU,CAAC,CAAC,EAAE,SAAS,CAAC,IAAI,CAAC,CAAC;QAC9B,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,IAAI,aAAwC,CAAC;AAE7C;;;;;;;GAOG;AACH,MAAM,UAAU,YAAY,CAAC,KAAK,GAAG,KAAK;IACxC,IAAI,CAAC,KAAK,IAAI,aAAa,KAAK,SAAS;QAAE,OAAO,aAAa,CAAC;IAChE,aAAa,GAAG,UAAU,EAAE,CAAC;IAC7B,OAAO,aAAa,CAAC;AACvB,CAAC;AAED,MAAM,UAAU,kBAAkB;IAChC,aAAa,GAAG,SAAS,CAAC;AAC5B,CAAC;AAED,SAAS,UAAU;IACjB,MAAM,GAAG,GAAG,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,UAAU,CAAC;IAEvE,KAAK,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,CAAC;QAC5D,IAAI,CAAC,GAAG;YAAE,SAAS;QACnB,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QACzB,IAAI,gBAAgB,CAAC,CAAC,CAAC;YAAE,OAAO,CAAC,CAAC;IACpC,CAAC;IAED,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,CAAC,CAAC;IACtD,IAAI,gBAAgB,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAE1C,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC;IAC5D,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,WAAW,CAAC,MAAM,CAAC;aACjC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;aACxC,IAAI,CAAC,kBAAkB,CAAC;aACxB,OAAO,EAAE,CAAC;QACb,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAC/B,MAAM,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;YAChC,IAAI,gBAAgB,CAAC,CAAC,CAAC;gBAAE,OAAO,CAAC,CAAC;QACpC,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,mBAAmB;IACrB,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,kBAAkB,CAAC,IAAY,EAAE,KAAa;IACrD,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC/D,MAAM,UAAU,GAAG,KAAK,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACjE,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,MAAM,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC;IAC7D,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAChC,MAAM,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAC7B,MAAM,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAC9B,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;QAClD,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;QAClD,IAAI,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,OAAO,KAAK,OAAO;YAAE,OAAO,OAAO,GAAG,OAAO,CAAC;QAC1G,IAAI,CAAC,KAAK,CAAC;YAAE,OAAO,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;IACzC,CAAC;IACD,OAAO,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;AACnC,CAAC"}
|
package/dist/cost.d.ts
CHANGED
|
@@ -23,9 +23,10 @@ interface PersistedState {
|
|
|
23
23
|
}>;
|
|
24
24
|
recent: TurnCost[];
|
|
25
25
|
}
|
|
26
|
+
export declare function flushLedgerSync(): void;
|
|
26
27
|
export interface RecordInput {
|
|
27
28
|
model: string;
|
|
28
|
-
usage
|
|
29
|
+
usage?: {
|
|
29
30
|
input_tokens?: number | null;
|
|
30
31
|
output_tokens?: number | null;
|
|
31
32
|
cache_read_input_tokens?: number | null;
|
package/dist/cost.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cost.d.ts","sourceRoot":"","sources":["../src/cost.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"cost.d.ts","sourceRoot":"","sources":["../src/cost.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAa5D,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC;IACxB,gBAAgB,EAAE,MAAM,CAAC;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,UAAU,cAAc;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,CAAC;IACzB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACvG,MAAM,EAAE,QAAQ,EAAE,CAAC;CACpB;AAoND,wBAAgB,eAAe,IAAI,IAAI,CAOtC;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE;QACN,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAC7B,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAC9B,uBAAuB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QACxC,2BAA2B,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;KAC7C,CAAC;IACF,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;CACzC;AAED,0DAA0D;AAC1D,wBAAgB,UAAU,CAAC,KAAK,EAAE,WAAW,GAAG,QAAQ,CAoBvD;AAED,MAAM,WAAW,YAAY;IAC3B,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,CAAC;IACzB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,cAAc,CAAC,SAAS,CAAC,CAAC;IACnC,MAAM,EAAE,QAAQ,EAAE,CAAC;CACpB;AAED,wBAAgB,SAAS,IAAI,YAAY,CAUxC;AAED,wBAAgB,WAAW,IAAI,IAAI,CAKlC;AAED,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE9C"}
|