dsh-loop-engine 1.0.0-rc7 → 1.0.0-rc8
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 +19 -0
- package/lib/client.js +6 -2
- package/lib/index.js +832 -258
- package/lib/invariant.js +2 -1
- package/lib/types/client/LoopEngineBadge.d.ts +1 -1
- package/lib/types/client/LoopEngineComposerSelect.d.ts +1 -1
- package/lib/types/client/LoopEngineSection.d.ts +1 -1
- package/lib/types/client/index.d.ts +1 -1
- package/lib/types/client/locales.d.ts +2 -0
- package/lib/types/client/store.d.ts +2 -1
- package/lib/types/engine-claude/agent.d.ts +2 -0
- package/lib/types/engine-claude/loop.d.ts +24 -2
- package/lib/types/engine-claude/mapping.d.ts +3 -3
- package/lib/types/engine-codex/agent.d.ts +2 -0
- package/lib/types/engine-codex/appserver/mapping.d.ts +4 -4
- package/lib/types/engine-codex/loop.d.ts +24 -2
- package/lib/types/engine-kimi/agent.d.ts +2 -0
- package/lib/types/engine-kimi/commands.d.ts +7 -0
- package/lib/types/engine-kimi/loop.d.ts +24 -2
- package/lib/types/engine-pi/agent.d.ts +2 -0
- package/lib/types/engine-pi/loop.d.ts +24 -2
- package/lib/types/index.d.ts +16 -0
- package/lib/types/patch-manager.d.ts +9 -0
- package/lib/types/preset.d.ts +73 -0
- package/lib/types/provider-route.d.ts +35 -0
- package/lib/types/settings.d.ts +5 -5
- package/package.json +23 -23
package/lib/invariant.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
// src/settings.ts
|
|
2
2
|
import z from "@deepseek-ai/schemastery";
|
|
3
|
-
import { settingsNamespace } from "@deepseek-ai/dsh-settings";
|
|
4
3
|
var LOOP_ENGINE_IDS = ["in-process", "claude-code", "codex", "pi", "kimi"];
|
|
5
4
|
var LOOP_ENGINE_SETTINGS_SCHEMA = z.object({
|
|
6
5
|
engine: z.union([z.const("in-process"), z.const("claude-code"), z.const("codex"), z.const("pi"), z.const("kimi")]).default("in-process"),
|
|
@@ -18,6 +17,8 @@ function renderManagedBlock(engine) {
|
|
|
18
17
|
`${MANAGED_BLOCK_BEGIN}${engine} --`,
|
|
19
18
|
"- id: agent-loop",
|
|
20
19
|
" disabled: true",
|
|
20
|
+
"- id: command-goal",
|
|
21
|
+
" disabled: true",
|
|
21
22
|
END_MARKER_LINE
|
|
22
23
|
].join("\n");
|
|
23
24
|
}
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* @module dsh-loop-engine/client/badge
|
|
10
10
|
*/
|
|
11
11
|
import type { JSX } from 'react';
|
|
12
|
-
import type { SnapshotStore } from '@deepseek-ai/dsh-client-
|
|
12
|
+
import type { SnapshotStore } from '@deepseek-ai/dsh-client-store';
|
|
13
13
|
import type { InjectFace } from '@deepseek-ai/dsh-client-ui-slots';
|
|
14
14
|
import type { LoopEngineState } from './store.ts';
|
|
15
15
|
import type { en } from './locales.ts';
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* @module dsh-loop-engine/client/composer
|
|
14
14
|
*/
|
|
15
15
|
import { type JSX } from 'react';
|
|
16
|
-
import type { SnapshotStore } from '@deepseek-ai/dsh-client-
|
|
16
|
+
import type { SnapshotStore } from '@deepseek-ai/dsh-client-store';
|
|
17
17
|
import type { InjectFace } from '@deepseek-ai/dsh-client-ui-slots';
|
|
18
18
|
import type { LoopEngineStore, LoopEngineState } from './store.ts';
|
|
19
19
|
import type { en } from './locales.ts';
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* @module dsh-loop-engine/client
|
|
13
13
|
*/
|
|
14
14
|
import { type JSX } from 'react';
|
|
15
|
-
import type { SnapshotStore } from '@deepseek-ai/dsh-client-
|
|
15
|
+
import type { SnapshotStore } from '@deepseek-ai/dsh-client-store';
|
|
16
16
|
import type { InjectFace } from '@deepseek-ai/dsh-client-ui-slots';
|
|
17
17
|
import type { LoopEngineStore, LoopEngineState } from './store.ts';
|
|
18
18
|
import type { en } from './locales.ts';
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* Export discipline: packages/client/AGENTS.md.
|
|
6
6
|
* @module dsh-loop-engine/client
|
|
7
7
|
*/
|
|
8
|
-
import type { ClientContext } from '@deepseek-ai/
|
|
8
|
+
import type { Context as ClientContext } from '@deepseek-ai/cordis';
|
|
9
9
|
import { type LoopEngineKey } from './locales.ts';
|
|
10
10
|
export type { LoopEngineSectionInjected, LoopEngineSectionProps } from './LoopEngineSection.tsx';
|
|
11
11
|
export type { LoopEngineBadgeInjected, LoopEngineBadgeProps } from './LoopEngineBadge.tsx';
|
|
@@ -34,6 +34,8 @@ export interface LoopEngineKey {
|
|
|
34
34
|
confirmAction: string;
|
|
35
35
|
/** Cancel action label. */
|
|
36
36
|
cancelAction: string;
|
|
37
|
+
/** Accessible close-button label of the confirmation dialog. */
|
|
38
|
+
closeLabel: string;
|
|
37
39
|
/** Notice shown while the Claude Code engine owns the slot: model selection is native. */
|
|
38
40
|
claudeModelNotice: string;
|
|
39
41
|
}
|
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
* and the store publishes a render-safe snapshot plus the write path.
|
|
4
4
|
* @module dsh-loop-engine/client/store
|
|
5
5
|
*/
|
|
6
|
-
import type { SettingsScope
|
|
6
|
+
import type { SettingsScope } from '@deepseek-ai/dsh-client-ui-settings/client';
|
|
7
|
+
import type { SnapshotStore } from '@deepseek-ai/dsh-client-store';
|
|
7
8
|
import type { LoopEngineId } from '../settings.ts';
|
|
8
9
|
/** State rendered by the loop engine section. */
|
|
9
10
|
export interface LoopEngineState {
|
|
@@ -12,6 +12,8 @@ import type { Scope } from '@deepseek-ai/dsh-scope';
|
|
|
12
12
|
import type { Session, SessionId, UserMessage } from '@deepseek-ai/dsh-session';
|
|
13
13
|
import type { Context } from '@deepseek-ai/cordis';
|
|
14
14
|
import type { ResolvedConfig } from './types.ts';
|
|
15
|
+
/** Provider route label used for logged header snapshots and message provenance. */
|
|
16
|
+
export declare const PROVIDER = "claude-code";
|
|
15
17
|
/** Drives one session through turn and step boundaries on Claude Code. */
|
|
16
18
|
export declare class ClaudeCodeAgent implements Agent {
|
|
17
19
|
private loopCtx;
|
|
@@ -70,12 +70,34 @@ export declare class ClaudeCodeLoop extends Service implements AgentFactory {
|
|
|
70
70
|
private setupAndPublish;
|
|
71
71
|
/**
|
|
72
72
|
* Create an agent and session under one caller-supplied identity, owned by
|
|
73
|
-
* the accessing fiber.
|
|
73
|
+
* the accessing fiber. When a persistence backend is mounted, the session's
|
|
74
|
+
* durable identity is stored before publication.
|
|
74
75
|
* @param ownerCtx - caller context that structurally owns the lifecycle.
|
|
75
76
|
* @param options - identities, session seed/metadata, loop options, setup, and cancellation.
|
|
76
77
|
* @returns the published handle.
|
|
77
78
|
*/
|
|
78
79
|
createAgent(ownerCtx: Context, options: CreateAgentOptions): Promise<AgentHandle>;
|
|
80
|
+
/**
|
|
81
|
+
* Take a fresh session's write ownership when persistence is mounted.
|
|
82
|
+
* Nothing is appended here: the constructor seed (which never re-emits
|
|
83
|
+
* through `session/event`) is stored by {@link appendUnstoredSuffix} at the
|
|
84
|
+
* publication commit point, so a failed or cancelled setup closes an
|
|
85
|
+
* unmaterialized handle and leaves no stored residue — the same id can be
|
|
86
|
+
* created again.
|
|
87
|
+
* @param session - the unpublished session to store.
|
|
88
|
+
* @param signal - optional cancellation forwarded to the backend create.
|
|
89
|
+
* @returns the owned handle and stored cursor, or `undefined` without a backend.
|
|
90
|
+
*/
|
|
91
|
+
private createStoredSession;
|
|
92
|
+
/**
|
|
93
|
+
* Durably store the session events appended since the last stored cursor.
|
|
94
|
+
* Pre-publication appends (constructor seed markers, setup-window events)
|
|
95
|
+
* never re-emit through `session/event`, so publication must flush them
|
|
96
|
+
* through the handle before live events start routing into it.
|
|
97
|
+
* @param stored - the session's owned handle and stored cursor, if any.
|
|
98
|
+
* @param session - the unpublished session whose suffix is stored.
|
|
99
|
+
*/
|
|
100
|
+
private appendUnstoredSuffix;
|
|
79
101
|
/**
|
|
80
102
|
* Resume an owned agent from the configured persistence service.
|
|
81
103
|
* @param ownerCtx - caller context that owns load, setup, and the live lifecycle.
|
|
@@ -83,7 +105,7 @@ export declare class ClaudeCodeLoop extends Service implements AgentFactory {
|
|
|
83
105
|
* @returns the published handle.
|
|
84
106
|
*/
|
|
85
107
|
resume(ownerCtx: Context, options: ResumeAgentOptions): Promise<AgentHandle>;
|
|
86
|
-
/** Resume through an explicit persistence
|
|
108
|
+
/** Resume through an explicit persistence service. */
|
|
87
109
|
private resumeWith;
|
|
88
110
|
}
|
|
89
111
|
//# sourceMappingURL=loop.d.ts.map
|
|
@@ -8,11 +8,11 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import type { BetaMessage, BetaRawMessageStreamEvent, BetaUsage } from '@anthropic-ai/sdk/resources/beta/messages/messages.mjs';
|
|
10
10
|
import type { MessageParam } from '@anthropic-ai/sdk/resources';
|
|
11
|
-
import {
|
|
11
|
+
import { ToolCallId, type ContentBlock, type StreamChunk, type TokenUsage, type ToolResultMessage } from '@deepseek-ai/dsh-llm';
|
|
12
12
|
/** One tool invocation surfaced from a Claude Code assistant message. */
|
|
13
13
|
export interface MappedToolCall {
|
|
14
14
|
/** SDK tool_use id, reused as the dsh call-id so results pair. */
|
|
15
|
-
readonly callId:
|
|
15
|
+
readonly callId: ToolCallId;
|
|
16
16
|
/** Tool name exactly as the SDK reported it. */
|
|
17
17
|
readonly name: string;
|
|
18
18
|
/** Raw JSON arguments string as the SDK produced them. */
|
|
@@ -63,7 +63,7 @@ export declare function mapToolResults(message: MessageParam): ToolResultMessage
|
|
|
63
63
|
export declare function mapUsage(usage: BetaUsage): TokenUsage;
|
|
64
64
|
/** Per-block-index tool-call identity captured at `content_block_start`, reused by `input_json_delta`. */
|
|
65
65
|
export interface StreamToolCall {
|
|
66
|
-
readonly callId:
|
|
66
|
+
readonly callId: ToolCallId;
|
|
67
67
|
readonly name: string;
|
|
68
68
|
}
|
|
69
69
|
/**
|
|
@@ -17,6 +17,8 @@ import type { Scope } from '@deepseek-ai/dsh-scope';
|
|
|
17
17
|
import type { Session, SessionId, UserMessage } from '@deepseek-ai/dsh-session';
|
|
18
18
|
import type { Context } from '@deepseek-ai/cordis';
|
|
19
19
|
import type { ResolvedConfig } from './types.ts';
|
|
20
|
+
/** Provider route label used for logged header snapshots and message provenance. */
|
|
21
|
+
export declare const PROVIDER = "codex";
|
|
20
22
|
/** Drives one session through turn and step boundaries on Codex. */
|
|
21
23
|
export declare class CodexAgent implements Agent {
|
|
22
24
|
private loopCtx;
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* @module dsh-loop-engine/engine-codex/appserver/mapping
|
|
9
9
|
*/
|
|
10
10
|
import type { TokenUsage, ToolResultMessage } from '@deepseek-ai/dsh-llm';
|
|
11
|
-
import {
|
|
11
|
+
import { ToolCallId } from '@deepseek-ai/dsh-llm';
|
|
12
12
|
/** Map app-server turn usage to dsh TokenUsage. */
|
|
13
13
|
export declare function mapUsage(usage: {
|
|
14
14
|
inputTokens: number;
|
|
@@ -25,7 +25,7 @@ export declare function mapCommandExecution(item: {
|
|
|
25
25
|
status?: string;
|
|
26
26
|
}): {
|
|
27
27
|
call: {
|
|
28
|
-
callId:
|
|
28
|
+
callId: ToolCallId;
|
|
29
29
|
name: string;
|
|
30
30
|
arguments: string;
|
|
31
31
|
};
|
|
@@ -38,7 +38,7 @@ export declare function mapFileChange(item: {
|
|
|
38
38
|
status?: string;
|
|
39
39
|
}): {
|
|
40
40
|
call: {
|
|
41
|
-
callId:
|
|
41
|
+
callId: ToolCallId;
|
|
42
42
|
name: string;
|
|
43
43
|
arguments: string;
|
|
44
44
|
};
|
|
@@ -58,7 +58,7 @@ export declare function mapMcpToolCall(item: {
|
|
|
58
58
|
};
|
|
59
59
|
}): {
|
|
60
60
|
call: {
|
|
61
|
-
callId:
|
|
61
|
+
callId: ToolCallId;
|
|
62
62
|
name: string;
|
|
63
63
|
arguments: string;
|
|
64
64
|
};
|
|
@@ -73,12 +73,34 @@ export declare class CodexLoop extends Service implements AgentFactory {
|
|
|
73
73
|
private setupAndPublish;
|
|
74
74
|
/**
|
|
75
75
|
* Create an agent and session under one caller-supplied identity, owned by
|
|
76
|
-
* the accessing fiber.
|
|
76
|
+
* the accessing fiber. When a persistence backend is mounted, the session's
|
|
77
|
+
* durable identity is stored before publication.
|
|
77
78
|
* @param ownerCtx - caller context that structurally owns the lifecycle.
|
|
78
79
|
* @param options - identities, session seed/metadata, loop options, setup, and cancellation.
|
|
79
80
|
* @returns the published handle.
|
|
80
81
|
*/
|
|
81
82
|
createAgent(ownerCtx: Context, options: CreateAgentOptions): Promise<AgentHandle>;
|
|
83
|
+
/**
|
|
84
|
+
* Take a fresh session's write ownership when persistence is mounted.
|
|
85
|
+
* Nothing is appended here: the constructor seed (which never re-emits
|
|
86
|
+
* through `session/event`) is stored by {@link appendUnstoredSuffix} at the
|
|
87
|
+
* publication commit point, so a failed or cancelled setup closes an
|
|
88
|
+
* unmaterialized handle and leaves no stored residue — the same id can be
|
|
89
|
+
* created again.
|
|
90
|
+
* @param session - the unpublished session to store.
|
|
91
|
+
* @param signal - optional cancellation forwarded to the backend create.
|
|
92
|
+
* @returns the owned handle and stored cursor, or `undefined` without a backend.
|
|
93
|
+
*/
|
|
94
|
+
private createStoredSession;
|
|
95
|
+
/**
|
|
96
|
+
* Durably store the session events appended since the last stored cursor.
|
|
97
|
+
* Pre-publication appends (constructor seed markers, setup-window events)
|
|
98
|
+
* never re-emit through `session/event`, so publication must flush them
|
|
99
|
+
* through the handle before live events start routing into it.
|
|
100
|
+
* @param stored - the session's owned handle and stored cursor, if any.
|
|
101
|
+
* @param session - the unpublished session whose suffix is stored.
|
|
102
|
+
*/
|
|
103
|
+
private appendUnstoredSuffix;
|
|
82
104
|
/**
|
|
83
105
|
* Resume an owned agent from the configured persistence service.
|
|
84
106
|
* @param ownerCtx - caller context that owns load, setup, and the live lifecycle.
|
|
@@ -86,7 +108,7 @@ export declare class CodexLoop extends Service implements AgentFactory {
|
|
|
86
108
|
* @returns the published handle.
|
|
87
109
|
*/
|
|
88
110
|
resume(ownerCtx: Context, options: ResumeAgentOptions): Promise<AgentHandle>;
|
|
89
|
-
/** Resume through an explicit persistence
|
|
111
|
+
/** Resume through an explicit persistence service. */
|
|
90
112
|
private resumeWith;
|
|
91
113
|
}
|
|
92
114
|
//# sourceMappingURL=loop.d.ts.map
|
|
@@ -17,6 +17,8 @@ import type { Session, SessionId, UserMessage } from '@deepseek-ai/dsh-session';
|
|
|
17
17
|
import type { Context } from '@deepseek-ai/cordis';
|
|
18
18
|
import type { ResolvedConfig } from './types.ts';
|
|
19
19
|
import type { KimiSpawnCapability } from './process.ts';
|
|
20
|
+
/** Provider route label used for logged header snapshots and message provenance. */
|
|
21
|
+
export declare const PROVIDER = "kimi";
|
|
20
22
|
/** Drives one session through turn and step boundaries on Kimi Code. */
|
|
21
23
|
export declare class KimiAgent implements Agent {
|
|
22
24
|
private loopCtx;
|
|
@@ -16,6 +16,13 @@
|
|
|
16
16
|
* the goal form). `skill:` commands are already carried by the dsh skill
|
|
17
17
|
* injection seam and Kimi's own shorthand, so they are not duplicated here.
|
|
18
18
|
*
|
|
19
|
+
* `model` is deliberately absent even though the CLI has it: the dsh web
|
|
20
|
+
* client owns a `/model` contribution, and a same-named host command makes
|
|
21
|
+
* `ui-commands` throw the whole command menu source away, leaving only the
|
|
22
|
+
* skill group. `/goal` stays: the managed block disables dsh's `command-goal`
|
|
23
|
+
* row for hosted engines, so the slot is free and the CLI's own goal mode
|
|
24
|
+
* takes it over.
|
|
25
|
+
*
|
|
19
26
|
* @module dsh-loop-engine/engine-kimi/commands
|
|
20
27
|
*/
|
|
21
28
|
import type { CommandDefinition, CommandInvocation, CommandResult } from '../commands.ts';
|
|
@@ -67,12 +67,34 @@ export declare class KimiLoop extends Service implements AgentFactory {
|
|
|
67
67
|
private setupAndPublish;
|
|
68
68
|
/**
|
|
69
69
|
* Create an agent and session under one caller-supplied identity, owned by
|
|
70
|
-
* the accessing fiber.
|
|
70
|
+
* the accessing fiber. When a persistence backend is mounted, the session's
|
|
71
|
+
* durable identity is stored before publication.
|
|
71
72
|
* @param ownerCtx - caller context that structurally owns the lifecycle.
|
|
72
73
|
* @param options - identities, session seed/metadata, loop options, setup, and cancellation.
|
|
73
74
|
* @returns the published handle.
|
|
74
75
|
*/
|
|
75
76
|
createAgent(ownerCtx: Context, options: CreateAgentOptions): Promise<AgentHandle>;
|
|
77
|
+
/**
|
|
78
|
+
* Take a fresh session's write ownership when persistence is mounted.
|
|
79
|
+
* Nothing is appended here: the constructor seed (which never re-emits
|
|
80
|
+
* through `session/event`) is stored by {@link appendUnstoredSuffix} at the
|
|
81
|
+
* publication commit point, so a failed or cancelled setup closes an
|
|
82
|
+
* unmaterialized handle and leaves no stored residue — the same id can be
|
|
83
|
+
* created again.
|
|
84
|
+
* @param session - the unpublished session to store.
|
|
85
|
+
* @param signal - optional cancellation forwarded to the backend create.
|
|
86
|
+
* @returns the owned handle and stored cursor, or `undefined` without a backend.
|
|
87
|
+
*/
|
|
88
|
+
private createStoredSession;
|
|
89
|
+
/**
|
|
90
|
+
* Durably store the session events appended since the last stored cursor.
|
|
91
|
+
* Pre-publication appends (constructor seed markers, setup-window events)
|
|
92
|
+
* never re-emit through `session/event`, so publication must flush them
|
|
93
|
+
* through the handle before live events start routing into it.
|
|
94
|
+
* @param stored - the session's owned handle and stored cursor, if any.
|
|
95
|
+
* @param session - the unpublished session whose suffix is stored.
|
|
96
|
+
*/
|
|
97
|
+
private appendUnstoredSuffix;
|
|
76
98
|
/**
|
|
77
99
|
* Resume an owned agent from the configured persistence service.
|
|
78
100
|
* @param ownerCtx - caller context that owns load, setup, and the live lifecycle.
|
|
@@ -80,7 +102,7 @@ export declare class KimiLoop extends Service implements AgentFactory {
|
|
|
80
102
|
* @returns the published handle.
|
|
81
103
|
*/
|
|
82
104
|
resume(ownerCtx: Context, options: ResumeAgentOptions): Promise<AgentHandle>;
|
|
83
|
-
/** Resume through an explicit persistence
|
|
105
|
+
/** Resume through an explicit persistence service. */
|
|
84
106
|
private resumeWith;
|
|
85
107
|
}
|
|
86
108
|
//# sourceMappingURL=loop.d.ts.map
|
|
@@ -17,6 +17,8 @@ import type { Session, SessionId, UserMessage } from '@deepseek-ai/dsh-session';
|
|
|
17
17
|
import type { Context } from '@deepseek-ai/cordis';
|
|
18
18
|
import type { ResolvedConfig } from './types.ts';
|
|
19
19
|
import { type PiSpawnCapability } from './rpc/client.ts';
|
|
20
|
+
/** Provider route label used for logged header snapshots and message provenance. */
|
|
21
|
+
export declare const PROVIDER = "pi";
|
|
20
22
|
/** Drives one session through turn and step boundaries on Pi. */
|
|
21
23
|
export declare class PiAgent implements Agent {
|
|
22
24
|
private loopCtx;
|
|
@@ -77,12 +77,34 @@ export declare class PiLoop extends Service implements AgentFactory {
|
|
|
77
77
|
private setupAndPublish;
|
|
78
78
|
/**
|
|
79
79
|
* Create an agent and session under one caller-supplied identity, owned by
|
|
80
|
-
* the accessing fiber.
|
|
80
|
+
* the accessing fiber. When a persistence backend is mounted, the session's
|
|
81
|
+
* durable identity is stored before publication.
|
|
81
82
|
* @param ownerCtx - caller context that structurally owns the lifecycle.
|
|
82
83
|
* @param options - identities, session seed/metadata, loop options, setup, and cancellation.
|
|
83
84
|
* @returns the published handle.
|
|
84
85
|
*/
|
|
85
86
|
createAgent(ownerCtx: Context, options: CreateAgentOptions): Promise<AgentHandle>;
|
|
87
|
+
/**
|
|
88
|
+
* Take a fresh session's write ownership when persistence is mounted.
|
|
89
|
+
* Nothing is appended here: the constructor seed (which never re-emits
|
|
90
|
+
* through `session/event`) is stored by {@link appendUnstoredSuffix} at the
|
|
91
|
+
* publication commit point, so a failed or cancelled setup closes an
|
|
92
|
+
* unmaterialized handle and leaves no stored residue — the same id can be
|
|
93
|
+
* created again.
|
|
94
|
+
* @param session - the unpublished session to store.
|
|
95
|
+
* @param signal - optional cancellation forwarded to the backend create.
|
|
96
|
+
* @returns the owned handle and stored cursor, or `undefined` without a backend.
|
|
97
|
+
*/
|
|
98
|
+
private createStoredSession;
|
|
99
|
+
/**
|
|
100
|
+
* Durably store the session events appended since the last stored cursor.
|
|
101
|
+
* Pre-publication appends (constructor seed markers, setup-window events)
|
|
102
|
+
* never re-emit through `session/event`, so publication must flush them
|
|
103
|
+
* through the handle before live events start routing into it.
|
|
104
|
+
* @param stored - the session's owned handle and stored cursor, if any.
|
|
105
|
+
* @param session - the unpublished session whose suffix is stored.
|
|
106
|
+
*/
|
|
107
|
+
private appendUnstoredSuffix;
|
|
86
108
|
/**
|
|
87
109
|
* Resume an owned agent from the configured persistence service.
|
|
88
110
|
* @param ownerCtx - caller context that owns load, setup, and the live lifecycle.
|
|
@@ -90,7 +112,7 @@ export declare class PiLoop extends Service implements AgentFactory {
|
|
|
90
112
|
* @returns the published handle.
|
|
91
113
|
*/
|
|
92
114
|
resume(ownerCtx: Context, options: ResumeAgentOptions): Promise<AgentHandle>;
|
|
93
|
-
/** Resume through an explicit persistence
|
|
115
|
+
/** Resume through an explicit persistence service. */
|
|
94
116
|
private resumeWith;
|
|
95
117
|
}
|
|
96
118
|
//# sourceMappingURL=loop.d.ts.map
|
package/lib/types/index.d.ts
CHANGED
|
@@ -17,6 +17,22 @@
|
|
|
17
17
|
* The settings section is seeded from the block so the UI mirrors the file,
|
|
18
18
|
* and a committed settings change writes the block (only when it differs).
|
|
19
19
|
*
|
|
20
|
+
* A hosted engine also takes over the session's command and skill surface:
|
|
21
|
+
* the block disables dsh's `command-goal` row, and the plugin authors a
|
|
22
|
+
* stripped copy of the `standard` agent preset into the user preset root
|
|
23
|
+
* (see `preset.ts`) and steers the `agent-presets` roster default to it, so
|
|
24
|
+
* new sessions get the engine's commands and skills instead of the dsh-native
|
|
25
|
+
* ones an external engine cannot honor. Switching back to `in-process`
|
|
26
|
+
* restores the previous default.
|
|
27
|
+
*
|
|
28
|
+
* While a hosted engine is mounted the plugin also serves its provider route
|
|
29
|
+
* label (`claude-code` / `codex` / `pi` / `kimi`) from the llm registry with
|
|
30
|
+
* a model-less placeholder adapter (see `provider-route.ts`): the engine logs
|
|
31
|
+
* that label into each session's request/header, and the web host refuses a
|
|
32
|
+
* turn whose session selection names a provider no adapter serves — without
|
|
33
|
+
* the placeholder the second prompt of every hosted session would fail with
|
|
34
|
+
* `model-unavailable`.
|
|
35
|
+
*
|
|
20
36
|
* @module dsh-loop-engine
|
|
21
37
|
*/
|
|
22
38
|
import { Context } from '@deepseek-ai/cordis';
|
|
@@ -12,8 +12,17 @@
|
|
|
12
12
|
* # -- dsh-loop-engine managed block: claude-code --
|
|
13
13
|
* - id: agent-loop
|
|
14
14
|
* disabled: true
|
|
15
|
+
* - id: command-goal
|
|
16
|
+
* disabled: true
|
|
15
17
|
* # -- /dsh-loop-engine managed block --
|
|
16
18
|
*
|
|
19
|
+
* The `command-goal` row goes down with the loop: a hosted engine owns the
|
|
20
|
+
* session's command surface, and dsh's `/goal` would otherwise collide with
|
|
21
|
+
* an engine's own goal command (Kimi) or dangle over a goal service nothing
|
|
22
|
+
* drives (the other engines). The remaining dsh-native commands (`/export`,
|
|
23
|
+
* `/feedback`, `/permission`) are engine-agnostic session/settings controls
|
|
24
|
+
* that keep working under a hosted engine, so they stay.
|
|
25
|
+
*
|
|
17
26
|
* `in-process` renders an absent block (the base bundle's `agent-loop` row
|
|
18
27
|
* stays active and supplies the factory), so switching back removes the span
|
|
19
28
|
* entirely. Any other engine renders the same disable block, and the begin
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hosted-engine agent preset: a managed copy of the deployment's `standard`
|
|
3
|
+
* preset with the dsh-native command and skill rows stripped.
|
|
4
|
+
*
|
|
5
|
+
* A hosted engine (Claude Code, Codex, Pi, Kimi) owns its session's command
|
|
6
|
+
* and skill surface: the engine's own slash commands and skill providers are
|
|
7
|
+
* registered globally by the plugin, and the dsh-native equivalents would only
|
|
8
|
+
* duplicate or mislead — dsh `/plan` is advisory prompt text an external
|
|
9
|
+
* engine never assembles, dsh `/compact` cannot shrink a context the engine's
|
|
10
|
+
* child process holds, and dsh skills would sit next to the engine's own
|
|
11
|
+
* catalog. Those rows live inside the agent-preset composition, which a
|
|
12
|
+
* profile patch cannot reach, so the plugin authors a stripped preset into the
|
|
13
|
+
* user preset root (`$DSH_HOME/.agent-presets/<id>`) and steers the roster's
|
|
14
|
+
* default at runtime (see the plugin's apply).
|
|
15
|
+
*
|
|
16
|
+
* The preset is REGENERATED from the current `standard` composition on every
|
|
17
|
+
* boot that needs it: text on disk is never authoritative, so a harness
|
|
18
|
+
* upgrade that changes `standard` flows through. The file is plain YAML the
|
|
19
|
+
* loader already accepts — the strip is a line transform that preserves
|
|
20
|
+
* everything it does not drop byte for byte, comments included.
|
|
21
|
+
*
|
|
22
|
+
* @module dsh-loop-engine/preset
|
|
23
|
+
*/
|
|
24
|
+
/** Preset id the plugin authors into the user preset root. */
|
|
25
|
+
export declare const HOSTED_PRESET_ID = "loop-engine";
|
|
26
|
+
/** Harness-home-relative directory of locally authored presets (mirrors `USER_PRESET_DIR` in `dsh-agent-presets`). */
|
|
27
|
+
export declare const USER_PRESET_DIR = ".agent-presets";
|
|
28
|
+
/** The composition file that makes a directory a preset. */
|
|
29
|
+
export declare const COMPOSITION_FILE = "agent.cordis.yml";
|
|
30
|
+
/** The display-metadata file beside a preset's composition. */
|
|
31
|
+
export declare const METADATA_FILE = "preset.yml";
|
|
32
|
+
/** Source preset the hosted preset derives from. */
|
|
33
|
+
export declare const SOURCE_PRESET_ID = "standard";
|
|
34
|
+
/**
|
|
35
|
+
* Top-level rows stripped from the source preset for hosted engines:
|
|
36
|
+
* - `skill-filesystem` / `tool-skill`: the dsh skill surface — each engine
|
|
37
|
+
* registers its own skill provider globally;
|
|
38
|
+
* - `tool-goal`: the model-facing goal tool — the managed block already
|
|
39
|
+
* disables dsh's `/goal` command for hosted engines;
|
|
40
|
+
* - `planning`: dsh plan mode — its only model-visible effect is a system
|
|
41
|
+
* prompt section an external engine never assembles;
|
|
42
|
+
* - `compaction`: dsh `/compact` and auto-compaction — a hosted engine owns
|
|
43
|
+
* its context and its own `/compact` (Claude, Kimi).
|
|
44
|
+
*/
|
|
45
|
+
export declare const STRIPPED_ROWS: readonly ["skill-filesystem", "tool-skill", "tool-goal", "planning", "compaction"];
|
|
46
|
+
/**
|
|
47
|
+
* Remove top-level entries by id from a preset composition, preserving every
|
|
48
|
+
* other byte. Each entry owns the comment/blank run directly above its opener
|
|
49
|
+
* — that run is the entry's section heading and drops with it — except the
|
|
50
|
+
* run above the FIRST entry, which is the file header and stays. Entries
|
|
51
|
+
* without an `id` opener are always kept: the transform touches only what it
|
|
52
|
+
* can name.
|
|
53
|
+
* @param text - the source composition.
|
|
54
|
+
* @param ids - top-level row ids to strip.
|
|
55
|
+
* @returns the stripped composition.
|
|
56
|
+
*/
|
|
57
|
+
export declare function stripPresetRows(text: string, ids?: readonly string[]): string;
|
|
58
|
+
/** Minimal read seam over the host's preset roster (`AgentPresets.read`). */
|
|
59
|
+
export interface PresetCompositionSource {
|
|
60
|
+
/** Read one preset's composition text; throws when the id is unknown. */
|
|
61
|
+
read(id: string): Promise<string>;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Regenerate the hosted-engine preset under the dsh home's user preset root
|
|
65
|
+
* from the roster's `standard` preset. Idempotent: an up-to-date directory is
|
|
66
|
+
* untouched, so no standing mount sees a spurious file-stamp change.
|
|
67
|
+
* @param dshHome - the resolved harness home.
|
|
68
|
+
* @param source - the roster's composition reader.
|
|
69
|
+
* @returns whether any file was written.
|
|
70
|
+
* @throws when the source preset cannot be read or the writes fail.
|
|
71
|
+
*/
|
|
72
|
+
export declare function ensureHostedPreset(dshHome: string, source: PresetCompositionSource): Promise<boolean>;
|
|
73
|
+
//# sourceMappingURL=preset.d.ts.map
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hosted-engine provider route placeholders.
|
|
3
|
+
*
|
|
4
|
+
* Every hosted engine logs its sessions' request/header with its own provider
|
|
5
|
+
* label (`claude-code`, `codex`, `pi`, `kimi`) rather than a model endpoint the
|
|
6
|
+
* harness llm registry serves — the engine owns its model natively. The web
|
|
7
|
+
* host derives a session's model selection from that header and refuses a turn
|
|
8
|
+
* whose provider no registered adapter serves, so without a placeholder route
|
|
9
|
+
* the SECOND prompt of every hosted session fails with `model-unavailable`.
|
|
10
|
+
* The placeholder serves the label while advertising no models; catalog groups
|
|
11
|
+
* that advertise nothing are dropped, so the model picker is unchanged.
|
|
12
|
+
*
|
|
13
|
+
* @module dsh-loop-engine/provider-route
|
|
14
|
+
*/
|
|
15
|
+
import type { GenerateOptions, StreamChunk } from '@deepseek-ai/dsh-llm';
|
|
16
|
+
import { LlmAdapter } from '@deepseek-ai/dsh-llm';
|
|
17
|
+
import type { LoopEngineId } from './settings.ts';
|
|
18
|
+
/** Provider route label each hosted engine logs into its sessions' request/header. */
|
|
19
|
+
export declare const HOSTED_PROVIDER_ROUTES: Readonly<Record<Exclude<LoopEngineId, 'in-process'>, string>>;
|
|
20
|
+
/**
|
|
21
|
+
* Placeholder adapter serving one hosted engine's provider route label. It
|
|
22
|
+
* inherits the empty catalog and default metadata (the engine's model is not a
|
|
23
|
+
* harness-selectable endpoint), and {@link stream} fails loud: a call reaching
|
|
24
|
+
* it means a real model query was routed to an engine that owns its model
|
|
25
|
+
* natively — a wiring bug, not a request to serve.
|
|
26
|
+
*/
|
|
27
|
+
export declare class HostedEngineRouteAdapter extends LlmAdapter {
|
|
28
|
+
private readonly label;
|
|
29
|
+
/**
|
|
30
|
+
* @param label - the provider route label this placeholder serves.
|
|
31
|
+
*/
|
|
32
|
+
constructor(label: string);
|
|
33
|
+
stream(_options: GenerateOptions): AsyncIterable<StreamChunk>;
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=provider-route.d.ts.map
|
package/lib/types/settings.d.ts
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
* Shared loop-engine identity, namespace, and schema.
|
|
3
3
|
*
|
|
4
4
|
* The namespace literal lives in the zero-import `./namespace.ts` so both
|
|
5
|
-
* halves agree on the section name: the node half brands it
|
|
6
|
-
* `
|
|
7
|
-
*
|
|
8
|
-
*
|
|
5
|
+
* halves agree on the section name: the node half brands it as a
|
|
6
|
+
* `SettingsNamespace`, while the browser half imports the same literal
|
|
7
|
+
* without pulling the host-side `dsh-settings` service into the client
|
|
8
|
+
* bundle (cross-plugin value imports go through cordis services, and
|
|
9
9
|
* `settings-scope.ts` follows the same discipline).
|
|
10
10
|
*
|
|
11
11
|
* @module dsh-loop-engine/settings
|
|
@@ -26,6 +26,6 @@ export interface LoopEngineSettings {
|
|
|
26
26
|
}
|
|
27
27
|
/** Schema of the loop engine settings section. */
|
|
28
28
|
export declare const LOOP_ENGINE_SETTINGS_SCHEMA: z<LoopEngineSettings>;
|
|
29
|
-
/**
|
|
29
|
+
/** The shared literal branded as a settings namespace on the node side. */
|
|
30
30
|
export declare function loopEngineSettingsNamespace(): SettingsNamespace;
|
|
31
31
|
//# sourceMappingURL=settings.d.ts.map
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-loop-engine",
|
|
3
3
|
"description": "Web-switchable agent loop engine selection for the DeepSeek Harness - out-of-tree plugin (Claude Code / Codex / Pi / Kimi Code drivers) maintained by @kuun993, zero main-repo changes",
|
|
4
|
-
"version": "1.0.0-
|
|
4
|
+
"version": "1.0.0-rc8",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -46,14 +46,13 @@
|
|
|
46
46
|
"client": {
|
|
47
47
|
"inject": [
|
|
48
48
|
"@deepseek-ai/dsh-client-locale",
|
|
49
|
-
"@deepseek-ai/dsh-client-runtime",
|
|
50
49
|
"@deepseek-ai/dsh-client-ui-settings",
|
|
51
50
|
"@deepseek-ai/dsh-api-remotes"
|
|
52
51
|
],
|
|
53
52
|
"platform": "web",
|
|
54
53
|
"external": [
|
|
55
54
|
"@deepseek-ai/dsh-client-locale/client",
|
|
56
|
-
"@deepseek-ai/dsh-client-
|
|
55
|
+
"@deepseek-ai/dsh-client-store",
|
|
57
56
|
"@deepseek-ai/dsh-client-ui-settings/client",
|
|
58
57
|
"@deepseek-ai/dsh-api-remotes/client",
|
|
59
58
|
"@deepseek-ai/dsh-settings/types"
|
|
@@ -69,28 +68,29 @@
|
|
|
69
68
|
},
|
|
70
69
|
"peerDependencies": {
|
|
71
70
|
"@deepseek-ai/cordis": "^4.0.1",
|
|
72
|
-
"@deepseek-ai/dsh-agent": "0.1.
|
|
73
|
-
"@deepseek-ai/dsh-invariants": "0.1.
|
|
74
|
-
"@deepseek-ai/dsh-llm": "0.1.
|
|
75
|
-
"@deepseek-ai/dsh-scope": "0.1.
|
|
76
|
-
"@deepseek-ai/dsh-session": "0.1.
|
|
77
|
-
"@deepseek-ai/dsh-session-persistence": "0.1.
|
|
78
|
-
"@deepseek-ai/dsh-settings": "0.1.
|
|
79
|
-
"@deepseek-ai/dsh-subprocess": "0.1.
|
|
80
|
-
"@deepseek-ai/dsh-timeout": "0.1.
|
|
71
|
+
"@deepseek-ai/dsh-agent": "0.1.2-rc.1",
|
|
72
|
+
"@deepseek-ai/dsh-invariants": "0.1.2-rc.1",
|
|
73
|
+
"@deepseek-ai/dsh-llm": "0.1.2-rc.1",
|
|
74
|
+
"@deepseek-ai/dsh-scope": "0.1.2-rc.1",
|
|
75
|
+
"@deepseek-ai/dsh-session": "0.1.2-rc.1",
|
|
76
|
+
"@deepseek-ai/dsh-session-persistence": "0.1.2-rc.1",
|
|
77
|
+
"@deepseek-ai/dsh-settings": "0.1.2-rc.1",
|
|
78
|
+
"@deepseek-ai/dsh-subprocess": "0.1.2-rc.1",
|
|
79
|
+
"@deepseek-ai/dsh-timeout": "0.1.2-rc.1"
|
|
81
80
|
},
|
|
82
81
|
"devDependencies": {
|
|
83
|
-
"@deepseek-ai/dsh-attachment": "0.1.
|
|
84
|
-
"@deepseek-ai/dsh-client-locale": "0.1.
|
|
85
|
-
"@deepseek-ai/dsh-client-
|
|
86
|
-
"@deepseek-ai/dsh-client-ui-
|
|
87
|
-
"@deepseek-ai/dsh-client-ui-
|
|
88
|
-
"@deepseek-ai/dsh-client-ui-
|
|
89
|
-
"@deepseek-ai/dsh-client-ui-
|
|
90
|
-
"@deepseek-ai/dsh-
|
|
91
|
-
"@deepseek-ai/dsh-
|
|
92
|
-
"@deepseek-ai/dsh-
|
|
93
|
-
"@deepseek-ai/dsh-
|
|
82
|
+
"@deepseek-ai/dsh-attachment": "0.1.2-rc.1",
|
|
83
|
+
"@deepseek-ai/dsh-client-locale": "0.1.2-rc.1",
|
|
84
|
+
"@deepseek-ai/dsh-client-store": "0.1.2-rc.1",
|
|
85
|
+
"@deepseek-ai/dsh-client-ui-renderer": "0.1.2-rc.1",
|
|
86
|
+
"@deepseek-ai/dsh-client-ui-conversation": "0.1.2-rc.1",
|
|
87
|
+
"@deepseek-ai/dsh-client-ui-primitives": "0.1.2-rc.1",
|
|
88
|
+
"@deepseek-ai/dsh-client-ui-settings": "0.1.2-rc.1",
|
|
89
|
+
"@deepseek-ai/dsh-client-ui-slots": "0.1.2-rc.1",
|
|
90
|
+
"@deepseek-ai/dsh-home-paths": "0.1.2-rc.1",
|
|
91
|
+
"@deepseek-ai/dsh-session-persistence-jsonl": "0.1.2-rc.1",
|
|
92
|
+
"@deepseek-ai/dsh-subprocess-local": "0.1.2-rc.1",
|
|
93
|
+
"@deepseek-ai/dsh-system-prompt": "0.1.2-rc.1",
|
|
94
94
|
"@types/node": "^22.20.0",
|
|
95
95
|
"@types/react": "^19.0.0",
|
|
96
96
|
"@vitest/coverage-v8": "^4.1.8",
|