dsh-rewind-plugin 0.20.0-alpha.3 → 0.20.0-alpha.4

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.js CHANGED
@@ -475,12 +475,13 @@ function waitForCommand(session, chatOf, match, timeoutMs = 8e3, watch) {
475
475
  check();
476
476
  });
477
477
  }
478
- var previewCall = null;
478
+ var UNAVAILABLE = () => Promise.resolve({ kind: "error", text: "host query is unavailable" });
479
+ var previewCall = UNAVAILABLE;
479
480
  function registerPreviewCall(call) {
480
- previewCall = call;
481
+ previewCall = call ?? UNAVAILABLE;
481
482
  }
482
483
  function previewImpact(sessionId, seq) {
483
- return previewCall?.(sessionId, seq) ?? Promise.resolve({ kind: "error", text: "host RPC is unavailable" });
484
+ return previewCall(sessionId, seq);
484
485
  }
485
486
  function el(tag2, className, text) {
486
487
  const node = document.createElement(tag2);
@@ -1530,12 +1531,18 @@ function createRewindBridge(deps) {
1530
1531
  };
1531
1532
  }
1532
1533
 
1533
- // src/client/host-rpc.ts
1534
- var CHANNEL = "/dsh-rewind";
1534
+ // src/client/host-api.ts
1535
1535
  var TIMEOUT_MS = 8e3;
1536
1536
  function isRecord(value) {
1537
1537
  return typeof value === "object" && value !== null && !Array.isArray(value);
1538
1538
  }
1539
+ function isResult(value) {
1540
+ if (!isRecord(value)) return false;
1541
+ if (value["ok"] === true) return true;
1542
+ if (value["ok"] !== false || !isRecord(value["error"])) return false;
1543
+ const error = value["error"];
1544
+ return typeof error["code"] === "string" && typeof error["message"] === "string" && isRecord(error["details"]);
1545
+ }
1539
1546
  function isImpact(value) {
1540
1547
  return isRecord(value) && typeof value["path"] === "string" && (value["action"] === "restore" || value["action"] === "delete");
1541
1548
  }
@@ -1546,53 +1553,67 @@ function isAbort(error) {
1546
1553
  const name2 = error?.name;
1547
1554
  return name2 === "AbortError" || name2 === "TimeoutError";
1548
1555
  }
