@dudousxd/nestjs-agent-opencode 0.1.2 → 0.2.1

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.md CHANGED
@@ -53,7 +53,8 @@ export class AppModule {}
53
53
  | OpenCode | The library's protocol and store |
54
54
  | --- | --- |
55
55
  | `session.text.delta` / `session.reasoning.delta` | `text` / `reasoning` |
56
- | a step (`session.step.ended`) | `step-start` … `step-finish` with usage; usage recorded per step |
56
+ | a step (`session.step.ended`) | `step-start` … `step-finish` with usage and cost; a `chat` usage row per step (see [Cost and usage](#cost-and-usage)) |
57
+ | the title OpenCode generates, a compaction | a `title` / `history_summary` usage row (see [Cost and usage](#cost-and-usage)) |
57
58
  | tools (`session.tool.*`) | `tool-input-*` / `tool-output*`, code-mode inner calls nested by `parentId` |
58
59
  | `permission.asked` | an `action` call + `approval-requested`, recorded `pending_approval`; `approve` / `reject` → `permission.reply` |
59
60
  | `form.created` | `elicitation`; `answer` / `skip` → `session.form.reply` / `cancel` |
@@ -64,6 +65,38 @@ export class AppModule {}
64
65
  Sessions: one per thread, kept by an `OpenCodeSessionStore` (in memory by default; persist it for
65
66
  several replicas) and recreated when the server's `bootId` changes, told the conversation so far.
66
67
 
68
+ ## Cost and usage
69
+
70
+ Every model call OpenCode makes for a turn — each step, the title it gives the session, a
71
+ compaction — goes to the same token-usage ledger the library's own loop writes (`recordUsage`:
72
+ `agent_token_usage` with `cost_usd` and `cost_source`), so the ledger quota (`quota: { limits }`),
73
+ the dashboard and `GET /quota` see an OpenCode turn like any other.
74
+
75
+ - **The title and compactions.** OpenCode records those calls on the session without streaming
76
+ them. The turn reads what the session had spent (`session.get`) before it prompts, and when the
77
+ execution ends records what the session spent since that its steps did not report, as a `title`
78
+ row (`history_summary` when a compaction ran). A `session.usage.recorded` event, from an OpenCode
79
+ that streams it, is recorded as it arrives and not counted twice.
80
+ - **Tokens.** OpenCode reports the uncached input in `tokens.input` and the cache beside it; the row
81
+ counts the whole input side in `inputTokens`, with `cacheReadTokens` / `cacheWriteTokens` as
82
+ subsets (the library's `MessageUsage`). The row's model is the one OpenCode names for the step
83
+ (`<providerID>/<model id>`, e.g. `amazon-bedrock/us-gov.anthropic.claude-sonnet-4-5-20250929-v1:0`).
84
+ - **Cost.** OpenCode prices each call itself, off its model catalog. A call it priced (`cost > 0`) is
85
+ recorded at that figure, `cost_source: 'provider'`. A call it priced at 0 — no price for the model
86
+ in its catalog — is estimated from the library's price for the model, `cost_source: 'estimate'`:
87
+ the pricing store's row, else (seeded into the store once, as at boot) `priceCatalog.prices`, the
88
+ built-in GovCloud Bedrock table (`priceCatalog.region` / `AWS_REGION`, or a `us-gov.` id) and
89
+ models.dev. A model the library cannot price keeps OpenCode's 0.
90
+ - `openCode({ cost: 'estimate' })` prefers the library's price whenever it has one — for models
91
+ OpenCode would price at a list price that is not yours (models.dev lists commercial Bedrock prices,
92
+ so Bedrock in GovCloud is priced too low unless OpenCode's config declares the model's `cost`).
93
+ - **The run's total** (`OpenCodeRunResult.usage` for `beforeSettle` / `onSettled`, and the usage on
94
+ the turn's last message) is added up from the turn's own calls, not read back from the store: each
95
+ milestone carries what was spent since the last one, and a durable run journals it with the
96
+ milestone, so a run resumed in another process (an approval answered after a restart) still reports
97
+ the whole run, cache tokens included. A process that dies while OpenCode works loses the calls it
98
+ saw from that total (their ledger rows are already written).
99
+
67
100
  ## Durable turns
68
101
 
69
102
  ```ts