@khorsheed/dsh-local-agent-kimi 0.2.0-rc.3 → 0.2.0
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 +16 -1
- package/README.en.md +24 -112
- package/README.i18n.yaml +2 -2
- package/README.md +24 -112
- package/lib/client.js +63 -63
- package/lib/index.js +618 -343
- package/lib/types/client/icons.d.ts +1 -1
- package/lib/types/kimi-cli-provider.js +39 -26
- package/lib/types/live-driver.d.ts +8 -5
- package/lib/types/live-driver.js +324 -119
- package/lib/types/model-broker.js +42 -1
- package/lib/types/session-mirror.d.ts +115 -52
- package/lib/types/session-mirror.js +286 -210
- package/lib/types/session-view.d.ts +23 -2
- package/lib/types/session-view.js +37 -7
- package/package.json +2 -2
|
@@ -15,7 +15,13 @@
|
|
|
15
15
|
* its transcript position so a delta mirror can sum a round's total.
|
|
16
16
|
* @module @khorsheed/dsh-local-agent-kimi/session-view
|
|
17
17
|
*/
|
|
18
|
-
import type { TokenUsage } from '@deepseek-ai/dsh-llm';
|
|
18
|
+
import type { ReasoningEffortId, TokenUsage } from '@deepseek-ai/dsh-llm';
|
|
19
|
+
/** The request config one `llm.request` wire event declares (its own words). */
|
|
20
|
+
export interface KimiRequestConfig {
|
|
21
|
+
model?: string;
|
|
22
|
+
reasoningEffort?: ReasoningEffortId;
|
|
23
|
+
maxTokens?: number;
|
|
24
|
+
}
|
|
19
25
|
/** One rendered transcript line. */
|
|
20
26
|
export type KimiTranscriptLine = ({
|
|
21
27
|
kind: 'user';
|
|
@@ -25,10 +31,14 @@ export type KimiTranscriptLine = ({
|
|
|
25
31
|
kind: 'assistant';
|
|
26
32
|
text: string;
|
|
27
33
|
turn: number;
|
|
34
|
+
wireStep?: number;
|
|
35
|
+
requestConfig?: KimiRequestConfig;
|
|
28
36
|
} | {
|
|
29
37
|
kind: 'think';
|
|
30
38
|
text: string;
|
|
31
39
|
turn: number;
|
|
40
|
+
wireStep?: number;
|
|
41
|
+
requestConfig?: KimiRequestConfig;
|
|
32
42
|
}
|
|
33
43
|
/**
|
|
34
44
|
* Tool activity: one call with its (possibly still pending) result. `id`
|
|
@@ -43,6 +53,8 @@ export type KimiTranscriptLine = ({
|
|
|
43
53
|
args?: string;
|
|
44
54
|
result?: string;
|
|
45
55
|
turn: number;
|
|
56
|
+
wireStep?: number;
|
|
57
|
+
requestConfig?: KimiRequestConfig;
|
|
46
58
|
}) & {
|
|
47
59
|
model?: string;
|
|
48
60
|
};
|
|
@@ -62,6 +74,13 @@ export interface KimiSessionTranscript {
|
|
|
62
74
|
readonly line: number;
|
|
63
75
|
readonly usage: TokenUsage;
|
|
64
76
|
}[];
|
|
77
|
+
/**
|
|
78
|
+
* Wire steps (`${turn}:${wireStep}`, turn 1-based) whose `step.end` the wire
|
|
79
|
+
* recorded — a closed step's content is complete, so a mirror may fold it
|
|
80
|
+
* without waiting for the next step to begin. Older wires carry no step
|
|
81
|
+
* markers; their lines simply never appear here.
|
|
82
|
+
*/
|
|
83
|
+
closedSteps: ReadonlySet<string>;
|
|
65
84
|
/**
|
|
66
85
|
* The model identifier the wire named: the `model` field of a `usage.record`
|
|
67
86
|
* or `llm.request` event, LAST one seen (a resumed session's later rounds
|
|
@@ -89,7 +108,9 @@ export declare function readKimiTranscript(sessionDir: string): Promise<KimiSess
|
|
|
89
108
|
* Map a wire `usage.record` payload onto the shared usage contract. kimi
|
|
90
109
|
* reports input (uncached), cache read, cache creation, and output; the
|
|
91
110
|
* creation counter is its cache-write analog. Non-numeric or missing
|
|
92
|
-
* counters are dropped so the record stays usable when kimi omits a field
|
|
111
|
+
* counters are dropped so the record stays usable when kimi omits a field;
|
|
112
|
+
* a reported cache-read counter is always written (zero included), so a
|
|
113
|
+
* reader can tell "no hits" from "not reported".
|
|
93
114
|
* @param raw - the event's `usage` value.
|
|
94
115
|
* @returns the shared usage record, or undefined when nothing was reported.
|
|
95
116
|
*/
|
|
@@ -148,11 +148,20 @@ export async function readKimiTranscript(sessionDir) {
|
|
|
148
148
|
const sessionId = sessionDir.split('session_').pop() ?? sessionDir;
|
|
149
149
|
const lines = [];
|
|
150
150
|
const usageRecords = [];
|
|
151
|
+
const closedSteps = new Set();
|
|
151
152
|
let model;
|
|
152
153
|
let modelTurn;
|
|
153
154
|
let lineModel;
|
|
155
|
+
// The latest llm.request's declared config; content/tool lines carry a
|
|
156
|
+
// snapshot of it, so the mirror can write each folded step's request/header
|
|
157
|
+
// in the wire's own words.
|
|
158
|
+
let lineConfig;
|
|
154
159
|
const push = (line) => {
|
|
155
|
-
lines.push({
|
|
160
|
+
lines.push({
|
|
161
|
+
...line,
|
|
162
|
+
...lineModel === undefined ? {} : { model: lineModel },
|
|
163
|
+
...line.kind !== 'user' && lineConfig !== undefined ? { requestConfig: { ...lineConfig } } : {},
|
|
164
|
+
});
|
|
156
165
|
};
|
|
157
166
|
// Wire turns are 0-based on loop events; a `turn.prompt` also opens a new
|
|
158
167
|
// round. The transcript uses 1-based turns matching the dsh child session's
|
|
@@ -169,7 +178,7 @@ export async function readKimiTranscript(sessionDir) {
|
|
|
169
178
|
}
|
|
170
179
|
catch (error) {
|
|
171
180
|
if (error.code === 'ENOENT') {
|
|
172
|
-
return { sessionId, lines, usageRecords };
|
|
181
|
+
return { sessionId, lines, usageRecords, closedSteps };
|
|
173
182
|
}
|
|
174
183
|
throw error;
|
|
175
184
|
}
|
|
@@ -192,6 +201,11 @@ export async function readKimiTranscript(sessionDir) {
|
|
|
192
201
|
if (typeof event.model === 'string' && event.model !== '') {
|
|
193
202
|
model = lineModel = event.model;
|
|
194
203
|
modelTurn = turn || 1;
|
|
204
|
+
// The record names the alias spelling (kimi-code/k3), llm.request the
|
|
205
|
+
// raw one (k3) — the pending header config follows the alias so the
|
|
206
|
+
// header and the message source name the model identically.
|
|
207
|
+
if (lineConfig !== undefined)
|
|
208
|
+
lineConfig = { ...lineConfig, model: event.model };
|
|
195
209
|
}
|
|
196
210
|
const usage = usageFromWire(event.usage);
|
|
197
211
|
if (usage !== undefined)
|
|
@@ -204,6 +218,13 @@ export async function readKimiTranscript(sessionDir) {
|
|
|
204
218
|
model = event.model;
|
|
205
219
|
modelTurn = turn || 1;
|
|
206
220
|
}
|
|
221
|
+
// The header contract requires provider+model; a wire that names no
|
|
222
|
+
// model records no config at all rather than an invented one.
|
|
223
|
+
lineConfig = lineModel === undefined ? undefined : {
|
|
224
|
+
model: lineModel,
|
|
225
|
+
...typeof event.thinkingEffort === 'string' && event.thinkingEffort !== '' ? { reasoningEffort: event.thinkingEffort } : {},
|
|
226
|
+
...typeof event.maxTokens === 'number' && Number.isFinite(event.maxTokens) ? { maxTokens: event.maxTokens } : {},
|
|
227
|
+
};
|
|
207
228
|
continue;
|
|
208
229
|
}
|
|
209
230
|
if (event.type === 'turn.prompt') {
|
|
@@ -252,13 +273,19 @@ export async function readKimiTranscript(sessionDir) {
|
|
|
252
273
|
turn = Math.max(turn, loopTurn);
|
|
253
274
|
turnSeen = true;
|
|
254
275
|
}
|
|
276
|
+
// The wire's own 1-based step within the turn: one loop step is one LLM
|
|
277
|
+
// request (its think/text parts and tool calls share it), so the mirror
|
|
278
|
+
// folds per wire step. Older wires omit it — their lines fold singly.
|
|
279
|
+
const wireStep = typeof loop.step === 'number' ? loop.step : undefined;
|
|
255
280
|
const part = loop.part;
|
|
256
281
|
const lineTurn = turn === 0 ? 1 : turn;
|
|
282
|
+
if (loop.type === 'step.end' && wireStep !== undefined)
|
|
283
|
+
closedSteps.add(`${lineTurn}:${wireStep}`);
|
|
257
284
|
if (part?.type === 'text' && part.text !== undefined && part.text.trim() !== '') {
|
|
258
|
-
push({ kind: 'assistant', text: part.text, turn: lineTurn });
|
|
285
|
+
push({ kind: 'assistant', text: part.text, turn: lineTurn, ...wireStep === undefined ? {} : { wireStep } });
|
|
259
286
|
}
|
|
260
287
|
else if (part?.type === 'think' && part.think !== undefined && part.think.trim() !== '') {
|
|
261
|
-
push({ kind: 'think', text: part.think, turn: lineTurn });
|
|
288
|
+
push({ kind: 'think', text: part.think, turn: lineTurn, ...wireStep === undefined ? {} : { wireStep } });
|
|
262
289
|
}
|
|
263
290
|
else if (loop.type === 'tool.call') {
|
|
264
291
|
const call = loop;
|
|
@@ -273,6 +300,7 @@ export async function readKimiTranscript(sessionDir) {
|
|
|
273
300
|
name,
|
|
274
301
|
...args === undefined ? {} : { args },
|
|
275
302
|
turn: lineTurn,
|
|
303
|
+
...wireStep === undefined ? {} : { wireStep },
|
|
276
304
|
});
|
|
277
305
|
if (typeof call.uuid === 'string')
|
|
278
306
|
callsByUuid.set(call.uuid, lineIndex);
|
|
@@ -316,13 +344,15 @@ export async function readKimiTranscript(sessionDir) {
|
|
|
316
344
|
}
|
|
317
345
|
}
|
|
318
346
|
}
|
|
319
|
-
return { sessionId, lines, usageRecords, ...model === undefined ? {} : { model }, ...modelTurn === undefined ? {} : { modelTurn } };
|
|
347
|
+
return { sessionId, lines, usageRecords, closedSteps, ...model === undefined ? {} : { model }, ...modelTurn === undefined ? {} : { modelTurn } };
|
|
320
348
|
}
|
|
321
349
|
/**
|
|
322
350
|
* Map a wire `usage.record` payload onto the shared usage contract. kimi
|
|
323
351
|
* reports input (uncached), cache read, cache creation, and output; the
|
|
324
352
|
* creation counter is its cache-write analog. Non-numeric or missing
|
|
325
|
-
* counters are dropped so the record stays usable when kimi omits a field
|
|
353
|
+
* counters are dropped so the record stays usable when kimi omits a field;
|
|
354
|
+
* a reported cache-read counter is always written (zero included), so a
|
|
355
|
+
* reader can tell "no hits" from "not reported".
|
|
326
356
|
* @param raw - the event's `usage` value.
|
|
327
357
|
* @returns the shared usage record, or undefined when nothing was reported.
|
|
328
358
|
*/
|
|
@@ -345,7 +375,7 @@ export function usageFromWire(raw) {
|
|
|
345
375
|
inputTokens: input ?? 0,
|
|
346
376
|
outputTokens: output ?? 0,
|
|
347
377
|
};
|
|
348
|
-
if (cacheRead !== undefined
|
|
378
|
+
if (cacheRead !== undefined)
|
|
349
379
|
usage.cacheReadTokens = cacheRead;
|
|
350
380
|
if (cacheWrite !== undefined && cacheWrite > 0)
|
|
351
381
|
usage.cacheWriteTokens = cacheWrite;
|
package/package.json
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"local-agent",
|
|
9
9
|
"kimi"
|
|
10
10
|
],
|
|
11
|
-
"version": "0.2.0
|
|
11
|
+
"version": "0.2.0",
|
|
12
12
|
"type": "module",
|
|
13
13
|
"main": "lib/index.js",
|
|
14
14
|
"types": "lib/types/index.d.ts",
|
|
@@ -69,7 +69,7 @@
|
|
|
69
69
|
"dsh": ">=0.1.5-rc.1 <0.3.0-0"
|
|
70
70
|
},
|
|
71
71
|
"dependencies": {
|
|
72
|
-
"@khorsheed/dsh-local-agent": "^0.2.0
|
|
72
|
+
"@khorsheed/dsh-local-agent": "^0.2.0"
|
|
73
73
|
},
|
|
74
74
|
"peerDependencies": {
|
|
75
75
|
"@deepseek-ai/cordis": "^4.0.1",
|