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/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-runtime/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-runtime/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-runtime/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/dsh-client-runtime/client';
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, SnapshotStore } from '@deepseek-ai/dsh-client-runtime/client';
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 handle. */
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 { CallId, type ContentBlock, type StreamChunk, type TokenUsage, type ToolResultMessage } from '@deepseek-ai/dsh-llm';
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: 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: 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 { CallId } from '@deepseek-ai/dsh-llm';
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: 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: 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: 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 handle. */
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 handle. */
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 handle. */
115
+ /** Resume through an explicit persistence service. */
94
116
  private resumeWith;
95
117
  }
96
118
  //# sourceMappingURL=loop.d.ts.map
@@ -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
@@ -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 through
6
- * `settingsNamespace()` (a runtime value), while the browser half imports the
7
- * same literal without pulling the host-side `dsh-settings` service into the
8
- * client bundle (cross-plugin value imports go through cordis services, and
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
- /** Brand the shared literal through the settings API on the node side. */
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-rc7",
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-runtime/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.1-rc.2",
73
- "@deepseek-ai/dsh-invariants": "0.1.1-rc.2",
74
- "@deepseek-ai/dsh-llm": "0.1.1-rc.2",
75
- "@deepseek-ai/dsh-scope": "0.1.1-rc.2",
76
- "@deepseek-ai/dsh-session": "0.1.1-rc.2",
77
- "@deepseek-ai/dsh-session-persistence": "0.1.1-rc.2",
78
- "@deepseek-ai/dsh-settings": "0.1.1-rc.2",
79
- "@deepseek-ai/dsh-subprocess": "0.1.1-rc.2",
80
- "@deepseek-ai/dsh-timeout": "0.1.1-rc.2"
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.1-rc.2",
84
- "@deepseek-ai/dsh-client-locale": "0.1.1-rc.2",
85
- "@deepseek-ai/dsh-client-runtime": "0.1.1-rc.2",
86
- "@deepseek-ai/dsh-client-ui-conversation": "0.1.1-rc.2",
87
- "@deepseek-ai/dsh-client-ui-primitives": "0.1.1-rc.2",
88
- "@deepseek-ai/dsh-client-ui-settings": "0.1.1-rc.2",
89
- "@deepseek-ai/dsh-client-ui-slots": "0.1.1-rc.2",
90
- "@deepseek-ai/dsh-home-paths": "0.1.1-rc.2",
91
- "@deepseek-ai/dsh-session-persistence-jsonl": "0.1.1-rc.2",
92
- "@deepseek-ai/dsh-subprocess-local": "0.1.1-rc.2",
93
- "@deepseek-ai/dsh-system-prompt": "0.1.1-rc.2",
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",