@try-works/dsh-recursive-mode 0.1.7 → 0.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/client/slots.d.ts +29 -0
- package/lib/client.js +20 -5
- package/package.json +1 -1
- package/src/client/slots.ts +21 -1
package/lib/client/slots.d.ts
CHANGED
|
@@ -1,3 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Slot registrations (SP2 R1 + run 08 R1/R3/R4): the sidebar launcher, the
|
|
3
|
+
* shell.overlay board, the conversation.input.dock status strip, and the
|
|
4
|
+
* settings.section page.
|
|
5
|
+
*
|
|
6
|
+
* Run 08: the launcher now OPENS the shared board store (onClick), and the
|
|
7
|
+
* shell.overlay entry renders the board gated on that store + the recursive
|
|
8
|
+
* preset, swapping to the drill-down inspector when a run is selected.
|
|
9
|
+
*
|
|
10
|
+
* Run 10 (LIVE BUG FIX): useSessions is a SnapshotSelectorHook (NOT a zero-arg
|
|
11
|
+
* thunk) — it is called WITH a selector, e.g. useSessions((s) => s) for the
|
|
12
|
+
* full SessionListStateLike. The old code called useSessions() with NO selector
|
|
13
|
+
* and wrapped the garbage in a fake {list:{getSnapshot}} — so the preset gate
|
|
14
|
+
* never saw the recursive preset and the board never mounted (launcher click
|
|
15
|
+
* did nothing). The board/strip now consume the SessionListStateLike directly.
|
|
16
|
+
*
|
|
17
|
+
* READ-ONLY (R9): the client only GETs the live host route; no mutation.
|
|
18
|
+
*/
|
|
19
|
+
import { type ReactNode } from 'react';
|
|
1
20
|
import type { ClientContext, SessionListStateLike, SnapshotSelectorHook } from './contract.ts';
|
|
2
21
|
import { isRecursivePreset, currentSessionCwd } from './contract.ts';
|
|
3
22
|
export type OverlayContent = 'hidden' | 'board' | 'inspector';
|
|
@@ -12,6 +31,16 @@ export declare function overlayContent(state: {
|
|
|
12
31
|
* Exported so the spec can assert the selector is actually passed.
|
|
13
32
|
*/
|
|
14
33
|
export declare function useRecursiveSessions(useSessions: SnapshotSelectorHook<SessionListStateLike>): SessionListStateLike;
|
|
34
|
+
/**
|
|
35
|
+
* Run 11 (UX gate): the ⧉ launcher renders ONLY in recursive sessions. The seat
|
|
36
|
+
* is root-scoped (the icon shows in every session otherwise), while the board it
|
|
37
|
+
* opens is recursive-preset-gated — in a code/other session the click was a dead
|
|
38
|
+
* no-op. Gating the launcher itself removes the trap: the icon appears exactly
|
|
39
|
+
* where clicking it opens the board.
|
|
40
|
+
*/
|
|
41
|
+
export declare function RecursiveLauncherGate({ useSessions }: {
|
|
42
|
+
useSessions: SnapshotSelectorHook<SessionListStateLike>;
|
|
43
|
+
}): ReactNode;
|
|
15
44
|
export declare function registerSlots(ctx: ClientContext): () => void;
|
|
16
45
|
/** Export the gate helpers for tests. */
|
|
17
46
|
export { isRecursivePreset, currentSessionCwd };
|
package/lib/client.js
CHANGED
|
@@ -528,6 +528,21 @@ window.__ModuleLoader__.load({
|
|
|
528
528
|
function useRecursiveSessions(useSessions) {
|
|
529
529
|
return useSessions((s) => s);
|
|
530
530
|
}
|
|
531
|
+
/**
|
|
532
|
+
* Run 11 (UX gate): the ⧉ launcher renders ONLY in recursive sessions. The seat
|
|
533
|
+
* is root-scoped (the icon shows in every session otherwise), while the board it
|
|
534
|
+
* opens is recursive-preset-gated — in a code/other session the click was a dead
|
|
535
|
+
* no-op. Gating the launcher itself removes the trap: the icon appears exactly
|
|
536
|
+
* where clicking it opens the board.
|
|
537
|
+
*/
|
|
538
|
+
function RecursiveLauncherGate({ useSessions }) {
|
|
539
|
+
if (!isRecursivePreset(useRecursiveSessions(useSessions))) return null;
|
|
540
|
+
return (0, react.createElement)("button", {
|
|
541
|
+
className: "rec-launcher",
|
|
542
|
+
title: "Recursive runs",
|
|
543
|
+
onClick: () => boardState.openBoard()
|
|
544
|
+
}, "⧉");
|
|
545
|
+
}
|
|
531
546
|
function registerSlots(ctx) {
|
|
532
547
|
const disposers = [];
|
|
533
548
|
disposers.push(ctx.slots.inject("sidebar.footer.action", () => ctx.slots.register({
|
|
@@ -535,11 +550,11 @@ window.__ModuleLoader__.load({
|
|
|
535
550
|
id: "recursive",
|
|
536
551
|
order: 50,
|
|
537
552
|
label: "Recursive runs"
|
|
538
|
-
}, () =>
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
}
|
|
553
|
+
}, (props) => {
|
|
554
|
+
const useSessions = props?.useSessions;
|
|
555
|
+
if (useSessions === void 0) return null;
|
|
556
|
+
return (0, react.createElement)(RecursiveLauncherGate, { useSessions });
|
|
557
|
+
})));
|
|
543
558
|
disposers.push(ctx.slots.inject("shell.overlay", () => ctx.slots.register({
|
|
544
559
|
name: "shell.overlay",
|
|
545
560
|
id: "recursive-board",
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@try-works/dsh-recursive-mode",
|
|
3
3
|
"description": "recursive-mode workflow as a DeepSeek Harness bundle: RecursiveRuntime service + recursive_status tool",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.8",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|
|
7
7
|
"types": "lib/index.d.ts",
|
package/src/client/slots.ts
CHANGED
|
@@ -58,16 +58,36 @@ export function useRecursiveSessions(useSessions: SnapshotSelectorHook<SessionLi
|
|
|
58
58
|
return useSessions((s) => s)
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
+
/**
|
|
62
|
+
* Run 11 (UX gate): the ⧉ launcher renders ONLY in recursive sessions. The seat
|
|
63
|
+
* is root-scoped (the icon shows in every session otherwise), while the board it
|
|
64
|
+
* opens is recursive-preset-gated — in a code/other session the click was a dead
|
|
65
|
+
* no-op. Gating the launcher itself removes the trap: the icon appears exactly
|
|
66
|
+
* where clicking it opens the board.
|
|
67
|
+
*/
|
|
68
|
+
export function RecursiveLauncherGate({ useSessions }: { useSessions: SnapshotSelectorHook<SessionListStateLike> }): ReactNode {
|
|
69
|
+
const list = useRecursiveSessions(useSessions)
|
|
70
|
+
if (!isRecursivePreset(list)) return null
|
|
71
|
+
return createElement('button', { className: 'rec-launcher', title: 'Recursive runs', onClick: () => boardState.openBoard() }, '⧉')
|
|
72
|
+
}
|
|
73
|
+
|
|
61
74
|
export function registerSlots(ctx: ClientContext): () => void {
|
|
62
75
|
const disposers: (() => void)[] = []
|
|
63
76
|
|
|
64
77
|
// Board launcher in the sidebar footer action list — OPENS the shared board store (run 08 R1).
|
|
78
|
+
// Run 11 (UX gate): the seat is root-scoped (visible in every session), but the board it
|
|
79
|
+
// opens is recursive-preset-gated. In a code/other session the icon was a dead click — a
|
|
80
|
+
// trap. The launcher itself now renders ONLY in recursive sessions, where it works.
|
|
65
81
|
disposers.push(ctx.slots.inject('sidebar.footer.action', () => ctx.slots.register({
|
|
66
82
|
name: 'sidebar.footer.action',
|
|
67
83
|
id: 'recursive',
|
|
68
84
|
order: 50,
|
|
69
85
|
label: 'Recursive runs',
|
|
70
|
-
}, (
|
|
86
|
+
}, (props: RootSlotProps) => {
|
|
87
|
+
const useSessions = props?.useSessions
|
|
88
|
+
if (useSessions === undefined) return null
|
|
89
|
+
return createElement(RecursiveLauncherGate, { useSessions })
|
|
90
|
+
})))
|
|
71
91
|
|
|
72
92
|
// Board panel overlay (root scope, cross-session read) — gated on the recursive preset + shared store.
|
|
73
93
|
disposers.push(ctx.slots.inject('shell.overlay', () => ctx.slots.register({
|