dsh-loop-engine-allinone 0.0.0-stage → 0.4.1

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.
Files changed (143) hide show
  1. package/CHANGELOG.md +119 -0
  2. package/CONTRIBUTING.md +78 -0
  3. package/LICENSE +23 -0
  4. package/NOTICE +45 -0
  5. package/README.md +223 -2
  6. package/README.zh.md +179 -0
  7. package/SECURITY.md +39 -0
  8. package/cordis.patch.yml +3 -0
  9. package/lib/client.js +2166 -0
  10. package/lib/index.js +11621 -0
  11. package/lib/invariant.js +453 -0
  12. package/lib/types/agent-preset-ids.d.ts +276 -0
  13. package/lib/types/client/LoopEngineBadge.d.ts +71 -0
  14. package/lib/types/client/LoopEngineComposerSelect.d.ts +126 -0
  15. package/lib/types/client/LoopEngineSection.d.ts +35 -0
  16. package/lib/types/client/engine-marks.d.ts +87 -0
  17. package/lib/types/client/index.d.ts +39 -0
  18. package/lib/types/client/locales.d.ts +182 -0
  19. package/lib/types/client/reload.d.ts +135 -0
  20. package/lib/types/client/session-engine.d.ts +508 -0
  21. package/lib/types/client/store.d.ts +103 -0
  22. package/lib/types/client/turn-status.d.ts +234 -0
  23. package/lib/types/client/use-session-engine.d.ts +74 -0
  24. package/lib/types/commands.d.ts +77 -0
  25. package/lib/types/compat.d.ts +25 -0
  26. package/lib/types/driver-acp/agent.d.ts +289 -0
  27. package/lib/types/driver-acp/approval.d.ts +27 -0
  28. package/lib/types/driver-acp/capabilities.d.ts +200 -0
  29. package/lib/types/driver-acp/client.d.ts +297 -0
  30. package/lib/types/driver-acp/executable.d.ts +53 -0
  31. package/lib/types/driver-acp/mapping.d.ts +76 -0
  32. package/lib/types/driver-acp/profile.d.ts +126 -0
  33. package/lib/types/driver-acp/runtime.d.ts +45 -0
  34. package/lib/types/driver-acp/subprocess.d.ts +19 -0
  35. package/lib/types/driver-acp/terminal.d.ts +98 -0
  36. package/lib/types/driver-acp/transport.d.ts +43 -0
  37. package/lib/types/driver-acp/types.d.ts +152 -0
  38. package/lib/types/driver-cli/capability.d.ts +42 -0
  39. package/lib/types/driver-cli/cli-agent.d.ts +258 -0
  40. package/lib/types/driver-cli/cli-loop.d.ts +46 -0
  41. package/lib/types/driver-cli/flatten.d.ts +35 -0
  42. package/lib/types/driver-cli/frames.d.ts +128 -0
  43. package/lib/types/driver-cli/ndjson.d.ts +106 -0
  44. package/lib/types/driver-cli/session-sink.d.ts +333 -0
  45. package/lib/types/driver-cli/stream-json.d.ts +61 -0
  46. package/lib/types/driver-cli/text.d.ts +66 -0
  47. package/lib/types/driver-cli/transport.d.ts +84 -0
  48. package/lib/types/driver-core/agents-md-skill-provider.d.ts +72 -0
  49. package/lib/types/driver-core/assistant-stream.d.ts +68 -0
  50. package/lib/types/driver-core/context-files.d.ts +62 -0
  51. package/lib/types/driver-core/host-servers.d.ts +119 -0
  52. package/lib/types/driver-core/hosted-engine-runtime.d.ts +190 -0
  53. package/lib/types/driver-core/hosted-tool-vocabulary.d.ts +78 -0
  54. package/lib/types/driver-core/idle-child.d.ts +57 -0
  55. package/lib/types/driver-core/image-access.d.ts +25 -0
  56. package/lib/types/driver-core/inbox.d.ts +104 -0
  57. package/lib/types/driver-core/model-handover.d.ts +134 -0
  58. package/lib/types/driver-core/ownership.d.ts +41 -0
  59. package/lib/types/driver-core/permission-knobs.d.ts +26 -0
  60. package/lib/types/driver-core/prompt.d.ts +64 -0
  61. package/lib/types/driver-core/session-lifetime.d.ts +62 -0
  62. package/lib/types/driver-core/session-model.d.ts +128 -0
  63. package/lib/types/driver-core/skill-inject.d.ts +59 -0
  64. package/lib/types/driver-core/step-close.d.ts +49 -0
  65. package/lib/types/driver-core/step-images.d.ts +62 -0
  66. package/lib/types/driver-core/step-tools.d.ts +43 -0
  67. package/lib/types/driver-core/system-head.d.ts +43 -0
  68. package/lib/types/engine-agy/agent.d.ts +67 -0
  69. package/lib/types/engine-agy/frames.d.ts +90 -0
  70. package/lib/types/engine-agy/loop.d.ts +64 -0
  71. package/lib/types/engine-agy/process.d.ts +173 -0
  72. package/lib/types/engine-claude/agent.d.ts +186 -0
  73. package/lib/types/engine-claude/loop.d.ts +73 -0
  74. package/lib/types/engine-claude/mapping.d.ts +108 -0
  75. package/lib/types/engine-claude/permission.d.ts +41 -0
  76. package/lib/types/engine-claude/process.d.ts +59 -0
  77. package/lib/types/engine-claude/sdk.d.ts +67 -0
  78. package/lib/types/engine-claude/types.d.ts +28 -0
  79. package/lib/types/engine-codex/agent.d.ts +216 -0
  80. package/lib/types/engine-codex/appserver/client.d.ts +80 -0
  81. package/lib/types/engine-codex/appserver/mapping.d.ts +67 -0
  82. package/lib/types/engine-codex/appserver/thread.d.ts +66 -0
  83. package/lib/types/engine-codex/appserver/types.d.ts +225 -0
  84. package/lib/types/engine-codex/loop.d.ts +75 -0
  85. package/lib/types/engine-codex/model-handover.d.ts +56 -0
  86. package/lib/types/engine-codex/permission.d.ts +126 -0
  87. package/lib/types/engine-codex/skills.d.ts +28 -0
  88. package/lib/types/engine-codex/types.d.ts +36 -0
  89. package/lib/types/engine-drivers.d.ts +132 -0
  90. package/lib/types/engine-grok/agent.d.ts +24 -0
  91. package/lib/types/engine-grok/loop.d.ts +61 -0
  92. package/lib/types/engine-grok/process.d.ts +46 -0
  93. package/lib/types/engine-grok/profile.d.ts +82 -0
  94. package/lib/types/engine-hermes/agent.d.ts +47 -0
  95. package/lib/types/engine-hermes/loop.d.ts +56 -0
  96. package/lib/types/engine-hermes/process.d.ts +92 -0
  97. package/lib/types/engine-kimi/acp/client.d.ts +123 -0
  98. package/lib/types/engine-kimi/acp/mapping.d.ts +73 -0
  99. package/lib/types/engine-kimi/acp/types.d.ts +143 -0
  100. package/lib/types/engine-kimi/agent.d.ts +24 -0
  101. package/lib/types/engine-kimi/commands.d.ts +44 -0
  102. package/lib/types/engine-kimi/loop.d.ts +62 -0
  103. package/lib/types/engine-kimi/model-handover.d.ts +32 -0
  104. package/lib/types/engine-kimi/permission.d.ts +28 -0
  105. package/lib/types/engine-kimi/process.d.ts +47 -0
  106. package/lib/types/engine-kimi/profile.d.ts +19 -0
  107. package/lib/types/engine-kimi/skills.d.ts +52 -0
  108. package/lib/types/engine-kimi/types.d.ts +25 -0
  109. package/lib/types/engine-minimaxcode/agent.d.ts +24 -0
  110. package/lib/types/engine-minimaxcode/loop.d.ts +83 -0
  111. package/lib/types/engine-minimaxcode/process.d.ts +53 -0
  112. package/lib/types/engine-minimaxcode/profile.d.ts +72 -0
  113. package/lib/types/engine-of-session.d.ts +97 -0
  114. package/lib/types/engine-pi/agent.d.ts +230 -0
  115. package/lib/types/engine-pi/loop.d.ts +72 -0
  116. package/lib/types/engine-pi/model-handover.d.ts +84 -0
  117. package/lib/types/engine-pi/permission.d.ts +47 -0
  118. package/lib/types/engine-pi/rpc/client.d.ts +107 -0
  119. package/lib/types/engine-pi/rpc/mapping.d.ts +37 -0
  120. package/lib/types/engine-pi/rpc/types.d.ts +249 -0
  121. package/lib/types/engine-pi/skills.d.ts +47 -0
  122. package/lib/types/engine-pi/types.d.ts +36 -0
  123. package/lib/types/engine-qoderclicn/agent.d.ts +59 -0
  124. package/lib/types/engine-qoderclicn/loop.d.ts +51 -0
  125. package/lib/types/engine-qoderclicn/process.d.ts +113 -0
  126. package/lib/types/engine-registry.d.ts +584 -0
  127. package/lib/types/engine-remote.d.ts +192 -0
  128. package/lib/types/engine-surface.d.ts +36 -0
  129. package/lib/types/engine-zcode/agent.d.ts +50 -0
  130. package/lib/types/engine-zcode/loop.d.ts +47 -0
  131. package/lib/types/engine-zcode/process.d.ts +111 -0
  132. package/lib/types/index.d.ts +205 -0
  133. package/lib/types/invariant.d.ts +26 -0
  134. package/lib/types/model-selection-reset.d.ts +271 -0
  135. package/lib/types/namespace.d.ts +25 -0
  136. package/lib/types/patch-manager.d.ts +104 -0
  137. package/lib/types/preset.d.ts +254 -0
  138. package/lib/types/provider-route.d.ts +245 -0
  139. package/lib/types/router-loop.d.ts +458 -0
  140. package/lib/types/session-engine-store.d.ts +138 -0
  141. package/lib/types/settings.d.ts +60 -0
  142. package/lib/types/skills.d.ts +85 -0
  143. package/package.json +152 -6
