dsh-edge 0.9.0 → 0.10.0

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 (56) hide show
  1. package/THIRD_PARTY_NOTICES.md +1318 -1075
  2. package/dist/assets/index-Df-65__b.js +110 -0
  3. package/dist/assets/index-b24khbeK.css +1 -0
  4. package/dist/assets/langs/{php-DDkx9sim.js → php-DJl5gRdb.js} +2 -2
  5. package/dist/assets/langs/{ruby-DCxyoPen.js → ruby-5eNB0pDK.js} +2 -2
  6. package/dist/assets/vendor-BNsW4eBh.css +1 -0
  7. package/dist/assets/vendor-CCJJTK99.js +411 -0
  8. package/dist/index.html +8 -8
  9. package/dist/plugins/@deepseek-ai/dsh-api-gateway/client.js +1513 -77
  10. package/dist/plugins/@deepseek-ai/dsh-api-remotes/client.js +3608 -757
  11. package/dist/plugins/@deepseek-ai/dsh-api-session-controller/client.js +2777 -0
  12. package/dist/plugins/@deepseek-ai/dsh-api-workspace-controller/client.js +415 -0
  13. package/dist/plugins/@deepseek-ai/dsh-client-connection/client.js +1975 -7466
  14. package/dist/plugins/@deepseek-ai/dsh-client-locale/client.js +225 -76
  15. package/dist/plugins/@deepseek-ai/dsh-client-modules/client.js +67 -15
  16. package/dist/plugins/@deepseek-ai/dsh-client-ui-agent-preset/client.js +270 -460
  17. package/dist/plugins/@deepseek-ai/dsh-client-ui-approval/client.js +292 -0
  18. package/dist/plugins/@deepseek-ai/dsh-client-ui-attachment/client.js +42 -17
  19. package/dist/plugins/@deepseek-ai/dsh-client-ui-brand-official/client.js +7 -9
  20. package/dist/plugins/@deepseek-ai/dsh-client-ui-chat/client.js +8177 -0
  21. package/dist/plugins/@deepseek-ai/dsh-client-ui-commands/client.js +22 -10
  22. package/dist/plugins/@deepseek-ai/dsh-client-ui-conversation/client.js +14950 -8910
  23. package/dist/plugins/@deepseek-ai/dsh-client-ui-deliverables/client.js +161 -137
  24. package/dist/plugins/@deepseek-ai/dsh-client-ui-goal/client.js +6 -7
  25. package/dist/plugins/@deepseek-ai/dsh-client-ui-input-trigger/client.js +268 -40
  26. package/dist/plugins/@deepseek-ai/dsh-client-ui-jobs/client.js +1 -1
  27. package/dist/plugins/@deepseek-ai/dsh-client-ui-layout/client.js +45 -11
  28. package/dist/plugins/@deepseek-ai/dsh-client-ui-message-feedback/client.js +30 -58
  29. package/dist/plugins/@deepseek-ai/dsh-client-ui-model-selection/client.js +188 -89
  30. package/dist/plugins/@deepseek-ai/dsh-client-ui-permission-presets/client.js +105 -75
  31. package/dist/plugins/@deepseek-ai/dsh-client-ui-renderer/client.js +650 -188
  32. package/dist/plugins/@deepseek-ai/dsh-client-ui-schedule/client.js +307 -0
  33. package/dist/plugins/@deepseek-ai/dsh-client-ui-session/client.js +340 -0
  34. package/dist/plugins/@deepseek-ai/dsh-client-ui-settings/client.js +57 -50
  35. package/dist/plugins/@deepseek-ai/dsh-client-ui-settings-general/client.js +134 -69
  36. package/dist/plugins/@deepseek-ai/dsh-client-ui-settings-models/client.js +575 -442
  37. package/dist/plugins/@deepseek-ai/dsh-client-ui-sidebar/client.js +24 -11
  38. package/dist/plugins/@deepseek-ai/dsh-client-ui-skill/client.js +13 -9
  39. package/dist/plugins/@deepseek-ai/dsh-client-ui-subagent/client.js +44 -20
  40. package/dist/plugins/@deepseek-ai/dsh-client-ui-theme/client.js +265 -94
  41. package/dist/plugins/@deepseek-ai/dsh-client-ui-tool/client.js +899 -433
  42. package/dist/plugins/@deepseek-ai/dsh-client-ui-trajectory/client.js +1472 -613
  43. package/dist/plugins/@deepseek-ai/dsh-client-ui-user-questions/client.js +249 -95
  44. package/dist/plugins/@deepseek-ai/dsh-client-ui-workflow-run/client.js +5 -5
  45. package/dist/plugins/@deepseek-ai/dsh-client-ui-workspace/client.js +425 -146
  46. package/dist/plugins/@deepseek-ai/dsh-typert-registry/client.js +29 -14
  47. package/dist/plugins/dsh-edge-client-ui/client.js +28 -26
  48. package/package.json +62 -58
  49. package/scripts/verify-packed.mjs +1 -1
  50. package/worker/direct/index.js +2866 -1466
  51. package/worker/isolated/index.js +2438 -1038
  52. package/dist/assets/index-C6eRlFa6.css +0 -1
  53. package/dist/assets/index-ClqxG24t.js +0 -96
  54. package/dist/assets/vendor-CjyC-hUb.css +0 -1
  55. package/dist/assets/vendor-D22_Mp1f.js +0 -411
  56. package/dist/plugins/@deepseek-ai/dsh-client-runtime/client.js +0 -10574
