@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
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Generated by scripts/sync-icon-artwork.mts from @deepseek-ai/dsh-client-ui-primitives
|
|
3
|
-
* (v0.1
|
|
3
|
+
* (v0.2.1-rc.1, harness 1600d8a1e1) — do not edit by hand. The 0.1.5 and rc.1 host lines
|
|
4
4
|
* share no icon export name, so the rc.1 artwork is inlined here: pure SVG,
|
|
5
5
|
* no host runtime identity, identical on every line. Re-run the generator
|
|
6
6
|
* after adding an icon import or bumping the harness checkout.
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
import { randomUUID } from 'node:crypto';
|
|
12
12
|
import { SessionId } from '@deepseek-ai/dsh-session';
|
|
13
13
|
import { NO_START_CAPABILITIES, SUBAGENT_DESCRIPTOR_VERSION, settleRunResult, subprocessRunHandle, } from '@deepseek-ai/dsh-subagent';
|
|
14
|
-
import { assertResumeCwdUnchanged, assertResumeScopeUnchanged, resolveRoundModel, containerExecSpawn, containerScopedHome, delegationEnv, establishSubagentCatalogChild, probeCliVersion, resolveChildCwd, subagentDelegationLabel, } from '@khorsheed/dsh-local-agent';
|
|
14
|
+
import { assertResumeCwdUnchanged, assertResumeScopeUnchanged, resolveRoundModel, containerExecSpawn, containerScopedHome, delegationEnv, establishSubagentCatalogChild, persistChildSession, probeCliVersion, resolveChildCwd, subagentDelegationLabel, } from '@khorsheed/dsh-local-agent';
|
|
15
15
|
import { MEMBER_BRIDGE_SOCKET_ENV, MEMBER_BRIDGE_TOKEN_ENV } from '@khorsheed/dsh-local-agent/types';
|
|
16
16
|
import { LiveChannelUnavailableError } from './live-driver.js';
|
|
17
17
|
import { injectMemberBridge, memberBridgeServerKey, removeMemberBridge } from './member-bridge-config.js';
|
|
@@ -623,8 +623,11 @@ async function mirrorKimiAfterExit(spec, stderr) {
|
|
|
623
623
|
// The round's turn selects which transcript lines the tool-call accounting
|
|
624
624
|
// belongs to — the mirror window would under-count a settle pass a live
|
|
625
625
|
// poll already drained, and over-count a resume round's earlier turns.
|
|
626
|
+
// Settle mode: calls whose result never reached the wire fold with a
|
|
627
|
+
// synthesized interrupted result instead of holding the offset forever.
|
|
626
628
|
const delta = await mirrorKimiDelta(spec.ctx, spec.childSession, spec.homeDir, kimiSessionId, {
|
|
627
629
|
turn: spec.resume?.turn ?? 1,
|
|
630
|
+
settle: true,
|
|
628
631
|
});
|
|
629
632
|
// Report the final mirrored-line count even when the live mirror already
|
|
630
633
|
// advanced the offset (empty delta): the settle report is authoritative.
|
|
@@ -818,24 +821,6 @@ export async function startKimiCliRun(request, spec) {
|
|
|
818
821
|
// or not the round is session-backed.
|
|
819
822
|
if (settled.stopReason === 'completed')
|
|
820
823
|
spec.onAuthSuccess?.();
|
|
821
|
-
// The turn closes at the real settle moment, so the timing projection's
|
|
822
|
-
// duration equals the actual CLI runtime. Every terminal path closes the
|
|
823
|
-
// window — a failed or cancelled run settles 'error'/'aborted' instead of
|
|
824
|
-
// leaving the turn open with a distorted tiny duration.
|
|
825
|
-
if (spec.childSession !== undefined) {
|
|
826
|
-
if (settled.stopReason === 'completed') {
|
|
827
|
-
spec.childSession.append('turn/end', { turn, reason: { kind: 'completed' } });
|
|
828
|
-
}
|
|
829
|
-
else if (settled.stopReason === 'aborted') {
|
|
830
|
-
spec.childSession.append('turn/end', { turn, reason: { kind: 'aborted', reason: { kind: 'parent' } } });
|
|
831
|
-
}
|
|
832
|
-
else {
|
|
833
|
-
spec.childSession.append('turn/end', {
|
|
834
|
-
turn,
|
|
835
|
-
reason: { kind: 'error', error: { message: 'kimi -p exited before the run completed', code: 'UNKNOWN' } },
|
|
836
|
-
});
|
|
837
|
-
}
|
|
838
|
-
}
|
|
839
824
|
return settled;
|
|
840
825
|
});
|
|
841
826
|
// After the child EXITS — however it ended (completed, killed by dispose, or
|
|
@@ -843,9 +828,12 @@ export async function startKimiCliRun(request, spec) {
|
|
|
843
828
|
// subagent session, so a cancelled round still preserves its partial work
|
|
844
829
|
// and real token usage instead of leaving the child blank. The mirror reads
|
|
845
830
|
// the wire file, so it only reflects what kimi flushed before the kill.
|
|
846
|
-
// Waits for the settle chain first
|
|
847
|
-
// the
|
|
848
|
-
//
|
|
831
|
+
// Waits for the settle chain first AND for the process to actually exit (so
|
|
832
|
+
// the wire file is complete) before reading it. Enqueued behind any
|
|
833
|
+
// in-flight live poll on the mirror queue. The turn closes AFTER the settle
|
|
834
|
+
// mirror, still inside the mirror queue: every mirrored step must land
|
|
835
|
+
// before turn/end — the released-log reader rejects a step outside an open
|
|
836
|
+
// turn on every cold read.
|
|
849
837
|
void result.then(() => child.done).then(() => {
|
|
850
838
|
// Auth detection runs post-exit: streams are drained by then, so a fast
|
|
851
839
|
// failure's stderr is complete (a settle-time read could race the flush).
|
|
@@ -863,16 +851,41 @@ export async function startKimiCliRun(request, spec) {
|
|
|
863
851
|
// usage into the round total, then reports the round's settled
|
|
864
852
|
// observation — the wire's model plus the round's accumulated usage.
|
|
865
853
|
enqueueMirror(async () => {
|
|
866
|
-
const settled = await
|
|
867
|
-
|
|
854
|
+
const settled = await result;
|
|
855
|
+
const mirrored = await mirrorKimiAfterExit(spec, stderr);
|
|
856
|
+
addRoundUsage(mirrored?.usage);
|
|
857
|
+
// The turn closes at the real settle moment, so the timing
|
|
858
|
+
// projection's duration equals the actual CLI runtime (plus the
|
|
859
|
+
// settle-mirror quiescence). Every terminal path closes the window —
|
|
860
|
+
// a failed or cancelled run settles 'error'/'aborted' instead of
|
|
861
|
+
// leaving the turn open with a distorted tiny duration.
|
|
862
|
+
if (spec.childSession !== undefined) {
|
|
863
|
+
if (settled.stopReason === 'completed') {
|
|
864
|
+
spec.childSession.append('turn/end', { turn, reason: { kind: 'completed' } });
|
|
865
|
+
}
|
|
866
|
+
else if (settled.stopReason === 'aborted') {
|
|
867
|
+
spec.childSession.append('turn/end', { turn, reason: { kind: 'aborted', reason: { kind: 'parent' } } });
|
|
868
|
+
}
|
|
869
|
+
else {
|
|
870
|
+
spec.childSession.append('turn/end', {
|
|
871
|
+
turn,
|
|
872
|
+
reason: { kind: 'error', error: { message: 'kimi -p exited before the run completed', code: 'UNKNOWN' } },
|
|
873
|
+
});
|
|
874
|
+
}
|
|
875
|
+
if (spec.ctx !== undefined) {
|
|
876
|
+
await persistChildSession(spec.ctx, spec.childSession).catch((error) => {
|
|
877
|
+
spec.ctx?.logger.warn(`subagent-kimi: turn/end persistence failed: ${thrown(error).message}`);
|
|
878
|
+
});
|
|
879
|
+
}
|
|
880
|
+
}
|
|
868
881
|
// The wire log names the model but never the CLI build, so the version
|
|
869
882
|
// is the executable's own answer, probed once per binary.
|
|
870
883
|
const cliVersion = await spec.cliVersion?.();
|
|
871
884
|
spec.onRoundSettled?.({
|
|
872
|
-
...
|
|
885
|
+
...mirrored?.model === undefined ? {} : { observedModel: mirrored.model },
|
|
873
886
|
...cliVersion === undefined ? {} : { cliVersion },
|
|
874
887
|
...roundUsage === undefined ? {} : { usage: roundUsage },
|
|
875
|
-
...
|
|
888
|
+
...mirrored?.toolCalls === undefined ? {} : { toolCalls: mirrored.toolCalls },
|
|
876
889
|
});
|
|
877
890
|
});
|
|
878
891
|
}, () => { });
|
|
@@ -16,11 +16,14 @@
|
|
|
16
16
|
* throttled `mirrorKimiDelta` passes and the settle pass stays authoritative
|
|
17
17
|
* (one fold, one offset, zero divergence between the two drivers). Every
|
|
18
18
|
* transcript item folds 1:1 into the child session log.
|
|
19
|
-
* Live output
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
19
|
+
* Live output rides the `local-agent/stream` channel: chunk deltas
|
|
20
|
+
* accumulate per streaming item and publish throttled updates at the item's
|
|
21
|
+
* reserved (turn, step) — the member live node renders them as-is — while
|
|
22
|
+
* the item's durable content lands as ONE atomic step/start→…→step/end
|
|
23
|
+
* triple at that step, written by the completing wire line's fold or at
|
|
24
|
+
* settle. Durable steps stay dense and strictly sequential (the released-log
|
|
25
|
+
* reader validates exactly that on every cold open); snapshots never hold a
|
|
26
|
+
* step open across appends.
|
|
24
27
|
*
|
|
25
28
|
* Lifecycle mirrors the dsh/codex live drivers' discipline: lazy spawn with an
|
|
26
29
|
* initialize handshake (loadSession capability required — crash recovery is
|