@deepseek-ai/dsh-session-stats 0.1.2-alpha.5 → 0.1.3-alpha.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
@@ -1,8 +1,9 @@
1
1
  import { z } from "zod";
2
+ import { assistantStreamFirstTokenTime } from "@deepseek-ai/dsh-llm";
2
3
  //#region lib/types/projection.js
3
4
  /**
4
5
  * The `sessionStats` projection unit: a pure fold of step boundaries, stream
5
- * chunks, tool pairs, and assembled assistant messages into whole-log counts
6
+ * embedded streams, tool pairs, and assembled assistant messages into whole-log counts
6
7
  * and wall times.
7
8
  *
8
9
  * `step/end` — not `assistant/message` — is the counted step event because it
@@ -24,15 +25,6 @@ import { z } from "zod";
24
25
  *
25
26
  * @module @deepseek-ai/dsh-session-stats/projection
26
27
  */
27
- /** Whether a stream chunk carries a non-empty first-token delta. */
28
- function isTokenDelta(chunk) {
29
- switch (chunk.type) {
30
- case "text-delta":
31
- case "reasoning-delta": return chunk.text !== "";
32
- case "tool-call-delta": return chunk.argumentsDelta !== "" || chunk.name !== void 0;
33
- default: return false;
34
- }
35
- }
36
28
  const sessionStatsSchema = z.object({
37
29
  turns: z.number().int().nonnegative(),
38
30
  steps: z.number().int().nonnegative(),
@@ -99,32 +91,34 @@ const sessionStatsProjectionDefinition = {
99
91
  firstTokenTime: null
100
92
  }
101
93
  };
102
- case "assistant/chunk": {
94
+ case "assistant/attempt": {
103
95
  const open = state.openStep;
104
96
  if (open === null || open.turn !== event.data.turn || open.step !== event.data.step) return state;
105
- if (open.firstTokenTime !== null || !isTokenDelta(event.data.chunk)) return state;
97
+ const first = assistantStreamFirstTokenTime(event.data.stream) ?? null;
98
+ if (open.firstTokenTime !== null || first === null) return state;
106
99
  return {
107
100
  ...state,
108
101
  openStep: {
109
102
  ...open,
110
- firstTokenTime: event.time
103
+ firstTokenTime: first
111
104
  }
112
105
  };
113
106
  }
114
107
  case "assistant/message": {
115
108
  const open = state.openStep;
116
109
  if (open === null || open.turn !== event.data.turn || open.step !== event.data.step) return state;
110
+ const firstToken = open.firstTokenTime ?? assistantStreamFirstTokenTime(event.data.stream) ?? null;
117
111
  const next = {
118
112
  ...state,
119
113
  llmMs: state.llmMs + Math.max(0, event.time - open.startTime),
120
114
  openStep: null
121
115
  };
122
- if (open.firstTokenTime !== null) {
123
- next.ttftMs += Math.max(0, open.firstTokenTime - open.startTime);
116
+ if (firstToken !== null) {
117
+ next.ttftMs += Math.max(0, firstToken - open.startTime);
124
118
  next.ttftSteps += 1;
125
119
  const outputTokens = usageOutputTokens(event.data.usage);
126
120
  if (outputTokens !== null) {
127
- next.decodeMs += Math.max(0, event.time - open.firstTokenTime);
121
+ next.decodeMs += Math.max(0, event.time - firstToken);
128
122
  next.decodeTokens += outputTokens;
129
123
  }
130
124
  }
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * The `sessionStats` projection unit: a pure fold of step boundaries, stream
3
- * chunks, tool pairs, and assembled assistant messages into whole-log counts
3
+ * embedded streams, tool pairs, and assembled assistant messages into whole-log counts
4
4
  * and wall times.
5
5
  *
6
6
  * `step/end` — not `assistant/message` — is the counted step event because it
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * The `sessionStats` projection unit: a pure fold of step boundaries, stream
3
- * chunks, tool pairs, and assembled assistant messages into whole-log counts
3
+ * embedded streams, tool pairs, and assembled assistant messages into whole-log counts
4
4
  * and wall times.
5
5
  *
6
6
  * `step/end` — not `assistant/message` — is the counted step event because it
@@ -23,19 +23,7 @@
23
23
  * @module @deepseek-ai/dsh-session-stats/projection
24
24
  */
25
25
  import { z } from 'zod';
26
- /* jscpd:ignore-start -- Session Stats owns its whole-log timing projection independently. */
27
- /** Whether a stream chunk carries a non-empty first-token delta. */
28
- function isTokenDelta(chunk) {
29
- switch (chunk.type) {
30
- case 'text-delta':
31
- case 'reasoning-delta':
32
- return chunk.text !== '';
33
- case 'tool-call-delta':
34
- return chunk.argumentsDelta !== '' || chunk.name !== undefined;
35
- default:
36
- return false;
37
- }
38
- }
26
+ import { assistantStreamFirstTokenTime } from '@deepseek-ai/dsh-llm';
39
27
  const sessionStatsSchema = z.object({
40
28
  turns: z.number().int().nonnegative(),
41
29
  steps: z.number().int().nonnegative(),
@@ -100,18 +88,20 @@ export const sessionStatsProjectionDefinition = {
100
88
  ...state,
101
89
  openStep: { turn: event.data.turn, step: event.data.step, startTime: event.time, firstTokenTime: null },
102
90
  };
103
- case 'assistant/chunk': {
91
+ case 'assistant/attempt': {
104
92
  const open = state.openStep;
105
93
  if (open === null || open.turn !== event.data.turn || open.step !== event.data.step)
106
94
  return state;
107
- if (open.firstTokenTime !== null || !isTokenDelta(event.data.chunk))
95
+ const first = assistantStreamFirstTokenTime(event.data.stream) ?? null;
96
+ if (open.firstTokenTime !== null || first === null)
108
97
  return state;
109
- return { ...state, openStep: { ...open, firstTokenTime: event.time } };
98
+ return { ...state, openStep: { ...open, firstTokenTime: first } };
110
99
  }
111
100
  case 'assistant/message': {
112
101
  const open = state.openStep;
113
102
  if (open === null || open.turn !== event.data.turn || open.step !== event.data.step)
114
103
  return state;
104
+ const firstToken = open.firstTokenTime ?? assistantStreamFirstTokenTime(event.data.stream) ?? null;
115
105
  // One assembled message per step: closing the boundary means a
116
106
  // defensive duplicate cannot accrue twice.
117
107
  const next = {
@@ -119,12 +109,12 @@ export const sessionStatsProjectionDefinition = {
119
109
  llmMs: state.llmMs + Math.max(0, event.time - open.startTime),
120
110
  openStep: null,
121
111
  };
122
- if (open.firstTokenTime !== null) {
123
- next.ttftMs += Math.max(0, open.firstTokenTime - open.startTime);
112
+ if (firstToken !== null) {
113
+ next.ttftMs += Math.max(0, firstToken - open.startTime);
124
114
  next.ttftSteps += 1;
125
115
  const outputTokens = usageOutputTokens(event.data.usage);
126
116
  if (outputTokens !== null) {
127
- next.decodeMs += Math.max(0, event.time - open.firstTokenTime);
117
+ next.decodeMs += Math.max(0, event.time - firstToken);
128
118
  next.decodeTokens += outputTokens;
129
119
  }
130
120
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@deepseek-ai/dsh-session-stats",
3
3
  "description": "Whole-log conversation counts and wall times projection (sessionStats) for the DeepSeek Harness",
4
- "version": "0.1.2-alpha.5",
4
+ "version": "0.1.3-alpha.2",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -36,20 +36,20 @@
36
36
  ],
37
37
  "license": "MIT",
38
38
  "peerDependencies": {
39
- "@deepseek-ai/dsh-llm": "^0.1.2-alpha.5",
40
- "@deepseek-ai/dsh-session": "^0.1.2-alpha.5",
41
- "@deepseek-ai/dsh-session-projection": "^0.1.2-alpha.5",
42
- "@deepseek-ai/cordis": "^4.0.2"
39
+ "@deepseek-ai/dsh-llm": "^0.1.3-alpha.2",
40
+ "@deepseek-ai/dsh-session": "^0.1.3-alpha.2",
41
+ "@deepseek-ai/cordis": "^4.0.2",
42
+ "@deepseek-ai/dsh-session-projection": "^0.1.3-alpha.2"
43
43
  },
44
44
  "dependencies": {
45
45
  "zod": "^4.4.3"
46
46
  },
47
47
  "devDependencies": {
48
- "@deepseek-ai/cordis-plugin-include": "^1.0.7",
49
48
  "@deepseek-ai/cordis-plugin-loader": "^1.0.3",
50
- "@deepseek-ai/dsh-llm": "^0.1.2-alpha.5",
51
- "@deepseek-ai/dsh-session-projection": "^0.1.2-alpha.5",
52
- "@deepseek-ai/dsh-session": "^0.1.2-alpha.5",
53
- "@deepseek-ai/cordis": "^4.0.2"
49
+ "@deepseek-ai/dsh-llm": "^0.1.3-alpha.2",
50
+ "@deepseek-ai/dsh-session": "^0.1.3-alpha.2",
51
+ "@deepseek-ai/dsh-session-projection": "^0.1.3-alpha.2",
52
+ "@deepseek-ai/cordis": "^4.0.2",
53
+ "@deepseek-ai/cordis-plugin-include": "^1.0.7"
54
54
  }
55
55
  }