1549
- async function previewOverRpc(connection, sessionId, seq) {
1550
- if (connection === void 0) return { kind: "error", text: "host RPC is unavailable" };
1556
+ function init(payload, signal) {
1557
+ return {
1558
+ method: "POST",
1559
+ headers: { "content-type": "application/json" },
1560
+ body: JSON.stringify(payload),
1561
+ signal
1562
+ };
1563
+ }
1564
+ async function settleQuery(response, route) {
1565
+ if (!response.ok) throw new Error(`transport failure for ${route}: HTTP ${response.status}`);
1566
+ const result = await response.json();
1567
+ if (!isResult(result)) throw new Error(`invalid response for ${route}`);
1568
+ return result;
1569
+ }
1570
+ async function previewOverApi(sessionId, seq) {
1551
1571
  try {
1552
- const result = await connection.rpc.call(CHANNEL, "preview", { sessionId, seq }, AbortSignal.timeout(TIMEOUT_MS));
1572
+ const response = await fetch("./api/dsh-rewind/preview", init({ sessionId, seq }, AbortSignal.timeout(TIMEOUT_MS)));
1573
+ const result = await settleQuery(response, "preview");
1553
1574
  if (!result.ok) {
1554
- rewindLog.warn("preview", `RPC preview failed for @${seq}`, result.error);
1575
+ rewindLog.warn("preview", `preview request failed for @${seq}`, result.error);
1555
1576
  return { kind: "error", text: result.error.message };
1556
1577
  }
1557
1578
  const value = result.value;
1558
1579
  if (!isRecord(value) || typeof value["backupOff"] !== "boolean" || !Array.isArray(value["files"]) || !value["files"].every(isImpact)) {
1559
- rewindLog.warn("preview", `RPC preview returned an invalid result for @${seq}`);
1580
+ rewindLog.warn("preview", `preview request returned an invalid result for @${seq}`);
1560
1581
  return { kind: "error", text: "invalid preview response" };
1561
1582
  }
1562
1583
  return { kind: "success", files: value["files"], backupOff: value["backupOff"] };
1563
1584
  } catch (error) {
1564
1585
  if (isAbort(error)) {
1565
- rewindLog.warn("preview", `RPC preview timed out for @${seq}`);
1586
+ rewindLog.warn("preview", `preview request timed out for @${seq}`);
1566
1587
  return null;
1567
1588
  }
1568
- rewindLog.warn("preview", `RPC preview threw for @${seq}`, error);
1589
+ rewindLog.warn("preview", `preview request threw for @${seq}`, error);
1569
1590
  return { kind: "error", text: error instanceof Error ? error.message : String(error) };
1570
1591
  }
1571
1592
  }
1572
- async function candidatesOverRpc(connection, sessionId) {
1573
- if (connection === void 0) return void 0;
1593
+ async function candidatesOverApi(sessionId) {
1574
1594
  try {
1575
- const result = await connection.rpc.call(CHANNEL, "candidates", { sessionId }, AbortSignal.timeout(TIMEOUT_MS));
1595
+ const response = await fetch("./api/dsh-rewind/candidates", init({ sessionId }, AbortSignal.timeout(TIMEOUT_MS)));
1596
+ const result = await settleQuery(response, "candidates");
1576
1597
  if (!result.ok) {
1577
- rewindLog.warn("preview", "RPC candidates failed", result.error);
1598
+ rewindLog.warn("preview", "candidate request failed", result.error);
1578
1599
  return void 0;
1579
1600
  }
1580
1601
  const value = result.value;
1581
1602
  if (!isRecord(value) || !Array.isArray(value["candidates"]) || !value["candidates"].every(isCandidate)) {
1582
- rewindLog.warn("preview", "RPC candidates returned an invalid result");
1603
+ rewindLog.warn("preview", "candidate request returned an invalid result");
1583
1604
  return void 0;
1584
1605
  }
1585
1606
  return value["candidates"];
1586
1607
  } catch (error) {
1587
- rewindLog.warn("preview", "RPC candidates threw", error);
1608
+ rewindLog.warn("preview", "candidate request threw", error);
1588
1609
  return void 0;
1589
1610
  }
1590
1611
  }
1591
1612
 
1592
1613
  // src/client/build-info.ts
1593
- var PLUGIN_VERSION = true ? "0.20.0-alpha.3" : "dev";
1614
+ var PLUGIN_VERSION = true ? "0.20.0-alpha.4" : "dev";
1594
1615
  var PLUGIN_PACKAGE = "dsh-rewind-plugin";
1595
- var BUILD_HASH = true ? "46008907" : "dev";
1616
+ var BUILD_HASH = true ? "c59b80ee" : "dev";
1596
1617
 
1597
1618
  // src/client/locales.ts
1598
1619
  var en = {
@@ -2063,7 +2084,7 @@ function SettingsCard(props) {
2063
2084
 
2064
2085
  // src/client/index.ts
2065
2086
  var name = "dsh-rewind";
2066
- var inject = ["slots", "sessions", "locale", "commandUi", "configForms", "connection"];
2087
+ var inject = ["slots", "sessions", "locale", "commandUi", "configForms"];
2067
2088
  var NS2 = "rewind";
2068
2089
  var HEADER_ACTIONS_SLOT = "conversation.session.header.actions";
2069
2090
  var COMPOSER_EDITABLE_SELECTOR2 = "[data-composer-input]";
@@ -2072,8 +2093,7 @@ function apply(ctx) {
2072
2093
  ctx.effect(function* () {
2073
2094
  yield ctx.locale.register(NS2, CLIENT_DICTS);
2074
2095
  const t = ctx.locale.bind(NS2);
2075
- const connection = ctx.get("connection");
2076
- registerPreviewCall((sessionId, seq) => previewOverRpc(connection, sessionId, seq));
2096
+ registerPreviewCall(previewOverApi);
2077
2097
  yield () => {
2078
2098
  registerPreviewCall(null);
2079
2099
  };
@@ -2227,7 +2247,7 @@ function apply(ctx) {
2227
2247
  const chat = chatOf(face);
2228
2248
  return chat !== void 0 && rewindCandidatesOfChat(chat).length > 0;
2229
2249
  };
2230
- const fetchHostCandidates = async (face) => candidatesOverRpc(connection, face.sessionId);
2250
+ const fetchHostCandidates = async (face) => candidatesOverApi(face.sessionId);
2231
2251
  const hostCandidatesCache = /* @__PURE__ */ new Map();
2232
2252
  const composerAnchor = () => {
2233
2253
  const surface = composerSurface2();
package/lib/index.js CHANGED
@@ -2583,7 +2583,8 @@ function shouldRunAutoSweep(lastAtMs, nowMs, intervalMs = AUTO_SWEEP_INTERVAL_MS
2583
2583
  var name = "dsh-rewind";
2584
2584
  var inject = ["commands", "tools", "settings"];
2585
2585
  var ENGINE_COMMAND = "rewind-plugin";
2586
- var REWIND_RPC_CHANNEL = "/dsh-rewind";
2586
+ var REWIND_PREVIEW_PATH = "/api/dsh-rewind/preview";
2587
+ var REWIND_CANDIDATES_PATH = "/api/dsh-rewind/candidates";
2587
2588
  var DEFAULT_FILE_CHECKPOINTING_ENABLED = true;
2588
2589
  var Config = z.object({
2589
2590
  snapshotDir: z.string().required(false),
@@ -2776,36 +2777,45 @@ async function previewImpact(store, session, seq, checkpointingEnabled) {
2776
2777
  function isRecord(value) {
2777
2778
  return typeof value === "object" && value !== null && !Array.isArray(value);
2778
2779
  }
2779
- function rpcFailure(code, message) {
2780
+ function queryFailure(code, message) {
2780
2781
  return { ok: false, error: { code, message, details: {} } };
2781
2782
  }
2782
- function createRewindRpcHandler(store, agentsOf, checkpointingEnabled) {
2783
- return async (endpoint, payload) => {
2783
+ function queryResponse(result) {
2784
+ return Response.json(result);
2785
+ }
2786
+ function createRewindQueryHandler(store, agentsOf, checkpointingEnabled, query) {
2787
+ return async (request) => {
2784
2788
  try {
2785
- if (!isRecord(payload)) return rpcFailure("rewind/bad-request", "invalid payload");
2789
+ if (request.headers.get("content-type")?.split(";", 1)[0]?.trim().toLowerCase() !== "application/json") {
2790
+ return new Response("content type must be application/json", { status: 415 });
2791
+ }
2792
+ let payload;
2793
+ try {
2794
+ payload = await request.json();
2795
+ } catch {
2796
+ return new Response("body is not JSON", { status: 400 });
2797
+ }
2798
+ if (!isRecord(payload)) return queryResponse(queryFailure("rewind/bad-request", "invalid payload"));
2786
2799
  const sessionId = payload["sessionId"];
2787
2800
  if (typeof sessionId !== "string" || sessionId.length === 0) {
2788
- return rpcFailure("rewind/bad-request", "sessionId must be a non-empty string");
2801
+ return queryResponse(queryFailure("rewind/bad-request", "sessionId must be a non-empty string"));
2789
2802
  }
2790
2803
  const agents = agentsOf();
2791
- if (agents === void 0) return rpcFailure("rewind/agents-unavailable", "agent registry is unavailable");
2804
+ if (agents === void 0) return queryResponse(queryFailure("rewind/agents-unavailable", "agent registry is unavailable"));
2792
2805
  const agent = agents.get(sessionId);
2793
- if (agent === void 0) return rpcFailure("rewind/session-not-found", `session ${sessionId} is not attached`);
2806
+ if (agent === void 0) return queryResponse(queryFailure("rewind/session-not-found", `session ${sessionId} is not attached`));
2794
2807
  const session = agent.session;
2795
- if (endpoint === "preview") {
2808
+ if (query === "preview") {
2796
2809
  const seq = payload["seq"];
2797
- if (!Number.isSafeInteger(seq)) return rpcFailure("rewind/bad-request", "seq must be an integer");
2798
- return { ok: true, value: await previewImpact(store, session, seq, checkpointingEnabled()) };
2799
- }
2800
- if (endpoint === "candidates") {
2801
- return {
2802
- ok: true,
2803
- value: { candidates: listRewindCandidates(session.snapshotEvents(), session.surface.nodes) }
2804
- };
2810
+ if (!Number.isSafeInteger(seq)) return queryResponse(queryFailure("rewind/bad-request", "seq must be an integer"));
2811
+ return queryResponse({ ok: true, value: await previewImpact(store, session, seq, checkpointingEnabled()) });
2805
2812
  }
2806
- return rpcFailure("rewind/unknown-endpoint", `unknown endpoint: ${endpoint}`);
2813
+ return queryResponse({
2814
+ ok: true,
2815
+ value: { candidates: listRewindCandidates(session.snapshotEvents(), session.surface.nodes) }
2816
+ });
2807
2817
  } catch (error) {
2808
- return rpcFailure("rewind/failed", error instanceof Error ? error.message : String(error));
2818
+ return queryResponse(queryFailure("rewind/failed", error instanceof Error ? error.message : String(error)));
2809
2819
  }
2810
2820
  };
2811
2821
  }
@@ -3244,21 +3254,24 @@ function apply(ctx, config) {
3244
3254
  })();
3245
3255
  }, { global: true });
3246
3256
  ctx.inject(["connection"], (scope) => {
3247
- try {
3248
- const connection = scope.root.connection;
3249
- if (connection === void 0) return;
3250
- const dispose = connection.rpc.handle(
3251
- REWIND_RPC_CHANNEL,
3252
- createRewindRpcHandler(
3253
- store,
3254
- () => scope.get("agents"),
3255
- () => isFileCheckpointingEnabled(config)
3256
- )
3257
- );
3258
- scope.effect(() => dispose, "dsh-rewind RPC channel");
3259
- } catch (error) {
3260
- ctx.logger.warn(`[dsh-rewind] RPC channel registration failed: ${error instanceof Error ? error.message : String(error)}`);
3261
- }
3257
+ const connection = scope.connection;
3258
+ if (connection === void 0) return;
3259
+ const agentsOf = () => scope.get("agents");
3260
+ const checkpointingEnabled = () => isFileCheckpointingEnabled(config);
3261
+ const register = (path, query) => {
3262
+ try {
3263
+ scope.effect(() => connection.fetch.register({
3264
+ path,
3265
+ methods: ["POST"],
3266
+ requestBody: "buffered",
3267
+ fetch: createRewindQueryHandler(store, agentsOf, checkpointingEnabled, query)
3268
+ }), `dsh-rewind ${path} route`);
3269
+ } catch (error) {
3270
+ ctx.logger.error(`[dsh-rewind] route registration failed for ${path}: ${error instanceof Error ? error.message : String(error)}`);
3271
+ }
3272
+ };
3273
+ register(REWIND_PREVIEW_PATH, "preview");
3274
+ register(REWIND_CANDIDATES_PATH, "candidates");
3262
3275
  });
3263
3276
  ctx.inject(["fs", "workingDirectory"], (scope) => {
3264
3277
  const fs = scope.fs;
@@ -74,7 +74,8 @@ export declare function rewindCandidatesOf(snap: CandidateChat, limit?: number):
74
74
  export declare function rewindCandidatesOfChat(snap: CandidateChat): RewindCandidate[];
75
75
  /**
76
76
  * Map typed candidates to popupSelect rows. The list comes from the host over
77
- * RPC, so it covers the FULL host surface rather than the windowed chat snapshot.
77
+ * the host query route, so it covers the FULL host surface rather than the
78
+ * windowed chat snapshot.
78
79
  */
79
80
  export declare function rewindOptionsFromCandidates(candidates: readonly RewindCandidate[], t: Translate): SelectOption[];
80
81
  export {};
@@ -0,0 +1,27 @@
1
+ /**
2
+ * The browser half of the two read-only host queries: the mode popover's impact
3
+ * preview and the `/rewind` candidate list, posted to their exact `/api` routes.
4
+ *
5
+ * @module dsh-rewind/client/host-api
6
+ */
7
+ import type { RewindCandidate } from './candidates.ts';
8
+ /** One file affected by a rewind. */
9
+ export interface PreviewFileImpact {
10
+ readonly path: string;
11
+ readonly action: 'restore' | 'delete';
12
+ }
13
+ /** One impact probe resolved, failed, or timed out (`null`). */
14
+ export type PreviewOutcome = {
15
+ readonly kind: 'success';
16
+ readonly files: readonly PreviewFileImpact[];
17
+ readonly backupOff: boolean;
18
+ } | {
19
+ readonly kind: 'error';
20
+ readonly text: string;
21
+ } | null;
22
+ /** Fetch one target's impact through the host query route. */
23
+ export type PreviewCall = (sessionId: string, seq: number) => Promise<PreviewOutcome>;
24
+ /** Resolve one target's file impact through the host query route. */
25
+ export declare function previewOverApi(sessionId: string, seq: number): Promise<PreviewOutcome>;
26
+ /** Fetch the full rewind candidate list through the host query route. */
27
+ export declare function candidatesOverApi(sessionId: string): Promise<readonly RewindCandidate[] | undefined>;
@@ -9,7 +9,7 @@
9
9
  * The command decoration (`ctx.commandUi.decorate`) makes a bare `/rewind` (or
10
10
  * its alias `/undo`) open the harness's own popupSelect instead of executing;
11
11
  * the parameterized `@<seq>` form stays the execution channel, while the
12
- * popover's impact and candidate reads go over the host RPC channel.
12
+ * popover's impact and candidate reads go over the host's exact `/api` routes.
13
13
  *
14
14
  * @module dsh-rewind/client
15
15
  */
@@ -2,7 +2,7 @@
2
2
  * The rewind mode-selection popover (plain DOM, no React). Step two of the
3
3
  * interaction: the target is already fixed (the clicked message); the popover
4
4
  * offers the two modes. Choosing "both" fetches the impact list over the host
5
- * RPC channel and shows it before confirming.
5
+ * `/api` preview route and shows it before confirming.
6
6
  *
7
7
  * Keyboard: ↑/↓ move focus across the step's ACTION buttons only (the two
8
8
  * modes, or the confirm button on the impact step), Enter activates the
@@ -16,7 +16,7 @@
16
16
  import type { SessionFace } from '@deepseek-ai/dsh-api-session-controller/client';
17
17
  import type { CommandNode } from '@deepseek-ai/dsh-client-ui-conversation/client';
18
18
  import { type ChatOf } from './hidden.ts';
19
- import type { PreviewCall } from './host-rpc.ts';
19
+ import type { PreviewCall } from './host-api.ts';
20
20
  import type { RewindKey } from './locales.ts';
21
21
  type Translate = (key: RewindKey, params?: Record<string, unknown>) => string;
22
22
  export interface PopoverOptions {
@@ -66,7 +66,7 @@ export declare function waitForCommand(session: SessionFace, chatOf: ChatOf, mat
66
66
  kind: 'success' | 'error';
67
67
  text?: string;
68
68
  } | null>;
69
- /** Register the host RPC preview call (null clears it on unload). */
69
+ /** Register the host preview call; null restores the unavailable default. */
70
70
  export declare function registerPreviewCall(call: PreviewCall | null): void;
71
71
  /** Open the mode-selection popover anchored near the given button. */
72
72
  export declare function openPopover(opts: PopoverOptions): void;
@@ -16,7 +16,7 @@
16
16
  *
17
17
  * The client half (`src/client/locales.ts`) owns all interactive UI copy via
18
18
  * `ctx.locale` + `t()`; the client never parses host prose (the popover reads
19
- * travel over the RPC channel).
19
+ * travel over the host `/api` query routes).
20
20
  *
21
21
  * DSH localizes only its OWN command descriptions via the client locale — a
22
22
  * closed `HOST_FACES` allowlist; third-party plugin descriptions are
@@ -179,7 +179,7 @@ export interface LinkEntry {
179
179
  export type StoredEntry = CheckpointEntry | LinkEntry;
180
180
  /** True when an entry is a dedup link (carries `ref`, not `before`). */
181
181
  export declare function isLinkEntry(entry: StoredEntry): entry is LinkEntry;
182
- /** Per-file restore impact preview (served by the host RPC channel). */
182
+ /** Per-file restore impact preview (served by the host preview route). */
183
183
  export interface FileImpact {
184
184
  readonly path: string;
185
185
  /** `restore` = write the before content back; `delete` = remove the file. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-rewind-plugin",
3
- "version": "0.20.0-alpha.3",
3
+ "version": "0.20.0-alpha.4",
4
4
  "description": "In-window conversation rewind with workspace file restore",
5
5
  "icon": "./assets/icon.svg",
6
6
  "keywords": [
@@ -58,7 +58,6 @@
58
58
  "client": {
59
59
  "inject": [
60
60
  "@deepseek-ai/dsh-client-locale",
61
- "@deepseek-ai/dsh-client-connection",
62
61
  "@deepseek-ai/dsh-client-ui-commands",
63
62
  "@deepseek-ai/dsh-client-ui-conversation",
64
63
  "@deepseek-ai/dsh-client-ui-settings"
@@ -155,45 +154,45 @@
155
154
  }
156
155
  },
157
156
  "devDependencies": {
158
- "@deepseek-ai/cordis": "4.0.6-alpha.1",
159
- "@deepseek-ai/cosmokit": "1.8.7-alpha.1",
160
- "@deepseek-ai/dsh-agent": "0.2.2-alpha.2",
161
- "@deepseek-ai/dsh-api-session-controller": "0.2.2-alpha.2",
162
- "@deepseek-ai/dsh-attachment": "0.2.2-alpha.2",
163
- "@deepseek-ai/dsh-client-connection": "0.2.2-alpha.2",
164
- "@deepseek-ai/dsh-client-locale": "0.2.2-alpha.2",
165
- "@deepseek-ai/dsh-client-store": "0.2.2-alpha.2",
166
- "@deepseek-ai/dsh-client-ui-commands": "0.2.2-alpha.2",
167
- "@deepseek-ai/dsh-client-ui-conversation": "0.2.2-alpha.2",
168
- "@deepseek-ai/dsh-client-ui-input-trigger": "0.2.2-alpha.2",
169
- "@deepseek-ai/dsh-client-ui-plugin-manager": "0.2.2-alpha.2",
170
- "@deepseek-ai/dsh-client-ui-primitives": "0.2.2-alpha.2",
171
- "@deepseek-ai/dsh-client-ui-session": "0.2.2-alpha.2",
172
- "@deepseek-ai/dsh-client-ui-settings": "0.2.2-alpha.2",
173
- "@deepseek-ai/dsh-client-ui-slots": "0.2.2-alpha.2",
174
- "@deepseek-ai/dsh-command-compact": "0.2.2-alpha.2",
175
- "@deepseek-ai/dsh-commands": "0.2.2-alpha.2",
176
- "@deepseek-ai/dsh-compaction": "0.2.2-alpha.2",
177
- "@deepseek-ai/dsh-compaction-basic": "0.2.2-alpha.2",
178
- "@deepseek-ai/dsh-compaction-image-offload": "0.2.2-alpha.2",
179
- "@deepseek-ai/dsh-fs": "0.2.2-alpha.2",
180
- "@deepseek-ai/dsh-goal": "0.2.2-alpha.2",
181
- "@deepseek-ai/dsh-home-paths": "0.2.2-alpha.2",
182
- "@deepseek-ai/dsh-llm": "0.2.2-alpha.2",
183
- "@deepseek-ai/dsh-plan-mode": "0.2.2-alpha.2",
184
- "@deepseek-ai/dsh-sandbox": "0.2.2-alpha.2",
185
- "@deepseek-ai/dsh-scope": "0.2.2-alpha.2",
186
- "@deepseek-ai/dsh-session": "0.2.2-alpha.2",
187
- "@deepseek-ai/dsh-session-projection": "0.2.2-alpha.2",
188
- "@deepseek-ai/dsh-session-stats": "0.2.2-alpha.2",
189
- "@deepseek-ai/dsh-session-title": "0.2.2-alpha.2",
190
- "@deepseek-ai/dsh-settings": "0.2.2-alpha.2",
191
- "@deepseek-ai/dsh-token-meter": "0.2.2-alpha.2",
192
- "@deepseek-ai/dsh-tools": "0.2.2-alpha.2",
193
- "@deepseek-ai/dsh-typert-protocol": "0.2.2-alpha.2",
194
- "@deepseek-ai/dsh-user-questions": "0.2.2-alpha.2",
195
- "@deepseek-ai/dsh-working-directory": "0.2.2-alpha.2",
196
- "@deepseek-ai/schemastery": "3.18.6-alpha.1",
157
+ "@deepseek-ai/cordis": "4.0.6-alpha.2",
158
+ "@deepseek-ai/cosmokit": "1.8.7-alpha.2",
159
+ "@deepseek-ai/dsh-agent": "0.2.2-alpha.3",
160
+ "@deepseek-ai/dsh-api-session-controller": "0.2.2-alpha.3",
161
+ "@deepseek-ai/dsh-attachment": "0.2.2-alpha.3",
162
+ "@deepseek-ai/dsh-client-connection": "0.2.2-alpha.3",
163
+ "@deepseek-ai/dsh-client-locale": "0.2.2-alpha.3",
164
+ "@deepseek-ai/dsh-client-store": "0.2.2-alpha.3",
165
+ "@deepseek-ai/dsh-client-ui-commands": "0.2.2-alpha.3",
166
+ "@deepseek-ai/dsh-client-ui-conversation": "0.2.2-alpha.3",
167
+ "@deepseek-ai/dsh-client-ui-input-trigger": "0.2.2-alpha.3",
168
+ "@deepseek-ai/dsh-client-ui-plugin-manager": "0.2.2-alpha.3",
169
+ "@deepseek-ai/dsh-client-ui-primitives": "0.2.2-alpha.3",
170
+ "@deepseek-ai/dsh-client-ui-session": "0.2.2-alpha.3",
171
+ "@deepseek-ai/dsh-client-ui-settings": "0.2.2-alpha.3",
172
+ "@deepseek-ai/dsh-client-ui-slots": "0.2.2-alpha.3",
173
+ "@deepseek-ai/dsh-command-compact": "0.2.2-alpha.3",
174
+ "@deepseek-ai/dsh-commands": "0.2.2-alpha.3",
175
+ "@deepseek-ai/dsh-compaction": "0.2.2-alpha.3",
176
+ "@deepseek-ai/dsh-compaction-basic": "0.2.2-alpha.3",
177
+ "@deepseek-ai/dsh-compaction-image-offload": "0.2.2-alpha.3",
178
+ "@deepseek-ai/dsh-fs": "0.2.2-alpha.3",
179
+ "@deepseek-ai/dsh-goal": "0.2.2-alpha.3",
180
+ "@deepseek-ai/dsh-home-paths": "0.2.2-alpha.3",
181
+ "@deepseek-ai/dsh-llm": "0.2.2-alpha.3",
182
+ "@deepseek-ai/dsh-plan-mode": "0.2.2-alpha.3",
183
+ "@deepseek-ai/dsh-sandbox": "0.2.2-alpha.3",
184
+ "@deepseek-ai/dsh-scope": "0.2.2-alpha.3",
185
+ "@deepseek-ai/dsh-session": "0.2.2-alpha.3",
186
+ "@deepseek-ai/dsh-session-projection": "0.2.2-alpha.3",
187
+ "@deepseek-ai/dsh-session-stats": "0.2.2-alpha.3",
188
+ "@deepseek-ai/dsh-session-title": "0.2.2-alpha.3",
189
+ "@deepseek-ai/dsh-settings": "0.2.2-alpha.3",
190
+ "@deepseek-ai/dsh-token-meter": "0.2.2-alpha.3",
191
+ "@deepseek-ai/dsh-tools": "0.2.2-alpha.3",
192
+ "@deepseek-ai/dsh-typert-protocol": "0.2.2-alpha.3",
193
+ "@deepseek-ai/dsh-user-questions": "0.2.2-alpha.3",
194
+ "@deepseek-ai/dsh-working-directory": "0.2.2-alpha.3",
195
+ "@deepseek-ai/schemastery": "3.18.6-alpha.2",
197
196
  "@types/node": "^24.0.0",
198
197
  "@types/react": "^18.3.31",
199
198
  "@types/react-dom": "^18.3.7",
@@ -1,45 +0,0 @@
1
- /**
2
- * The browser half of the rewind RPC channel: the mode popover's impact
3
- * preview and the `/rewind` candidate list. Both are read-only host queries,
4
- * so they travel over Connection RPC instead of the human command channel.
5
- *
6
- * @module dsh-rewind/client/host-rpc
7
- */
8
- import type { RewindCandidate } from './candidates.ts';
9
- /** One file affected by a rewind. */
10
- export interface PreviewFileImpact {
11
- readonly path: string;
12
- readonly action: 'restore' | 'delete';
13
- }
14
- /** One impact probe resolved, failed, or timed out (`null`). */
15
- export type PreviewOutcome = {
16
- readonly kind: 'success';
17
- readonly files: readonly PreviewFileImpact[];
18
- readonly backupOff: boolean;
19
- } | {
20
- readonly kind: 'error';
21
- readonly text: string;
22
- } | null;
23
- /** Fetch one target's impact through the registered RPC call. */
24
- export type PreviewCall = (sessionId: string, seq: number) => Promise<PreviewOutcome>;
25
- type RpcResult = {
26
- readonly ok: true;
27
- readonly value: unknown;
28
- } | {
29
- readonly ok: false;
30
- readonly error: {
31
- readonly code: string;
32
- readonly message: string;
33
- };
34
- };
35
- /** The slice of the client `connection` service this module reads. */
36
- export interface ConnectionLike {
37
- readonly rpc: {
38
- call(channel: string, endpoint: string, payload: unknown, signal?: AbortSignal): Promise<RpcResult>;
39
- };
40
- }
41
- /** Resolve one target's file impact over RPC. */
42
- export declare function previewOverRpc(connection: ConnectionLike | undefined, sessionId: string, seq: number): Promise<PreviewOutcome>;
43
- /** Fetch the full rewind candidate list over RPC. */
44
- export declare function candidatesOverRpc(connection: ConnectionLike | undefined, sessionId: string): Promise<readonly RewindCandidate[] | undefined>;
45
- export {};