@@ -0,0 +1,292 @@
1
+ window.__ModuleLoader__.load({
2
+ id: "@deepseek-ai/dsh-client-ui-approval",
3
+ factory: (require) => {
4
+ var module = { exports: {} };
5
+ var exports = module.exports;
6
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
7
+ let react_jsx_runtime = require("react/jsx-runtime");
8
+ let react = require("react");
9
+ let _deepseek_ai_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
10
+ //#region \0dsh-css:/home/runner/work/deepseek-harness/deepseek-harness/packages/client/ui-approval/src/client/ApprovalPanel.module.css.mjs
11
+ const css = ".mna1RW_root{padding:8px calc(var(--dsh-composer-side-clearance) + 16px) 12px;flex-direction:column;align-items:center;display:flex}.mna1RW_card{width:100%;max-width:var(--dsh-chat-content-width);border:1px solid var(--dsw-alias-state-warn-secondary);background:var(--dsw-specific-input-major);box-shadow:var(--dsw-shadow-lv2);--dsh-scrollbar-thumb:var(--dsw-alias-scrollbar-bg-l2);--dsh-scrollbar-thumb-hover:var(--dsw-alias-scrollbar-hover-l2);border-radius:20px;overflow:hidden}.mna1RW_strip{background:var(--dsw-alias-state-warn-tertiary);color:var(--dsw-alias-state-warn-primary);align-items:center;gap:8px;padding:10px 16px;font-size:13px;line-height:18px;display:flex}.mna1RW_dot{corner-shape:round;background:var(--dsw-alias-state-warn-primary);border-radius:50%;width:8px;height:8px}.mna1RW_body{box-sizing:border-box;max-height:var(--dsh-composer-text-max-height);flex-direction:column;gap:6px;padding:12px 16px 0;display:flex;overflow-y:auto}.mna1RW_headline{color:var(--dsw-alias-label-primary);font-size:15px;font-weight:500;line-height:24px}.mna1RW_command{color:var(--dsw-alias-label-tertiary);font-family:var(--ds-font-family-code);word-break:break-all;font-size:13px;line-height:20px}.mna1RW_actionRow{justify-content:flex-end;gap:8px;padding:14px 16px;display:flex}.mna1RW_reject:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover-danger);color:var(--dsw-alias-state-error-primary);border-color:#0000}";
12
+ const tagId = "@deepseek-ai/dsh-client-ui-approval/ApprovalPanel.module.css";
13
+ if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
14
+ const tag = document.createElement("style");
15
+ tag.dataset.plugin = "@deepseek-ai/dsh-client-ui-approval";
16
+ tag.dataset.pluginCss = tagId;
17
+ tag.textContent = css;
18
+ document.head.appendChild(tag);
19
+ }
20
+ var ApprovalPanel_module_css_default = {
21
+ "actionRow": "mna1RW_actionRow",
22
+ "body": "mna1RW_body",
23
+ "card": "mna1RW_card",
24
+ "command": "mna1RW_command",
25
+ "dot": "mna1RW_dot",
26
+ "headline": "mna1RW_headline",
27
+ "reject": "mna1RW_reject",
28
+ "root": "mna1RW_root",
29
+ "strip": "mna1RW_strip"
30
+ };
31
+ //#endregion
32
+ //#region lib/types/client/ApprovalPanel.js
33
+ /** Composer takeover for one pending approval waterfall. */
34
+ /**
35
+ * Render one pending approval and its optional Tool-owned detail.
36
+ * @param props - selector-matched request and standard Slot props.
37
+ * @returns The approval composer takeover.
38
+ */
39
+ function ApprovalPanel(props) {
40
+ const approval = props.matched;
41
+ return (0, react_jsx_runtime.jsx)(ApprovalFlow, {
42
+ pending: approval,
43
+ detail: approval.callId === void 0 ? null : props.renderSlot("conversation.approval.detail", { callId: approval.callId }),
44
+ t: props.t
45
+ }, approval.key);
46
+ }
47
+ function ApprovalFlow({ pending, detail, t }) {
48
+ const [answered, setAnswered] = (0, react.useState)(false);
49
+ const answer = (outcome) => {
50
+ setAnswered(true);
51
+ pending.answer(outcome).catch(() => {
52
+ setAnswered(false);
53
+ });
54
+ };
55
+ return (0, react_jsx_runtime.jsx)("div", {
56
+ className: ApprovalPanel_module_css_default.root,
57
+ "data-approval-key": pending.key,
58
+ children: (0, react_jsx_runtime.jsxs)("div", {
59
+ className: ApprovalPanel_module_css_default.card,
60
+ children: [
61
+ (0, react_jsx_runtime.jsxs)("div", {
62
+ className: ApprovalPanel_module_css_default.strip,
63
+ children: [(0, react_jsx_runtime.jsx)("span", { className: ApprovalPanel_module_css_default.dot }), t("waiting")]
64
+ }),
65
+ (0, react_jsx_runtime.jsxs)("div", {
66
+ className: ApprovalPanel_module_css_default.body,
67
+ "data-approval-scroll": "",
68
+ tabIndex: 0,
69
+ role: "group",
70
+ "aria-label": t("detail.aria"),
71
+ children: [(0, react_jsx_runtime.jsx)("div", {
72
+ className: ApprovalPanel_module_css_default.headline,
73
+ children: pending.reason ?? t("escalation", { toolName: pending.toolName })
74
+ }), detail !== null && (0, react_jsx_runtime.jsx)("div", {
75
+ className: ApprovalPanel_module_css_default.command,
76
+ children: detail
77
+ })]
78
+ }),
79
+ (0, react_jsx_runtime.jsxs)("div", {
80
+ className: ApprovalPanel_module_css_default.actionRow,
81
+ children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
82
+ variant: "outline",
83
+ className: ApprovalPanel_module_css_default.reject,
84
+ disabled: answered,
85
+ onClick: () => {
86
+ answer("rejected");
87
+ },
88
+ children: t("reject")
89
+ }), (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
90
+ variant: "primary",
91
+ disabled: answered,
92
+ onClick: () => {
93
+ answer("allowed-once");
94
+ },
95
+ children: t("allowOnce")
96
+ })]
97
+ })
98
+ ]
99
+ })
100
+ });
101
+ }
102
+ //#endregion
103
+ //#region lib/types/client/contract/slots.js
104
+ function settlePendingComposer(settle, failureMessage) {
105
+ try {
106
+ settle();
107
+ return Promise.resolve();
108
+ } catch (error) {
109
+ return Promise.reject(error instanceof Error ? error : new Error(failureMessage, { cause: error }));
110
+ }
111
+ }
112
+ let nextApprovalKey = 0;
113
+ /** One answerable Client presentation of a pending Host waterfall. */
114
+ var PendingApproval = class {
115
+ sessionId;
116
+ /** Domain discriminator used by Session pending-interaction consumers. */
117
+ kind = "approval";
118
+ /** Opaque render identity and one-shot remount axis. */
119
+ key;
120
+ /** Tool requesting the decision. */
121
+ toolName;
122
+ /** Correlated Tool call, when supplied by the asker. */
123
+ callId;
124
+ /** Human-readable reason supplied by the asker. */
125
+ reason;
126
+ /** Result returned by the Remote Event listener to the Host waterfall. */
127
+ result;
128
+ #resolve;
129
+ #reject;
130
+ #signal;
131
+ #onAbort;
132
+ #delegated = Symbol("pending approval delegated");
133
+ #settled = false;
134
+ /**
135
+ * @param sessionId - Agent/Session identity owning the scoped request.
136
+ * @param request - Host approval request projected through the Remote Event.
137
+ */
138
+ constructor(sessionId, request) {
139
+ this.sessionId = sessionId;
140
+ nextApprovalKey += 1;
141
+ this.key = `approval:${String(nextApprovalKey)}`;
142
+ this.toolName = request.toolName;
143
+ this.callId = request.callId;
144
+ this.reason = request.reason;
145
+ const completion = Promise.withResolvers();
146
+ this.result = completion.promise;
147
+ this.#resolve = completion.resolve;
148
+ this.#reject = completion.reject;
149
+ this.#signal = request.signal;
150
+ if (request.signal === void 0) {
151
+ this.#onAbort = void 0;
152
+ return;
153
+ }
154
+ const onAbort = () => {
155
+ this.abort(request.signal?.reason ?? /* @__PURE__ */ new Error("approval request was aborted"));
156
+ };
157
+ this.#onAbort = onAbort;
158
+ request.signal.addEventListener("abort", onAbort, { once: true });
159
+ if (request.signal.aborted) onAbort();
160
+ }
161
+ /**
162
+ * Resolve the Host waterfall with the user's decision.
163
+ * @param outcome - supported interactive decision.
164
+ */
165
+ answer(outcome) {
166
+ return settlePendingComposer(() => {
167
+ this.finish(() => {
168
+ this.#resolve(outcome);
169
+ });
170
+ }, "pending approval settlement failed");
171
+ }
172
+ /** Delegate an unanswered request to the next waterfall listener. */
173
+ delegate() {
174
+ if (this.#settled) return;
175
+ this.finish(() => {
176
+ this.#reject(this.#delegated);
177
+ });
178
+ }
179
+ /**
180
+ * Test whether a rejection requests waterfall delegation.
181
+ * @param reason - rejection received from {@link PendingApproval.result}.
182
+ * @returns whether {@link PendingApproval.delegate} produced it.
183
+ */
184
+ isDelegation(reason) {
185
+ return reason === this.#delegated;
186
+ }
187
+ /**
188
+ * End an unanswered presentation when its transport, scope, or plugin lifetime ends.
189
+ * @param reason - rejection exposed to the waiting Remote Event listener.
190
+ */
191
+ abort(reason) {
192
+ if (this.#settled) return;
193
+ this.finish(() => {
194
+ this.#reject(reason);
195
+ });
196
+ }
197
+ finish(settle) {
198
+ if (this.#settled) throw new Error(`pending approval ${this.key} is already settled`);
199
+ this.#settled = true;
200
+ if (this.#signal !== void 0 && this.#onAbort !== void 0) this.#signal.removeEventListener("abort", this.#onAbort);
201
+ settle();
202
+ }
203
+ };
204
+ //#endregion
205
+ //#region lib/types/client/locales.js
206
+ /** `approval` namespace dictionaries. */
207
+ /** Simplified Chinese dictionary and key-set source of truth. */
208
+ const zh = {
209
+ waiting: "等待审批",
210
+ "detail.aria": "审批详情",
211
+ escalation: "工具 {toolName} 请求越权执行",
212
+ reject: "拒绝",
213
+ allowOnce: "允许一次"
214
+ };
215
+ /** English dictionary, checked against the Chinese key set. */
216
+ const en = {
217
+ waiting: "Waiting for approval",
218
+ "detail.aria": "Approval details",
219
+ escalation: "Tool {toolName} requests privileged execution",
220
+ reject: "Reject",
221
+ allowOnce: "Allow once"
222
+ };
223
+ //#endregion
224
+ //#region lib/types/client/index.js
225
+ /** Required services: Agent scopes, Remote Events, Session UI, Slot registry, and copy. */
226
+ const inject = [
227
+ "sessions",
228
+ "remote",
229
+ "uiSession",
230
+ "slots",
231
+ "locale"
232
+ ];
233
+ const NS = "approval";
234
+ /** Present one request until the user answers or its lifetime ends. */
235
+ async function answerApproval(ctx, owner, request, next, registerPendingInteraction) {
236
+ const sessionId = ctx.sessions.scopeOf(owner);
237
+ if (sessionId === void 0) return next();
238
+ const pending = new PendingApproval(sessionId, {
239
+ toolName: request.toolName,
240
+ ...request.callId === void 0 ? {} : { callId: request.callId },
241
+ ...request.reason === void 0 ? {} : { reason: request.reason },
242
+ ...request.signal === void 0 ? {} : { signal: request.signal }
243
+ });
244
+ const completed = Promise.withResolvers();
245
+ const remove = registerPendingInteraction(pending, async () => {
246
+ pending.delegate();
247
+ await completed.promise;
248
+ });
249
+ try {
250
+ try {
251
+ return await pending.result;
252
+ } catch (error) {
253
+ if (pending.isDelegation(error)) return await next();
254
+ throw error;
255
+ }
256
+ } finally {
257
+ remove();
258
+ completed.resolve();
259
+ }
260
+ }
261
+ /**
262
+ * Install approval copy and the scoped waterfall consumer.
263
+ * @param ctx - Client root context.
264
+ */
265
+ function apply(ctx) {
266
+ ctx.effect(() => ctx.locale.register(NS, {
267
+ zh,
268
+ en
269
+ }), "ui-approval: dictionaries");
270
+ const registerPendingInteraction = ctx.uiSession.registerPendingInteraction(() => 0);
271
+ ctx.slots.inject("conversation.composer", () => ctx.slots.register({
272
+ name: "conversation.composer",
273
+ priority: 1,
274
+ select: ({ pendingInteraction }) => pendingInteraction instanceof PendingApproval ? pendingInteraction : null,
275
+ locale: NS,
276
+ children: { "conversation.approval.detail": {
277
+ kind: "single",
278
+ scope: "session"
279
+ } }
280
+ }, ApprovalPanel));
281
+ ctx.remote.$on("approval/request", function(request, next) {
282
+ return answerApproval(ctx, this, request, next, registerPendingInteraction);
283
+ });
284
+ }
285
+ //#endregion
286
+ exports.apply = apply;
287
+ exports.inject = inject;
288
+ return module.exports;
289
+ }
290
+ });
291
+
292
+ //# sourceMappingURL=client.js.map
@@ -24,7 +24,7 @@ window.__ModuleLoader__.load({
24
24
  }
25
25
  //#endregion
26
26
  //#region \0dsh-css:/home/runner/work/deepseek-harness/deepseek-harness/packages/client/ui-attachment/src/AttachmentRail.module.css.mjs
27
- const css$4 = ".JVDQca_root{min-width:0;position:relative}.JVDQca_rail{scrollbar-width:none;--dsh-scrollbar-thumb:var(--dsw-alias-scrollbar-bg-l2);--dsh-scrollbar-thumb-hover:var(--dsw-alias-scrollbar-hover-l2);gap:10px;display:flex;overflow:auto hidden}.JVDQca_rail::-webkit-scrollbar{display:none}.JVDQca_item{flex:0 0 64px;width:64px;height:64px;position:relative}.JVDQca_thumbnail{border:1px solid var(--dsw-alias-border-l2-darkmode-thin);background:var(--dsw-alias-interactive-bg-hover);cursor:zoom-in;border-radius:16px;width:64px;height:64px;padding:0;overflow:hidden}.JVDQca_thumbnail img{object-fit:cover;width:100%;height:100%;display:block}.JVDQca_remove{z-index:1;background:var(--dsw-alias-button-contrast-fill);width:18px;height:18px;color:var(--dsw-alias-label-primary-inverted);cursor:pointer;opacity:0;border:none;border-radius:50%;place-items:center;padding:0;transition:opacity .2s ease-in-out;display:grid;position:absolute;top:4px;right:4px}.JVDQca_item:hover .JVDQca_remove,.JVDQca_remove:focus-visible{opacity:1}@media (pointer:coarse){.JVDQca_remove{opacity:1}}@media (prefers-reduced-motion:reduce){.JVDQca_remove{transition:none}}.JVDQca_arrow{z-index:2;border:1px solid var(--dsw-alias-border-l2-darkmode-thin);background:var(--dsw-specific-input-major);width:24px;height:24px;color:var(--dsw-alias-label-secondary);box-shadow:var(--dsw-shadow-lv2);cursor:pointer;border-radius:999px;place-items:center;padding:0;display:grid;position:absolute;top:50%;transform:translateY(-50%)}.JVDQca_arrow:hover{background:var(--dsw-alias-interactive-bg-hover-solid)}.JVDQca_arrowLeft{left:4px}.JVDQca_arrowRight{right:4px}";
27
+ const css$4 = ".JVDQca_root{min-width:0;position:relative}.JVDQca_rail{scrollbar-width:none;--dsh-scrollbar-thumb:var(--dsw-alias-scrollbar-bg-l2);--dsh-scrollbar-thumb-hover:var(--dsw-alias-scrollbar-hover-l2);gap:10px;display:flex;overflow:auto hidden}.JVDQca_rail::-webkit-scrollbar{display:none}.JVDQca_item{flex:0 0 64px;width:64px;height:64px;position:relative}.JVDQca_thumbnail{border:.5px solid var(--dsw-alias-border-l2-darkmode-thin);background:var(--dsw-alias-interactive-bg-hover);cursor:zoom-in;border-radius:16px;width:64px;height:64px;padding:0;overflow:hidden}.JVDQca_thumbnail img{object-fit:cover;width:100%;height:100%;display:block}.JVDQca_remove{z-index:1;corner-shape:round;background:var(--dsw-alias-button-contrast-fill);width:18px;height:18px;color:var(--dsw-alias-label-primary-inverted);cursor:pointer;opacity:0;border:none;border-radius:50%;place-items:center;padding:0;transition:opacity .2s ease-in-out;display:grid;position:absolute;top:4px;right:4px}.JVDQca_item:hover .JVDQca_remove,.JVDQca_remove:focus-visible{opacity:1}@media (pointer:coarse){.JVDQca_remove{opacity:1}}@media (prefers-reduced-motion:reduce){.JVDQca_remove{transition:none}}.JVDQca_arrow{z-index:2;--dsw-elevation-stroke-color:var(--dsw-alias-border-l2-darkmode-thin);corner-shape:round;background:var(--dsw-specific-input-major);width:24px;height:24px;color:var(--dsw-alias-label-secondary);box-shadow:var(--dsw-elevation-panel);cursor:pointer;border:0;border-radius:999px;place-items:center;padding:0;display:grid;position:absolute;top:50%;transform:translateY(-50%)}.JVDQca_arrow:hover{background:var(--dsw-alias-interactive-bg-hover-solid)}.JVDQca_arrowLeft{left:4px}.JVDQca_arrowRight{right:4px}";
28
28
  const tagId$4 = "@deepseek-ai/dsh-client-ui-attachment/AttachmentRail.module.css";
29
29
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$4) + "]") === null) {
30
30
  const tag = document.createElement("style");
@@ -379,7 +379,7 @@ window.__ModuleLoader__.load({
379
379
  });
380
380
  //#endregion
381
381
  //#region \0dsh-css:/home/runner/work/deepseek-harness/deepseek-harness/packages/client/ui-attachment/src/ImageLightbox.module.css.mjs
382
- const css$2 = ".fNh4Da_backdrop{z-index:1000;place-items:center;padding:40px;display:grid;position:fixed;inset:0}.fNh4Da_mask{background:var(--dsw-alias-bg-mask-1);backdrop-filter:var(--dsw-mask-blur);position:absolute;inset:0}.fNh4Da_image{object-fit:contain;background:var(--dsw-specific-input-major);max-width:min(100%,1600px);max-height:calc(100vh - 80px);box-shadow:var(--dsw-shadow-lv3);border-radius:12px;position:relative}.fNh4Da_close{z-index:1;border:1px solid var(--dsw-alias-border-l2-darkmode-thin);background:var(--dsw-specific-input-major);width:36px;height:36px;color:var(--dsw-alias-label-primary);cursor:pointer;border-radius:999px;place-items:center;display:grid;position:fixed;top:20px;right:20px}";
382
+ const css$2 = ".fNh4Da_backdrop{z-index:1000;place-items:center;padding:40px;display:grid;position:fixed;inset:0}.fNh4Da_mask{background:var(--dsw-alias-bg-mask-1);backdrop-filter:var(--dsw-mask-blur);position:absolute;inset:0}.fNh4Da_image{object-fit:contain;background:var(--dsw-specific-input-major);max-width:min(100%,1600px);max-height:calc(100vh - 80px);box-shadow:var(--dsw-shadow-lv3);border-radius:12px;position:relative}.fNh4Da_close{z-index:1;border:.5px solid var(--dsw-alias-border-l2-darkmode-thin);corner-shape:round;background:var(--dsw-specific-input-major);width:36px;height:36px;color:var(--dsw-alias-label-primary);cursor:pointer;border-radius:999px;place-items:center;display:grid;position:fixed;top:20px;right:20px}";
383
383
  const tagId$2 = "@deepseek-ai/dsh-client-ui-attachment/ImageLightbox.module.css";
384
384
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$2) + "]") === null) {
385
385
  const tag = document.createElement("style");
@@ -615,7 +615,7 @@ window.__ModuleLoader__.load({
615
615
  }
616
616
  //#endregion
617
617
  //#region \0dsh-css:/home/runner/work/deepseek-harness/deepseek-harness/packages/client/ui-attachment/src/MessageImage.module.css.mjs
618
- const css = ".R_Yw7q_gallery{flex-wrap:wrap;gap:10px;max-width:100%;display:flex}.R_Yw7q_gallery[data-align=end]{justify-content:flex-end;align-self:flex-end}.R_Yw7q_gallery[data-align=start]{justify-content:flex-start;align-self:flex-start}.R_Yw7q_frame{border:1px solid var(--dsw-alias-border-l2-darkmode-thin);background:var(--dsw-alias-interactive-bg-hover);cursor:zoom-in;border-radius:16px;flex:none;place-items:center;min-width:44px;min-height:44px;padding:0;display:grid;overflow:hidden}.R_Yw7q_frame[data-variant=tile]{width:64px;min-width:64px;height:64px;min-height:64px}.R_Yw7q_frame img{object-fit:cover;width:100%;height:100%;display:block}.R_Yw7q_loading,.R_Yw7q_error{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px}.R_Yw7q_error{border:1px solid var(--dsw-alias-border-l2-darkmode-thin);background:var(--dsw-alias-interactive-bg-hover-danger);cursor:pointer;border-radius:10px;max-width:240px;padding:10px 12px}.R_Yw7q_error[data-variant=tile]{border-radius:16px;width:64px;height:64px;padding:4px;overflow:hidden}";
618
+ const css = ".R_Yw7q_gallery{flex-wrap:wrap;gap:10px;max-width:100%;display:flex}.R_Yw7q_gallery[data-align=end]{justify-content:flex-end;align-self:flex-end}.R_Yw7q_gallery[data-align=start]{justify-content:flex-start;align-self:flex-start}.R_Yw7q_frame{border:.5px solid var(--dsw-alias-border-l2-darkmode-thin);background:var(--dsw-alias-interactive-bg-hover);cursor:zoom-in;border-radius:16px;flex:none;place-items:center;min-width:44px;min-height:44px;padding:0;display:grid;overflow:hidden}.R_Yw7q_frame[data-variant=tile]{width:64px;min-width:64px;height:64px;min-height:64px}.R_Yw7q_frame img{object-fit:cover;width:100%;height:100%;display:block}.R_Yw7q_loading,.R_Yw7q_error{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px}.R_Yw7q_error{border:.5px solid var(--dsw-alias-border-l2-darkmode-thin);background:var(--dsw-alias-interactive-bg-hover-danger);cursor:pointer;border-radius:10px;max-width:240px;padding:10px 12px}.R_Yw7q_error[data-variant=tile]{border-radius:16px;width:64px;height:64px;padding:4px;overflow:hidden}";
619
619
  const tagId = "@deepseek-ai/dsh-client-ui-attachment/MessageImage.module.css";
620
620
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
621
621
  const tag = document.createElement("style");
@@ -637,8 +637,8 @@ window.__ModuleLoader__.load({
637
637
  * `object-fit: cover` — and never upscaled past the image's natural size. The
638
638
  * crop anchor keeps the top of very tall images and the left of very wide
639
639
  * ones, where the informative content usually starts. */
640
- function singleFit(attachment) {
641
- const natural = attachment.width / attachment.height;
640
+ function singleFit(dimensions) {
641
+ const natural = dimensions.width / dimensions.height;
642
642
  const ratio = Math.min(4, Math.max(.25, natural));
643
643
  const box = ratio >= 1 ? {
644
644
  width: 240,
@@ -647,26 +647,37 @@ window.__ModuleLoader__.load({
647
647
  width: 240 * ratio,
648
648
  height: 240
649
649
  };
650
- const scale = Math.min(1, attachment.width / box.width, attachment.height / box.height);
650
+ const scale = Math.min(1, dimensions.width / box.width, dimensions.height / box.height);
651
651
  return {
652
652
  width: Math.max(1, Math.round(box.width * scale)),
653
653
  height: Math.max(1, Math.round(box.height * scale)),
654
654
  objectPosition: natural < .25 ? "center top" : natural > 4 ? "left center" : "center"
655
655
  };
656
656
  }
657
+ /** Intrinsic dimensions of one gallery entry; a preview's stay unknown until its intake probe resolved. */
658
+ function dimensionsOf(image) {
659
+ if ("attachment" in image) return image.attachment;
660
+ return image.preview.width !== void 0 && image.preview.height !== void 0 ? {
661
+ width: image.preview.width,
662
+ height: image.preview.height
663
+ } : void 0;
664
+ }
657
665
  /**
658
666
  * Compact history renderer with retryable loading and click-to-open original
659
667
  * preview. A lone image renders at its `singleFit` size; an image among
660
- * several renders as a fixed 64px square tile.
668
+ * several renders as a fixed 64px square tile. The preview arm displays its
669
+ * local URL directly — no loader round-trip, no failure/retry surface.
661
670
  *
662
- * @param props.attachment - the durable image reference to load and bound.
663
- * @param props.load - session-authorized URL loader.
671
+ * @param props.image - the durable reference to load, or the local preview to display.
672
+ * @param props.load - session-authorized URL loader for the durable arm.
664
673
  * @param props.variant - `single` for a message's lone image, `tile` otherwise.
665
674
  * @param props.labels - resolved strings (tooltip, loading, retry, lightbox).
666
675
  * @returns the bounded thumbnail button, or the retry control on failure.
667
676
  */
668
- function MessageImage({ attachment, load, variant, labels }) {
669
- const [src, setSrc] = (0, react.useState)(null);
677
+ function MessageImage({ image, load, variant, labels }) {
678
+ const preview = "preview" in image ? image.preview : void 0;
679
+ const attachment = "attachment" in image ? image.attachment : void 0;
680
+ const [loaded, setLoaded] = (0, react.useState)(() => attachment === void 0 ? null : load.peek?.(attachment) ?? null);
670
681
  const [error, setError] = (0, react.useState)(false);
671
682
  const [open, setOpen] = (0, react.useState)(false);
672
683
  const [attempt, setAttempt] = (0, react.useState)(0);
@@ -676,13 +687,22 @@ window.__ModuleLoader__.load({
676
687
  const close = (0, react.useCallback)(() => {
677
688
  setOpen(false);
678
689
  }, []);
679
- const fit = (0, react.useMemo)(() => variant === "single" ? singleFit(attachment) : void 0, [attachment, variant]);
690
+ const dimensions = (0, react.useMemo)(() => dimensionsOf(image), [image]);
691
+ const fit = (0, react.useMemo)(() => {
692
+ if (variant !== "single") return void 0;
693
+ return dimensions === void 0 ? {
694
+ width: 240,
695
+ height: 240,
696
+ objectPosition: "center"
697
+ } : singleFit(dimensions);
698
+ }, [dimensions, variant]);
680
699
  (0, react.useEffect)(() => {
700
+ if (attachment === void 0) return;
681
701
  let live = true;
682
702
  setError(false);
683
- setSrc(null);
703
+ setLoaded(load.peek?.(attachment) ?? null);
684
704
  load(attachment).then((url) => {
685
- if (live) setSrc(url);
705
+ if (live) setLoaded(url);
686
706
  }).catch(() => {
687
707
  if (live) setError(true);
688
708
  });
@@ -694,7 +714,8 @@ window.__ModuleLoader__.load({
694
714
  load,
695
715
  attempt
696
716
  ]);
697
- const label = attachment.name ?? labels.image;
717
+ const src = preview?.url ?? loaded;
718
+ const label = preview?.name ?? attachment?.name ?? labels.image;
698
719
  if (error) return (0, react_jsx_runtime.jsx)("button", {
699
720
  type: "button",
700
721
  className: MessageImage_module_css_default.error,
@@ -739,11 +760,11 @@ window.__ModuleLoader__.load({
739
760
  className: MessageImage_module_css_default.gallery,
740
761
  "data-align": align,
741
762
  children: images.map((image, index) => (0, react_jsx_runtime.jsx)(MessageImage, {
742
- ...image,
763
+ image,
743
764
  load,
744
765
  variant,
745
766
  labels
746
- }, `${image.attachment.attachmentId}:${index}`))
767
+ }, `${"attachment" in image ? image.attachment.attachmentId : image.preview.url}:${index}`))
747
768
  });
748
769
  }
749
770
  //#endregion
@@ -771,6 +792,10 @@ window.__ModuleLoader__.load({
771
792
  name: "conversation.message.images",
772
793
  locale: "conversation"
773
794
  }, MessageImages));
795
+ ctx.slots.inject("conversation.trajectory.images", () => ctx.slots.register({
796
+ name: "conversation.trajectory.images",
797
+ locale: "conversation"
798
+ }, MessageImages));
774
799
  }
775
800
  //#endregion
776
801
  exports.apply = apply;
@@ -12,11 +12,8 @@ window.__ModuleLoader__.load({
12
12
  * @param props - Host-supplied mark presentation.
13
13
  * @returns the official whale mark.
14
14
  */
15
- function OfficialBrandMark({ size, className }) {
16
- return (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.FishLogo, {
17
- size,
18
- className
19
- });
15
+ function OfficialBrandMark({ size }) {
16
+ return (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.FishLogo, { size });
20
17
  }
21
18
  /**
22
19
  * Render the official name artwork without its independently slotted mark.
@@ -30,15 +27,16 @@ window.__ModuleLoader__.load({
30
27
  /** Required service: the UI slot registry. */
31
28
  const inject = ["slots"];
32
29
  /**
33
- * Fill every shipped brand slot as one declaration-aware registration set.
30
+ * Fill the sidebar brand slots as one declaration-aware registration set. The
31
+ * conversation hero stays on its declaring package's animated fish fallback,
32
+ * so the official build registers nothing there.
34
33
  * @param ctx - Client root context.
35
34
  */
36
35
  function apply(ctx) {
37
- ctx.slots.inject("sidebar.brand.mark", () => ctx.slots.inject("sidebar.brand.name", () => ctx.slots.inject("conversation.hero.brand.mark", function* () {
36
+ ctx.slots.inject("sidebar.brand.mark", () => ctx.slots.inject("sidebar.brand.name", function* () {
38
37
  yield ctx.slots.register({ name: "sidebar.brand.mark" }, OfficialBrandMark);
39
38
  yield ctx.slots.register({ name: "sidebar.brand.name" }, OfficialBrandName);
40
- yield ctx.slots.register({ name: "conversation.hero.brand.mark" }, OfficialBrandMark);
41
- })));
39
+ }));
42
40
  }
43
41
  //#endregion
44
42
  exports.apply = apply;