dsh-plugin-lookatstudy 0.12.3 → 0.12.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
@@ -298,10 +298,10 @@ window.__ModuleLoader__.load({
298
298
  * ic_ds_* glyphs vendored from @deepseek-ai/dsh-client-ui-primitives
299
299
  * (src/icons/index.tsx, same figma source as the host's icon set) so the
300
300
  * plugin's client bundle stays self-contained per the dsh client-bundle
301
- * contract — only react and dsh-client-runtime/client are runtime-external;
302
- * importing the host package root would drag its CSS modules into the
303
- * inlined bundle. Re-sync these three paths if the host icon set redesigns
304
- * them; scripts/verify.mjs pins the path data.
301
+ * contract — only react is runtime-external; importing the host package
302
+ * root would drag its CSS modules into the inlined bundle. Re-sync these
303
+ * three paths if the host icon set redesigns them; scripts/verify.mjs
304
+ * pins the path data.
305
305
  *
306
306
  * 2026-09-01 critique round: seven more ic_ds glyphs vendored (play/plus/
307
307
  * trash/refresh/globe/goal/warning) plus plugin-original learning-domain
@@ -2045,10 +2045,10 @@ window.__ModuleLoader__.load({
2045
2045
  return runs.at(-1) ?? [];
2046
2046
  }
2047
2047
  function textOf(blocks) {
2048
- return blocks.filter((b) => b.type === "text").map((b) => b.text ?? "").join("\n\n").trim();
2048
+ return (blocks ?? []).filter((b) => b.type === "text").map((b) => b.text ?? "").join("\n\n").trim();
2049
2049
  }
2050
2050
  function assistantText(blocks) {
2051
- return blocks.filter((b) => b.kind === "text").map((b) => b.text).join("\n\n").trim();
2051
+ return (blocks ?? []).filter((b) => b.kind === "text").map((b) => b.text ?? "").join("\n\n").trim();
2052
2052
  }
2053
2053
  /**
2054
2054
  * Fold conversation nodes (plus the streaming partial) into render rows.
@@ -2088,7 +2088,7 @@ window.__ModuleLoader__.load({
2088
2088
  case "turn-error": rows.push({
2089
2089
  key: `e${node.seq}`,
2090
2090
  role: "error",
2091
- text: node.message
2091
+ text: node.message ?? ""
2092
2092
  });
2093
2093
  }
2094
2094
  if (partial != null) {
@@ -2111,6 +2111,17 @@ window.__ModuleLoader__.load({
2111
2111
  if (error === null) return null;
2112
2112
  return (0, react.createElement)("div", { className: "lks-propcard-err" }, error);
2113
2113
  }
2114
+ /**
2115
+ * Resolve the transcript across host generations. 0.1.3+ hosts expose the
2116
+ * node array as the Chat target's `legacy` slice; pre-0.1.3 hosts hand the
2117
+ * whole conversation snapshot (nodes + partial) through `useSession`, whose
2118
+ * 0.1.3+ successor returns the session MACHINE (no node array). The array
2119
+ * check tells those two `useSession` shapes apart. Pure.
2120
+ */
2121
+ function pickTranscript(chatLegacy, sessionSnapshot) {
2122
+ if (chatLegacy !== void 0) return chatLegacy;
2123
+ return sessionSnapshot !== void 0 && Array.isArray(sessionSnapshot.nodes) ? sessionSnapshot : void 0;
2124
+ }
2114
2125
  /** sessionStorage key keeping the narrow-mode pane across view remounts (tab switches) and reloads. */
2115
2126
  const PANE_KEY = "dsh-plugin-lookatstudy:pane";
2116
2127
  /** Narrow the stored value back to a pane id; anything else (or nothing stored) falls back to 导师. Pure, unit-testable. */
@@ -2137,9 +2148,12 @@ window.__ModuleLoader__.load({
2137
2148
  };
2138
2149
  }
2139
2150
  /** Tab body: the factory-bound ctx carries workspaces/sessions for the per-lesson session jumps. */
2140
- function StudyTab({ useSession, inputActions, ctx }) {
2151
+ function StudyTab({ inputActions, ctx, ...standard }) {
2141
2152
  const { data, activate, setMode, setFocus, searchLessons, deleteCourse, bindLessonSession } = useStudy();
2142
- const snapshot = useSession((s) => s);
2153
+ const chatLegacy = standard.useChat?.((s) => s.legacy);
2154
+ const sessionSnapshot = standard.useSession?.((s) => s);
2155
+ const snapshot = pickTranscript(chatLegacy, sessionSnapshot);
2156
+ const currentSessionId = standard.sessionId ?? snapshot?.sessionId ?? "";
2143
2157
  const [pane, setPane] = (0, react.useState)(storedPane);
2144
2158
  const rootRef = (0, react.useRef)(null);
2145
2159
  (0, react.useEffect)(() => {
@@ -2237,7 +2251,7 @@ window.__ModuleLoader__.load({
2237
2251
  bindLessonSession,
2238
2252
  send,
2239
2253
  ctx,
2240
- currentSessionId: snapshot?.sessionId ?? ""
2254
+ currentSessionId
2241
2255
  }), (0, react.createElement)(TutorColumn, {
2242
2256
  data,
2243
2257
  setMode,
@@ -2268,7 +2282,7 @@ window.__ModuleLoader__.load({
2268
2282
  if (!area.ok) throw new Error(`study area unavailable (HTTP ${area.status})`);
2269
2283
  const { path } = await area.json();
2270
2284
  const workspace = await ctx.workspaces.create({ path });
2271
- const sessionId = await ctx.workspaces.connectWorkspace(workspace.workspaceId);
2285
+ const sessionId = ctx.workspaces.connectWorkspace !== void 0 ? await ctx.workspaces.connectWorkspace(workspace.workspaceId) : await ctx.sessions.create({ workspaceId: workspace.workspaceId });
2272
2286
  const actx = ctx.sessions.scope(sessionId);
2273
2287
  const face = actx === void 0 ? void 0 : ctx.sessions.sessionOf(actx);
2274
2288
  if (face === void 0) throw new Error("lesson session is not addressable yet");
@@ -2669,8 +2683,9 @@ window.__ModuleLoader__.load({
2669
2683
  * @returns the component for `conversation.input.left`.
2670
2684
  */
2671
2685
  function studyStartButton(ctx) {
2672
- return function StudyStartButton({ session }) {
2673
- if (session?.blank !== true) return null;
2686
+ return function StudyStartButton(props) {
2687
+ const machine = props.useSession?.((s) => s);
2688
+ if ((props.session?.blank ?? machine?.blank) !== true) return null;
2674
2689
  return (0, react.createElement)(Inner, {
2675
2690
  key: "inner",
2676
2691
  ctx
@@ -2693,7 +2708,7 @@ window.__ModuleLoader__.load({
2693
2708
  if (!area.ok) throw new Error(`study area unavailable (HTTP ${area.status})`);
2694
2709
  const { path } = await area.json();
2695
2710
  const workspace = await ctx.workspaces.create({ path });
2696
- const sessionId = await ctx.workspaces.connectWorkspace(workspace.workspaceId);
2711
+ const sessionId = ctx.workspaces.connectWorkspace !== void 0 ? await ctx.workspaces.connectWorkspace(workspace.workspaceId) : await ctx.sessions.create({ workspaceId: workspace.workspaceId });
2697
2712
  const actx = ctx.sessions.scope(sessionId);
2698
2713
  const face = actx === void 0 ? void 0 : ctx.sessions.sessionOf(actx);
2699
2714
  if (face === void 0) throw new Error("study session is not addressable yet");