dsh-loop-engine-allinone 0.0.0-stage → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +100 -0
- package/CONTRIBUTING.md +78 -0
- package/LICENSE +23 -0
- package/NOTICE +45 -0
- package/README.md +221 -2
- package/README.zh.md +89 -0
- package/SECURITY.md +39 -0
- package/cordis.patch.yml +3 -0
- package/lib/client.js +2166 -0
- package/lib/index.js +11621 -0
- package/lib/invariant.js +453 -0
- package/lib/types/agent-preset-ids.d.ts +276 -0
- package/lib/types/client/LoopEngineBadge.d.ts +71 -0
- package/lib/types/client/LoopEngineComposerSelect.d.ts +126 -0
- package/lib/types/client/LoopEngineSection.d.ts +35 -0
- package/lib/types/client/engine-marks.d.ts +87 -0
- package/lib/types/client/index.d.ts +39 -0
- package/lib/types/client/locales.d.ts +182 -0
- package/lib/types/client/reload.d.ts +135 -0
- package/lib/types/client/session-engine.d.ts +508 -0
- package/lib/types/client/store.d.ts +103 -0
- package/lib/types/client/turn-status.d.ts +234 -0
- package/lib/types/client/use-session-engine.d.ts +74 -0
- package/lib/types/commands.d.ts +77 -0
- package/lib/types/compat.d.ts +25 -0
- package/lib/types/driver-acp/agent.d.ts +289 -0
- package/lib/types/driver-acp/approval.d.ts +27 -0
- package/lib/types/driver-acp/capabilities.d.ts +200 -0
- package/lib/types/driver-acp/client.d.ts +297 -0
- package/lib/types/driver-acp/executable.d.ts +53 -0
- package/lib/types/driver-acp/mapping.d.ts +76 -0
- package/lib/types/driver-acp/profile.d.ts +126 -0
- package/lib/types/driver-acp/runtime.d.ts +45 -0
- package/lib/types/driver-acp/subprocess.d.ts +19 -0
- package/lib/types/driver-acp/terminal.d.ts +98 -0
- package/lib/types/driver-acp/transport.d.ts +43 -0
- package/lib/types/driver-acp/types.d.ts +152 -0
- package/lib/types/driver-cli/capability.d.ts +42 -0
- package/lib/types/driver-cli/cli-agent.d.ts +258 -0
- package/lib/types/driver-cli/cli-loop.d.ts +46 -0
- package/lib/types/driver-cli/flatten.d.ts +35 -0
- package/lib/types/driver-cli/frames.d.ts +128 -0
- package/lib/types/driver-cli/ndjson.d.ts +106 -0
- package/lib/types/driver-cli/session-sink.d.ts +333 -0
- package/lib/types/driver-cli/stream-json.d.ts +61 -0
- package/lib/types/driver-cli/text.d.ts +66 -0
- package/lib/types/driver-cli/transport.d.ts +84 -0
- package/lib/types/driver-core/agents-md-skill-provider.d.ts +72 -0
- package/lib/types/driver-core/assistant-stream.d.ts +68 -0
- package/lib/types/driver-core/context-files.d.ts +62 -0
- package/lib/types/driver-core/host-servers.d.ts +119 -0
- package/lib/types/driver-core/hosted-engine-runtime.d.ts +190 -0
- package/lib/types/driver-core/hosted-tool-vocabulary.d.ts +78 -0
- package/lib/types/driver-core/idle-child.d.ts +57 -0
- package/lib/types/driver-core/image-access.d.ts +25 -0
- package/lib/types/driver-core/inbox.d.ts +104 -0
- package/lib/types/driver-core/model-handover.d.ts +134 -0
- package/lib/types/driver-core/ownership.d.ts +41 -0
- package/lib/types/driver-core/permission-knobs.d.ts +26 -0
- package/lib/types/driver-core/prompt.d.ts +64 -0
- package/lib/types/driver-core/session-lifetime.d.ts +62 -0
- package/lib/types/driver-core/session-model.d.ts +128 -0
- package/lib/types/driver-core/skill-inject.d.ts +59 -0
- package/lib/types/driver-core/step-close.d.ts +49 -0
- package/lib/types/driver-core/step-images.d.ts +62 -0
- package/lib/types/driver-core/step-tools.d.ts +43 -0
- package/lib/types/driver-core/system-head.d.ts +43 -0
- package/lib/types/engine-agy/agent.d.ts +67 -0
- package/lib/types/engine-agy/frames.d.ts +90 -0
- package/lib/types/engine-agy/loop.d.ts +64 -0
- package/lib/types/engine-agy/process.d.ts +173 -0
- package/lib/types/engine-claude/agent.d.ts +186 -0
- package/lib/types/engine-claude/loop.d.ts +73 -0
- package/lib/types/engine-claude/mapping.d.ts +108 -0
- package/lib/types/engine-claude/permission.d.ts +41 -0
- package/lib/types/engine-claude/process.d.ts +59 -0
- package/lib/types/engine-claude/sdk.d.ts +67 -0
- package/lib/types/engine-claude/types.d.ts +28 -0
- package/lib/types/engine-codex/agent.d.ts +216 -0
- package/lib/types/engine-codex/appserver/client.d.ts +80 -0
- package/lib/types/engine-codex/appserver/mapping.d.ts +67 -0
- package/lib/types/engine-codex/appserver/thread.d.ts +66 -0
- package/lib/types/engine-codex/appserver/types.d.ts +225 -0
- package/lib/types/engine-codex/loop.d.ts +75 -0
- package/lib/types/engine-codex/model-handover.d.ts +56 -0
- package/lib/types/engine-codex/permission.d.ts +126 -0
- package/lib/types/engine-codex/skills.d.ts +28 -0
- package/lib/types/engine-codex/types.d.ts +36 -0
- package/lib/types/engine-drivers.d.ts +132 -0
- package/lib/types/engine-grok/agent.d.ts +24 -0
- package/lib/types/engine-grok/loop.d.ts +61 -0
- package/lib/types/engine-grok/process.d.ts +46 -0
- package/lib/types/engine-grok/profile.d.ts +82 -0
- package/lib/types/engine-hermes/agent.d.ts +47 -0
- package/lib/types/engine-hermes/loop.d.ts +56 -0
- package/lib/types/engine-hermes/process.d.ts +92 -0
- package/lib/types/engine-kimi/acp/client.d.ts +123 -0
- package/lib/types/engine-kimi/acp/mapping.d.ts +73 -0
- package/lib/types/engine-kimi/acp/types.d.ts +143 -0
- package/lib/types/engine-kimi/agent.d.ts +24 -0
- package/lib/types/engine-kimi/commands.d.ts +44 -0
- package/lib/types/engine-kimi/loop.d.ts +62 -0
- package/lib/types/engine-kimi/model-handover.d.ts +32 -0
- package/lib/types/engine-kimi/permission.d.ts +28 -0
- package/lib/types/engine-kimi/process.d.ts +47 -0
- package/lib/types/engine-kimi/profile.d.ts +19 -0
- package/lib/types/engine-kimi/skills.d.ts +52 -0
- package/lib/types/engine-kimi/types.d.ts +25 -0
- package/lib/types/engine-minimaxcode/agent.d.ts +24 -0
- package/lib/types/engine-minimaxcode/loop.d.ts +83 -0
- package/lib/types/engine-minimaxcode/process.d.ts +53 -0
- package/lib/types/engine-minimaxcode/profile.d.ts +72 -0
- package/lib/types/engine-of-session.d.ts +97 -0
- package/lib/types/engine-pi/agent.d.ts +230 -0
- package/lib/types/engine-pi/loop.d.ts +72 -0
- package/lib/types/engine-pi/model-handover.d.ts +84 -0
- package/lib/types/engine-pi/permission.d.ts +47 -0
- package/lib/types/engine-pi/rpc/client.d.ts +107 -0
- package/lib/types/engine-pi/rpc/mapping.d.ts +37 -0
- package/lib/types/engine-pi/rpc/types.d.ts +249 -0
- package/lib/types/engine-pi/skills.d.ts +47 -0
- package/lib/types/engine-pi/types.d.ts +36 -0
- package/lib/types/engine-qoderclicn/agent.d.ts +59 -0
- package/lib/types/engine-qoderclicn/loop.d.ts +51 -0
- package/lib/types/engine-qoderclicn/process.d.ts +113 -0
- package/lib/types/engine-registry.d.ts +584 -0
- package/lib/types/engine-remote.d.ts +192 -0
- package/lib/types/engine-surface.d.ts +36 -0
- package/lib/types/engine-zcode/agent.d.ts +50 -0
- package/lib/types/engine-zcode/loop.d.ts +47 -0
- package/lib/types/engine-zcode/process.d.ts +111 -0
- package/lib/types/index.d.ts +205 -0
- package/lib/types/invariant.d.ts +26 -0
- package/lib/types/model-selection-reset.d.ts +271 -0
- package/lib/types/namespace.d.ts +25 -0
- package/lib/types/patch-manager.d.ts +104 -0
- package/lib/types/preset.d.ts +254 -0
- package/lib/types/provider-route.d.ts +245 -0
- package/lib/types/router-loop.d.ts +458 -0
- package/lib/types/session-engine-store.d.ts +138 -0
- package/lib/types/settings.d.ts +60 -0
- package/lib/types/skills.d.ts +85 -0
- package/package.json +150 -4
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Loop engine ids, the agent-preset ids that select them, and the two plain
|
|
3
|
+
* wire shapes both halves of the plugin share — in a module with no imports at
|
|
4
|
+
* all.
|
|
5
|
+
*
|
|
6
|
+
* The mapping is pure identity arithmetic (an engine to a preset id and back),
|
|
7
|
+
* so it belongs to neither half; it lives here for the same reason
|
|
8
|
+
* `./namespace.ts` does — the browser bundle needs it, and the files that
|
|
9
|
+
* otherwise carry it are host-side: `./settings.ts` imports `schemastery` and
|
|
10
|
+
* the `dsh-settings` brand type, `./preset.ts` imports `node:fs/promises`.
|
|
11
|
+
* Importing either from `src/client/**` would pull a host package into the
|
|
12
|
+
* client artifact. Both of them re-export what this module defines, so the
|
|
13
|
+
* existing import paths and names stay valid on the node side.
|
|
14
|
+
*
|
|
15
|
+
* The two shapes are here for that same reason: {@link SessionEngine} is what
|
|
16
|
+
* the browser half renders and {@link LoopEngineSelectResult} is what its switch
|
|
17
|
+
* comes back with, so both halves name the same types without either half's
|
|
18
|
+
* modules crossing the boundary. The refusal codes travel with the second one
|
|
19
|
+
* ({@link LoopEngineRefusalCode}) for the same reason plus one more: the browser
|
|
20
|
+
* half is what turns a refusal into copy, so the codes it may read have to be
|
|
21
|
+
* knowable without importing the host's router.
|
|
22
|
+
*
|
|
23
|
+
* @module dsh-loop-engine-allinone/agent-preset-ids
|
|
24
|
+
*/
|
|
25
|
+
export { HOSTED_ENGINE_IDS, LOOP_ENGINE_IDS, isHostedEngine, isLoopEngineId, } from './engine-registry.ts';
|
|
26
|
+
export type { HostedEngineId, LoopEngineId } from './engine-registry.ts';
|
|
27
|
+
import type { HostedEngineId, LoopEngineId } from './engine-registry.ts';
|
|
28
|
+
/**
|
|
29
|
+
* The single provider route label EVERY hosted engine logs into its sessions'
|
|
30
|
+
* `request/header`, and the one placeholder route this plugin registers in the
|
|
31
|
+
* llm registry.
|
|
32
|
+
*
|
|
33
|
+
* One label for every hosted engine, because the browser model catalog is built
|
|
34
|
+
* for the whole Host GENERATION and is not scoped to a session
|
|
35
|
+
* (`packages/api/session-controller/src/catalog.ts` — "Build the browser model
|
|
36
|
+
* catalog without requiring a Session"; it walks `ctx.llm.listProviders()`
|
|
37
|
+
* once). A per-engine label would therefore surface one provider group per
|
|
38
|
+
* engine in every session's menu at once — four identical `default` entries —
|
|
39
|
+
* which is what this constant collapses away.
|
|
40
|
+
*
|
|
41
|
+
* The value is ASCII on purpose: it is a WIRE value. It is written into each
|
|
42
|
+
* session's `request/header`, it travels through selections, and the host
|
|
43
|
+
* compares it (`providerInfo().id` must equal the provider the adapter
|
|
44
|
+
* registered for — `packages/llm/llm/src/index.ts` `prepareRoutes`). The
|
|
45
|
+
* display name ({@link HOSTED_ROUTE_NAME}) is the same token, for the reason
|
|
46
|
+
* that constant documents.
|
|
47
|
+
*/
|
|
48
|
+
export declare const HOSTED_ROUTE_LABEL = "external";
|
|
49
|
+
/**
|
|
50
|
+
* The user-visible name of the one hosted route ({@link HOSTED_ROUTE_LABEL}),
|
|
51
|
+
* shown as the model menu's provider group label.
|
|
52
|
+
*
|
|
53
|
+
* The same token as the wire value, and deliberately not localized: the catalog
|
|
54
|
+
* carries exactly one string per provider group (`ModelCatalog`'s `group.name`,
|
|
55
|
+
* taken from `LlmProviderInfo.name`) and the browser half has no hook to
|
|
56
|
+
* re-translate it, so one fixed name is what every locale sees.
|
|
57
|
+
*/
|
|
58
|
+
export declare const HOSTED_ROUTE_NAME = "external";
|
|
59
|
+
/**
|
|
60
|
+
* The one model id a hosted engine's provider route advertises to the model
|
|
61
|
+
* menu, and the model label that engine logs into its sessions'
|
|
62
|
+
* `request/header` when the deployment pins none.
|
|
63
|
+
*
|
|
64
|
+
* The two are ONE string on purpose, and that is a host-side requirement rather
|
|
65
|
+
* than a style choice: the picker builds its selection out of a catalog entry
|
|
66
|
+
* (`ModelSelect.tsx` `choices` — `model: model.id`) and resolves a session's
|
|
67
|
+
* `(provider, model)` back to that entry by comparing the pair with the logged
|
|
68
|
+
* header (`selectedIndex`), so an entry whose `id` differs from the logged
|
|
69
|
+
* label falls through to the raw `provider/model` string — how a menu ends up
|
|
70
|
+
* showing a model that does not exist. The label is the engine's own word for
|
|
71
|
+
* "whatever it decides"; `name` is the same string because `LlmModelInfo.name`
|
|
72
|
+
* is rendered verbatim and has no localization hook.
|
|
73
|
+
*/
|
|
74
|
+
export declare const HOSTED_DEFAULT_MODEL = "default";
|
|
75
|
+
/** Prefix every plugin-authored preset id carries. */
|
|
76
|
+
export declare const HOSTED_PRESET_PREFIX = "loop-engine-";
|
|
77
|
+
/** The deployment's own preset id, which selects the harness loop. */
|
|
78
|
+
export declare const SOURCE_PRESET_ID = "standard";
|
|
79
|
+
/**
|
|
80
|
+
* The pre-routing single preset id: older versions of this plugin authored one
|
|
81
|
+
* preset for every hosted engine and pinned the profile to one of them, so a
|
|
82
|
+
* session carrying this id DID run a hosted engine — but the id does not say
|
|
83
|
+
* which one. It is not a hosted preset id ({@link engineOfPreset} reads it as
|
|
84
|
+
* `undefined`, so the router keeps such a session on the harness loop), and it
|
|
85
|
+
* is not `standard` either; surfaces that name a session's engine must report it
|
|
86
|
+
* as "a hosted engine, unrecorded" rather than claim the in-process loop.
|
|
87
|
+
*/
|
|
88
|
+
export declare const LEGACY_HOSTED_PRESET_ID = "loop-engine";
|
|
89
|
+
/**
|
|
90
|
+
* The preset id that selects one engine for a session. `in-process` names the
|
|
91
|
+
* deployment's own `standard` preset: the harness loop is not something this
|
|
92
|
+
* plugin authors a preset for.
|
|
93
|
+
* @param engine - the engine a session should run.
|
|
94
|
+
* @returns the preset id to record on the session.
|
|
95
|
+
*/
|
|
96
|
+
export declare function enginePresetId(engine: LoopEngineId): string;
|
|
97
|
+
/**
|
|
98
|
+
* The engine a preset id selects, or `undefined` for a preset this plugin does
|
|
99
|
+
* not own (any deployment-authored preset, including `standard`).
|
|
100
|
+
* @param presetId - the session's preset id, when it has one.
|
|
101
|
+
* @returns the hosted engine it names, or undefined for the harness loop.
|
|
102
|
+
*/
|
|
103
|
+
export declare function engineOfPreset(presetId: string | undefined): HostedEngineId | undefined;
|
|
104
|
+
/**
|
|
105
|
+
* What a session's recorded preset says about the engine that session runs.
|
|
106
|
+
*
|
|
107
|
+
* Not every session has an answer: the pre-routing single preset id names a
|
|
108
|
+
* hosted engine without recording which one, and a deployment that composes no
|
|
109
|
+
* presets (or a transcript whose projection is gone) records nothing at all.
|
|
110
|
+
* Both are reported as themselves — a surface that names a session's engine must
|
|
111
|
+
* never read "unknown" as the in-process loop.
|
|
112
|
+
*/
|
|
113
|
+
export type SessionEngine = {
|
|
114
|
+
readonly kind: 'engine';
|
|
115
|
+
readonly engine: LoopEngineId;
|
|
116
|
+
}
|
|
117
|
+
/** The pre-routing preset: this session ran a hosted engine, but the id does not say which. */
|
|
118
|
+
| {
|
|
119
|
+
readonly kind: 'legacy';
|
|
120
|
+
}
|
|
121
|
+
/** The session records no preset at all (a deployment that composes none, or one created before presets existed). */
|
|
122
|
+
| {
|
|
123
|
+
readonly kind: 'unset';
|
|
124
|
+
};
|
|
125
|
+
/**
|
|
126
|
+
* What one session's engine report carries: the engine the session ACTUALLY
|
|
127
|
+
* runs, and — when they differ — the engine its own record names for it.
|
|
128
|
+
*
|
|
129
|
+
* The two are one answer because a surface must never render the second as if it
|
|
130
|
+
* were the first. A session switched onto or off the harness loop has its agent
|
|
131
|
+
* RELEASED (`src/router-loop.ts` `move`), so the session is simply cold
|
|
132
|
+
* afterwards and its record IS what its next build runs — no second fact, no
|
|
133
|
+
* pending. This field therefore survives for the one case in which a live agent
|
|
134
|
+
* still differs from the record: the release did not take (its teardown failed,
|
|
135
|
+
* or another process wrote the record), so the session keeps running its old
|
|
136
|
+
* engine while the record names another. Reporting only the live agent would
|
|
137
|
+
* hide that a switch was accepted at all — the "显示在撒谎" bug this report
|
|
138
|
+
* exists to prevent — so both travel, and {@link pending} says which is which.
|
|
139
|
+
*/
|
|
140
|
+
export interface SessionEngineReport {
|
|
141
|
+
/** The engine driving this session NOW. */
|
|
142
|
+
readonly engine: SessionEngine;
|
|
143
|
+
/**
|
|
144
|
+
* Present only while the session has an engine recorded that its LIVE agent is
|
|
145
|
+
* not running — i.e. a recorded switch whose release did not complete. Absent
|
|
146
|
+
* whenever the record and the live agent agree, and always absent for a session
|
|
147
|
+
* with no live agent (there the record IS what the session runs).
|
|
148
|
+
*/
|
|
149
|
+
readonly pending?: LoopEngineId;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Every way this plugin refuses to move a session to another engine, as a stable
|
|
153
|
+
* code.
|
|
154
|
+
*
|
|
155
|
+
* A code exists because the host's own sentence is not what a surface shows any
|
|
156
|
+
* more: the browser half localizes the refusal from the code (`refusalFace` in
|
|
157
|
+
* `./client/locales.ts`) and keeps {@link LoopEngineRefusal.reason} only as
|
|
158
|
+
* detail, so the codes are part of the wire contract and a value may be added but
|
|
159
|
+
* never quietly repurposed. The list is exactly the refusals the host can produce
|
|
160
|
+
* — one per branch of `RouterLoop.selectEngine`, plus the Remote's own
|
|
161
|
+
* "no router mounted" answer:
|
|
162
|
+
*
|
|
163
|
+
* - `session-closed`: the session has no agent in this process (nothing is open
|
|
164
|
+
* to move);
|
|
165
|
+
* - `turn-running`: a turn is in flight, and it is never interrupted;
|
|
166
|
+
* - `subagent-session`: a delegated child's agent belongs to its delegation;
|
|
167
|
+
* - `not-driven`: an agent is live but this router did not build it (the mount
|
|
168
|
+
* window in which the base loop still owns the factory slot);
|
|
169
|
+
* - `router-unmounted`: no router is mounted at all yet;
|
|
170
|
+
* - `record-failed`: the plugin's own per-session record could not be written,
|
|
171
|
+
* so the choice could not be committed;
|
|
172
|
+
* - `rebuild-failed`: the outgoing machine was retired, the successor could not
|
|
173
|
+
* be built, and the session was left cold on the recorded engine.
|
|
174
|
+
*
|
|
175
|
+
* A malformed REQUEST is deliberately NOT one of these: it travels as a
|
|
176
|
+
* `RemoteError` with `gateway/bad-request`, because it is the caller's fault
|
|
177
|
+
* rather than a state of the session.
|
|
178
|
+
*/
|
|
179
|
+
export declare const LOOP_ENGINE_REFUSAL_CODES: readonly ["session-closed", "turn-running", "subagent-session", "not-driven", "router-unmounted", "record-failed", "rebuild-failed"];
|
|
180
|
+
/** Why one session's engine switch was refused. */
|
|
181
|
+
export type LoopEngineRefusalCode = (typeof LOOP_ENGINE_REFUSAL_CODES)[number];
|
|
182
|
+
/**
|
|
183
|
+
* Whether an untyped value is one of {@link LOOP_ENGINE_REFUSAL_CODES}.
|
|
184
|
+
*
|
|
185
|
+
* The boundary test the browser half needs: a code is only a code when this
|
|
186
|
+
* build knows it, so a value it does not recognize is normalized away and the
|
|
187
|
+
* host's `reason` stays readable instead (`./client/session-engine.ts`
|
|
188
|
+
* `parseSelectResult`).
|
|
189
|
+
* @param value - the value to classify.
|
|
190
|
+
* @returns whether `value` is a known refusal code.
|
|
191
|
+
*/
|
|
192
|
+
export declare function isLoopEngineRefusalCode(value: unknown): value is LoopEngineRefusalCode;
|
|
193
|
+
/**
|
|
194
|
+
* What one attempt to move a session to another engine produced.
|
|
195
|
+
*
|
|
196
|
+
* A refusal is a VALUE rather than a thrown error: every reason below is a
|
|
197
|
+
* predictable state of the session (it is not open, it is mid-turn, it belongs
|
|
198
|
+
* to subagent routing) that the surface must show — localized by
|
|
199
|
+
* {@link LoopEngineRefusal.code}, with the host's own sentence kept as detail —
|
|
200
|
+
* and only a malformed REQUEST is the caller's fault (`gateway/bad-request`).
|
|
201
|
+
*/
|
|
202
|
+
export type LoopEngineSelectResult = {
|
|
203
|
+
readonly ok: true;
|
|
204
|
+
readonly engine: LoopEngineId;
|
|
205
|
+
/**
|
|
206
|
+
* Present when the switch was made to land by RELEASING the session's live
|
|
207
|
+
* agent rather than by moving it: a change with the harness loop on either
|
|
208
|
+
* side of it cannot be applied in place, so the agent is torn down, the
|
|
209
|
+
* session goes cold, and the record's engine is what its next build uses.
|
|
210
|
+
*
|
|
211
|
+
* The page must reload for that next build to happen: releasing publishes
|
|
212
|
+
* `session/disposed`, which the browser half reads as this session being
|
|
213
|
+
* gone — with no way back in that page's lifetime — so a reload (and a
|
|
214
|
+
* re-open of the session) is what replaces the page state with a fresh list
|
|
215
|
+
* and a fresh build. The flag is how the surface knows to do that instead of
|
|
216
|
+
* leaving the user on a session that looks broken.
|
|
217
|
+
*/
|
|
218
|
+
readonly reload?: true;
|
|
219
|
+
}
|
|
220
|
+
/** The switch did not happen; the branch that refused it is `code`. */
|
|
221
|
+
| {
|
|
222
|
+
readonly ok: false;
|
|
223
|
+
/**
|
|
224
|
+
* Which refusal this is, for the surface to localize
|
|
225
|
+
* ({@link LoopEngineRefusalCode}). Every refusal this plugin's host produces
|
|
226
|
+
* carries one — `refuse(code, reason)` in `./router-loop.ts` takes it as a
|
|
227
|
+
* required argument, so the node half cannot forget it.
|
|
228
|
+
*
|
|
229
|
+
* Optional in the SHAPE only, because the browser half is what reads it off
|
|
230
|
+
* the wire: a code this build does not know (a newer host, or a hand-written
|
|
231
|
+
* answer) is normalized to absent so that `reason` — which is always there —
|
|
232
|
+
* is what the user reads, instead of the whole answer failing the boundary
|
|
233
|
+
* check and leaving the surface with nothing to show.
|
|
234
|
+
*/
|
|
235
|
+
readonly code?: LoopEngineRefusalCode;
|
|
236
|
+
/**
|
|
237
|
+
* The host's own complete sentence about this session. It is DETAIL, not the
|
|
238
|
+
* message any more: a surface shows its own localized copy for `code` and
|
|
239
|
+
* keeps this beside it (small print) or falls back to it when `code` is
|
|
240
|
+
* absent.
|
|
241
|
+
*/
|
|
242
|
+
readonly reason: string;
|
|
243
|
+
};
|
|
244
|
+
/**
|
|
245
|
+
* The engine one session's recorded preset says it runs, with the harness's own
|
|
246
|
+
* fallback for a preset this plugin does not own: the deployment's `standard` and
|
|
247
|
+
* anything else a deployment authored keep the session on the harness loop.
|
|
248
|
+
*
|
|
249
|
+
* The two answers that are not an engine stay distinct: {@link LEGACY_HOSTED_PRESET_ID}
|
|
250
|
+
* is a hosted engine whose name was never recorded, and a missing preset is this
|
|
251
|
+
* session recording nothing.
|
|
252
|
+
*
|
|
253
|
+
* This is the ONE preset-id → engine judgement: the router routes on what it
|
|
254
|
+
* returns and the plugin's own Remote reports it, so "what the session runs" and
|
|
255
|
+
* "what the session is shown as running" cannot disagree
|
|
256
|
+
* (`src/engine-of-session.ts` supplies the preset id from the durable log;
|
|
257
|
+
* `src/engine-remote.ts` publishes the answer to the browser half).
|
|
258
|
+
* @param presetId - the session's recorded preset id, when it has one. Reads off
|
|
259
|
+
* an untyped projection, so anything that is not a string is as good as no
|
|
260
|
+
* preset at all.
|
|
261
|
+
* @returns what that id says about the session's engine.
|
|
262
|
+
*/
|
|
263
|
+
export declare function sessionEngineOf(presetId: unknown): SessionEngine;
|
|
264
|
+
/**
|
|
265
|
+
* The hosted engine one {@link SessionEngine} names, or `undefined` for every
|
|
266
|
+
* answer that is not this plugin's own engine preset.
|
|
267
|
+
*
|
|
268
|
+
* This is the router's half of the judgement: the harness loop still owns
|
|
269
|
+
* `in-process`, the pre-routing id and an unrecorded session both run whatever
|
|
270
|
+
* the deployment's own composition gives them (the harness loop).
|
|
271
|
+
* @param session - what a session's preset says about its engine.
|
|
272
|
+
* @returns the hosted engine to build a driver runtime for, or undefined for the
|
|
273
|
+
* harness loop.
|
|
274
|
+
*/
|
|
275
|
+
export declare function hostedEngineOf(session: SessionEngine): HostedEngineId | undefined;
|
|
276
|
+
//# sourceMappingURL=agent-preset-ids.d.ts.map
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session header engine chip: a read-only pill naming the engine THIS session
|
|
3
|
+
* runs, read from this plugin's own Remote — which answers from the plugin's own
|
|
4
|
+
* per-session record and, for a session with none, from the session's durable
|
|
5
|
+
* log: the same read the router routes on, so the chip cannot disagree with what
|
|
6
|
+
* the session is actually driven by.
|
|
7
|
+
*
|
|
8
|
+
* It deliberately does NOT read the client session list's `agentPreset`
|
|
9
|
+
* projection: that value is a cache-shaped hint, and it names the preset the
|
|
10
|
+
* session was CREATED with, which is the wrong answer both for a session that
|
|
11
|
+
* switched while it was blank and for one that switched after it started. The
|
|
12
|
+
* harness's own preset label reads that same hint and lags the same way; this
|
|
13
|
+
* chip does not.
|
|
14
|
+
*
|
|
15
|
+
* The settings section's engine is NOT what this chip shows: that value is only
|
|
16
|
+
* the default for sessions created later, and a session created before a default
|
|
17
|
+
* change keeps running the engine it has. The one settings value this chip DOES
|
|
18
|
+
* read is the display toggle: `showEngineBadge` off means the chip renders
|
|
19
|
+
* nothing at all, the way the composer picker renders nothing when
|
|
20
|
+
* `showInComposer` is off. The two sessions that name no engine
|
|
21
|
+
* are reported as themselves rather than as the in-process loop: the pre-routing
|
|
22
|
+
* single preset id reads as "legacy hosted engine" (it ran a hosted engine, the
|
|
23
|
+
* id just never recorded which), and a session whose engine is not known — no
|
|
24
|
+
* record, no preset, or no answer from the host — renders nothing, which is also
|
|
25
|
+
* what the chip does until the host's first answer arrives.
|
|
26
|
+
*
|
|
27
|
+
* "What the session runs" is the ACTUAL engine, and for a live session that is
|
|
28
|
+
* the agent in front of it rather than the plugin's record: a switch onto the
|
|
29
|
+
* harness loop makes the host RELEASE the session's agent and reload the page,
|
|
30
|
+
* and if that release did not take, the session keeps running the engine it had
|
|
31
|
+
* while its record names another. This chip never renders the record as its name;
|
|
32
|
+
* it appends the `切到 X · 尚未接管` marker beside the engine that really runs,
|
|
33
|
+
* and its tooltip says what to do about it (`pendingSessionNotice`). See
|
|
34
|
+
* `SessionEngineReport` in `src/agent-preset-ids.ts`.
|
|
35
|
+
*
|
|
36
|
+
* Styling is token-driven inline styles like the settings section (the
|
|
37
|
+
* client-module bundle is esbuild-built without a CSS loader).
|
|
38
|
+
* @module dsh-loop-engine-allinone/client/badge
|
|
39
|
+
*/
|
|
40
|
+
import type { JSX } from 'react';
|
|
41
|
+
import type { InjectFace, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots';
|
|
42
|
+
import type { SnapshotStore } from '@deepseek-ai/dsh-client-store';
|
|
43
|
+
import type { SessionEngineCache, SessionSeat } from './session-engine.ts';
|
|
44
|
+
import type { LoopEngineState } from './store.ts';
|
|
45
|
+
import { type en } from './locales.ts';
|
|
46
|
+
/** Registration-side business face for the header badge. */
|
|
47
|
+
export interface LoopEngineBadgeInjected {
|
|
48
|
+
/** The plugin's authoritative per-session engine cache. */
|
|
49
|
+
sessionEngines: SessionEngineCache;
|
|
50
|
+
hooks: {
|
|
51
|
+
/** Badge-visibility snapshot bound by the UI renderer as useSnapshot. */
|
|
52
|
+
snapshot: SnapshotStore<LoopEngineState>;
|
|
53
|
+
};
|
|
54
|
+
/** Section copy bound to the engine dictionaries. */
|
|
55
|
+
t: (key: keyof typeof en) => string;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Props delivered by the slot outlet (the renderer erases the share boundary).
|
|
59
|
+
* The seat members stay partial here so the registration face matches the slot's
|
|
60
|
+
* own props; {@link BadgeFace} asserts them the way the component reads them.
|
|
61
|
+
*/
|
|
62
|
+
export type LoopEngineBadgeProps = PropsRuntime<'conversation.session.header.actions'> & Partial<SessionSeat> & Partial<InjectFace<LoopEngineBadgeInjected>>;
|
|
63
|
+
/**
|
|
64
|
+
* Render the session header's loop-engine chip for the session on screen.
|
|
65
|
+
* @param props - composed slot props.
|
|
66
|
+
* @returns the chip, or null when the seat carries no session to speak about,
|
|
67
|
+
* the session's engine is not known yet (or not recorded at all), or the
|
|
68
|
+
* settings hide the chip.
|
|
69
|
+
*/
|
|
70
|
+
export declare function LoopEngineBadge(props: LoopEngineBadgeProps): JSX.Element | null;
|
|
71
|
+
//# sourceMappingURL=LoopEngineBadge.d.ts.map
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Composer loop-engine picker: a compact dropdown registered at the
|
|
3
|
+
* `conversation.input.right` seat, so it sits immediately left of the model
|
|
4
|
+
* select in the composer's tool row.
|
|
5
|
+
*
|
|
6
|
+
* It picks the engine of the session it is rendered in — the picker's value is
|
|
7
|
+
* this plugin's own authoritative read of that session's engine, and a pick
|
|
8
|
+
* moves the session over this plugin's own `loopEngine/select` Remote. Any
|
|
9
|
+
* session can be moved, at any point in its life, as long as it is open and no
|
|
10
|
+
* turn is in flight, and the host picks one of two ways to make the pick land:
|
|
11
|
+
*
|
|
12
|
+
* - between two hosted engines it REBUILDS that session's agent IN PLACE, on the
|
|
13
|
+
* session's own live Session object, so the conversation it is rendered beside
|
|
14
|
+
* never closes;
|
|
15
|
+
* - when the harness loop is on either side of the change, the host RELEASES
|
|
16
|
+
* that session's agent and answers `reload: true`: the session goes cold with
|
|
17
|
+
* its record naming the new engine, this page is reloaded (which is what
|
|
18
|
+
* clears the client state a `session/disposed` leaves behind), and the page
|
|
19
|
+
* that comes back opens the same session again — the host then builds it on
|
|
20
|
+
* the engine the record names (`src/client/reload.ts`). This control says so
|
|
21
|
+
* in a notice rather than letting the reload look like a glitch.
|
|
22
|
+
*
|
|
23
|
+
* Either way the host refuses one that is
|
|
24
|
+
* running, and a refusal leaves the session's engine untouched — the label goes
|
|
25
|
+
* back to the engine the session actually runs. The refusal is rendered from its
|
|
26
|
+
* CODE in the user's own language (`refusalFace`), with the host's own sentence
|
|
27
|
+
* kept as detail — never as the message itself, which is how a raw
|
|
28
|
+
* `session "…" is running; …` used to reach the user.
|
|
29
|
+
*
|
|
30
|
+
* A pick commits as soon as the host can apply it, with ONE exception: when the
|
|
31
|
+
* target and the engine this session ACTUALLY runs differ in being the in-process
|
|
32
|
+
* one, the host cannot hand the session over in place, so the switch releases its
|
|
33
|
+
* agent and reloads this page — and a reload costs this page's scroll position and
|
|
34
|
+
* any unsent draft in it. That one pick is staged behind a confirmation
|
|
35
|
+
* (`switchNeedsReload(报告里的实际引擎, 目标引擎)`, resolved before anything is
|
|
36
|
+
* sent) and only then committed; a pick between two hosted engines, which swaps
|
|
37
|
+
* the agent in place and reloads nothing, still commits immediately and opens no
|
|
38
|
+
* dialog at all. That judgement is only ever made about an engine somebody knows:
|
|
39
|
+
* until the host has answered what this session runs there is no engine to judge,
|
|
40
|
+
* and a session with no answer may reload in EITHER direction — so the control is
|
|
41
|
+
* DISABLED for as long as it is reading (`engineSwitchReady`), rather than
|
|
42
|
+
* guessing a direction. This control deliberately asks NOTHING else: whether the session
|
|
43
|
+
* can be moved right now is the host's own judgement — it refuses one that is not
|
|
44
|
+
* open, one that is mid-turn, and a subagent's own session, each with a code and a
|
|
45
|
+
* sentence — so a pick that cannot land costs nothing, and the control never
|
|
46
|
+
* reads an idle hint off a cached session list.
|
|
47
|
+
*
|
|
48
|
+
* So it opens two dialogs, with different jobs: the CONFIRMATION (two buttons,
|
|
49
|
+
* cancel and switch) that a reloading pick must pass before it is sent, and the
|
|
50
|
+
* NOTICE (one button, close) that reports what the host answered — the refusal's
|
|
51
|
+
* localized copy with the host's sentence as detail, or this plugin's own
|
|
52
|
+
* sentence for a reloaded pick.
|
|
53
|
+
*
|
|
54
|
+
* WITH a session, the settings default is never shown — not even while the first
|
|
55
|
+
* answer is still in flight: a session on the pre-routing single preset id reads
|
|
56
|
+
* "legacy hosted engine", one whose engine is not recorded (or not readable)
|
|
57
|
+
* reads "not recorded", and a session whose engine has not been answered yet
|
|
58
|
+
* reads "reading" AND is disabled while it does (see above) — a default or a stale
|
|
59
|
+
* hint would be a claim about a session this control has no facts for, and a pick
|
|
60
|
+
* would have to be judged against an engine nobody knows. Without a session (the
|
|
61
|
+
* seat renders only with one, so this is the defensive branch) the trigger names
|
|
62
|
+
* the default and a pick writes it — immediately, like every other pick here, and
|
|
63
|
+
* with the control usable from the start: a new-session page is waiting for
|
|
64
|
+
* nothing, and that pick reloads nothing. The settings section's own picker is the
|
|
65
|
+
* one that still stages its choice behind a confirmation.
|
|
66
|
+
*
|
|
67
|
+
* Styling is token-driven inline styles like the badge and section (the
|
|
68
|
+
* client-module bundle is esbuild-built without a CSS loader).
|
|
69
|
+
* @module dsh-loop-engine-allinone/client/composer
|
|
70
|
+
*/
|
|
71
|
+
import { type JSX } from 'react';
|
|
72
|
+
import type { SnapshotStore } from '@deepseek-ai/dsh-client-store';
|
|
73
|
+
import type { InjectFace, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots';
|
|
74
|
+
import type { LoopEngineStore, LoopEngineState } from './store.ts';
|
|
75
|
+
import type { LoopEngineId } from '../agent-preset-ids.ts';
|
|
76
|
+
import { type SessionEngineCache, type SessionEngineSwitcher, type SessionSeat } from './session-engine.ts';
|
|
77
|
+
import { type en } from './locales.ts';
|
|
78
|
+
/** Injected dependencies of {@link LoopEngineComposerSelect} (slot `inject`). */
|
|
79
|
+
export interface LoopEngineComposerSelectInjected {
|
|
80
|
+
/** The selection store (loaded on mount, refreshed by scope pushes). */
|
|
81
|
+
controller: LoopEngineStore;
|
|
82
|
+
hooks: {
|
|
83
|
+
/** Engine snapshot bound by the UI renderer as useSnapshot. */
|
|
84
|
+
snapshot: SnapshotStore<LoopEngineState>;
|
|
85
|
+
};
|
|
86
|
+
/** The plugin's authoritative per-session engine cache. */
|
|
87
|
+
sessionEngines: SessionEngineCache;
|
|
88
|
+
/** Move one session to another engine. */
|
|
89
|
+
switchEngine: SessionEngineSwitcher;
|
|
90
|
+
/** Composer copy bound to the loop engine dictionaries. */
|
|
91
|
+
t: (key: keyof typeof en) => string;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Props delivered by the slot outlet (the renderer erases the share boundary).
|
|
95
|
+
* The seat members stay partial here so the registration face matches the slot's
|
|
96
|
+
* own props; {@link ComposerFace} asserts them the way the component reads them.
|
|
97
|
+
*/
|
|
98
|
+
export type LoopEngineComposerSelectProps = PropsRuntime<'conversation.input.right'> & Partial<SessionSeat> & Partial<InjectFace<LoopEngineComposerSelectInjected>>;
|
|
99
|
+
/**
|
|
100
|
+
* One engine's mark, tinted by `currentColor` so it follows the trigger and menu
|
|
101
|
+
* text. The composer bundle is esbuild-built without a CSS loader, so these are
|
|
102
|
+
* inline SVGs.
|
|
103
|
+
*
|
|
104
|
+
* The paths live in `./engine-marks.ts` as DATA, not here: they come from each
|
|
105
|
+
* vendor's own artwork (traced or measured — see that module), and putting them
|
|
106
|
+
* in a data module is what lets a test assert that every registered engine has a
|
|
107
|
+
* mark. That assertion matters: when four engines were added, all four fell
|
|
108
|
+
* through to `default` and rendered the harness's DeepSeek fish beside their
|
|
109
|
+
* names.
|
|
110
|
+
*
|
|
111
|
+
* `in-process` is the one session kind that really is DeepSeek's, so it is the
|
|
112
|
+
* one that keeps the fish.
|
|
113
|
+
* @param engine - the engine whose mark to draw.
|
|
114
|
+
* @param size - edge length in CSS pixels.
|
|
115
|
+
* @returns the mark, as an inline SVG.
|
|
116
|
+
*/
|
|
117
|
+
export declare function engineGlyph(engine: LoopEngineId, size?: number): JSX.Element;
|
|
118
|
+
/**
|
|
119
|
+
* Render the composer's loop-engine dropdown for the session on screen. Hides
|
|
120
|
+
* until the settings scope settles, so the picker never flashes a provisional
|
|
121
|
+
* default while a session's own engine is already known.
|
|
122
|
+
* @param props - composed slot props.
|
|
123
|
+
* @returns the picker, or null while the picker is unavailable or switched off.
|
|
124
|
+
*/
|
|
125
|
+
export declare function LoopEngineComposerSelect(props: LoopEngineComposerSelectProps): JSX.Element | null;
|
|
126
|
+
//# sourceMappingURL=LoopEngineComposerSelect.d.ts.map
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Loop engine settings section component: one dropdown choosing the DEFAULT
|
|
3
|
+
* agent loop engine for new sessions, backed by the duplicated settings scope
|
|
4
|
+
* through the inject face. The commit is confirmed first because it changes
|
|
5
|
+
* what every future session runs; sessions that already exist keep the engine
|
|
6
|
+
* they run, so nothing is interrupted and nothing reloads.
|
|
7
|
+
*
|
|
8
|
+
* Styling is token-driven like the rest of the settings shell (`--dsw-*`
|
|
9
|
+
* aliases), with the picker rendered through the shared `Menu` primitive and
|
|
10
|
+
* the confirmation through `Modal`. The client-module bundle is esbuild-built
|
|
11
|
+
* without a CSS loader, so the section shell uses token-based inline styles
|
|
12
|
+
* instead of a CSS module.
|
|
13
|
+
* @module dsh-loop-engine-allinone/client
|
|
14
|
+
*/
|
|
15
|
+
import { type JSX } from 'react';
|
|
16
|
+
import type { SnapshotStore } from '@deepseek-ai/dsh-client-store';
|
|
17
|
+
import type { InjectFace } from '@deepseek-ai/dsh-client-ui-slots';
|
|
18
|
+
import type { LoopEngineStore, LoopEngineState } from './store.ts';
|
|
19
|
+
import type { en } from './locales.ts';
|
|
20
|
+
/** Injected dependencies of {@link LoopEngineSection} (slot `inject`). */
|
|
21
|
+
export interface LoopEngineSectionInjected {
|
|
22
|
+
/** The selection store (loaded on mount, refreshed by scope pushes). */
|
|
23
|
+
controller: LoopEngineStore;
|
|
24
|
+
hooks: {
|
|
25
|
+
/** Section snapshot bound by the UI renderer as useSnapshot. */
|
|
26
|
+
snapshot: SnapshotStore<LoopEngineState>;
|
|
27
|
+
};
|
|
28
|
+
/** Section copy. */
|
|
29
|
+
t: (key: keyof typeof en) => string;
|
|
30
|
+
}
|
|
31
|
+
/** Props delivered by the slot outlet (the renderer erases the share boundary). */
|
|
32
|
+
export type LoopEngineSectionProps = Partial<InjectFace<LoopEngineSectionInjected>>;
|
|
33
|
+
/** Render the engine dropdown plus the interrupt notice and the switch confirmation. */
|
|
34
|
+
export declare function LoopEngineSection(props: LoopEngineSectionProps): JSX.Element;
|
|
35
|
+
//# sourceMappingURL=LoopEngineSection.d.ts.map
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One vector mark per hosted engine, as data.
|
|
3
|
+
*
|
|
4
|
+
* Data rather than JSX so it can be TESTED: the composer component cannot be
|
|
5
|
+
* imported by the node test runner (it pulls
|
|
6
|
+
* `@deepseek-ai/dsh-client-ui-primitives`, which resolves React through its own
|
|
7
|
+
* package path rather than through the test alias), while this module imports
|
|
8
|
+
* nothing at all. The regression it guards is concrete: every engine added to the
|
|
9
|
+
* registry once fell through the mark switch's `default` arm and rendered the
|
|
10
|
+
* harness's own DeepSeek fish beside its name.
|
|
11
|
+
*
|
|
12
|
+
* `in-process` is deliberately absent: it is the harness's own loop, it really is
|
|
13
|
+
* DeepSeek's, and its mark is the `FishLogo` component rather than a path here.
|
|
14
|
+
*
|
|
15
|
+
* ## Where each mark comes from
|
|
16
|
+
*
|
|
17
|
+
* The four original engines carry their vendors' published paths. The four added
|
|
18
|
+
* by the registry fork are traced or measured from the vendors' OWN artwork found
|
|
19
|
+
* on this machine (see `data/trace-icons.py`, which records the source file and
|
|
20
|
+
* the mask rule for each), because hand-drawing them produced shapes that did not
|
|
21
|
+
* resemble the real marks.
|
|
22
|
+
*
|
|
23
|
+
* Each mark keeps its own `viewBox` and `fillRule`: they come from different
|
|
24
|
+
* sources at different scales, and normalizing them would either distort the
|
|
25
|
+
* vendor's proportions or force a re-trace for no gain.
|
|
26
|
+
*
|
|
27
|
+
* @module dsh-loop-engine-allinone/client/engine-marks
|
|
28
|
+
*/
|
|
29
|
+
import type { HostedEngineId } from '../engine-registry.ts';
|
|
30
|
+
/** One engine's mark, ready to render as a single `<path>`. */
|
|
31
|
+
export interface EngineMark {
|
|
32
|
+
/** The source artwork's own coordinate system. */
|
|
33
|
+
readonly viewBox: string;
|
|
34
|
+
/** Path data, in that coordinate system. */
|
|
35
|
+
readonly d: string;
|
|
36
|
+
/**
|
|
37
|
+
* `evenodd` for marks that rely on a counter (a hole); omitted for the default
|
|
38
|
+
* `nonzero`, which is what a single solid path needs.
|
|
39
|
+
*/
|
|
40
|
+
readonly fillRule?: 'nonzero' | 'evenodd';
|
|
41
|
+
/**
|
|
42
|
+
* A second subpath drawn in its OWN colour, for a mark whose brand identity is
|
|
43
|
+
* two-tone (Kimi's white "K" carries a blue dot).
|
|
44
|
+
*
|
|
45
|
+
* Everything else stays `currentColor`, so the mark follows the menu's text
|
|
46
|
+
* colour; an accent is the deliberate exception, and it exists rather than a
|
|
47
|
+
* two-tone path because a single `d` can only be filled one way.
|
|
48
|
+
*/
|
|
49
|
+
readonly accent?: {
|
|
50
|
+
readonly d: string;
|
|
51
|
+
readonly fill: string;
|
|
52
|
+
};
|
|
53
|
+
/**
|
|
54
|
+
* Draw the path as a STROKE rather than a fill, at this width in viewBox units.
|
|
55
|
+
*
|
|
56
|
+
* Some vendors publish the same mark twice: a solid app-tile version and a
|
|
57
|
+
* monochrome outline one. Qoder is such a case, and the outline is the variant
|
|
58
|
+
* that matches how the other marks read here.
|
|
59
|
+
*/
|
|
60
|
+
readonly strokeWidth?: number;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* How one mark should be painted, decided once.
|
|
64
|
+
*
|
|
65
|
+
* Both the component (JSX props) and the preview scripts (SVG attribute strings)
|
|
66
|
+
* read this, because they each used to decide for themselves — and the preview
|
|
67
|
+
* silently kept rendering a fill after Qoder's mark became a stroke, so the
|
|
68
|
+
* picture I was judging by was no longer the picture the picker draws.
|
|
69
|
+
*/
|
|
70
|
+
export interface MarkPaint {
|
|
71
|
+
/** Paint the path's interior, or trace its outline. */
|
|
72
|
+
readonly mode: 'fill' | 'stroke';
|
|
73
|
+
/** The paint colour. */
|
|
74
|
+
readonly colour: string;
|
|
75
|
+
/** Stroke width in viewBox units; present only in `stroke` mode. */
|
|
76
|
+
readonly width?: number;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Resolve how to paint one mark.
|
|
80
|
+
* @param mark - the engine's mark.
|
|
81
|
+
* @param colour - the colour the surface wants (`currentColor` resolves to it).
|
|
82
|
+
* @returns the paint decision.
|
|
83
|
+
*/
|
|
84
|
+
export declare function markPaint(mark: EngineMark, colour: string): MarkPaint;
|
|
85
|
+
/** Every hosted engine's mark, keyed by engine id. */
|
|
86
|
+
export declare const ENGINE_MARKS: Readonly<Record<HostedEngineId, EngineMark>>;
|
|
87
|
+
//# sourceMappingURL=engine-marks.d.ts.map
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Loop engine settings plugin, browser half. Registers the "Loop engine" page
|
|
3
|
+
* under the settings section slot and binds one store to whichever settings
|
|
4
|
+
* client the running harness serves: the 0.1.7 `configForms` form for the
|
|
5
|
+
* plugin's own `loop-engine` profile entry, or the 0.1.5 `settingsScope` for its
|
|
6
|
+
* `agent-loop-engine` settings section. Two inject callbacks register the page,
|
|
7
|
+
* one per generation — whichever service exists fires, and the client bundle
|
|
8
|
+
* never imports a host package, so it cannot probe the generation like the node
|
|
9
|
+
* half does.
|
|
10
|
+
* Export discipline: packages/client/AGENTS.md.
|
|
11
|
+
* @module dsh-loop-engine-allinone/client
|
|
12
|
+
*/
|
|
13
|
+
import type { Context as ClientContext } from '@deepseek-ai/cordis';
|
|
14
|
+
import { type LoopEngineKey } from './locales.ts';
|
|
15
|
+
export type { LoopEngineSectionInjected, LoopEngineSectionProps } from './LoopEngineSection.tsx';
|
|
16
|
+
export type { LoopEngineBadgeInjected, LoopEngineBadgeProps } from './LoopEngineBadge.tsx';
|
|
17
|
+
export type { LoopEngineComposerSelectInjected, LoopEngineComposerSelectProps } from './LoopEngineComposerSelect.tsx';
|
|
18
|
+
export type { LoopEngineState } from './store.ts';
|
|
19
|
+
declare module '@deepseek-ai/dsh-client-ui-slots' {
|
|
20
|
+
interface LocaleNamespaceMap {
|
|
21
|
+
/** The Loop engine settings page copy. */
|
|
22
|
+
'settings.loop-engine': LoopEngineKey;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Required services (cordis fiber inject). Only the services BOTH generations
|
|
27
|
+
* provide are listed statically: `configForms` (0.1.7) and `settingsScope`
|
|
28
|
+
* (0.1.5) are mutually exclusive, so each is injected inside its own callback
|
|
29
|
+
* rather than named here. The target slot is declared by ui-settings' apply;
|
|
30
|
+
* registration depends on it through `slots.inject()`.
|
|
31
|
+
*/
|
|
32
|
+
export declare const inject: string[];
|
|
33
|
+
/**
|
|
34
|
+
* Register the Loop engine section once the `settings.section` declaration is
|
|
35
|
+
* on the ledger and bind its store to whichever settings client is present.
|
|
36
|
+
* @param ctx - client root context.
|
|
37
|
+
*/
|
|
38
|
+
export declare function apply(ctx: ClientContext): void;
|
|
39
|
+
//# sourceMappingURL=index.d.ts.map
|