dsh-rewind-plugin 0.7.4 → 0.8.0-alpha.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.
package/lib/index.js CHANGED
@@ -1,7 +1,6 @@
1
1
  // src/index.ts
2
2
  import { createAssistantMessage } from "@deepseek-ai/dsh-llm";
3
3
  import { unlink as unlink2 } from "node:fs/promises";
4
- import * as dshSettings from "@deepseek-ai/dsh-settings";
5
4
  import "@deepseek-ai/schemastery";
6
5
 
7
6
  // src/locales.ts
@@ -111,20 +110,6 @@ function translate(lang, key, params = {}) {
111
110
  return text;
112
111
  }
113
112
 
114
- // src/session-events.ts
115
- function eventsOf(session) {
116
- const s = session;
117
- if (s.snapshotEvents !== void 0) return s.snapshotEvents();
118
- if (s.events !== void 0) return s.events;
119
- return [];
120
- }
121
-
122
- // src/settings-locale.ts
123
- function readSettingsSection(provider, ns, brand) {
124
- const key = brand?.(ns) ?? ns;
125
- return provider.get(key);
126
- }
127
-
128
113
  // src/rewind.ts
129
114
  var RewindError = class extends Error {
130
115
  constructor(code, message) {
@@ -1524,7 +1509,7 @@ function mutationPathOf(exec) {
1524
1509
  return void 0;
1525
1510
  }
1526
1511
  function anchorSeqOf(session, cache) {
1527
- const events = eventsOf(session);
1512
+ const events = session.snapshotEvents();
1528
1513
  const cached = cache.get(session);
1529
1514
  if (cached !== void 0 && cached.eventsLength === events.length) return cached.anchor;
1530
1515
  let anchor = cached?.anchor;
@@ -1702,15 +1687,15 @@ async function executeRewind(ctx, store, fs, invocation, rawTarget, mode, inflig
1702
1687
  }
1703
1688
  let plan;
1704
1689
  try {
1705
- plan = resolveOrError(eventsOf(agent.session), agent.session.surface.nodes, rawTarget);
1690
+ plan = resolveOrError(agent.session.snapshotEvents(), agent.session.surface.nodes, rawTarget);
1706
1691
  } catch (error) {
1707
1692
  return rewindErrorResult(error);
1708
1693
  }
1709
1694
  const marker = buildMarker();
1710
1695
  let event;
1711
1696
  try {
1712
- const turn = markerTurnOf(eventsOf(agent.session));
1713
- const step = markerStepOf(eventsOf(agent.session), turn);
1697
+ const turn = markerTurnOf(agent.session.snapshotEvents());
1698
+ const step = markerStepOf(agent.session.snapshotEvents(), turn);
1714
1699
  agent.session.append("step/start", { turn, step });
1715
1700
  try {
1716
1701
  event = agent.session.append("assistant/message", { turn, step, message: marker }, {
@@ -1764,7 +1749,7 @@ async function handleRewind(ctx, store, fs, invocation, inflight) {
1764
1749
  const session = invocation.agent.session;
1765
1750
  const input = invocation.rawInput.trim();
1766
1751
  if (input === "") {
1767
- const candidates = listRewindCandidates(eventsOf(session), session.surface.nodes, 1);
1752
+ const candidates = listRewindCandidates(session.snapshotEvents(), session.surface.nodes, 1);
1768
1753
  if (candidates.length === 0) {
1769
1754
  return { kind: "error", text: t("noUserMessages") };
1770
1755
  }
@@ -1776,7 +1761,7 @@ async function handleRewind(ctx, store, fs, invocation, inflight) {
1776
1761
  if (target2 === void 0) return { kind: "error", text: usage() };
1777
1762
  let plan;
1778
1763
  try {
1779
- plan = resolveOrError(eventsOf(session), session.surface.nodes, target2);
1764
+ plan = resolveOrError(session.snapshotEvents(), session.surface.nodes, target2);
1780
1765
  } catch (error) {
1781
1766
  return rewindErrorResult(error);
1782
1767
  }
@@ -1784,7 +1769,7 @@ async function handleRewind(ctx, store, fs, invocation, inflight) {
1784
1769
  return { kind: "success", text: formatPlan(plan, impacts) };
1785
1770
  }
1786
1771
  if (parts[0] === "__candidates") {
1787
- const candidates = listRewindCandidates(eventsOf(session), session.surface.nodes);
1772
+ const candidates = listRewindCandidates(session.snapshotEvents(), session.surface.nodes);
1788
1773
  return { kind: "success", text: formatCandidateList(candidates) };
1789
1774
  }
1790
1775
  const target = parts[0];
@@ -1930,15 +1915,16 @@ function apply(ctx, config) {
1930
1915
  const trackedBySession = /* @__PURE__ */ new Map();
1931
1916
  let fsService;
1932
1917
  ctx.inject(["settings"], (settingsCtx) => {
1933
- const section = readSettingsSection(
1934
- settingsCtx.settings,
1935
- "locale",
1936
- dshSettings.settingsNamespace
1937
- );
1918
+ const settings = settingsCtx;
1919
+ const section = settings.settings.get("locale");
1938
1920
  if (section?.preference === "zh" || section?.preference === "en") {
1939
1921
  activeLocale = section.preference;
1940
1922
  }
1941
- const cleanupScope = settingsCtx.settings.register(CLEANUP_SETTINGS_NAMESPACE, CleanupConfigSchema, { base: DEFAULT_CLEANUP_CONFIG });
1923
+ const cleanupScope = settings.settings.register(
1924
+ CLEANUP_SETTINGS_NAMESPACE,
1925
+ CleanupConfigSchema,
1926
+ { base: DEFAULT_CLEANUP_CONFIG }
1927
+ );
1942
1928
  cleanupStore = settingsCleanupStore(cleanupScope);
1943
1929
  void migrateLegacyCleanupConfig(
1944
1930
  resolveCleanupConfigPath(dshHome),
@@ -5,7 +5,17 @@
5
5
  *
6
6
  * @module dsh-rewind/client/hidden
7
7
  */
8
- import type { ChatConversationViewNode, CommandNode } from '@deepseek-ai/dsh-client-runtime/client';
8
+ import type { CommandNode } from '@deepseek-ai/dsh-client-ui-conversation/client';
9
+ /** A chat-snapshot view node as the hiding / composer-refill logic reads it.
10
+ * The harness's view node shape plus the `anchorSeq` the chat snapshot carries
11
+ * (the plugin reads `anchorSeq` off each node; it is not declared on the
12
+ * harness's `ConversationViewNode`). */
13
+ export interface ChatConversationViewNode {
14
+ readonly key: string;
15
+ readonly kind?: string;
16
+ readonly data?: unknown;
17
+ readonly anchorSeq: number;
18
+ }
9
19
  /** Minimal chat snapshot reader the hiding logic needs. */
10
20
  export interface HiddenChat {
11
21
  readonly order: readonly string[];
@@ -14,53 +24,36 @@ export interface HiddenChat {
14
24
  };
15
25
  }
16
26
  /**
17
- * Reader for one session's live chat snapshot. The dual channel hides the
18
- * harness split behind SiriLee/dsh-rewind#7: rc.2 serves the chat from the
19
- * session face snapshot, while 0.1.2-alpha.1+ serves it from the
20
- * `uiConversation` service's named "chat" view (contributed by
21
- * dsh-client-ui-chat through the uiSession slot hook).
27
+ * Reader for one session's live chat snapshot. On the 0.1.2-rc.1 line (the
28
+ * plugin's single baseline) the chat is served by the `uiConversation`
29
+ * service's named "chat" view (contributed by dsh-client-ui-chat through the
30
+ * uiSession slot hook).
22
31
  */
23
32
  export type ChatOf = (session: {
24
33
  readonly sessionId: string;
25
- getSnapshot(): {
26
- chat?: unknown;
27
- };
28
34
  } | undefined) => HiddenChat | undefined;
29
35
  /**
30
36
  * Subscribe to one session's live chat-update signal, for waiting on a chat
31
- * snapshot change without polling. Dual-channel, mirroring `chatOf`: the
32
- * alpha.1+ `uiConversation` "chat" view when registered, else the session face
33
- * (rc.2, whose snapshot still carries `chat`, so its own `subscribe` is the
34
- * chat-update signal). `cb` fires whenever the chat snapshot invalidates.
37
+ * snapshot change without polling. The 0.1.2-rc.1 `uiConversation` "chat"
38
+ * view's own `subscribe` is the chat-update signal; `cb` fires whenever the
39
+ * chat snapshot invalidates.
35
40
  */
36
41
  export type ChatWatch = (sessionId: string, cb: () => void) => () => void;
37
42
  /**
38
- * Choose the chat-update subscription for `waitForCommand`: prefer the
39
- * `uiConversation` "chat" view's own `subscribe` when available (alpha.1+,
40
- * where the chat-update signal lives), else the session face's `subscribe`
41
- * (rc.2, whose snapshot still carries the chat, so its own subscribe is the
42
- * chat-update signal). Extracted as a pure channel-selection step so the
43
- * "view vs face" branch is unit-testable; the resolvers are injected by the
44
- * caller (see `watchChat` in index.ts). Never throws.
43
+ * Choose the chat-update subscription for `waitForCommand`: the
44
+ * `uiConversation` "chat" view's own `subscribe`. Extracted as a pure
45
+ * channel-selection step so the resolver is unit-testable; the resolver is
46
+ * injected by the caller (see `watchChat` in index.ts). Never throws.
45
47
  */
46
48
  export declare function resolveChatWatch(resolveView: (sessionId: string) => {
47
49
  subscribe?(cb: () => void): () => void;
48
- } | undefined, resolveFace: (sessionId: string) => {
49
- subscribe(cb: () => void): () => void;
50
50
  } | undefined, sessionId: string, cb: () => void): () => void;
51
51
  /**
52
- * Resolve the chat snapshot across the two harness channels: the session-face
53
- * snapshot first (rc.2 on alpha.1+ the face no longer carries `chat`, so the
54
- * field reads `undefined`), then the `uiConversation` "chat" view. The view's
55
- * `getSnapshot()` returns undefined until the named view is registered, so
56
- * both channels missing degrades to `undefined` (no targets, no hiding —
57
- * never a crash).
52
+ * Resolve the chat snapshot from the `uiConversation` "chat" view. The view's
53
+ * `getSnapshot()` returns undefined until the named view is registered, which
54
+ * degrades to `undefined` (no targets, no hiding never a crash).
58
55
  */
59
- export declare function chatSnapshotOf(face: {
60
- getSnapshot(): {
61
- chat?: unknown;
62
- };
63
- } | undefined, chatView: {
56
+ export declare function chatSnapshotOf(chatView: {
64
57
  getSnapshot(): unknown;
65
58
  } | undefined): HiddenChat | undefined;
66
59
  /**
@@ -26,9 +26,27 @@
26
26
  *
27
27
  * @module dsh-rewind/client
28
28
  */
29
- import type { ClientContext } from '@deepseek-ai/dsh-client-runtime/client';
29
+ import type { ISessions } from '@deepseek-ai/dsh-api-session-controller/client';
30
30
  export declare const name = "dsh-rewind";
31
31
  export declare const inject: string[];
32
+ /**
33
+ * The client plugin root context read by `apply(ctx)`. Local structural face:
34
+ * the harness client context is a cordis `Context` augmented by runtime
35
+ * services, so the plugin declares the subset it reads. `sessions` is the real
36
+ * `ISessions` from `@deepseek-ai/dsh-api-session-controller`.
37
+ */
38
+ export interface ClientContext {
39
+ effect(execute: () => Iterable<unknown>, label?: string): unknown;
40
+ locale: {
41
+ register(namespace: string, messages: Record<string, Record<string, string>>): unknown;
42
+ bind(namespace: string): (key: string) => string;
43
+ subscribe(cb: () => void): () => void;
44
+ };
45
+ sessions: ISessions;
46
+ get(name: string): unknown;
47
+ slots: unknown;
48
+ commandUi: unknown;
49
+ }
32
50
  /**
33
51
  * Client plugin body: command decoration + parameterized guard + locale + the
34
52
  * portal bridge.
@@ -13,8 +13,8 @@
13
13
  *
14
14
  * @module dsh-rewind/client/popover
15
15
  */
16
- import type { SessionFace } from '@deepseek-ai/dsh-client-runtime/client';
17
- import type { CommandNode } from '@deepseek-ai/dsh-client-runtime/client';
16
+ import type { SessionFace } from '@deepseek-ai/dsh-api-session-controller/client';
17
+ import type { CommandNode } from '@deepseek-ai/dsh-client-ui-conversation/client';
18
18
  import { type ChatOf, type ChatWatch } from './hidden.ts';
19
19
  import type { RewindKey } from './locales.ts';
20
20
  type Translate = (key: RewindKey, params?: Record<string, unknown>) => string;
@@ -33,16 +33,15 @@ export interface PopoverOptions {
33
33
  readonly onRetract?: () => void;
34
34
  readonly preview: string;
35
35
  /**
36
- * Dual-channel chat reader (rc.2 session face / alpha.1+ uiConversation
37
- * view): the durable variant's command probes scan the chat through it.
38
- * Unused by the pending-retract variant.
36
+ * Chat reader on the 0.1.2-rc.1 `uiConversation` "chat" view: the durable
37
+ * variant's command probes scan the chat through it. Unused by the
38
+ * pending-retract variant.
39
39
  */
40
40
  readonly chatOf: ChatOf;
41
41
  /**
42
42
  * Subscribe to one session's live chat-update signal, so a probe waiting on
43
- * a command's chat node can be woken when the chat snapshot changes (alpha.1+
44
- * the session face no longer fires on a chat update). Passed straight through
45
- * to `waitForCommand`.
43
+ * a command's chat node can be woken when the chat snapshot changes. Passed
44
+ * straight through to `waitForCommand`.
46
45
  */
47
46
  readonly watchChat: ChatWatch;
48
47
  /** The button that opened the popover (outside-click ignore target). */
@@ -70,7 +69,7 @@ export declare function knownCommandSeqs(session: SessionFace, chatOf: ChatOf, m
70
69
  * session snapshot (command/run + command/done land as one CommandNode).
71
70
  * @returns the outcome text-bearing node, or null on timeout.
72
71
  */
73
- export declare function waitForCommand(session: SessionFace, chatOf: ChatOf, match: (node: CommandNode) => boolean, timeoutMs?: number, watch?: (cb: () => void) => () => void): Promise<{
72
+ export declare function waitForCommand(session: SessionFace, chatOf: ChatOf, match: (node: CommandNode) => boolean, timeoutMs: number | undefined, watch: (cb: () => void) => () => void): Promise<{
74
73
  kind: 'success' | 'error';
75
74
  text?: string;
76
75
  } | null>;
@@ -23,7 +23,7 @@
23
23
  * @module dsh-rewind/client/portals
24
24
  */
25
25
  import { type ReactNode } from 'react';
26
- import type { SessionFace } from '@deepseek-ai/dsh-client-runtime/client';
26
+ import type { SessionFace } from '@deepseek-ai/dsh-api-session-controller/client';
27
27
  import { type ChatOf, type ChatWatch, type HiddenChat } from './hidden.ts';
28
28
  import type { RewindKey } from './locales.ts';
29
29
  type Translate = (key: RewindKey, params?: Record<string, unknown>) => string;
@@ -53,26 +53,23 @@ export type PortalTarget = {
53
53
  export interface RewindBridgeDeps {
54
54
  readonly sessionOf: (sessionId: string) => SessionFace | undefined;
55
55
  /**
56
- * Dual-channel chat reader (rc.2 session face / alpha.1+ uiConversation
57
- * "chat" view): every chat snapshot read goes through it. See
58
- * `chatSnapshotOf` in hidden.ts for the channel precedence.
56
+ * Chat reader on the 0.1.2-rc.1 `uiConversation` "chat" view: every chat
57
+ * snapshot read goes through it. See `chatSnapshotOf` in hidden.ts.
59
58
  */
60
59
  readonly chatOf: ChatOf;
61
60
  /**
62
61
  * Subscribe to one session's live chat-update signal, so the composer refill
63
62
  * waiting on an executed rewind's chat node can be woken when the chat
64
- * snapshot changes (alpha.1+ the session face no longer fires on a chat
65
- * update). Passed through to `waitForCommand`.
63
+ * snapshot changes. Passed through to `waitForCommand`.
66
64
  */
67
65
  readonly watchChat: ChatWatch;
68
66
  readonly currentSessionId: () => string | undefined;
69
67
  readonly t: Translate;
70
68
  readonly subscribeLocale: (cb: () => void) => () => void;
71
69
  /**
72
- * Session-aware dual-channel composer writer (see `writeComposer`): the
73
- * alpha.1+ `conversation.input` facade `setDraft` when reachable, else the
74
- * rc.2/alpha.1 DOM fill. Session-scoped so the refill only lands in the
75
- * session that just rewound.
70
+ * Session-aware composer writer (see `writeComposer`): the 0.1.2-rc.1
71
+ * `conversation.input` facade `setDraft` when reachable, else the DOM fill.
72
+ * Session-scoped so the refill only lands in the session that just rewound.
76
73
  */
77
74
  readonly setComposerText: (sessionId: string, text: string) => boolean;
78
75
  }
@@ -90,7 +87,7 @@ export interface SlotsLike {
90
87
  }
91
88
  /** Join the text blocks of a user message into one plain preview. */
92
89
  /**
93
- * The alpha.1+ session input facade's write face (structural, so the plugin
90
+ * The 0.1.2-rc.1 session input facade's write face (structural, so the plugin
94
91
  * never imports the conversation UI package). `setDraft` replaces the whole
95
92
  * composer draft through the harness's own Lexical editor — the correct way
96
93
  * to restore the withdrawn text.
@@ -99,22 +96,20 @@ interface ComposerDraftWriter {
99
96
  setDraft(text: string): void;
100
97
  }
101
98
  /**
102
- * Fill the dsh composer with `text`. DOM dual-channel fallback: the rc.2
103
- * `<textarea>` path, then the alpha.1+ `contenteditable` path. Used by
104
- * `setComposerText` (the harness-facade-aware writer) as the last-resort and
105
- * by `runRewindAndFill` to put the withdrawn target message back into the
106
- * composer after a rewind. Best-effort — no composer match means false,
107
- * never a throw.
99
+ * Fill the dsh composer with `text` through the 0.1.2-rc.1 `contenteditable`
100
+ * DOM path. Used by `setComposerText` (the harness-facade-aware writer) as the
101
+ * last-resort and by `runRewindAndFill` to put the withdrawn target message
102
+ * back into the composer after a rewind. Best-effort no composer match means
103
+ * false, never a throw.
108
104
  */
109
105
  export declare function fillComposer(text: string): boolean;
110
106
  /**
111
- * Dual-channel composer write, mirroring `chatSnapshotOf`: prefer the harness
112
- * facade's `setDraft` (alpha.1+, correct whole-draft replace), then degrade
113
- * to the DOM `fillComposer` (rc.2 textarea / alpha.1 contenteditable). A
114
- * facade that throws (session teardown) is treated as absent so the DOM path
115
- * still restores the text. Never throws.
107
+ * Composer write: prefer the harness facade's `setDraft` (0.1.2-rc.1, correct
108
+ * whole-draft replace), then degrade to the DOM `fillComposer` (0.1.2-rc.1
109
+ * contenteditable). A facade that throws (session teardown) is treated as
110
+ * absent so the DOM path still restores the text. Never throws.
116
111
  * @param text - the withdrawn target message text.
117
- * @param facade - the alpha.1+ session input draft writer, when reachable.
112
+ * @param facade - the 0.1.2-rc.1 session input draft writer, when reachable.
118
113
  * @returns whether a channel applied the text.
119
114
  */
120
115
  export declare function writeComposer(text: string, facade: ComposerDraftWriter | undefined): boolean;
@@ -136,21 +131,15 @@ export declare function runRewindAndFill(session: SessionFace, seq: number, mode
136
131
  * Locate the actions container of a user/steering seat row — the element the
137
132
  * ↶ button portals into (the copy/branch IconActions row).
138
133
  *
139
- * Dual channel:
140
- * - rc.2 (0.1.1-rc.2) / alpha.2+ (0.1.2-alpha.2): the hover-reveal root is
141
- * attribute-marked (`[data-time-hover-root]` rc.x, `[data-actions-reveal]`
142
- * alpha.2+) and mounts the actions row as its LAST child. A pending row IS
143
- * that root; a durable row CONTAINS it as a descendant.
144
- * - alpha.4 (0.1.2-alpha.4): the marker was removed from user rows (it now
145
- * lives only on the per-turn tail footer, `TurnTailNodeView`), and the user
146
- * action row is revealed via CSS `:has()`. The container is instead located
147
- * structurally: the direct holder of the copy `<button>` (the
148
- * `MessageIconActions` container, which mounts that button as a direct
149
- * child — `MessageIconActions.tsx:83,86`).
134
+ * On the 0.1.2-rc.1 line the `data-time-hover-root` marker lives only on the
135
+ * per-turn tail footer (`TurnTailNodeView`), and the user action row is
136
+ * revealed via CSS `:has()`. The container is located structurally: the direct
137
+ * holder of the copy `<button>` (the `MessageIconActions` container, which
138
+ * mounts that button as a direct child `MessageIconActions.tsx:83,86`).
150
139
  *
151
140
  * Returns undefined when no qualifying container is found; the caller refuses
152
141
  * to portal (never a crash, never a wrong attachment). Exported as a test seam
153
- * (see `collectTargets`) so the dual-channel finder is exercised directly for
142
+ * (see `collectTargets`) so the row-shape finder is exercised directly for
154
143
  * both durable and pending row shapes without a full React portal render.
155
144
  */
156
145
  export declare function actionsContainerOf(row: HTMLElement | undefined): HTMLElement | undefined;
@@ -171,9 +160,9 @@ interface RewindPortalsProps extends RewindBridgeDeps {
171
160
  * synchronous full-transcript scan inside a commit microtask.
172
161
  */
173
162
  export declare function RewindPortals({ sessionId, sessionOf, chatOf, currentSessionId, watchChat, t, subscribeLocale, setComposerText }: RewindPortalsProps): ReactNode;
174
- /** The current composer draft, on whichever channel: rc.2 textarea `.value`,
175
- * alpha.1+ contenteditable `textContent`. Empty when the composer is absent.
176
- * Exported as a test seam (the empty-composer guard in `retractPending`). */
163
+ /** The current composer draft: the 0.1.2-rc.1 contenteditable `textContent`.
164
+ * Empty when the composer is absent. Exported as a test seam (the
165
+ * empty-composer guard in `retractPending`). */
177
166
  export declare function composerText(): string;
178
167
  /**
179
168
  * Build the slot-entry component for the plugin apply(): a tiny bridge that
@@ -11,10 +11,10 @@
11
11
  * host schema enforces). "Discard changes" restores the last-read baseline.
12
12
  *
13
13
  * It neither imports the client settings typed contract nor depends on the
14
- * alpha-only `mutate` write API: it reads `getSnapshot().value` and writes via
15
- * the `set(field, value)` method present on both rc.2 and alpha, and the card
16
- * receives a tiny structural `CleanupCardApi` supplied by `src/client/index.ts`
17
- * so the component stays harness-agnostic and unit-testable in isolation.
14
+ * 0.1.2-rc.1-only `mutate` write API: it reads `getSnapshot().value` and writes
15
+ * via the `set(field, value)` method, and the card receives a tiny structural
16
+ * `CleanupCardApi` supplied by `src/client/index.ts` so the component stays
17
+ * harness-agnostic and unit-testable in isolation.
18
18
  *
19
19
  * @module dsh-rewind/client/settings-card
20
20
  */
@@ -23,4 +23,4 @@ export declare const CLASS: {
23
23
  /** The ↶ glyph, drawn inline so the bundle stays dependency-free. */
24
24
  export declare const REWIND_ICON_SVG: string;
25
25
  /** One injected stylesheet (scoped under `.dsh-rewind-*`). */
26
- export declare const STYLE = "\n.dsh-rewind-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n padding: 6px;\n border: none;\n border-radius: 28px;\n background: transparent;\n color: var(--dsw-alias-label-tertiary);\n cursor: pointer;\n}\n.dsh-rewind-btn:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n color: var(--dsw-alias-label-secondary);\n}\n\n.dsh-rewind-popover {\n position: fixed;\n z-index: 1000;\n width: 288px;\n padding: 12px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 12px;\n background: var(--dsw-specific-menu, var(--dsw-alias-bg-layer-3));\n box-shadow: var(--dsw-shadow-lv3);\n font-size: 14px;\n line-height: 20px;\n color: var(--dsw-alias-label-primary);\n}\n.dsh-rewind-popover-title {\n font-size: 14px;\n font-weight: 600;\n line-height: 20px;\n}\n.dsh-rewind-popover-target {\n margin: 4px 0 10px;\n font-size: 12px;\n line-height: 16px;\n color: var(--dsw-alias-label-tertiary);\n word-break: break-all;\n}\n.dsh-rewind-popover-option {\n display: flex;\n flex-direction: column;\n gap: 2px;\n width: 100%;\n margin: 0 0 6px;\n padding: 8px 10px;\n border: 1px solid transparent;\n border-radius: 8px;\n background: transparent;\n color: inherit;\n font: inherit;\n text-align: left;\n cursor: pointer;\n}\n.dsh-rewind-popover-option:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n.dsh-rewind-popover-option:disabled {\n opacity: 0.5;\n cursor: default;\n}\n.dsh-rewind-popover-option-label {\n font-weight: 500;\n}\n.dsh-rewind-popover-option-hint {\n font-size: 12px;\n line-height: 16px;\n color: var(--dsw-alias-label-tertiary);\n}\n.dsh-rewind-popover-impact {\n margin: 4px 0 10px;\n padding: 8px 10px;\n border-radius: 8px;\n background: var(--dsw-alias-interactive-bg-hover);\n font-size: 12px;\n line-height: 16px;\n color: var(--dsw-alias-label-secondary);\n white-space: pre-wrap;\n max-height: 160px;\n overflow: auto;\n}\n.dsh-rewind-popover-actions {\n display: flex;\n justify-content: flex-end;\n gap: 8px;\n}\n.dsh-rewind-popover-primary,\n.dsh-rewind-popover-ghost {\n padding: 5px 12px;\n border: none;\n border-radius: 8px;\n font: inherit;\n font-size: 13px;\n line-height: 18px;\n cursor: pointer;\n}\n.dsh-rewind-popover-primary {\n background: var(--dsw-alias-button-primary-fill);\n color: var(--dsw-alias-label-primary-foreground);\n}\n.dsh-rewind-popover-primary:hover:not(:disabled) {\n background: var(--dsw-alias-button-primary-hover);\n}\n.dsh-rewind-popover-primary:disabled {\n opacity: 0.5;\n cursor: default;\n}\n.dsh-rewind-popover-ghost {\n background: transparent;\n color: var(--dsw-alias-label-secondary);\n}\n.dsh-rewind-popover-ghost:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.dsh-rewind-guard-hint {\n position: fixed;\n z-index: 1000;\n max-width: min(440px, calc(100vw - 24px));\n padding: 8px 12px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 10px;\n background: var(--dsw-specific-menu, var(--dsw-alias-bg-layer-3));\n box-shadow: var(--dsw-shadow-lv3);\n font-size: 13px;\n line-height: 18px;\n color: var(--dsw-alias-label-primary);\n pointer-events: none;\n}\n\n/* ---- Snapshot-cleanup settings card (mirrors the harness PluginCard look) ---- */\n/* Dual-channel note: the harness card corner/border drifted across versions \u2014\n rc.2 uses border-radius 12px + 1px solid border-l2, while alpha uses 16px +\n 0.5px border-l4 (and adds corner-shape: round). We intentionally keep the\n rc.2 values here for now; if the alpha look is wanted, switch these on the\n host version like the other dual-channel surfaces (see the host-version probe\n in src/client/index.ts). */\n.dsh-rewind-cleanup-card {\n list-style: none;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 12px;\n background: var(--dsw-alias-bg-layer-3);\n transition: border-color .16s, background .16s;\n}\n.dsh-rewind-cleanup-card:hover {\n border-color: var(--dsw-alias-label-dimmed);\n}\n.dsh-rewind-cleanup-card-open {\n background: var(--dsw-alias-bg-layer-2);\n border-color: var(--dsw-alias-label-dimmed);\n}\n.dsh-rewind-cleanup-header {\n width: 100%;\n appearance: none;\n border: 0;\n background: none;\n font: inherit;\n color: inherit;\n text-align: left;\n cursor: pointer;\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 14px 16px;\n border-radius: 12px;\n}\n.dsh-rewind-cleanup-header:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: -2px;\n}\n.dsh-rewind-cleanup-head-text {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n.dsh-rewind-cleanup-name {\n font-size: 15px;\n font-weight: 600;\n line-height: 1.4;\n color: var(--dsw-alias-label-primary);\n}\n.dsh-rewind-cleanup-desc {\n font-size: 13px;\n line-height: 1.5;\n color: var(--dsw-alias-label-tertiary);\n}\n.dsh-rewind-cleanup-chevron {\n flex: none;\n color: var(--dsw-alias-label-tertiary);\n transition: transform .16s;\n}\n.dsh-rewind-cleanup-chevron-open {\n transform: rotate(180deg);\n}\n.dsh-rewind-cleanup-pending {\n flex: none;\n border-radius: 999px;\n padding: 1px 8px;\n font-size: 11px;\n line-height: 17px;\n font-weight: 500;\n white-space: nowrap;\n background: var(--dsw-alias-bg-module-platform);\n color: var(--dsw-alias-label-secondary);\n}\n.dsh-rewind-cleanup-body {\n border-top: 1px solid var(--dsw-alias-border-l2);\n margin: 0 16px;\n padding: 4px 0 8px;\n}\n.dsh-rewind-cleanup-readonly {\n margin: 12px 0 0;\n font-size: 12px;\n line-height: 1.5;\n color: var(--dsw-alias-label-tertiary);\n}\n.dsh-rewind-cleanup-permission {\n display: grid;\n gap: 6px;\n padding: 12px 0;\n}\n.dsh-rewind-cleanup-field {\n display: flex;\n flex-direction: column;\n gap: 6px;\n padding: 12px 0;\n}\n.dsh-rewind-cleanup-field + .dsh-rewind-cleanup-field {\n border-top: 1px solid var(--dsw-alias-border-l2);\n}\n.dsh-rewind-cleanup-head {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n.dsh-rewind-cleanup-label {\n flex: 1;\n min-width: 0;\n font-size: 13px;\n font-weight: 500;\n line-height: 1.5;\n color: var(--dsw-alias-label-primary);\n}\n.dsh-rewind-cleanup-hint {\n margin: 0;\n font-size: 12px;\n line-height: 1.5;\n color: var(--dsw-alias-label-tertiary);\n}\n.dsh-rewind-cleanup-error {\n margin: 0;\n font-size: 12px;\n line-height: 1.5;\n color: var(--dsw-alias-label-error);\n}\n/* Switch row: label left, role=switch button right, hint below (Subagent module). */\n.dsh-rewind-cleanup-toggle-row {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n gap: 16px;\n font-size: 13px;\n line-height: 1.5;\n color: var(--dsw-alias-label-primary);\n}\n.dsh-rewind-cleanup-toggle-label {\n flex: 1;\n min-width: 0;\n}\n.dsh-rewind-cleanup-switch {\n box-sizing: border-box;\n position: relative;\n flex: 0 0 auto;\n width: 36px;\n height: 20px;\n padding: 2px;\n border: 0;\n border-radius: 10px;\n background: var(--dsw-alias-border-l3);\n cursor: pointer;\n}\n.dsh-rewind-cleanup-switch-on {\n background: var(--dsw-alias-brand-primary);\n}\n.dsh-rewind-cleanup-switch:disabled {\n cursor: default;\n opacity: 0.5;\n}\n.dsh-rewind-cleanup-switch:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: 2px;\n}\n.dsh-rewind-cleanup-thumb {\n display: block;\n width: 16px;\n height: 16px;\n border-radius: 50%;\n corner-shape: round;\n background: var(--dsw-alias-label-primary-foreground);\n transition: transform 120ms ease;\n}\n.dsh-rewind-cleanup-switch-on .dsh-rewind-cleanup-thumb {\n transform: translateX(16px);\n}\n.dsh-rewind-cleanup-input {\n box-sizing: border-box;\n height: 34px;\n padding: 0 12px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 8px;\n background: var(--dsw-alias-bg-layer-3);\n font: inherit;\n font-size: 13px;\n line-height: 1.5;\n color: var(--dsw-alias-label-primary);\n}\n.dsh-rewind-cleanup-input:focus-visible {\n outline: none;\n border-color: var(--dsw-alias-brand-primary);\n}\n.dsh-rewind-cleanup-input:disabled {\n color: var(--dsw-alias-label-tertiary);\n cursor: default;\n}\n.dsh-rewind-cleanup-input-invalid {\n border-color: var(--dsw-alias-label-error);\n}\n.dsh-rewind-cleanup-footer {\n display: flex;\n align-items: center;\n justify-content: flex-end;\n gap: 8px;\n padding: 12px 0 4px;\n border-top: 1px solid var(--dsw-alias-border-l2);\n}\n.dsh-rewind-cleanup-failed {\n flex: 1;\n min-width: 0;\n margin: 0;\n font-size: 12px;\n line-height: 1.5;\n color: var(--dsw-alias-label-error);\n}\n.dsh-rewind-cleanup-discard,\n.dsh-rewind-cleanup-save {\n appearance: none;\n border: 1px solid transparent;\n border-radius: 8px;\n padding: 5px 14px;\n font: inherit;\n font-size: 13px;\n line-height: 1.5;\n cursor: pointer;\n}\n.dsh-rewind-cleanup-discard {\n border-color: var(--dsw-alias-border-l2);\n background: none;\n color: var(--dsw-alias-label-secondary);\n}\n.dsh-rewind-cleanup-discard:hover:not(:disabled) {\n color: var(--dsw-alias-label-primary);\n border-color: var(--dsw-alias-label-dimmed);\n}\n.dsh-rewind-cleanup-save {\n background: var(--dsw-alias-label-primary);\n color: var(--dsw-alias-bg-layer-3);\n}\n.dsh-rewind-cleanup-discard:disabled,\n.dsh-rewind-cleanup-save:disabled {\n opacity: 0.4;\n cursor: default;\n}\n.dsh-rewind-cleanup-discard:focus-visible,\n.dsh-rewind-cleanup-save:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: 1px;\n}\n";
26
+ export declare const STYLE = "\n.dsh-rewind-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n padding: 6px;\n border: none;\n border-radius: 28px;\n background: transparent;\n color: var(--dsw-alias-label-tertiary);\n cursor: pointer;\n}\n.dsh-rewind-btn:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n color: var(--dsw-alias-label-secondary);\n}\n\n.dsh-rewind-popover {\n position: fixed;\n z-index: 1000;\n width: 288px;\n padding: 12px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 12px;\n background: var(--dsw-specific-menu, var(--dsw-alias-bg-layer-3));\n box-shadow: var(--dsw-shadow-lv3);\n font-size: 14px;\n line-height: 20px;\n color: var(--dsw-alias-label-primary);\n}\n.dsh-rewind-popover-title {\n font-size: 14px;\n font-weight: 600;\n line-height: 20px;\n}\n.dsh-rewind-popover-target {\n margin: 4px 0 10px;\n font-size: 12px;\n line-height: 16px;\n color: var(--dsw-alias-label-tertiary);\n word-break: break-all;\n}\n.dsh-rewind-popover-option {\n display: flex;\n flex-direction: column;\n gap: 2px;\n width: 100%;\n margin: 0 0 6px;\n padding: 8px 10px;\n border: 1px solid transparent;\n border-radius: 8px;\n background: transparent;\n color: inherit;\n font: inherit;\n text-align: left;\n cursor: pointer;\n}\n.dsh-rewind-popover-option:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n.dsh-rewind-popover-option:disabled {\n opacity: 0.5;\n cursor: default;\n}\n.dsh-rewind-popover-option-label {\n font-weight: 500;\n}\n.dsh-rewind-popover-option-hint {\n font-size: 12px;\n line-height: 16px;\n color: var(--dsw-alias-label-tertiary);\n}\n.dsh-rewind-popover-impact {\n margin: 4px 0 10px;\n padding: 8px 10px;\n border-radius: 8px;\n background: var(--dsw-alias-interactive-bg-hover);\n font-size: 12px;\n line-height: 16px;\n color: var(--dsw-alias-label-secondary);\n white-space: pre-wrap;\n max-height: 160px;\n overflow: auto;\n}\n.dsh-rewind-popover-actions {\n display: flex;\n justify-content: flex-end;\n gap: 8px;\n}\n.dsh-rewind-popover-primary,\n.dsh-rewind-popover-ghost {\n padding: 5px 12px;\n border: none;\n border-radius: 8px;\n font: inherit;\n font-size: 13px;\n line-height: 18px;\n cursor: pointer;\n}\n.dsh-rewind-popover-primary {\n background: var(--dsw-alias-button-primary-fill);\n color: var(--dsw-alias-label-primary-foreground);\n}\n.dsh-rewind-popover-primary:hover:not(:disabled) {\n background: var(--dsw-alias-button-primary-hover);\n}\n.dsh-rewind-popover-primary:disabled {\n opacity: 0.5;\n cursor: default;\n}\n.dsh-rewind-popover-ghost {\n background: transparent;\n color: var(--dsw-alias-label-secondary);\n}\n.dsh-rewind-popover-ghost:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.dsh-rewind-guard-hint {\n position: fixed;\n z-index: 1000;\n max-width: min(440px, calc(100vw - 24px));\n padding: 8px 12px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 10px;\n background: var(--dsw-specific-menu, var(--dsw-alias-bg-layer-3));\n box-shadow: var(--dsw-shadow-lv3);\n font-size: 13px;\n line-height: 18px;\n color: var(--dsw-alias-label-primary);\n pointer-events: none;\n}\n\n/* ---- Snapshot-cleanup settings card (mirrors the harness PluginCard look) ---- */\n/* Standardized on the 0.1.2 harness card look (border-radius 16px + 0.5px\n border-l4, 0.5px internal separators). */\n.dsh-rewind-cleanup-card {\n list-style: none;\n border: 0.5px solid var(--dsw-alias-border-l4);\n border-radius: 16px;\n background: var(--dsw-alias-bg-layer-3);\n transition: border-color .16s, background .16s;\n}\n.dsh-rewind-cleanup-card:hover {\n border-color: var(--dsw-alias-label-dimmed);\n}\n.dsh-rewind-cleanup-card-open {\n background: var(--dsw-alias-bg-layer-2);\n border-color: var(--dsw-alias-label-dimmed);\n}\n.dsh-rewind-cleanup-header {\n width: 100%;\n appearance: none;\n border: 0;\n background: none;\n font: inherit;\n color: inherit;\n text-align: left;\n cursor: pointer;\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 14px 16px;\n border-radius: 12px;\n}\n.dsh-rewind-cleanup-header:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: -2px;\n}\n.dsh-rewind-cleanup-head-text {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n.dsh-rewind-cleanup-name {\n font-size: 15px;\n font-weight: 600;\n line-height: 1.4;\n color: var(--dsw-alias-label-primary);\n}\n.dsh-rewind-cleanup-desc {\n font-size: 13px;\n line-height: 1.5;\n color: var(--dsw-alias-label-tertiary);\n}\n.dsh-rewind-cleanup-chevron {\n flex: none;\n color: var(--dsw-alias-label-tertiary);\n transition: transform .16s;\n}\n.dsh-rewind-cleanup-chevron-open {\n transform: rotate(180deg);\n}\n.dsh-rewind-cleanup-pending {\n flex: none;\n border-radius: 999px;\n padding: 1px 8px;\n font-size: 11px;\n line-height: 17px;\n font-weight: 500;\n white-space: nowrap;\n background: var(--dsw-alias-bg-module-platform);\n color: var(--dsw-alias-label-secondary);\n}\n.dsh-rewind-cleanup-body {\n border-top: 0.5px solid var(--dsw-alias-border-l2);\n margin: 0 16px;\n padding: 4px 0 8px;\n}\n.dsh-rewind-cleanup-readonly {\n margin: 12px 0 0;\n font-size: 12px;\n line-height: 1.5;\n color: var(--dsw-alias-label-tertiary);\n}\n.dsh-rewind-cleanup-permission {\n display: grid;\n gap: 6px;\n padding: 12px 0;\n}\n.dsh-rewind-cleanup-field {\n display: flex;\n flex-direction: column;\n gap: 6px;\n padding: 12px 0;\n}\n.dsh-rewind-cleanup-field + .dsh-rewind-cleanup-field {\n border-top: 0.5px solid var(--dsw-alias-border-l2);\n}\n.dsh-rewind-cleanup-head {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n.dsh-rewind-cleanup-label {\n flex: 1;\n min-width: 0;\n font-size: 13px;\n font-weight: 500;\n line-height: 1.5;\n color: var(--dsw-alias-label-primary);\n}\n.dsh-rewind-cleanup-hint {\n margin: 0;\n font-size: 12px;\n line-height: 1.5;\n color: var(--dsw-alias-label-tertiary);\n}\n.dsh-rewind-cleanup-error {\n margin: 0;\n font-size: 12px;\n line-height: 1.5;\n color: var(--dsw-alias-label-error);\n}\n/* Switch row: label left, role=switch button right, hint below (Subagent module). */\n.dsh-rewind-cleanup-toggle-row {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n gap: 16px;\n font-size: 13px;\n line-height: 1.5;\n color: var(--dsw-alias-label-primary);\n}\n.dsh-rewind-cleanup-toggle-label {\n flex: 1;\n min-width: 0;\n}\n.dsh-rewind-cleanup-switch {\n box-sizing: border-box;\n position: relative;\n flex: 0 0 auto;\n width: 36px;\n height: 20px;\n padding: 2px;\n border: 0;\n border-radius: 10px;\n background: var(--dsw-alias-border-l3);\n cursor: pointer;\n}\n.dsh-rewind-cleanup-switch-on {\n background: var(--dsw-alias-brand-primary);\n}\n.dsh-rewind-cleanup-switch:disabled {\n cursor: default;\n opacity: 0.5;\n}\n.dsh-rewind-cleanup-switch:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: 2px;\n}\n.dsh-rewind-cleanup-thumb {\n display: block;\n width: 16px;\n height: 16px;\n border-radius: 50%;\n corner-shape: round;\n background: var(--dsw-alias-label-primary-foreground);\n transition: transform 120ms ease;\n}\n.dsh-rewind-cleanup-switch-on .dsh-rewind-cleanup-thumb {\n transform: translateX(16px);\n}\n.dsh-rewind-cleanup-input {\n box-sizing: border-box;\n height: 34px;\n padding: 0 12px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 8px;\n background: var(--dsw-alias-bg-layer-3);\n font: inherit;\n font-size: 13px;\n line-height: 1.5;\n color: var(--dsw-alias-label-primary);\n}\n.dsh-rewind-cleanup-input:focus-visible {\n outline: none;\n border-color: var(--dsw-alias-brand-primary);\n}\n.dsh-rewind-cleanup-input:disabled {\n color: var(--dsw-alias-label-tertiary);\n cursor: default;\n}\n.dsh-rewind-cleanup-input-invalid {\n border-color: var(--dsw-alias-label-error);\n}\n.dsh-rewind-cleanup-footer {\n display: flex;\n align-items: center;\n justify-content: flex-end;\n gap: 8px;\n padding: 12px 0 4px;\n border-top: 1px solid var(--dsw-alias-border-l2);\n}\n.dsh-rewind-cleanup-failed {\n flex: 1;\n min-width: 0;\n margin: 0;\n font-size: 12px;\n line-height: 1.5;\n color: var(--dsw-alias-label-error);\n}\n.dsh-rewind-cleanup-discard,\n.dsh-rewind-cleanup-save {\n appearance: none;\n border: 1px solid transparent;\n border-radius: 8px;\n padding: 5px 14px;\n font: inherit;\n font-size: 13px;\n line-height: 1.5;\n cursor: pointer;\n}\n.dsh-rewind-cleanup-discard {\n border-color: var(--dsw-alias-border-l2);\n background: none;\n color: var(--dsw-alias-label-secondary);\n}\n.dsh-rewind-cleanup-discard:hover:not(:disabled) {\n color: var(--dsw-alias-label-primary);\n border-color: var(--dsw-alias-label-dimmed);\n}\n.dsh-rewind-cleanup-save {\n background: var(--dsw-alias-label-primary);\n color: var(--dsw-alias-bg-layer-3);\n}\n.dsh-rewind-cleanup-discard:disabled,\n.dsh-rewind-cleanup-save:disabled {\n opacity: 0.4;\n cursor: default;\n}\n.dsh-rewind-cleanup-discard:focus-visible,\n.dsh-rewind-cleanup-save:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: 1px;\n}\n";
@@ -46,9 +46,9 @@ export declare const CleanupConfigSchema: z<CleanupConfig>;
46
46
  /**
47
47
  * Structural face of the settings scope the host needs for the policy: a
48
48
  * resolved read and a validated write. Kept local (never imports the settings
49
- * contract) so the host bundle links on both rc.2 and alpha — the settings
50
- * API drift (alpha adds `mutate`, rd2 does not) is confined to the seam the
51
- * host passes in, never to this module.
49
+ * contract) so the host bundle does not type-couple on the client settings
50
+ * API (0.1.2 adds `mutate`; it is unused here), and the seam the host passes
51
+ * in isolates the drift to this module.
52
52
  */
53
53
  export interface CleanupSettingsScope {
54
54
  /** The resolved policy: schema defaults, then base, then the user layer. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-rewind-plugin",
3
- "version": "0.7.4",
3
+ "version": "0.8.0-alpha.1",
4
4
  "description": "DSH 插件:真正便捷无感的同窗口内对话回退,从不新建分支;自带轻量工作区备份,可一并还原文件(完整 Claude Code /rewind 语义)。 · DSH plugin: genuinely effortless in-window conversation rewind — never forking a new session; ships a lightweight workspace backup that restores files together with the rewind (full Claude Code /rewind semantics).",
5
5
  "keywords": [
6
6
  "deepseek-harness",
@@ -52,7 +52,6 @@
52
52
  "client": {
53
53
  "inject": [
54
54
  "@deepseek-ai/dsh-client-locale",
55
- "@deepseek-ai/dsh-client-runtime",
56
55
  "@deepseek-ai/dsh-client-ui-commands",
57
56
  "@deepseek-ai/dsh-client-ui-conversation",
58
57
  "@deepseek-ai/dsh-client-ui-settings"
@@ -74,19 +73,18 @@
74
73
  "peerDependencies": {
75
74
  "@deepseek-ai/cordis": "^4.0.1",
76
75
  "@deepseek-ai/schemastery": "^3.18.1",
77
- "@deepseek-ai/dsh-client-locale": "^0.1.0-rc.6 || ^0.1.1-rc.2 || ^0.1.2-alpha.2",
78
- "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.6 || ^0.1.1-rc.2",
79
- "@deepseek-ai/dsh-client-ui-commands": "^0.1.0-rc.6 || ^0.1.1-rc.2 || ^0.1.2-alpha.2",
80
- "@deepseek-ai/dsh-client-ui-settings": "^0.1.0-rc.6 || ^0.1.1-rc.2 || ^0.1.2-alpha.2",
81
- "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.6 || ^0.1.1-rc.2 || ^0.1.2-alpha.2",
82
- "@deepseek-ai/dsh-commands": "^0.1.0-rc.6 || ^0.1.1-rc.2 || ^0.1.2-alpha.2",
83
- "@deepseek-ai/dsh-fs": "^0.1.0-rc.6 || ^0.1.1-rc.2 || ^0.1.2-alpha.2",
84
- "@deepseek-ai/dsh-home-paths": "^0.1.0-rc.6 || ^0.1.1-rc.2 || ^0.1.2-alpha.2",
85
- "@deepseek-ai/dsh-llm": "^0.1.0-rc.6 || ^0.1.1-rc.2 || ^0.1.2-alpha.2",
86
- "@deepseek-ai/dsh-sandbox": "^0.1.0-rc.6 || ^0.1.1-rc.2 || ^0.1.2-alpha.2",
87
- "@deepseek-ai/dsh-session": "^0.1.0-rc.6 || ^0.1.1-rc.2 || ^0.1.2-alpha.2",
88
- "@deepseek-ai/dsh-settings": "^0.1.0-rc.8 || ^0.1.1-rc.2 || ^0.1.2-alpha.2",
89
- "@deepseek-ai/dsh-tools": "^0.1.0-rc.6 || ^0.1.1-rc.2 || ^0.1.2-alpha.2"
76
+ "@deepseek-ai/dsh-client-locale": "^0.1.2-rc.1",
77
+ "@deepseek-ai/dsh-client-ui-commands": "^0.1.2-rc.1",
78
+ "@deepseek-ai/dsh-client-ui-settings": "^0.1.2-rc.1",
79
+ "@deepseek-ai/dsh-client-ui-slots": "^0.1.2-rc.1",
80
+ "@deepseek-ai/dsh-commands": "^0.1.2-rc.1",
81
+ "@deepseek-ai/dsh-fs": "^0.1.2-rc.1",
82
+ "@deepseek-ai/dsh-home-paths": "^0.1.2-rc.1",
83
+ "@deepseek-ai/dsh-llm": "^0.1.2-rc.1",
84
+ "@deepseek-ai/dsh-sandbox": "^0.1.2-rc.1",
85
+ "@deepseek-ai/dsh-session": "^0.1.2-rc.1",
86
+ "@deepseek-ai/dsh-settings": "^0.1.2-rc.1",
87
+ "@deepseek-ai/dsh-tools": "^0.1.2-rc.1"
90
88
  },
91
89
  "peerDependenciesMeta": {
92
90
  "@deepseek-ai/cordis": {
@@ -98,9 +96,6 @@
98
96
  "@deepseek-ai/dsh-client-locale": {
99
97
  "optional": true
100
98
  },
101
- "@deepseek-ai/dsh-client-runtime": {
102
- "optional": true
103
- },
104
99
  "@deepseek-ai/dsh-client-ui-commands": {
105
100
  "optional": true
106
101
  },
@@ -138,29 +133,37 @@
138
133
  "devDependencies": {
139
134
  "@deepseek-ai/cordis": "^4.0.1",
140
135
  "@deepseek-ai/schemastery": "^3.18.1",
141
- "@deepseek-ai/dsh-agent": "^0.1.1-rc.2",
142
- "@deepseek-ai/dsh-client-locale": "^0.1.1-rc.2",
143
- "@deepseek-ai/dsh-client-runtime": "^0.1.1-rc.2",
144
- "@deepseek-ai/dsh-client-ui-commands": "^0.1.1-rc.2",
145
- "@deepseek-ai/dsh-client-ui-input-trigger": "^0.1.1-rc.2",
146
- "@deepseek-ai/dsh-client-ui-slots": "^0.1.1-rc.2",
147
- "@deepseek-ai/dsh-command-compact": "^0.1.1-rc.2",
148
- "@deepseek-ai/dsh-commands": "^0.1.1-rc.2",
149
- "@deepseek-ai/dsh-compaction": "^0.1.1-rc.2",
150
- "@deepseek-ai/dsh-compaction-basic": "^0.1.1-rc.2",
151
- "@deepseek-ai/dsh-fs": "^0.1.1-rc.2",
152
- "@deepseek-ai/dsh-goal": "^0.1.1-rc.2",
153
- "@deepseek-ai/dsh-home-paths": "^0.1.1-rc.2",
154
- "@deepseek-ai/dsh-llm": "^0.1.1-rc.2",
155
- "@deepseek-ai/dsh-plan-mode": "^0.1.1-rc.2",
156
- "@deepseek-ai/dsh-sandbox": "^0.1.1-rc.2",
157
- "@deepseek-ai/dsh-session": "^0.1.1-rc.2",
158
- "@deepseek-ai/dsh-session-projection": "^0.1.1-rc.2",
159
- "@deepseek-ai/dsh-session-stats": "^0.1.1-rc.2",
160
- "@deepseek-ai/dsh-session-title": "^0.1.1-rc.2",
161
- "@deepseek-ai/dsh-settings": "^0.1.1-rc.2",
162
- "@deepseek-ai/dsh-token-meter": "^0.1.1-rc.2",
163
- "@deepseek-ai/dsh-tools": "^0.1.1-rc.2",
136
+ "@deepseek-ai/dsh-agent": "^0.1.2-rc.1",
137
+ "@deepseek-ai/dsh-attachment": "^0.1.2-rc.1",
138
+ "@deepseek-ai/dsh-client-locale": "^0.1.2-rc.1",
139
+ "@deepseek-ai/dsh-client-connection": "^0.1.2-rc.1",
140
+ "@deepseek-ai/dsh-client-store": "^0.1.2-rc.1",
141
+ "@deepseek-ai/dsh-client-ui-primitives": "^0.1.2-rc.1",
142
+ "@deepseek-ai/dsh-api-session-controller": "^0.1.2-rc.1",
143
+ "@deepseek-ai/dsh-client-ui-conversation": "^0.1.2-rc.1",
144
+ "@deepseek-ai/dsh-scope": "^0.1.2-rc.1",
145
+ "@deepseek-ai/dsh-typert-protocol": "^0.1.2-rc.1",
146
+ "@deepseek-ai/dsh-user-questions": "^0.1.2-rc.1",
147
+ "@deepseek-ai/dsh-client-ui-commands": "^0.1.2-rc.1",
148
+ "@deepseek-ai/dsh-client-ui-input-trigger": "^0.1.2-rc.1",
149
+ "@deepseek-ai/dsh-client-ui-slots": "^0.1.2-rc.1",
150
+ "@deepseek-ai/dsh-command-compact": "^0.1.2-rc.1",
151
+ "@deepseek-ai/dsh-commands": "^0.1.2-rc.1",
152
+ "@deepseek-ai/dsh-compaction": "^0.1.2-rc.1",
153
+ "@deepseek-ai/dsh-compaction-basic": "^0.1.2-rc.1",
154
+ "@deepseek-ai/dsh-fs": "^0.1.2-rc.1",
155
+ "@deepseek-ai/dsh-goal": "^0.1.2-rc.1",
156
+ "@deepseek-ai/dsh-home-paths": "^0.1.2-rc.1",
157
+ "@deepseek-ai/dsh-llm": "^0.1.2-rc.1",
158
+ "@deepseek-ai/dsh-plan-mode": "^0.1.2-rc.1",
159
+ "@deepseek-ai/dsh-sandbox": "^0.1.2-rc.1",
160
+ "@deepseek-ai/dsh-session": "^0.1.2-rc.1",
161
+ "@deepseek-ai/dsh-session-projection": "^0.1.2-rc.1",
162
+ "@deepseek-ai/dsh-session-stats": "^0.1.2-rc.1",
163
+ "@deepseek-ai/dsh-session-title": "^0.1.2-rc.1",
164
+ "@deepseek-ai/dsh-settings": "^0.1.2-rc.1",
165
+ "@deepseek-ai/dsh-token-meter": "^0.1.2-rc.1",
166
+ "@deepseek-ai/dsh-tools": "^0.1.2-rc.1",
164
167
  "@types/node": "^24.0.0",
165
168
  "@types/react": "^18.3.31",
166
169
  "@types/react-dom": "^18.3.7",
@@ -1,34 +0,0 @@
1
- /**
2
- * Cross-channel session event-log reader.
3
- *
4
- * Harness 0.1.1-rc.2 exposes the full log as `Session.events`
5
- * (`get events(): readonly SessionEvent[]`), while 0.1.2-alpha.4 removed that
6
- * member and replaced it with the on-demand APIs `snapshotEvents(from?, to?)`
7
- * (half-open range, internally cached), `eventAt(seq)`, `ownEvents()` and
8
- * `seq`. This module reads the full log through whichever channel the host
9
- * exposes, so the plugin keeps one code path across both.
10
- *
11
- * `snapshotEvents()` is deliberately preferred over `ownEvents()`:
12
- * `snapshotEvents()` defaults to the whole log (including any fork-inherited
13
- * prefix), which is exactly what `Session.events` returned on rc.2 — the
14
- * rewind semantics are preserved for fork-seeded sessions. `ownEvents()`
15
- * would drop the inherited prefix and change behaviour.
16
- *
17
- * @module dsh-rewind/session-events
18
- */
19
- import type { Session, SessionEvent } from '@deepseek-ai/dsh-session';
20
- /**
21
- * Read the full event log of a session, transparently across harness channels:
22
- * - 0.1.1-rc.2 (`Session.events`): the live immutable log array.
23
- * - 0.1.2-alpha.4 (`Session.snapshotEvents()`): a deep-frozen snapshot, cached
24
- * by the session until the next append.
25
- *
26
- * Falls back to an empty log when the session exposes neither member (a future
27
- * harness shape) rather than throwing — callers already treat the empty log as
28
- * "no candidates".
29
- *
30
- * @param session - the session to read.
31
- * @returns the full event log in log order (the same shape rc.2's `events`
32
- * returned, so existing consumers are unchanged).
33
- */
34
- export declare function eventsOf(session: Session): readonly SessionEvent[];