@amaster.ai/dsh-storage 0.1.1 → 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/lib/index.js CHANGED
@@ -48,7 +48,7 @@ export function apply(ctx, config) {
48
48
  // Lifecycle: this cordis fork has no 'ready'/'dispose' events — startup
49
49
  // work goes in ctx.effect() (runs immediately at plugin load; the returned
50
50
  // disposer runs on fiber unload at shutdown). Event taps verified against
51
- // @deepseek-ai/dsh-session@0.1.2-rc.1: session/event(session, event),
51
+ // @deepseek-ai/dsh-session@0.1.5-rc.1: session/event(session, event),
52
52
  // session/disposed(session), and the awaited session/flush(session)
53
53
  // durability checkpoint. The cast stays because the dsh-session types that
54
54
  // declare these event names are not installed.
@@ -171,7 +171,7 @@ export function apply(ctx, config) {
171
171
  }
172
172
  }
173
173
  // Latest-wins title snapshot (log-only `session/title` event; payload
174
- // { title, messageSeqs, source } verified against dsh-session-title@0.1.2-rc.1).
174
+ // { title, messageSeqs, source } verified against dsh-session-title@0.1.5-rc.1).
175
175
  if (event?.type === 'session/title' && typeof event.data?.title === 'string') {
176
176
  accum.title = event.data.title;
177
177
  }
package/lib/projector.js CHANGED
@@ -7,10 +7,11 @@
7
7
  * - envelope: `{ type, seq, time, data }` — payload lives under `data`.
8
8
  * - surface events (the only ones producing LLM messages, and the only ones
9
9
  * projected to rows): `user/message`, `assistant/message`, `tool/result`.
10
- * - token usage: `assistant/chunk` `{ type: 'usage' }` is authoritative per
11
- * step; `assistant/message`'s `data.usage` only counts when no usage chunk
12
- * was seen for the step (dedup in usageOf). `turn/end` carries none — it
13
- * only serves as a rollup checkpoint.
10
+ * - token usage (V3 log): `assistant/message.data.usage` is the settled
11
+ * step's accounting; a failed/cancelled attempt commits `assistant/attempt`
12
+ * instead, with the adapter's usage chunk preserved as a raw record in its
13
+ * embedded compact stream (recovered in usageSampleOf). `turn/end` carries
14
+ * none — it only serves as a rollup checkpoint.
14
15
  * - compaction summaries enter the surface as a `user/message` with
15
16
  * `surfaceOp: replace`, so they flow through the user path unchanged.
16
17
  */
@@ -106,9 +107,9 @@ export function projectEvent(_session, event, sessionId) {
106
107
  };
107
108
  }
108
109
  default:
109
- // Log-only events (assistant/chunk, turn/step lifecycle, approvals,
110
+ // Log-only events (assistant/attempt, turn/step lifecycle, approvals,
110
111
  // compaction markers, ...) are not standalone rows; usage rolls up into
111
- // SessionRow via usageOf (usage chunks and assistant/message).
112
+ // SessionRow via usageSampleOf (assistant/message and assistant/attempt).
112
113
  return null;
113
114
  }
114
115
  }
