dsh-loop-engine 0.1.5-rc4 → 0.1.7-rc1
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 +1 -1
- package/README.zh.md +1 -1
- package/lib/client.js +174 -76
- package/lib/index.js +136 -57
- package/lib/invariant.js +8 -0
- package/lib/types/client/index.d.ts +16 -6
- package/lib/types/client/session-engine.d.ts +40 -6
- package/lib/types/client/store.d.ts +53 -18
- package/lib/types/client/turn-status.d.ts +27 -6
- package/lib/types/client/use-session-engine.d.ts +12 -4
- package/lib/types/compat.d.ts +25 -0
- package/lib/types/driver-core/host-servers.d.ts +6 -2
- package/lib/types/driver-core/hosted-engine-runtime.d.ts +3 -3
- package/lib/types/driver-core/model-handover.d.ts +22 -4
- package/lib/types/driver-core/system-head.d.ts +43 -0
- package/lib/types/engine-codex/model-handover.d.ts +21 -9
- package/lib/types/engine-pi/model-handover.d.ts +4 -0
- package/lib/types/index.d.ts +25 -3
- package/lib/types/namespace.d.ts +20 -4
- package/lib/types/preset.d.ts +7 -3
- package/lib/types/settings.d.ts +31 -11
- package/package.json +27 -27
|
@@ -20,8 +20,8 @@
|
|
|
20
20
|
* default, a session running pi included.
|
|
21
21
|
*
|
|
22
22
|
* The reflection's SUBJECT is still a document-level attribute rather than the
|
|
23
|
-
* row's own element: the sheet has to reach a class the harness hashes
|
|
24
|
-
*
|
|
23
|
+
* row's own element: the sheet has to reach a class the harness hashes (see
|
|
24
|
+
* {@link ROW_SELECTORS}), which takes an attribute selector on an ancestor,
|
|
25
25
|
* and the row offers no session-scoped hook for a plugin to hang it on. A
|
|
26
26
|
* document-level attribute has exactly ONE owner at a time, though — and on this
|
|
27
27
|
* page the WRITERS outnumber the reader: the chip and the composer of every
|
|
@@ -47,10 +47,24 @@
|
|
|
47
47
|
* paints by it, and a leftover attribute is inert on a page whose turn-status row
|
|
48
48
|
* is not rendered.
|
|
49
49
|
*
|
|
50
|
+
* The paint is also gated on the session being MID-TURN, through a second
|
|
51
|
+
* document-level attribute ({@link RUNNING_ATTR}, written from the same
|
|
52
|
+
* reflection). On the 0.1.5 line the row only exists while a turn is in flight,
|
|
53
|
+
* so the engine attribute alone was enough; on the 0.1.7 line that same button
|
|
54
|
+
* stays on screen after the turn ends, as the collapsed summary that reads
|
|
55
|
+
* "用时 4秒" — an engine-only gate leaves the glyph and the sweep animating on a
|
|
56
|
+
* finished turn, which is not what the live line means. The gate is a surface's
|
|
57
|
+
* own answer (`session.running`, which every session-scoped seat receives), so a
|
|
58
|
+
* surface that cannot answer passes nothing and leaves it alone rather than
|
|
59
|
+
* guessing.
|
|
60
|
+
*
|
|
50
61
|
* Three facts about the harness markup make that safe and specific:
|
|
51
|
-
* - the row
|
|
52
|
-
*
|
|
53
|
-
* `
|
|
62
|
+
* - the row has one stable handle per harness generation — an
|
|
63
|
+
* `[hash]_turnStatus` class suffix on the 0.1.5 line, and, on the 0.1.7
|
|
64
|
+
* line, the `data-turn-process` button whose text is a `<span>` whose hashed
|
|
65
|
+
* class ends `_label` — so each generation gets its own copy of the sheet
|
|
66
|
+
* ({@link ROW_SELECTORS}) and the one the running app renders matches while
|
|
67
|
+
* the other stays inert;
|
|
54
68
|
* - its gradient paints through the `--dsw-static-deepseek-*` custom
|
|
55
69
|
* properties, so recoloring is a variable override rather than a fight
|
|
56
70
|
* over `background` and `background-clip`;
|
|
@@ -93,6 +107,11 @@ import type { LoopEngineId } from '../agent-preset-ids.ts';
|
|
|
93
107
|
* clears the attribute, because the sibling surface of the same session is still
|
|
94
108
|
* on screen painting through it.
|
|
95
109
|
*
|
|
110
|
+
* The MID-TURN gate is written from here as well, but only by a surface that can
|
|
111
|
+
* answer it (`running` given): the sheet is gated on both, because the 0.1.7 row
|
|
112
|
+
* outlives its turn, and a surface with no answer must leave the gate as the
|
|
113
|
+
* surface that has one left it rather than guess.
|
|
114
|
+
*
|
|
96
115
|
* The NO-OP covers the late reflection as well — the one from the session the
|
|
97
116
|
* user has just left, whose own answer landing after the switch used to paint
|
|
98
117
|
* over the session that replaced it.
|
|
@@ -101,8 +120,10 @@ import type { LoopEngineId } from '../agent-preset-ids.ts';
|
|
|
101
120
|
* row): such a page has nothing to say about the row, so nothing is written and
|
|
102
121
|
* nothing is withdrawn — it leaves the row it found alone.
|
|
103
122
|
* @param engine - the engine that session runs, when it is known.
|
|
123
|
+
* @param running - whether that session is mid-turn, when the surface knows;
|
|
124
|
+
* omitted by a surface with no answer, which leaves the gate alone.
|
|
104
125
|
*/
|
|
105
|
-
export declare function reflectTurnStatusEngine(sessionId: string | undefined, engine: LoopEngineId | undefined): void;
|
|
126
|
+
export declare function reflectTurnStatusEngine(sessionId: string | undefined, engine: LoopEngineId | undefined, running?: boolean): void;
|
|
106
127
|
/**
|
|
107
128
|
* Declare which session's surfaces are on screen — the row's one subject.
|
|
108
129
|
*
|
|
@@ -55,12 +55,20 @@ import type { SessionEngineCache } from './session-engine.ts';
|
|
|
55
55
|
*
|
|
56
56
|
* One effect does the whole thing, so the three steps cannot come apart: declare
|
|
57
57
|
* this session as the row's subject (`focusTurnStatusSession`), reflect its
|
|
58
|
-
* engine by that declaration (`reflectTurnStatusEngine`),
|
|
59
|
-
* declaration when this surface goes away
|
|
60
|
-
* withdraws it only while it is still this
|
|
58
|
+
* engine and its mid-turn gate by that declaration (`reflectTurnStatusEngine`),
|
|
59
|
+
* and release the declaration when this surface goes away
|
|
60
|
+
* (`blurTurnStatusSession`, which withdraws it only while it is still this
|
|
61
|
+
* session's).
|
|
62
|
+
*
|
|
63
|
+
* `running` is the session's own live state (`session.running`, from the
|
|
64
|
+
* session-scoped standard kit) and it is part of the effect's key: the 0.1.7 row
|
|
65
|
+
* stays on screen after the turn ends, so the paint has to come off when the turn
|
|
66
|
+
* does — a surface that does not know the state passes nothing and leaves the
|
|
67
|
+
* gate alone.
|
|
61
68
|
* @param cache - the cache the plugin mounted.
|
|
62
69
|
* @param sessionId - the session to follow, or undefined off a session scope.
|
|
70
|
+
* @param running - whether that session is mid-turn, when the surface knows.
|
|
63
71
|
* @returns the engine report, or undefined while it is unknown.
|
|
64
72
|
*/
|
|
65
|
-
export declare function useEngineOfSession(cache: SessionEngineCache, sessionId: string | undefined): SessionEngineReport | undefined;
|
|
73
|
+
export declare function useEngineOfSession(cache: SessionEngineCache, sessionId: string | undefined, running?: boolean): SessionEngineReport | undefined;
|
|
66
74
|
//# sourceMappingURL=use-session-engine.d.ts.map
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime harness-generation probe. One released build must serve the 0.1.5
|
|
3
|
+
* line (`0.1.5-rc.1` … `0.1.5-rc.3`, all sharing the OLD settings API) and the
|
|
4
|
+
* 0.1.7 line (`0.1.7-rc.1`), which rewrote the settings host and client and
|
|
5
|
+
* turned the agent-creation announcement async. The differences are not
|
|
6
|
+
* version strings but API SHAPES, so the switch is a structural probe of the
|
|
7
|
+
* imported module rather than a semver parse: `@deepseek-ai/dsh-settings`
|
|
8
|
+
* exported a named `SettingsProvider` class on the 0.1.5 line, and the 0.1.7
|
|
9
|
+
* rewrite deleted it in favour of `SettingsForms` plus per-entry volatile
|
|
10
|
+
* Config fields.
|
|
11
|
+
*
|
|
12
|
+
* The probe resolves to whichever `@deepseek-ai/dsh-settings` the running
|
|
13
|
+
* profile actually provides. It is host-side only: the browser bundle must not
|
|
14
|
+
* import host packages, so `src/client/*` never imports this module.
|
|
15
|
+
*
|
|
16
|
+
* @module dsh-loop-engine/compat
|
|
17
|
+
*/
|
|
18
|
+
/**
|
|
19
|
+
* Whether the running harness predates the profile-backed settings rewrite
|
|
20
|
+
* (the 0.1.5 line). `true` selects the legacy settings host/client, the
|
|
21
|
+
* synchronous agent-creation announcement, and the legacy tool-result message
|
|
22
|
+
* introspection.
|
|
23
|
+
*/
|
|
24
|
+
export declare const LEGACY_HARNESS: boolean;
|
|
25
|
+
//# sourceMappingURL=compat.d.ts.map
|
|
@@ -30,8 +30,12 @@ export interface SkillsService {
|
|
|
30
30
|
export interface AgentPresetsService {
|
|
31
31
|
/** The effective default preset id. */
|
|
32
32
|
readonly defaultId: string;
|
|
33
|
-
/**
|
|
34
|
-
read(id: string): Promise<string>;
|
|
33
|
+
/** 0.1.5 line: read one preset's composition text directly. */
|
|
34
|
+
read?(id: string): Promise<string>;
|
|
35
|
+
/** 0.1.7 line: read one preset's document; its `content` is the composition text. */
|
|
36
|
+
readDocument?(id: string): Promise<{
|
|
37
|
+
readonly content: string;
|
|
38
|
+
}>;
|
|
35
39
|
}
|
|
36
40
|
/** The host settings service's mutation seam, as this plugin uses it. */
|
|
37
41
|
export interface SettingsMutator {
|
|
@@ -91,9 +91,9 @@ export interface SwapAgentOptions {
|
|
|
91
91
|
*
|
|
92
92
|
* Creation and resume follow the registry factory contract and the shared
|
|
93
93
|
* publication transaction: prepare, run setup, then publish through both
|
|
94
|
-
* registries
|
|
95
|
-
* same transaction onto a session another agent entered, which is
|
|
96
|
-
* difference between taking a session over and owning it from birth.
|
|
94
|
+
* registries and await the serial `agent/created` announcement. {@link swap}
|
|
95
|
+
* follows the same transaction onto a session another agent entered, which is
|
|
96
|
+
* the only difference between taking a session over and owning it from birth.
|
|
97
97
|
*/
|
|
98
98
|
export declare abstract class HostedEngineRuntime<TConfig, TAgent extends HostedAgent> implements AgentFactory {
|
|
99
99
|
/** Validated configuration owned by this engine instance. */
|
|
@@ -32,6 +32,11 @@
|
|
|
32
32
|
* and never a guess. The warning names the provider and the model, never a
|
|
33
33
|
* credential.
|
|
34
34
|
*
|
|
35
|
+
* What counts as "recognized" is deliberately narrow: a non-empty `baseURL` and
|
|
36
|
+
* a resolvable credential. The wire protocol is handed over when the deployment
|
|
37
|
+
* declares one, but its absence does NOT refuse the handover — see
|
|
38
|
+
* {@link resolveModelHandover} and {@link SHIPPED_ROUTE_APIS}.
|
|
39
|
+
*
|
|
35
40
|
* @module dsh-loop-engine/driver-core/model-handover
|
|
36
41
|
*/
|
|
37
42
|
import type { Context } from '@deepseek-ai/cordis';
|
|
@@ -54,8 +59,13 @@ export interface DshModelHandover {
|
|
|
54
59
|
readonly model: string;
|
|
55
60
|
/** Endpoint base as dsh configured it. */
|
|
56
61
|
readonly baseURL: string;
|
|
57
|
-
/**
|
|
58
|
-
|
|
62
|
+
/**
|
|
63
|
+
* dsh's wire protocol name for this endpoint, when the deployment declares
|
|
64
|
+
* one (or {@link SHIPPED_ROUTE_APIS} knows it for a shipped route). `undefined`
|
|
65
|
+
* is a normal answer, not a failure: engines that need a protocol degrade the
|
|
66
|
+
* way each one documents, and engines that do not (`claude-code`) ignore it.
|
|
67
|
+
*/
|
|
68
|
+
readonly api: string | undefined;
|
|
59
69
|
/** The resolved credential value; never logged, never evented. */
|
|
60
70
|
readonly apiKey: string;
|
|
61
71
|
}
|
|
@@ -102,8 +112,16 @@ export interface CredentialsService {
|
|
|
102
112
|
* `undefined` is the answer in exactly two situations: the selection names no
|
|
103
113
|
* real dsh model ({@link SessionModelOverride} is already `undefined` for the
|
|
104
114
|
* hosted seat), or a real model whose endpoint/credential dsh does not disclose
|
|
105
|
-
* to this read
|
|
106
|
-
* operator can see and fix, not a silent downgrade.
|
|
115
|
+
* to this read — no `baseURL`, or no credential. Both warn once: they are
|
|
116
|
+
* deployment-shape gaps the operator can see and fix, not a silent downgrade.
|
|
117
|
+
*
|
|
118
|
+
* The wire protocol is NOT such a gate. A profile that names no `api` still
|
|
119
|
+
* hands over its endpoint (with `api: undefined`), because refusing would let
|
|
120
|
+
* the engine send dsh's model id to the engine's OWN endpoint — a failure that
|
|
121
|
+
* reads like an auth or model problem while the real one is "wrong endpoint".
|
|
122
|
+
* Shipped routes whose adapter owns the wire are named in
|
|
123
|
+
* {@link SHIPPED_ROUTE_APIS} so they hand over a real protocol; anything still
|
|
124
|
+
* unknown degrades per engine, which is the engine's call to make.
|
|
107
125
|
*
|
|
108
126
|
* Called fresh on every step by each driver, so a model or provider picked
|
|
109
127
|
* mid-conversation reaches the engine's next request rather than being frozen
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Give a session started on a hosted engine the protected system head the
|
|
3
|
+
* harness's own loop would have logged.
|
|
4
|
+
*
|
|
5
|
+
* The harness loop logs the rendered system prompt as a `system/message` on a
|
|
6
|
+
* session's first step (`packages/core/agent-loop/src/agent.ts`:
|
|
7
|
+
* `systemPrompt.project` → `session.append('system/message', …)`). A hosted
|
|
8
|
+
* engine's external CLI owns its own system prompt, so these drivers log no dsh
|
|
9
|
+
* system message at all: a session that STARTS on a hosted engine has no surface
|
|
10
|
+
* head, and if it is later served by the in-process loop the harness logs its
|
|
11
|
+
* system message MID-log. Session format v4 requires the system message — when
|
|
12
|
+
* one exists — to be the FIRST surface event, so such a mixed session is refused
|
|
13
|
+
* on the v3→v4 migration (`packages/session/session-format-v3-to-v4/src/
|
|
14
|
+
* relationships.ts` `foldSurface`: "system/message requires a protected first
|
|
15
|
+
* surface head").
|
|
16
|
+
*
|
|
17
|
+
* Appending an EMPTY system message as the session's first surface event closes
|
|
18
|
+
* that hole: the head is protected from the start (a later in-process system
|
|
19
|
+
* message REPLACES it rather than arriving misplaced), and empty content is
|
|
20
|
+
* dropped from the derived history (`deriveEventMessage` yields `null`), so no
|
|
21
|
+
* system prompt is injected into what the engine is handed — the drivers build
|
|
22
|
+
* their prompt from `serializeHistory`, which ignores the `system` role too.
|
|
23
|
+
*
|
|
24
|
+
* Conservative and idempotent: it appends ONLY while the session has no surface
|
|
25
|
+
* event of its own, so a session the harness loop created (or one already
|
|
26
|
+
* carrying history) is left exactly as it is. A mid-surface system head would be
|
|
27
|
+
* refused by the SAME v4 rule and is never produced here.
|
|
28
|
+
*
|
|
29
|
+
* @module dsh-loop-engine/driver-core/system-head
|
|
30
|
+
*/
|
|
31
|
+
import type { Session } from '@deepseek-ai/dsh-session';
|
|
32
|
+
/**
|
|
33
|
+
* Append an empty `system/message` head when the session has no surface event
|
|
34
|
+
* yet, so a hosted-engine session carries the protected head format v4 expects.
|
|
35
|
+
*
|
|
36
|
+
* A no-op once any surface event exists: the head can only ever be the FIRST
|
|
37
|
+
* surface event, and a later one would be refused on migration.
|
|
38
|
+
* @param session - the session a hosted driver is about to run a step on.
|
|
39
|
+
* @param turn - the open turn's number.
|
|
40
|
+
* @param step - the open step's number.
|
|
41
|
+
*/
|
|
42
|
+
export declare function appendSystemHeadIfMissing(session: Session, turn: number, step: number): void;
|
|
43
|
+
//# sourceMappingURL=system-head.d.ts.map
|
|
@@ -3,17 +3,28 @@
|
|
|
3
3
|
* overrides and environment that point it at dsh's model.
|
|
4
4
|
*
|
|
5
5
|
* Codex resolves a custom endpoint through `model_providers.<id>` in its own
|
|
6
|
-
* `config.toml` (`base_url`, `wire_api`, and an `env_key` naming the
|
|
7
|
-
* the credential is read from), and `codex app-server` accepts those as
|
|
8
|
-
* key=value` overrides — so the handover needs no edit of `~/.codex`. The
|
|
6
|
+
* `config.toml` (`name`, `base_url`, `wire_api`, and an `env_key` naming the
|
|
7
|
+
* variable the credential is read from), and `codex app-server` accepts those as
|
|
8
|
+
* `-c key=value` overrides — so the handover needs no edit of `~/.codex`. The
|
|
9
9
|
* credential travels in the child's environment under {@link CODEX_DSH_API_KEY_ENV},
|
|
10
10
|
* which the `env_key` names.
|
|
11
11
|
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
12
|
+
* `name` is not optional in practice even though the CLI's own docs describe it
|
|
13
|
+
* as display metadata: codex 0.149.1 (the version this plugin pins) refuses to
|
|
14
|
+
* load a provider whose `name` is empty — "provider name must not be empty in
|
|
15
|
+
* `model_providers`" — and that config error kills `app-server` on startup, which
|
|
16
|
+
* the driver can only report as "process exited unexpectedly". Omitting it looked
|
|
17
|
+
* correct and failed before any request was ever sent, so every override this
|
|
18
|
+
* module builds carries it (verified against the pinned binary).
|
|
19
|
+
*
|
|
20
|
+
* Codex speaks only OpenAI's `responses` wire as of the version this plugin pins
|
|
21
|
+
* (0.149.1 dropped `chat`). A dsh protocol with no codex equivalent (Anthropic
|
|
22
|
+
* Messages, and now OpenAI Chat Completions) is NOT guessed: `wire_api` is
|
|
23
|
+
* omitted, so codex falls back to its own default wire and fails loud on the
|
|
24
|
+
* request — the honest outcome, since the plugin cannot make codex speak a
|
|
25
|
+
* protocol it does not implement. That default is `responses` as of 0.149.1: the
|
|
26
|
+
* request lands on `<baseURL>/responses`, which an Anthropic Messages or Chat
|
|
27
|
+
* Completions endpoint does not serve.
|
|
17
28
|
*
|
|
18
29
|
* @module dsh-loop-engine/engine-codex/model-handover
|
|
19
30
|
*/
|
|
@@ -36,7 +47,8 @@ export interface CodexModelConfig {
|
|
|
36
47
|
* The provider id ({@link CODEX_DSH_PROVIDER}) is a plugin-owned name: it exists
|
|
37
48
|
* only in this child's command line, so it cannot collide with a provider the
|
|
38
49
|
* user configured, and the model itself is still handed over as the thread's own
|
|
39
|
-
* `model` param.
|
|
50
|
+
* `model` param. The provider's `name` repeats that id because codex rejects an
|
|
51
|
+
* empty one at config load, before any request is made.
|
|
40
52
|
* @param handover - the resolved dsh endpoint for the session's selection.
|
|
41
53
|
* @returns the argv entries and environment to spawn the app-server with.
|
|
42
54
|
*/
|
|
@@ -17,6 +17,10 @@
|
|
|
17
17
|
* user's own `~/.pi` skills/auth/theme. That is the trade the deployment makes
|
|
18
18
|
* by selecting a real dsh model on pi.
|
|
19
19
|
*
|
|
20
|
+
* pi's provider schema requires a wire protocol (`api`), so this is the one
|
|
21
|
+
* engine that cannot express a handover without one; the driver drops such a
|
|
22
|
+
* handover before it reaches here instead of writing a file pi rejects.
|
|
23
|
+
*
|
|
20
24
|
* @module dsh-loop-engine/engine-pi/model-handover
|
|
21
25
|
*/
|
|
22
26
|
import type { DshModelHandover } from '../driver-core/model-handover.ts';
|
package/lib/types/index.d.ts
CHANGED
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
* with no record) — it is no longer the thing that decides a running session's
|
|
30
30
|
* engine.
|
|
31
31
|
*
|
|
32
|
-
* The `
|
|
32
|
+
* The plugin's own live `engine` Config field carries the DEFAULT engine for new
|
|
33
33
|
* sessions — which preset the roster's default points at — not a process-wide
|
|
34
34
|
* switch: existing sessions keep the engine they run, and nothing is torn down or
|
|
35
35
|
* reloaded by it. (A PER-SESSION switch is a different thing: it is made from the
|
|
@@ -38,10 +38,11 @@
|
|
|
38
38
|
*
|
|
39
39
|
* @module dsh-loop-engine
|
|
40
40
|
*/
|
|
41
|
-
import type { Context } from '@deepseek-ai/cordis';
|
|
41
|
+
import type { Context, Volatile } from '@deepseek-ai/cordis';
|
|
42
42
|
import z from '@deepseek-ai/schemastery';
|
|
43
43
|
import { type Config as ClaudeCodeConfig } from './engine-claude/loop.ts';
|
|
44
44
|
import type { CodexApprovalPolicy, CodexSandboxMode } from './engine-codex/types.ts';
|
|
45
|
+
import { type LoopEngineId } from './settings.ts';
|
|
45
46
|
export declare const name = "loop-engine";
|
|
46
47
|
/**
|
|
47
48
|
* Services the plugin's own fiber requires. The plugin declares none of its
|
|
@@ -69,7 +70,20 @@ export interface Config extends ClaudeCodeConfig {
|
|
|
69
70
|
piThinking?: string;
|
|
70
71
|
/** Kimi CLI executable; `'kimi'` resolves through PATH when not pinned to an absolute path. */
|
|
71
72
|
kimiBin?: string;
|
|
73
|
+
/**
|
|
74
|
+
* Default engine NEW sessions are created on. A live, profile-backed field:
|
|
75
|
+
* the settings shell edits it and the running plugin reads it through this
|
|
76
|
+
* volatile reference (`config.engine.get()`).
|
|
77
|
+
*/
|
|
78
|
+
engine: Volatile<LoopEngineId>;
|
|
79
|
+
/** Whether the chat composer shows the engine picker; a live, profile-backed field. */
|
|
80
|
+
showInComposer: Volatile<boolean>;
|
|
72
81
|
}
|
|
82
|
+
/** Rejected input of the composition entry: live fields arrive as plain values and resolve to references. */
|
|
83
|
+
type ConfigInput = Omit<Config, 'engine' | 'showInComposer'> & {
|
|
84
|
+
engine?: LoopEngineId;
|
|
85
|
+
showInComposer?: boolean;
|
|
86
|
+
};
|
|
73
87
|
/**
|
|
74
88
|
* Schema of the loop engine composition entry.
|
|
75
89
|
*
|
|
@@ -80,8 +94,15 @@ export interface Config extends ClaudeCodeConfig {
|
|
|
80
94
|
* omitted deployment tunables fall back to the session). The composition entry
|
|
81
95
|
* is an engine-agnostic superset: every hosted engine's knobs live here at
|
|
82
96
|
* once, because any session may select any engine.
|
|
97
|
+
*
|
|
98
|
+
* On the 0.1.7 line `engine` and `showInComposer` are the entry's live fields:
|
|
99
|
+
* `.volatile()` makes them profile-backed settings the settings shell projects
|
|
100
|
+
* as form fields, and the runtime reads each one through its reference
|
|
101
|
+
* (`config.engine.get()`). On the 0.1.5 line there are no live Config fields —
|
|
102
|
+
* the selection is a settings section (`LOOP_ENGINE_SETTINGS_SCHEMA`), whose
|
|
103
|
+
* provider owns the storage — so the entry is the engine knobs alone.
|
|
83
104
|
*/
|
|
84
|
-
export declare const Config: z<Config>;
|
|
105
|
+
export declare const Config: z<ConfigInput, Config>;
|
|
85
106
|
/** Resolve the managed patch file from configuration, defaulting to the web profile. */
|
|
86
107
|
export declare function resolvePatchPath(config: Config): string;
|
|
87
108
|
/** Atomically replace the patch file (same-directory temp + rename). */
|
|
@@ -112,4 +133,5 @@ export declare function syncManagedBlock(path: string): Promise<boolean>;
|
|
|
112
133
|
* @param config - composition entry for the managed patch file and engine knobs.
|
|
113
134
|
*/
|
|
114
135
|
export declare function apply(ctx: Context, config: Config): void;
|
|
136
|
+
export {};
|
|
115
137
|
//# sourceMappingURL=index.d.ts.map
|
package/lib/types/namespace.d.ts
CHANGED
|
@@ -1,9 +1,25 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Loop engine namespace
|
|
3
|
-
* module with no runtime imports so the browser bundle can import
|
|
2
|
+
* Loop engine namespace literals: the strings both halves agree on, in a
|
|
3
|
+
* module with no runtime imports so the browser bundle can import them without
|
|
4
4
|
* dragging `dsh-settings` (a host-side service) into the client artifact.
|
|
5
5
|
* @module dsh-loop-engine/namespace
|
|
6
6
|
*/
|
|
7
|
-
/**
|
|
8
|
-
|
|
7
|
+
/**
|
|
8
|
+
* Settings namespace carrying the deployment's selected agent loop engine on
|
|
9
|
+
* the 0.1.7 line.
|
|
10
|
+
*
|
|
11
|
+
* Profile-backed settings are addressed by the composing entry id, so this
|
|
12
|
+
* literal is the plugin's own profile entry id: the shipped `cordis.patch.yml`
|
|
13
|
+
* inserts the entry as `loop-engine`, and the browser half passes the same
|
|
14
|
+
* string to `ctx.configForms.get(...)`. A deployment that renames the entry id
|
|
15
|
+
* must change this literal with it.
|
|
16
|
+
*/
|
|
17
|
+
export declare const LOOP_ENGINE_SETTINGS_NAMESPACE_LITERAL = "loop-engine";
|
|
18
|
+
/**
|
|
19
|
+
* Settings namespace carrying the same selection on the 0.1.5 line, where a
|
|
20
|
+
* settings section is addressed by the namespace a provider registers rather
|
|
21
|
+
* than by a composing entry id. This is the literal the pre-rewrite plugin
|
|
22
|
+
* shipped; it is stable across the whole 0.1.5 line.
|
|
23
|
+
*/
|
|
24
|
+
export declare const LEGACY_LOOP_ENGINE_SETTINGS_NAMESPACE_LITERAL = "agent-loop-engine";
|
|
9
25
|
//# sourceMappingURL=namespace.d.ts.map
|
package/lib/types/preset.d.ts
CHANGED
|
@@ -68,10 +68,14 @@ export declare const STRIPPED_ROWS: readonly ["skill-filesystem", "tool-skill",
|
|
|
68
68
|
* @returns the stripped composition.
|
|
69
69
|
*/
|
|
70
70
|
export declare function stripPresetRows(text: string, ids?: readonly string[]): string;
|
|
71
|
-
/** Minimal read seam over the host's preset roster
|
|
71
|
+
/** Minimal read seam over the host's preset roster, per harness generation. */
|
|
72
72
|
export interface PresetCompositionSource {
|
|
73
|
-
/**
|
|
74
|
-
read(id: string): Promise<string>;
|
|
73
|
+
/** 0.1.5 line: read one preset's composition text; throws when the id is unknown. */
|
|
74
|
+
read?(id: string): Promise<string>;
|
|
75
|
+
/** 0.1.7 line: read one preset's document; `content` is the composition text. */
|
|
76
|
+
readDocument?(id: string): Promise<{
|
|
77
|
+
readonly content: string;
|
|
78
|
+
}>;
|
|
75
79
|
}
|
|
76
80
|
/**
|
|
77
81
|
* Regenerate every hosted engine's preset under the dsh home's user preset root
|
package/lib/types/settings.d.ts
CHANGED
|
@@ -1,21 +1,30 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Shared loop-engine identity,
|
|
2
|
+
* Shared loop-engine identity, namespaces, and schemas.
|
|
3
3
|
*
|
|
4
|
-
* Both the namespace
|
|
4
|
+
* Both the namespace literals and the engine/preset-id mapping live in
|
|
5
5
|
* zero-import modules (`./namespace.ts`, `./agent-preset-ids.ts`) so both halves
|
|
6
6
|
* agree on them: the node half brands the literal as a `SettingsNamespace` and
|
|
7
|
-
* builds
|
|
8
|
-
* pulling host-side packages (`dsh-settings`, `schemastery`, `node:fs`)
|
|
9
|
-
* client bundle (cross-plugin value imports go through cordis
|
|
10
|
-
*
|
|
11
|
-
*
|
|
7
|
+
* builds these schemas, while the browser half imports the same literals
|
|
8
|
+
* without pulling host-side packages (`dsh-settings`, `schemastery`, `node:fs`)
|
|
9
|
+
* into the client bundle (cross-plugin value imports go through cordis
|
|
10
|
+
* services). This module re-exports them so node-side importers keep their
|
|
11
|
+
* paths.
|
|
12
|
+
*
|
|
13
|
+
* The two live schema families exist because one build serves two harness
|
|
14
|
+
* generations: the 0.1.5 line addresses a settings SECTION registered by a
|
|
15
|
+
* provider under a namespace string ({@link LOOP_ENGINE_SETTINGS_SCHEMA} via
|
|
16
|
+
* {@link loopEngineSettingsNamespace}), while the 0.1.7 line makes the plugin's
|
|
17
|
+
* two live fields profile-backed Config entries
|
|
18
|
+
* ({@link LOOP_ENGINE_ENGINE_SCHEMA} / {@link LOOP_ENGINE_SHOW_IN_COMPOSER_SCHEMA}).
|
|
19
|
+
* Which family a running plugin builds is decided by `./compat.ts`
|
|
20
|
+
* (`LEGACY_HARNESS`) in `./index.ts`.
|
|
12
21
|
*
|
|
13
22
|
* @module dsh-loop-engine/settings
|
|
14
23
|
*/
|
|
15
24
|
import z from '@deepseek-ai/schemastery';
|
|
16
25
|
import type { SettingsNamespace } from '@deepseek-ai/dsh-settings';
|
|
17
26
|
import type { LoopEngineId } from './agent-preset-ids.ts';
|
|
18
|
-
export { LOOP_ENGINE_SETTINGS_NAMESPACE_LITERAL } from './namespace.ts';
|
|
27
|
+
export { LOOP_ENGINE_SETTINGS_NAMESPACE_LITERAL, LEGACY_LOOP_ENGINE_SETTINGS_NAMESPACE_LITERAL } from './namespace.ts';
|
|
19
28
|
export { HOSTED_ENGINE_IDS, HOSTED_PRESET_PREFIX, LOOP_ENGINE_IDS, SOURCE_PRESET_ID, engineOfPreset, enginePresetId, } from './agent-preset-ids.ts';
|
|
20
29
|
export type { HostedEngineId, LoopEngineId } from './agent-preset-ids.ts';
|
|
21
30
|
/** Stored and composed loop engine selection. */
|
|
@@ -26,10 +35,21 @@ export interface LoopEngineSettings {
|
|
|
26
35
|
showInComposer: boolean;
|
|
27
36
|
}
|
|
28
37
|
/**
|
|
29
|
-
* Schema of the loop engine settings section
|
|
30
|
-
* {@link LOOP_ENGINE_IDS}, so adding
|
|
38
|
+
* Schema of the loop engine settings section, as the 0.1.5 line's settings host
|
|
39
|
+
* consumes it. The engine union derives from {@link LOOP_ENGINE_IDS}, so adding
|
|
40
|
+
* an engine there also admits it here.
|
|
31
41
|
*/
|
|
32
42
|
export declare const LOOP_ENGINE_SETTINGS_SCHEMA: z<LoopEngineSettings>;
|
|
33
|
-
/** The
|
|
43
|
+
/** The 0.1.5-line namespace branded as a settings namespace on the node side. */
|
|
34
44
|
export declare function loopEngineSettingsNamespace(): SettingsNamespace;
|
|
45
|
+
/**
|
|
46
|
+
* Live Config field schema for the default engine (0.1.7 line). `.volatile()`
|
|
47
|
+
* declares it profile-backed: the settings shell projects it as a form field,
|
|
48
|
+
* and a committed edit reaches the running plugin through the live Config
|
|
49
|
+
* reference. The engine union derives from {@link LOOP_ENGINE_IDS}, so adding
|
|
50
|
+
* an engine there admits it here too.
|
|
51
|
+
*/
|
|
52
|
+
export declare const LOOP_ENGINE_ENGINE_SCHEMA: z<"in-process" | "claude-code" | "codex" | "pi" | "kimi", "in-process" | "claude-code" | "codex" | "pi" | "kimi", "volatile-defined">;
|
|
53
|
+
/** Live Config field schema for the composer picker toggle (0.1.7 line). */
|
|
54
|
+
export declare const LOOP_ENGINE_SHOW_IN_COMPOSER_SCHEMA: z<boolean, boolean, "volatile-defined">;
|
|
35
55
|
//# 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": "0.1.
|
|
4
|
+
"version": "0.1.7-rc1",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -63,39 +63,39 @@
|
|
|
63
63
|
"dependencies": {
|
|
64
64
|
"@anthropic-ai/claude-agent-sdk": "0.3.220",
|
|
65
65
|
"@anthropic-ai/sdk": "0.93.0",
|
|
66
|
-
"@deepseek-ai/schemastery": "3.18.
|
|
66
|
+
"@deepseek-ai/schemastery": "3.18.4",
|
|
67
67
|
"@earendil-works/pi-coding-agent": "0.84.3",
|
|
68
68
|
"@openai/codex": "0.149.1"
|
|
69
69
|
},
|
|
70
70
|
"peerDependencies": {
|
|
71
71
|
"@deepseek-ai/cordis": "^4.0.1",
|
|
72
|
-
"@deepseek-ai/dsh-agent": "0.1.5-rc.
|
|
73
|
-
"@deepseek-ai/dsh-agent-loop": "0.1.5-rc.
|
|
74
|
-
"@deepseek-ai/dsh-invariants": "0.1.5-rc.
|
|
75
|
-
"@deepseek-ai/dsh-llm": "0.1.5-rc.
|
|
76
|
-
"@deepseek-ai/dsh-scope": "0.1.5-rc.
|
|
77
|
-
"@deepseek-ai/dsh-session": "0.1.5-rc.
|
|
78
|
-
"@deepseek-ai/dsh-session-persistence": "0.1.5-rc.
|
|
79
|
-
"@deepseek-ai/dsh-settings": "0.1.5-rc.
|
|
80
|
-
"@deepseek-ai/dsh-subprocess": "0.1.5-rc.
|
|
81
|
-
"@deepseek-ai/dsh-timeout": "0.1.5-rc.
|
|
82
|
-
"@deepseek-ai/dsh-typert-protocol": "0.1.5-rc.
|
|
72
|
+
"@deepseek-ai/dsh-agent": ">=0.1.5-rc.1 <0.1.6-0 || >=0.1.7-rc.1 <0.1.8-0",
|
|
73
|
+
"@deepseek-ai/dsh-agent-loop": ">=0.1.5-rc.1 <0.1.6-0 || >=0.1.7-rc.1 <0.1.8-0",
|
|
74
|
+
"@deepseek-ai/dsh-invariants": ">=0.1.5-rc.1 <0.1.6-0 || >=0.1.7-rc.1 <0.1.8-0",
|
|
75
|
+
"@deepseek-ai/dsh-llm": ">=0.1.5-rc.1 <0.1.6-0 || >=0.1.7-rc.1 <0.1.8-0",
|
|
76
|
+
"@deepseek-ai/dsh-scope": ">=0.1.5-rc.1 <0.1.6-0 || >=0.1.7-rc.1 <0.1.8-0",
|
|
77
|
+
"@deepseek-ai/dsh-session": ">=0.1.5-rc.1 <0.1.6-0 || >=0.1.7-rc.1 <0.1.8-0",
|
|
78
|
+
"@deepseek-ai/dsh-session-persistence": ">=0.1.5-rc.1 <0.1.6-0 || >=0.1.7-rc.1 <0.1.8-0",
|
|
79
|
+
"@deepseek-ai/dsh-settings": ">=0.1.5-rc.1 <0.1.6-0 || >=0.1.7-rc.1 <0.1.8-0",
|
|
80
|
+
"@deepseek-ai/dsh-subprocess": ">=0.1.5-rc.1 <0.1.6-0 || >=0.1.7-rc.1 <0.1.8-0",
|
|
81
|
+
"@deepseek-ai/dsh-timeout": ">=0.1.5-rc.1 <0.1.6-0 || >=0.1.7-rc.1 <0.1.8-0",
|
|
82
|
+
"@deepseek-ai/dsh-typert-protocol": ">=0.1.5-rc.1 <0.1.6-0 || >=0.1.7-rc.1 <0.1.8-0"
|
|
83
83
|
},
|
|
84
84
|
"devDependencies": {
|
|
85
|
-
"@deepseek-ai/dsh-agent-loop": "0.1.
|
|
86
|
-
"@deepseek-ai/dsh-attachment": "0.1.
|
|
87
|
-
"@deepseek-ai/dsh-client-locale": "0.1.
|
|
88
|
-
"@deepseek-ai/dsh-client-store": "0.1.
|
|
89
|
-
"@deepseek-ai/dsh-client-ui-conversation": "0.1.
|
|
90
|
-
"@deepseek-ai/dsh-client-ui-primitives": "0.1.
|
|
91
|
-
"@deepseek-ai/dsh-client-ui-renderer": "0.1.
|
|
92
|
-
"@deepseek-ai/dsh-client-ui-settings": "0.1.
|
|
93
|
-
"@deepseek-ai/dsh-client-ui-slots": "0.1.
|
|
94
|
-
"@deepseek-ai/dsh-home-paths": "0.1.
|
|
95
|
-
"@deepseek-ai/dsh-session-persistence-jsonl": "0.1.
|
|
96
|
-
"@deepseek-ai/dsh-subprocess-local": "0.1.
|
|
97
|
-
"@deepseek-ai/dsh-system-prompt": "0.1.
|
|
98
|
-
"@deepseek-ai/dsh-typert-protocol": "0.1.
|
|
85
|
+
"@deepseek-ai/dsh-agent-loop": "0.1.7-rc.1",
|
|
86
|
+
"@deepseek-ai/dsh-attachment": "0.1.7-rc.1",
|
|
87
|
+
"@deepseek-ai/dsh-client-locale": "0.1.7-rc.1",
|
|
88
|
+
"@deepseek-ai/dsh-client-store": "0.1.7-rc.1",
|
|
89
|
+
"@deepseek-ai/dsh-client-ui-conversation": "0.1.7-rc.1",
|
|
90
|
+
"@deepseek-ai/dsh-client-ui-primitives": "0.1.7-rc.1",
|
|
91
|
+
"@deepseek-ai/dsh-client-ui-renderer": "0.1.7-rc.1",
|
|
92
|
+
"@deepseek-ai/dsh-client-ui-settings": "0.1.7-rc.1",
|
|
93
|
+
"@deepseek-ai/dsh-client-ui-slots": "0.1.7-rc.1",
|
|
94
|
+
"@deepseek-ai/dsh-home-paths": "0.1.7-rc.1",
|
|
95
|
+
"@deepseek-ai/dsh-session-persistence-jsonl": "0.1.7-rc.1",
|
|
96
|
+
"@deepseek-ai/dsh-subprocess-local": "0.1.7-rc.1",
|
|
97
|
+
"@deepseek-ai/dsh-system-prompt": "0.1.7-rc.1",
|
|
98
|
+
"@deepseek-ai/dsh-typert-protocol": "0.1.7-rc.1",
|
|
99
99
|
"@types/node": "^22.20.0",
|
|
100
100
|
"@types/react": "^19.0.0",
|
|
101
101
|
"@vitest/coverage-v8": "^4.1.8",
|