@@ -0,0 +1,234 @@
1
+ /**
2
+ * Per-engine styling for the chat turn-status line (the "深度求索中..." row).
3
+ *
4
+ * That row is rendered from inside the harness's ChatView and its words belong
5
+ * to ui-chat: the row is not a slot, and ui-chat owns the `chat` locale
6
+ * namespace (a second `locale.register` for the same namespace throws), so a
7
+ * plugin cannot change the text. What it CAN do is restyle the element, and
8
+ * that is all this module does — it paints an engine-specific glyph and color
9
+ * onto the row while the session on screen runs a hosted engine, and leaves the
10
+ * stock look alone otherwise. On the 0.2.0 line it also takes the harness's own
11
+ * indicator out of that row ({@link RUNNING_ICON}): that generation draws a
12
+ * DeepSeek whale there, and a hosted engine turning under a DeepSeek mark is
13
+ * exactly what this row must not say.
14
+ *
15
+ * WHICH engine it paints is the SESSION ON SCREEN's, not the settings default.
16
+ * {@link reflectTurnStatusEngine} is driven from the per-session engine cache
17
+ * (`./session-engine.ts`) — the same authoritative answer the header chip and
18
+ * the composer render from, the plugin's own Remote read off the session's
19
+ * durable log — and it is driven by the ONE hook those two surfaces share
20
+ * (`./use-session-engine.ts`). So this row cannot disagree with the two surfaces
21
+ * beside it; while it was keyed off the settings store it did, and painted
22
+ * Claude Code's glyph onto every session's row whenever claude-code was the
23
+ * default, a session running pi included.
24
+ *
25
+ * The reflection's SUBJECT is still a document-level attribute rather than the
26
+ * row's own element: the sheet has to reach a class the harness hashes (see
27
+ * {@link ROW_SELECTORS}), which takes an attribute selector on an ancestor,
28
+ * and the row offers no session-scoped hook for a plugin to hang it on — the one
29
+ * attribute this module does put on a row ({@link LIVE_ATTR}) claims no session,
30
+ * it says "the turn in flight is this one" and is re-derived every time the rows
31
+ * change. A document-level attribute has exactly ONE owner at a time, though —
32
+ * and on this page the WRITERS outnumber the reader: the chip and the composer of every
33
+ * session that has been rendered carry an answer, the session the user has just
34
+ * left included, and the cache publishes a session's answer regardless of what is
35
+ * on screen. So "whoever reflected last" is not "the session on screen", and an
36
+ * implementation that read it as one shipped the bug this guard ends: a
37
+ * background session's answer — or the late answer of the session the user just
38
+ * left — painted ITS engine onto the row of the session on screen, and a session
39
+ * running pi showed Kimi's moon.
40
+ *
41
+ * The owner is therefore DECLARED, not inferred: a reflection names the session
42
+ * it speaks for and writes only while that session is the row's focus
43
+ * ({@link focusTurnStatusSession}); a reflection whose subject is not the focused
44
+ * session is a NO-OP, so only the session on screen can paint and only it can
45
+ * un-paint. The chip and the composer of one session reflect the same value (the
46
+ * write is idempotent); the focus is withdrawn by
47
+ * {@link blurTurnStatusSession}, which acts only while the focus is still the
48
+ * departing session's (React runs a departing component's cleanup in no
49
+ * guaranteed order against an arriving one's, so an unconditional withdrawal
50
+ * would un-focus the session that just took over); and the attribute itself is
51
+ * never withdrawn on unmount: the sibling surface of the same session still
52
+ * paints by it, and a leftover attribute is inert on a page whose turn-status row
53
+ * is not rendered.
54
+ *
55
+ * The paint is gated TWICE, and both gates are needed on the 0.1.7 line — the
56
+ * 0.2.0 line needs neither of them, for the reason given below.
57
+ *
58
+ * First, on the session being MID-TURN, through a second document-level
59
+ * attribute ({@link RUNNING_ATTR}, written from the same reflection). On the
60
+ * 0.1.5 line the row only exists while a turn is in flight, so the engine
61
+ * attribute alone was enough; on the 0.1.7 line that same button stays on screen
62
+ * after the turn ends, as the collapsed summary that reads "用时 4秒" — an
63
+ * engine-only gate leaves the glyph and the sweep animating on a finished turn,
64
+ * which is not what the live line means. The gate is a surface's own answer
65
+ * (`session.running`, which every session-scoped seat receives), so a surface
66
+ * that cannot answer passes nothing and leaves it alone rather than guessing.
67
+ *
68
+ * Second, and this is the one a session-level gate cannot express: on the
69
+ * 0.1.7 line EVERY turn's row stays on screen, so while turn N runs, turns
70
+ * 1..N-1 are still there. A session-wide gate turns the whole sheet on for all
71
+ * of them — the finished rows would wear the glyph again for as long as any
72
+ * later turn ran. So the live row is MARKED, and the row selector is gated on
73
+ * the mark (see {@link LIVE_ATTR}, {@link markLiveRow} and
74
+ * {@link ROW_SELECTORS}): "the last row in the document" is the turn in flight,
75
+ * because the rows are rendered in turn order and only the newest one can still
76
+ * be running. The two gates answer different questions — "is a turn in flight
77
+ * for this session" and "is this row the one it belongs to" — and neither alone
78
+ * is enough.
79
+ *
80
+ * The 0.2.0 line needs NEITHER gate, because it moved the live row out of the
81
+ * turn-process button. There the running indicator is the harness's own node —
82
+ * `RunningStatus`, a `[data-chat-running]` div mounted only while the session
83
+ * runs — and `TurnProcessNodeView` renders nothing at all until its turn closes,
84
+ * so a turn-process button is now always a settled summary. The third sheet
85
+ * ({@link sheetForRunning}) is therefore gated on the engine attribute alone,
86
+ * and the per-row mark is not merely unnecessary there but WRONG:
87
+ * {@link markLiveRow} stamps nothing while such a node is on screen, because the
88
+ * last turn-process button on that page is a finished turn's summary — exactly
89
+ * the row the mark exists to leave alone.
90
+ *
91
+ * Three facts about the harness markup make that safe and specific:
92
+ * - the row has one stable handle per harness generation — an
93
+ * `[hash]_turnStatus` class suffix on the 0.1.5 line, the
94
+ * `data-turn-process` button on the 0.1.7 line (whose text is a `<span>`
95
+ * whose hashed class ends `_label`), and the harness's own
96
+ * `data-chat-running` attribute on the 0.2.0 line — so each generation gets
97
+ * its own copy of the sheet ({@link ROW_SELECTORS}, {@link RUNNING_ROW}) and
98
+ * the one the running app renders matches while the others stay inert;
99
+ * - its colours paint through custom properties — the 0.1.x rows through the
100
+ * `--dsw-static-deepseek-*` gradient pair, 0.2.0's through the
101
+ * `--dsw-alias-label-deep-diving*` pair it resolves its own text colour and
102
+ * shimmer tint from — so recoloring is a variable override rather than a
103
+ * fight over `background` and `background-clip` or over the harness's own
104
+ * animation;
105
+ * - the glyph rides a `::before` pseudo-element, so the row's real text node
106
+ * — and the status it announces — is untouched.
107
+ *
108
+ * This sheet deliberately keeps the 0.1.x rows animating even when the OS
109
+ * reports `prefers-reduced-motion: reduce` (see the re-asserted sweep below):
110
+ * the deployment's Windows images ship with client-area animation off, which
111
+ * otherwise freezes every indicator here — the sweep and the glyph alike. On the
112
+ * 0.2.0 line the harness runs its own shimmer and honours that preference
113
+ * itself, so the plugin neither re-declares it nor overrides it there; only the
114
+ * glyph keeps animating. In-process sessions keep the stock reduced-motion
115
+ * behaviour on every line.
116
+ *
117
+ * @module dsh-loop-engine-allinone/client/turn-status
118
+ */
119
+ import type { Context as ClientContext } from '@deepseek-ai/cordis';
120
+ import type { LoopEngineId, HostedEngineId } from '../agent-preset-ids.ts';
121
+ /**
122
+ * One engine's paint: the colours, the glyph and the animation that drives it.
123
+ *
124
+ * Exported for the coverage test, which asserts that EVERY hosted engine has an
125
+ * entry here. Without that assertion a new engine silently keeps the row
126
+ * unpainted — and because the 0.2.0 sheet hides the harness's own whale on any
127
+ * `data-loop-engine` value, "unpainted" does not fall back to the DeepSeek
128
+ * brand, it falls back to nothing at all.
129
+ */
130
+ export interface EnginePaint {
131
+ /** The text's own colour — and the glyph's, where the glyph is not an emoji. */
132
+ readonly colour: string;
133
+ /** The lighter tint the sweep (0.1.x gradient, 0.2.0 overlay) travels in. */
134
+ readonly tint: string;
135
+ /** The glyph itself, unquoted; the glyph rule adds the `content` quoting. */
136
+ readonly glyph: string;
137
+ /** Further declarations the glyph rule carries after `color`, in order. */
138
+ readonly extras: readonly string[];
139
+ /** The `animation` shorthand driving the glyph; its `@keyframes` is below. */
140
+ readonly animation: string;
141
+ }
142
+ /**
143
+ * Every hosted engine's paint, in the order the sheets emit it.
144
+ *
145
+ * This is the one place an engine's identity on the row lives. The pair is the
146
+ * same on every generation — a base colour and the lighter tint its sweep
147
+ * travels in — and only the custom properties it is written to change, so a
148
+ * sheet is this table emitted through that generation's selectors and variables
149
+ * rather than a second copy of the engine roster.
150
+ */
151
+ export declare const ENGINE_PAINT: ReadonlyArray<readonly [HostedEngineId, EnginePaint]>;
152
+ /**
153
+ * Reflect the engine of the session ON SCREEN; `undefined` restores the stock
154
+ * row.
155
+ *
156
+ * The caller names the session it speaks for, and that is the row's SUBJECT: a
157
+ * reflection paints its session's engine only while that session is the focused
158
+ * one ({@link focusTurnStatusSession}), and is a NO-OP otherwise — the whole
159
+ * guard, and the reason the attribute can no longer be taken over by a session
160
+ * the user is not looking at. The subject is an explicit argument rather than
161
+ * ambient state, so a caller cannot reflect without saying whose engine it is,
162
+ * and cannot say "whoever, I don't know".
163
+ *
164
+ * `in-process` is the harness's own row, and `undefined` is every answer that
165
+ * names no engine at all: a session the host reports as `legacy` (it ran a
166
+ * hosted engine, the id never said which) or `unset`, a session whose first
167
+ * answer has not landed yet, and an answer dropped in preparation for a re-read.
168
+ * None of them paints — naming an engine for an unknown one is the misreport
169
+ * this module was fixed for — so each clears the attribute. The clear is as
170
+ * authoritative as the paint: a session that takes the focus with no answer yet
171
+ * takes the previous session's paint off with it.
172
+ *
173
+ * The write is idempotent and never a withdrawal: the chip and the composer of
174
+ * one session both come through here with the same value, and unmounting never
175
+ * clears the attribute, because the sibling surface of the same session is still
176
+ * on screen painting through it.
177
+ *
178
+ * The MID-TURN gate is written from here as well, but only by a surface that can
179
+ * answer it (`running` given): the sheet is gated on both, because the 0.1.7 row
180
+ * outlives its turn, and a surface with no answer must leave the gate as the
181
+ * surface that has one left it rather than guess.
182
+ *
183
+ * The NO-OP covers the late reflection as well — the one from the session the
184
+ * user has just left, whose own answer landing after the switch used to paint
185
+ * over the session that replaced it.
186
+ * @param sessionId - the session this reflection speaks for, or undefined for a
187
+ * page with no session at all (the new-session page, which has no turn-status
188
+ * row): such a page has nothing to say about the row, so nothing is written and
189
+ * nothing is withdrawn — it leaves the row it found alone.
190
+ * @param engine - the engine that session runs, when it is known.
191
+ * @param running - whether that session is mid-turn, when the surface knows;
192
+ * omitted by a surface with no answer, which leaves the gate alone.
193
+ */
194
+ export declare function reflectTurnStatusEngine(sessionId: string | undefined, engine: LoopEngineId | undefined, running?: boolean): void;
195
+ /**
196
+ * Declare which session's surfaces are on screen — the row's one subject.
197
+ *
198
+ * Only the focused session may paint ({@link reflectTurnStatusEngine}), which is
199
+ * what keeps the row on the session the user is looking at: the alternative,
200
+ * "whoever writes last owns the row", was the bug this guard ends, because the
201
+ * chip and the composer of EVERY session that has been rendered write here, and
202
+ * a session's answer can land after the user has left it.
203
+ *
204
+ * The caller is the component that renders that session: only a component knows
205
+ * which session is the one on screen, and the hook both of that session's
206
+ * surfaces share (`./use-session-engine.ts`) is the only place that declares it.
207
+ * @param sessionId - the session whose surfaces are now on screen.
208
+ */
209
+ export declare function focusTurnStatusSession(sessionId: string): void;
210
+ /**
211
+ * Withdraw the focus — but only while it is still this session's.
212
+ *
213
+ * The guard is the point: React offers no ordering guarantee between a departing
214
+ * component's cleanup and an arriving one's, so an unconditional withdrawal would
215
+ * let the session the user has just left un-focus the session that replaced it
216
+ * and silence the row. A session that is no longer the focus has nothing to
217
+ * withdraw; unmounting also never clears the attribute itself, which the sibling
218
+ * surface of the same session (and, for a session that is still on screen, the
219
+ * next focus) still paints by.
220
+ * @param sessionId - the session whose surface is going away.
221
+ */
222
+ export declare function blurTurnStatusSession(sessionId: string): void;
223
+ /**
224
+ * Install the per-engine turn-status stylesheet for the lifetime of `ctx`.
225
+ *
226
+ * This is the sheet and nothing else: which engine it selects is written by
227
+ * {@link reflectTurnStatusEngine}, driven from the session on screen's own
228
+ * authoritative answer (`./session-engine.ts`), through the hook the chip and
229
+ * the composer share (`./use-session-engine.ts`) — not from the settings
230
+ * default.
231
+ * @param ctx - the client root context.
232
+ */
233
+ export declare function installTurnStatusStyles(ctx: ClientContext): void;
234
+ //# sourceMappingURL=turn-status.d.ts.map
@@ -0,0 +1,74 @@
1
+ /**
2
+ * The React binding over the plugin's per-session engine cache.
3
+ *
4
+ * Separated from `./session-engine.ts` on purpose: the cache, the contribution,
5
+ * and the switcher are plain logic with no React import, so they are exercised
6
+ * in node (`tests/session-engine-cache.spec.ts`) — this file is the only part of
7
+ * the read path that needs a component to render.
8
+ *
9
+ * It is also the ONE driver of the chat turn-status row
10
+ * (`./turn-status.ts`): the row is painted through a document-level attribute,
11
+ * and a component is the only place that knows whether the session it renders is
12
+ * the one on screen. The cache cannot know that — it answers for every session a
13
+ * surface has watched — so a reflection made from there could be (and was) taken
14
+ * over by a background session. Here the chip and the composer of the session on
15
+ * screen declare that session as the row's subject while they are mounted, with
16
+ * the focus guard inside `reflectTurnStatusEngine`, and the reflection follows
17
+ * the cache's answer so a switch repaints the row.
18
+ *
19
+ * @module dsh-loop-engine-allinone/client/use-session-engine
20
+ */
21
+ import { type SessionEngineReport } from '../agent-preset-ids.ts';
22
+ import type { SessionEngineCache } from './session-engine.ts';
23
+ /**
24
+ * Follow one session's engine report in a component, and — because a component
25
+ * is what knows whether this session is the one on screen — drive the chat
26
+ * turn-status row from it.
27
+ *
28
+ * The value is read from the cache DURING render, so a session switch can never
29
+ * paint the previous session's engine: only the re-render is deferred, and only
30
+ * until the host answers. The reflection runs in an effect rather than during
31
+ * render (it writes to the document), and re-runs when the ANSWER changes — not
32
+ * just when the session id does — so the row follows a switch: the picker's
33
+ * `invalidate` drops the cached answer, the cache re-asks, the hook's watcher
34
+ * bumps, the engine changes, and the attribute lands on the engine the session
35
+ * now runs.
36
+ *
37
+ * Only the ACTUAL engine reaches the row. A recorded engine that differs from it
38
+ * is one whose switch never took over (its release did not complete), so the row
39
+ * keeps painting what is really running — the same rule the chip and the composer
40
+ * follow when they name an engine; they merely also carry the marker
41
+ * ({@link SessionEngineReport}).
42
+ *
43
+ * The value is read from the cache DURING render, so a session switch can never
44
+ * paint the previous session's engine: only the re-render is deferred, and only
45
+ * until the host answers. This effect is also the trigger that re-reads the
46
+ * session: it runs when the session on screen CHANGES (a mount, a switch, or the
47
+ * same session opened again), and the subscription it installs re-reads the
48
+ * session on its first watch (`SessionEngineCache.watch` → `refresh`), so a
49
+ * session the user comes back to cannot keep rendering a report this page took
50
+ * before — coming back is not what moves the session (a switch is performed on
51
+ * the host, and the one that has to release the session reloads this page), but
52
+ * it is long enough for the answer to be old.
53
+ * Re-renders of the same session do not re-run this effect, so nothing here asks
54
+ * again while the session stays on screen.
55
+ *
56
+ * One effect does the whole thing, so the three steps cannot come apart: declare
57
+ * this session as the row's subject (`focusTurnStatusSession`), reflect its
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.
68
+ * @param cache - the cache the plugin mounted.
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.
71
+ * @returns the engine report, or undefined while it is unknown.
72
+ */
73
+ export declare function useEngineOfSession(cache: SessionEngineCache, sessionId: string | undefined, running?: boolean): SessionEngineReport | undefined;
74
+ //# sourceMappingURL=use-session-engine.d.ts.map
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Claude Code slash-command bridge.
3
+ *
4
+ * The dsh `commands` runtime executes a registered command locally — the line
5
+ * is consumed and never reaches the model — so a command whose real processing
6
+ * lives inside the Claude Code CLI must forward the raw line back to the
7
+ * engine. The definitions here do exactly that: the handler delivers
8
+ * `/<name> [args]` to the receiving agent as a plain user message, and the CLI
9
+ * then expands it natively (built-ins and custom `.claude/commands/*.md`).
10
+ * Registering the built-ins keeps them visible in the dsh web slash menu;
11
+ * unregistered `/lines` pass through as user text, but the menu would hide the
12
+ * engine's command surface.
13
+ *
14
+ * User-level custom slash commands (`~/.claude/commands/*.md`) are discovered
15
+ * and registered the same way, so they appear in the menu AND reach the CLI.
16
+ * Project-level `.claude/commands/` files are left to the CLI entirely: they
17
+ * are cwd-dependent, and a global dsh registration would collide across
18
+ * projects.
19
+ *
20
+ * The built-in list is limited to commands the CLI actually recognizes in SDK
21
+ * mode (verified against Claude Code 2.1.220 by driving real SDK queries):
22
+ * unknown ones are not forwarded to the model at all — the CLI answers
23
+ * `Unknown command: /name` — but registering one would still advertise a
24
+ * command that does not exist. Note that some recognized commands report
25
+ * `isn't available in this environment` outside the interactive TUI; that
26
+ * report is the engine's own answer and travels back as an assistant message.
27
+ *
28
+ * @module dsh-loop-engine-allinone/commands
29
+ */
30
+ import type { UserMessage } from '@deepseek-ai/dsh-session';
31
+ /** Minimal shape of a DSH command definition (avoiding a direct peer dep on @deepseek-ai/dsh-commands). */
32
+ export interface CommandDefinition {
33
+ readonly name: string;
34
+ readonly description: string;
35
+ readonly input?: {
36
+ readonly hint: string;
37
+ readonly images?: boolean;
38
+ };
39
+ readonly handler: (invocation: CommandInvocation) => CommandResult | Promise<CommandResult>;
40
+ }
41
+ /** Invocation delivered to one registered command handler. */
42
+ export interface CommandInvocation {
43
+ readonly commandId: string;
44
+ /** The receiving agent; forwarding handlers deliver the raw line back to it. */
45
+ readonly agent: {
46
+ readonly followup: (input: UserMessage) => void;
47
+ };
48
+ /** Exact text following the command name, including separator whitespace. */
49
+ readonly rawInput: string;
50
+ readonly signal: AbortSignal;
51
+ }
52
+ /** Settled result of one command handler. */
53
+ export interface CommandResult {
54
+ readonly kind: 'success' | 'error';
55
+ readonly text?: string;
56
+ }
57
+ /**
58
+ * Build the forwarding handler for one Claude Code slash command: it
59
+ * re-delivers the full `/<name> [args]` line to the receiving agent as a
60
+ * plain user message, where the CLI expands it. `rawInput` already carries the
61
+ * separator whitespace and any arguments.
62
+ * @param name - the command name without the leading slash.
63
+ * @returns the command handler.
64
+ */
65
+ export declare function forwardClaudeCodeCommand(name: string): (invocation: CommandInvocation) => CommandResult;
66
+ /** Claude Code's built-in slash commands. */
67
+ export declare const CLAUDE_CODE_COMMANDS: readonly CommandDefinition[];
68
+ /**
69
+ * Discover the user-level custom slash commands from `~/.claude/commands/*.md`
70
+ * and build forwarding definitions for them. The scan is synchronous so the
71
+ * agent-creation path can register the commands before the agent is published;
72
+ * files without a usable name or description, and names already taken by the
73
+ * built-ins, are skipped.
74
+ * @returns forwarding definitions, sorted by file name.
75
+ */
76
+ export declare function discoverUserSlashCommands(): CommandDefinition[];
77
+ //# sourceMappingURL=commands.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-allinone/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