@@ -116,17 +117,17 @@ export function projectEvent(_session, event, sessionId) {
116
117
  * Extract the usage sample carried by one event, keyed by its step, or null
117
118
  * when the event carries none.
118
119
  *
119
- * dsh-llm emits usage as:
120
- * - `assistant/chunk` with `chunk.type === 'usage'` — the step's accounting,
121
- * emitted even when the request later fails (a failed step produces no
122
- * assistant/message, so message-only accounting would miss it entirely);
123
- * - `assistant/message.data.usage` — the same step's final accounting.
120
+ * V3 session log (dsh-session@0.1.5-rc.1):
121
+ * - `assistant/message.data.usage` — the settled step's final accounting;
122
+ * - `assistant/attempt` — a failed/retried/cancelled step commits no surface
123
+ * message; the adapter's usage chunk survives as a raw `chunk` record in the
124
+ * embedded compact `stream` (deltas are packed, but usage is a raw type).
124
125
  *
125
126
  * Samples for one `(turn, step)` are REPLACEMENTS, not additive: later
126
- * samples supersede earlier ones (progressive chunks, then the message).
127
- * The caller keeps the latest sample per step and folds only the delta into
128
- * its rollup. Totals include the cache buckets: cacheRead/cacheWrite are
129
- * billed in their own buckets (observed cacheReadTokens ≫ inputTokens in
127
+ * samples supersede earlier ones (a failed attempt's usage, then the settled
128
+ * message's). The caller keeps the latest sample per step and folds only the
129
+ * delta into its rollup. Totals include the cache buckets: cacheRead/cacheWrite
130
+ * are billed in their own buckets (observed cacheReadTokens ≫ inputTokens in
130
131
  * dsh session logs — they are not subsets of inputTokens).
131
132
  */
132
133
  export function usageSampleOf(event) {
@@ -136,13 +137,13 @@ export function usageSampleOf(event) {
136
137
  });
137
138
  let data;
138
139
  let usage;
139
- if (event?.type === 'assistant/chunk' && event.data?.chunk?.type === 'usage') {
140
+ if (event?.type === 'assistant/message') {
140
141
  data = event.data;
141
- usage = data.chunk.usage;
142
+ usage = data?.usage;
142
143
  }
143
- else if (event?.type === 'assistant/message') {
144
+ else if (event?.type === 'assistant/attempt') {
144
145
  data = event.data;
145
- usage = data?.usage;
146
+ usage = (Array.isArray(data?.stream) ? data.stream : []).find((r) => r?.type === 'chunk' && r.chunk?.type === 'usage')?.chunk?.usage;
146
147
  }
147
148
  else {
148
149
  return null;
@@ -7,10 +7,11 @@
7
7
  * - envelope: `{ type, seq, time, data }` — payload lives under `data`.
8
8
  * - surface events (the only ones producing LLM messages, and the only ones
9
9
  * projected to rows): `user/message`, `assistant/message`, `tool/result`.
10
- * - token usage: `assistant/chunk` `{ type: 'usage' }` is authoritative per
11
- * step; `assistant/message`'s `data.usage` only counts when no usage chunk
12
- * was seen for the step (dedup in usageOf). `turn/end` carries none — it
13
- * only serves as a rollup checkpoint.
10
+ * - token usage (V3 log): `assistant/message.data.usage` is the settled
11
+ * step's accounting; a failed/cancelled attempt commits `assistant/attempt`
12
+ * instead, with the adapter's usage chunk preserved as a raw record in its
13
+ * embedded compact stream (recovered in usageSampleOf). `turn/end` carries
14
+ * none — it only serves as a rollup checkpoint.
14
15
  * - compaction summaries enter the surface as a `user/message` with
15
16
  * `surfaceOp: replace`, so they flow through the user path unchanged.
16
17
  */
@@ -29,17 +30,17 @@ export interface UsageSample {
29
30
  * Extract the usage sample carried by one event, keyed by its step, or null
30
31
  * when the event carries none.
31
32
  *
32
- * dsh-llm emits usage as:
33
- * - `assistant/chunk` with `chunk.type === 'usage'` — the step's accounting,
34
- * emitted even when the request later fails (a failed step produces no
35
- * assistant/message, so message-only accounting would miss it entirely);
36
- * - `assistant/message.data.usage` — the same step's final accounting.
33
+ * V3 session log (dsh-session@0.1.5-rc.1):
34
+ * - `assistant/message.data.usage` — the settled step's final accounting;
35
+ * - `assistant/attempt` — a failed/retried/cancelled step commits no surface
36
+ * message; the adapter's usage chunk survives as a raw `chunk` record in the
37
+ * embedded compact `stream` (deltas are packed, but usage is a raw type).
37
38
  *
38
39
  * Samples for one `(turn, step)` are REPLACEMENTS, not additive: later
39
- * samples supersede earlier ones (progressive chunks, then the message).
40
- * The caller keeps the latest sample per step and folds only the delta into
41
- * its rollup. Totals include the cache buckets: cacheRead/cacheWrite are
42
- * billed in their own buckets (observed cacheReadTokens ≫ inputTokens in
40
+ * samples supersede earlier ones (a failed attempt's usage, then the settled
41
+ * message's). The caller keeps the latest sample per step and folds only the
42
+ * delta into its rollup. Totals include the cache buckets: cacheRead/cacheWrite
43
+ * are billed in their own buckets (observed cacheReadTokens ≫ inputTokens in
43
44
  * dsh session logs — they are not subsets of inputTokens).
44
45
  */
45
46
  export declare function usageSampleOf(event: any): {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@amaster.ai/dsh-storage",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "Session storage mirror for DeepSeek Harness: projects the session event stream into MySQL/PostgreSQL/SQLite/SQL Server (ai_messages / ai_chat_histories) without replacing dsh's local persistence.",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",
@@ -37,7 +37,7 @@
37
37
  },
38
38
  "peerDependencies": {
39
39
  "@deepseek-ai/cordis": "^4.0.1",
40
- "@deepseek-ai/dsh-session": "0.1.2-rc.1",
40
+ "@deepseek-ai/dsh-session": "0.1.5-rc.1",
41
41
  "@prisma/adapter-libsql": "^7.9.1",
42
42
  "@prisma/adapter-mariadb": "^7.9.1",
43
43
  "@prisma/adapter-mssql": "^7.9.1",