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
@@ -5,7 +5,7 @@ window.__ModuleLoader__.load({
5
5
  var exports = module.exports;
6
6
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
7
7
  let _deepseek_ai_cordis = require("@deepseek-ai/cordis");
8
- let _deepseek_ai_dsh_client_runtime_client = require("@deepseek-ai/dsh-client-runtime/client");
8
+ let _deepseek_ai_dsh_client_store = require("@deepseek-ai/dsh-client-store");
9
9
  let react_jsx_runtime = require("react/jsx-runtime");
10
10
  let react = require("react");
11
11
  let _deepseek_ai_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
@@ -185,7 +185,8 @@ window.__ModuleLoader__.load({
185
185
  * open menu, or the roster is dropped; a settlement or failure leaving every
186
186
  * group ready-and-empty (or no groups) auto-closes; `source-failed` silently
187
187
  * removes the group (the shell logs); `move` cycles the highlight across
188
- * ready items.
188
+ * ready items; `hover` parks it on one ready item (pointer and keyboard
189
+ * share the single highlight — last input wins).
189
190
  *
190
191
  * @param state - Current menu state.
191
192
  * @param ev - Menu event.
@@ -201,10 +202,9 @@ window.__ModuleLoader__.load({
201
202
  generation: state.generation + 1,
202
203
  groups: state.groups.map((g) => ({
203
204
  ...g,
204
- status: "pending",
205
- items: []
205
+ status: "pending"
206
206
  })),
207
- highlight: null
207
+ highlight: state.highlight
208
208
  };
209
209
  case "source-settled": {
210
210
  if (!state.open || ev.generation !== state.generation) return state;
@@ -250,6 +250,20 @@ window.__ModuleLoader__.load({
250
250
  highlight: next
251
251
  };
252
252
  }
253
+ case "hover": {
254
+ if (!state.open) return state;
255
+ const target = validHighlight({
256
+ source: ev.source,
257
+ index: ev.index
258
+ }, state.groups);
259
+ if (target === null) return state;
260
+ const hl = state.highlight;
261
+ if (hl && hl.source === target.source && hl.index === target.index) return state;
262
+ return {
263
+ ...state,
264
+ highlight: target
265
+ };
266
+ }
253
267
  case "close": return closed(state);
254
268
  }
255
269
  };
@@ -263,13 +277,20 @@ window.__ModuleLoader__.load({
263
277
  var InputTriggerController = class {
264
278
  deps;
265
279
  /** Menu state store (per-session; survives session switches, dies with the scope). */
266
- menu = (0, _deepseek_ai_dsh_client_runtime_client.createSnapshotStore)(MENU_CLOSED);
280
+ menu = (0, _deepseek_ai_dsh_client_store.createSnapshotStore)(MENU_CLOSED);
267
281
  /**
268
282
  * Name of the source opened through the programmatic launcher, or null for
269
283
  * trigger-detected/closed menus. Composer chrome subscribes to this store
270
284
  * for the launcher's expanded state without owning a second menu model.
271
285
  */
272
- launcher = (0, _deepseek_ai_dsh_client_runtime_client.createSnapshotStore)(null);
286
+ launcher = (0, _deepseek_ai_dsh_client_store.createSnapshotStore)(null);
287
+ /**
288
+ * Crumbs published by each header-bearing source for the open menu, keyed
289
+ * by source name. A snapshot store like {@link InputTriggerController.launcher}:
290
+ * the answer changes with every hit, and render-side consumers subscribe
291
+ * instead of re-polling sources during a render.
292
+ */
293
+ headers = (0, _deepseek_ai_dsh_client_store.createSnapshotStore)(/* @__PURE__ */ new Map());
273
294
  /**
274
295
  * Aggregated hot reference lexicon, grouped by trigger (plain-text-reference decision;
275
296
  * see .agents/notes/implemented/architecture/2026-07-25-web-input-machine-and-slash-pipeline.md):
@@ -280,9 +301,11 @@ window.__ModuleLoader__.load({
280
301
  * spawn/exit) — render-side consumers subscribe instead of re-reading a
281
302
  * mutable answer.
282
303
  */
283
- lexicon = (0, _deepseek_ai_dsh_client_runtime_client.createSnapshotStore)(/* @__PURE__ */ new Map());
304
+ lexicon = (0, _deepseek_ai_dsh_client_store.createSnapshotStore)(/* @__PURE__ */ new Map());
284
305
  /** The authoritative hit: single truth for span CAS material (menu snapshot never carries it alone). */
285
306
  hit = null;
307
+ /** Whether the open menu was reached by a drill pick; cleared with the menu. */
308
+ drilled = false;
286
309
  fetch = null;
287
310
  disposed = false;
288
311
  /** Per-source lexicon unsubscribers (sources without the hook never enter). */
@@ -337,6 +360,7 @@ window.__ModuleLoader__.load({
337
360
  type: "hit",
338
361
  hit
339
362
  });
363
+ this.refreshHeaders(hit, roster);
340
364
  this.fetchCandidates(hit, roster);
341
365
  }
342
366
  /**
@@ -366,6 +390,7 @@ window.__ModuleLoader__.load({
366
390
  type: "hit",
367
391
  hit
368
392
  });
393
+ this.refreshHeaders(hit, [match]);
369
394
  this.fetchCandidates(hit, [match]);
370
395
  }
371
396
  /**
@@ -373,8 +398,9 @@ window.__ModuleLoader__.load({
373
398
  * and execute claim/insert outcomes via the scoped input events.
374
399
  * @param source - source (group) name.
375
400
  * @param index - candidate index within the group.
401
+ * @param action - settling pick (default) or the candidate's drill action.
376
402
  */
377
- pick(source, index) {
403
+ pick(source, index, action = "pick") {
378
404
  const state = this.menu.getSnapshot();
379
405
  const hit = this.hit;
380
406
  if (this.disposed || !state.open || hit === null) return;
@@ -383,22 +409,51 @@ window.__ModuleLoader__.load({
383
409
  if (candidate === void 0) return;
384
410
  const src = this.deps.roster.sources(hit.trigger).find((s) => s.name === source);
385
411
  if (src === void 0) return;
386
- const outcome = src.onPick({
387
- candidate,
388
- session: this.project(),
389
- position: hit.position,
390
- via: "menu",
391
- span: hit.span
412
+ this.settle(src, candidate, hit, action);
413
+ }
414
+ /**
415
+ * Pointer pick on one crumb of a source's menu header: route it through the
416
+ * same drill path a folder row takes, so returning to a step and descending
417
+ * into one share one outcome.
418
+ * @param source - source (group) name.
419
+ * @param index - crumb index within that source's published header.
420
+ */
421
+ pickCrumb(source, index) {
422
+ const hit = this.hit;
423
+ if (this.disposed || !this.menu.getSnapshot().open || hit === null) return;
424
+ const crumb = this.headers.getSnapshot().get(source)?.[index];
425
+ if (crumb === void 0 || crumb.current === true) return;
426
+ const src = this.deps.roster.sources(hit.trigger).find((s) => s.name === source);
427
+ if (src === void 0) return;
428
+ this.settle(src, {
429
+ name: crumb.label,
430
+ value: crumb.value
431
+ }, hit, "drill");
432
+ }
433
+ /**
434
+ * Pointer hover from MenuView: park the shared highlight on the hovered
435
+ * candidate (keyboard `move` and pointer hover drive one highlight —
436
+ * last input wins).
437
+ * @param source - source (group) name.
438
+ * @param index - candidate index within the group.
439
+ */
440
+ hover(source, index) {
441
+ if (this.disposed) return;
442
+ this.reduce({
443
+ type: "hover",
444
+ source,
445
+ index
392
446
  });
393
- this.stopFetch();
394
- this.reduce({ type: "close" });
395
- this.execute(outcome, hit.span);
396
447
  }
397
448
  /**
398
449
  * Keyboard arbitration while the menu is open.
399
450
  * @param key - intercepted key.
400
451
  * @param composing - inside IME composition: everything passes.
401
- * @returns consumed / pick-highlighted / pass.
452
+ * @returns `pass` when the browser keeps the key (closed menu, no
453
+ * highlight, or a vanished candidate), `consumed` when the menu handled
454
+ * the key without a settling pick (move, close, drill descent, or a
455
+ * pending-refinement no-op), or `pick-highlighted` when the highlighted
456
+ * candidate settled and the menu closed.
402
457
  */
403
458
  arbitrate(key, composing) {
404
459
  if (composing || this.disposed) return "pass";
@@ -421,10 +476,26 @@ window.__ModuleLoader__.load({
421
476
  this.stopFetch();
422
477
  this.reduce({ type: "close" });
423
478
  return "consumed";
424
- case "enter":
479
+ case "enter": {
480
+ if (state.highlight === null) return "pass";
481
+ const group = state.groups.find((g) => g.source === state.highlight?.source);
482
+ if (group === void 0 || group.status !== "ready") return "consumed";
483
+ this.pick(state.highlight.source, state.highlight.index);
484
+ return "pick-highlighted";
485
+ }
486
+ case "tab": {
425
487
  if (state.highlight === null) return "pass";
488
+ const group = state.groups.find((g) => g.source === state.highlight?.source);
489
+ if (group === void 0 || group.status !== "ready") return "consumed";
490
+ const item = group.items[state.highlight.index];
491
+ if (item === void 0) return "pass";
492
+ if (item.drill === true) {
493
+ this.pick(state.highlight.source, state.highlight.index, "drill");
494
+ return "consumed";
495
+ }
426
496
  this.pick(state.highlight.source, state.highlight.index);
427
497
  return "pick-highlighted";
498
+ }
428
499
  }
429
500
  }
430
501
  /**
@@ -571,6 +642,12 @@ window.__ModuleLoader__.load({
571
642
  if (source.lexicon === void 0 || source.subscribeLexicon === void 0) return;
572
643
  this.lexiconOffs.set(source, source.subscribeLexicon(projection, () => {
573
644
  this.refreshLexicon();
645
+ const hit = this.hit;
646
+ if (hit === null || !this.menu.getSnapshot().open || hit.trigger !== source.trigger) return;
647
+ Promise.resolve().then(() => {
648
+ if (this.disposed || this.hit !== hit || !this.menu.getSnapshot().open) return;
649
+ this.fetchCandidates(hit, this.deps.roster.sources(hit.trigger));
650
+ });
574
651
  }));
575
652
  }
576
653
  /** Launch the candidate fetch for one hit generation, superseding the previous one. */
@@ -584,6 +661,7 @@ window.__ModuleLoader__.load({
584
661
  query: hit.query,
585
662
  quoted: hit.quoted,
586
663
  position: hit.position,
664
+ drilled: this.drilled,
587
665
  signal: controller.signal
588
666
  }).then((items) => {
589
667
  if (controller.signal.aborted) return;
@@ -607,6 +685,57 @@ window.__ModuleLoader__.load({
607
685
  this.fetch?.abort();
608
686
  this.fetch = null;
609
687
  }
688
+ /**
689
+ * Run one candidate (or crumb) through its source and apply the outcome.
690
+ *
691
+ * A drill is the one pick that leaves the menu open, so it is also the one
692
+ * that records how the next query was reached; every other pick closes the
693
+ * menu, which clears that record.
694
+ * @param src - the owning source.
695
+ * @param candidate - the picked candidate, or a crumb projected as one.
696
+ * @param hit - the authoritative hit supplying position and span CAS.
697
+ * @param action - settling pick or drill.
698
+ */
699
+ settle(src, candidate, hit, action) {
700
+ const outcome = src.onPick({
701
+ candidate,
702
+ session: this.project(),
703
+ position: hit.position,
704
+ via: "menu",
705
+ action,
706
+ span: hit.span
707
+ });
708
+ this.stopFetch();
709
+ this.reduce({ type: "close" });
710
+ this.drilled = action === "drill";
711
+ if (!this.execute(outcome, hit.span)) this.drilled = false;
712
+ }
713
+ /** Re-poll every header-bearing source in the hit roster and publish their crumbs. */
714
+ refreshHeaders(hit, roster) {
715
+ const projection = this.project();
716
+ const crumbs = /* @__PURE__ */ new Map();
717
+ for (const src of roster) {
718
+ if (src.header === void 0) continue;
719
+ let published;
720
+ try {
721
+ published = src.header(projection, {
722
+ query: hit.query,
723
+ quoted: hit.quoted,
724
+ drilled: this.drilled
725
+ });
726
+ } catch (error) {
727
+ console.error(`[ui-input-trigger] source "${src.name}" header failed:`, error);
728
+ continue;
729
+ }
730
+ if (published === void 0 || published.length === 0) continue;
731
+ crumbs.set(src.name, published);
732
+ }
733
+ this.setHeaders(crumbs);
734
+ }
735
+ setHeaders(next) {
736
+ if (this.headers.getSnapshot().size === 0 && next.size === 0) return;
737
+ this.headers.set(next);
738
+ }
610
739
  clearLauncher() {
611
740
  if (this.launcher.getSnapshot() !== null) this.launcher.set(null);
612
741
  }
@@ -614,7 +743,10 @@ window.__ModuleLoader__.load({
614
743
  const cur = this.menu.getSnapshot();
615
744
  const next = menuReduce(cur, ev);
616
745
  if (next !== cur) this.menu.set(next);
617
- if (!next.open) this.clearLauncher();
746
+ if (next.open) return;
747
+ this.clearLauncher();
748
+ this.drilled = false;
749
+ this.setHeaders(/* @__PURE__ */ new Map());
618
750
  }
619
751
  };
620
752
  //#endregion
@@ -714,7 +846,7 @@ window.__ModuleLoader__.load({
714
846
  }
715
847
  //#endregion
716
848
  //#region \0dsh-css:/home/runner/work/deepseek-harness/deepseek-harness/packages/client/ui-input-trigger/src/client/MenuView.module.css.mjs
717
- const css = "._3e4SsG_menu{z-index:100;--dsh-scrollbar-thumb:var(--dsw-alias-scrollbar-bg-l2);--dsh-scrollbar-thumb-hover:var(--dsw-alias-scrollbar-hover-l2);border:1px solid var(--dsw-alias-border-inverted);background:var(--dsw-specific-menu);min-width:min(260px,100%);max-width:min(537px,100%);max-height:320px;box-shadow:var(--dsw-shadow-lv3);border-radius:12px;flex-direction:column;padding:4px;display:flex;position:absolute;bottom:calc(100% + 4px);left:0;overflow:hidden}._3e4SsG_viewport{flex-direction:column;min-height:0;display:flex;overflow-y:auto}._3e4SsG_item{cursor:pointer;width:100%;min-height:40px;color:var(--dsw-alias-label-primary);text-align:left;background:0 0;border:none;border-radius:10px;align-items:center;gap:8px;padding:8px 10px;font-size:14px;line-height:22px;display:flex}._3e4SsG_item:hover,._3e4SsG_item._3e4SsG_active{background:var(--dsw-alias-interactive-bg-hover)}._3e4SsG_sectionTitle{min-height:26px;color:var(--dsw-alias-label-tertiary);flex:none;padding:6px 10px 2px;font-size:12px;font-weight:500;line-height:18px}._3e4SsG_sectionTitle:not(:first-child){margin-top:4px}._3e4SsG_itemIcon{width:16px;height:16px;color:var(--dsw-alias-label-tertiary);flex:none;justify-content:center;align-items:center;display:inline-flex}._3e4SsG_itemName{text-overflow:ellipsis;white-space:nowrap;flex:none;max-width:40%;overflow:hidden}._3e4SsG_itemDescription{text-overflow:ellipsis;white-space:nowrap;min-width:0;color:var(--dsw-alias-label-tertiary);flex:1;overflow:hidden}._3e4SsG_groupTitle{color:var(--dsw-alias-label-tertiary);padding:8px 10px;font-size:12px;line-height:16px}._3e4SsG_loading{min-height:40px;color:var(--dsw-alias-label-dimmed);align-items:center;padding:8px 10px;font-size:14px;line-height:22px;display:flex}";
849
+ const css = "._3e4SsG_menu{z-index:100;--dsh-scrollbar-thumb:var(--dsw-alias-scrollbar-bg-l2);--dsh-scrollbar-thumb-hover:var(--dsw-alias-scrollbar-hover-l2);background:var(--dsw-specific-menu);--dsw-elevation-stroke-color:var(--dsw-alias-border-l1);max-height:320px;box-shadow:var(--dsw-elevation-prominent);border:0;border-radius:20px;flex-direction:column;padding:4px;display:flex;position:absolute;bottom:calc(100% + 4px);left:0;right:0;overflow:hidden}._3e4SsG_viewport{flex-direction:column;min-height:0;display:flex;overflow-y:auto}._3e4SsG_item{cursor:pointer;width:100%;min-height:40px;color:var(--dsw-alias-label-primary);text-align:left;background:0 0;border:none;border-radius:10px;align-items:center;gap:8px;padding:8px 10px;font-size:14px;line-height:22px;display:flex}._3e4SsG_item._3e4SsG_active{background:var(--dsw-alias-interactive-bg-hover)}._3e4SsG_sectionTitle{min-height:26px;color:var(--dsw-alias-label-tertiary);flex:none;padding:6px 10px 2px;font-size:12px;font-weight:500;line-height:18px}._3e4SsG_sectionTitle:not(:first-child){margin-top:4px}._3e4SsG_itemIcon{width:16px;height:16px;color:var(--dsw-alias-label-tertiary);flex:none;justify-content:center;align-items:center;display:inline-flex}._3e4SsG_itemName{text-overflow:ellipsis;white-space:nowrap;flex:none;max-width:40%;overflow:hidden}._3e4SsG_itemDescription{text-overflow:ellipsis;white-space:nowrap;min-width:0;color:var(--dsw-alias-label-tertiary);flex:1;overflow:hidden}._3e4SsG_trailing{flex:none;align-items:center;gap:4px;margin-left:auto;display:inline-flex}._3e4SsG_drillHintText{color:var(--dsw-alias-label-caption);white-space:nowrap;font-size:11px;line-height:18px;display:none}._3e4SsG_drillHint{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-caption);border-radius:4px;padding:0 5px;font-family:inherit;font-size:11px;line-height:18px;display:none}._3e4SsG_item._3e4SsG_active ._3e4SsG_drillHintText,._3e4SsG_item._3e4SsG_active ._3e4SsG_drillHint{display:inline-flex}._3e4SsG_drill{width:20px;height:20px;color:var(--dsw-alias-label-caption);border-radius:4px;flex:none;place-items:center;display:inline-grid}._3e4SsG_drill:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}._3e4SsG_groupTitle{color:var(--dsw-alias-label-tertiary);padding:8px 10px;font-size:12px;line-height:16px}._3e4SsG_skeletonRow{box-sizing:border-box;align-items:center;min-height:40px;padding:8px 10px;display:flex}._3e4SsG_skeletonBar{background:var(--dsw-alias-bg-skeleton);border-radius:4px;height:20px;animation:2s cubic-bezier(.36,0,.64,1) infinite _3e4SsG_dsh-menu-skeleton}@keyframes _3e4SsG_dsh-menu-skeleton{0%{opacity:1}40%{opacity:.6}80%,to{opacity:1}}._3e4SsG_crumbs{border-bottom:.5px solid var(--dsw-alias-border-l1);flex-wrap:wrap;flex:none;align-items:center;gap:2px;margin-bottom:2px;padding:4px 4px 6px;display:flex}._3e4SsG_crumb{max-width:40%;color:var(--dsw-alias-label-tertiary);cursor:pointer;text-overflow:ellipsis;white-space:nowrap;background:0 0;border:none;border-radius:6px;flex:0 auto;padding:2px 6px;font-family:inherit;font-size:12px;line-height:18px;overflow:hidden}._3e4SsG_crumb:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}._3e4SsG_crumbCurrent,._3e4SsG_crumbCurrent:hover{color:var(--dsw-alias-label-primary);cursor:default;background:0 0}._3e4SsG_crumbSeparator{color:var(--dsw-alias-label-caption);flex:none;display:inline-flex}";
718
850
  const tagId = "@deepseek-ai/dsh-client-ui-input-trigger/MenuView.module.css";
719
851
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
720
852
  const tag = document.createElement("style");
@@ -725,14 +857,24 @@ window.__ModuleLoader__.load({
725
857
  }
726
858
  var MenuView_module_css_default = {
727
859
  "active": "_3e4SsG_active",
860
+ "crumb": "_3e4SsG_crumb",
861
+ "crumbCurrent": "_3e4SsG_crumbCurrent",
862
+ "crumbSeparator": "_3e4SsG_crumbSeparator",
863
+ "crumbs": "_3e4SsG_crumbs",
864
+ "drill": "_3e4SsG_drill",
865
+ "drillHint": "_3e4SsG_drillHint",
866
+ "drillHintText": "_3e4SsG_drillHintText",
867
+ "dsh-menu-skeleton": "_3e4SsG_dsh-menu-skeleton",
728
868
  "groupTitle": "_3e4SsG_groupTitle",
729
869
  "item": "_3e4SsG_item",
730
870
  "itemDescription": "_3e4SsG_itemDescription",
731
871
  "itemIcon": "_3e4SsG_itemIcon",
732
872
  "itemName": "_3e4SsG_itemName",
733
- "loading": "_3e4SsG_loading",
734
873
  "menu": "_3e4SsG_menu",
735
874
  "sectionTitle": "_3e4SsG_sectionTitle",
875
+ "skeletonBar": "_3e4SsG_skeletonBar",
876
+ "skeletonRow": "_3e4SsG_skeletonRow",
877
+ "trailing": "_3e4SsG_trailing",
736
878
  "viewport": "_3e4SsG_viewport"
737
879
  };
738
880
  //#endregion
@@ -741,10 +883,13 @@ window.__ModuleLoader__.load({
741
883
  * Trigger candidate menu: renders the InputTriggerService menu store into the
742
884
  * conversation.input.overlay anchor. Closed state renders null (the overlay
743
885
  * slot stays mounted); groups render in roster order under localized title
744
- * rows, pending groups as a loading row; pointer picks route back through
886
+ * rows. A pending group keeps showing the items it already had (the reducer
887
+ * retains them across a query refinement) and falls back to two skeleton
888
+ * rows only while it has none; pointer picks route back through
745
889
  * the service (combobox pattern — focus never leaves the textarea, so rows
746
890
  * are mousedown-handled and the highlight is exposed via
747
- * aria-activedescendant on the listbox).
891
+ * aria-activedescendant on the listbox). A source publishing crumbs gets a
892
+ * breadcrumb header pinned above the scrolling list.
748
893
  */
749
894
  /** Design cap on the list height (figma SLASH 39:26572 MenuDropdown). */
750
895
  const MAX_HEIGHT = 320;
@@ -757,8 +902,9 @@ window.__ModuleLoader__.load({
757
902
  * @param props - injected face (the menu store and the pick route); `t` rides the standard locale seat.
758
903
  * @returns the dropdown while open; null while closed.
759
904
  */
760
- function MenuView({ menu, onPick, onDismiss, t }) {
905
+ function MenuView({ menu, headers, onPick, onCrumb, onHover, onDismiss, t }) {
761
906
  const state = (0, react.useSyncExternalStore)((fn) => menu.subscribe(fn), () => menu.getSnapshot());
907
+ const crumbs = (0, react.useSyncExternalStore)((fn) => headers.subscribe(fn), () => headers.getSnapshot());
762
908
  const listRef = (0, react.useRef)(null);
763
909
  const maxHeight = (0, _deepseek_ai_dsh_client_ui_primitives.useAnchoredMaxHeight)(listRef, MAX_HEIGHT, state);
764
910
  const highlight = state.open ? state.highlight : null;
@@ -780,24 +926,59 @@ window.__ModuleLoader__.load({
780
926
  };
781
927
  }, [state.open, onDismiss]);
782
928
  if (!state.open) return null;
783
- return (0, react_jsx_runtime.jsx)("div", {
929
+ return (0, react_jsx_runtime.jsxs)("div", {
784
930
  ref: listRef,
785
931
  className: MenuView_module_css_default.menu,
786
932
  style: { maxHeight },
787
- role: "listbox",
788
- "aria-label": t("suggestions.aria"),
789
- "aria-activedescendant": highlight !== null ? optionId(highlight.source, highlight.index) : void 0,
790
- children: (0, react_jsx_runtime.jsx)("div", {
933
+ "data-trigger-menu": "",
934
+ children: [state.groups.map((group) => {
935
+ const trail = crumbs.get(group.source);
936
+ return trail === void 0 ? null : (0, react_jsx_runtime.jsx)("nav", {
937
+ className: MenuView_module_css_default.crumbs,
938
+ "aria-label": t("crumbs.aria"),
939
+ children: trail.map((crumb, index) => (0, react_jsx_runtime.jsxs)(react.Fragment, { children: [index > 0 && (0, react_jsx_runtime.jsx)("span", {
940
+ className: MenuView_module_css_default.crumbSeparator,
941
+ "aria-hidden": true,
942
+ children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronRightOutline14, {})
943
+ }), (0, react_jsx_runtime.jsx)("button", {
944
+ type: "button",
945
+ className: clsx(MenuView_module_css_default.crumb, crumb.current === true && MenuView_module_css_default.crumbCurrent),
946
+ "aria-current": crumb.current === true ? "location" : void 0,
947
+ disabled: crumb.current === true,
948
+ onMouseDown: (ev) => {
949
+ ev.preventDefault();
950
+ onCrumb(group.source, index);
951
+ },
952
+ children: crumb.label
953
+ })] }, `${String(index)}-${crumb.value}`))
954
+ }, group.source);
955
+ }), (0, react_jsx_runtime.jsx)("div", {
791
956
  className: MenuView_module_css_default.viewport,
957
+ role: "listbox",
958
+ "aria-label": t("suggestions.aria"),
959
+ "aria-activedescendant": highlight !== null ? optionId(highlight.source, highlight.index) : void 0,
792
960
  children: state.groups.map((group) => group.status === "ready" && group.items.length === 0 ? null : (0, react_jsx_runtime.jsxs)(react.Fragment, { children: [group.showGroupTitle === false || group.items.some((item) => item.section !== void 0) ? null : (0, react_jsx_runtime.jsx)("div", {
793
961
  className: MenuView_module_css_default.groupTitle,
794
962
  role: "presentation",
795
963
  "data-source": group.source,
796
964
  children: t(group.source)
797
- }), group.status === "pending" ? (0, react_jsx_runtime.jsx)("div", {
798
- className: MenuView_module_css_default.loading,
965
+ }), group.status === "pending" && group.items.length === 0 ? (0, react_jsx_runtime.jsxs)("div", {
966
+ role: "status",
967
+ "aria-label": t("loading"),
799
968
  "data-source": group.source,
800
- children: t("loading")
969
+ children: [(0, react_jsx_runtime.jsx)("div", {
970
+ className: MenuView_module_css_default.skeletonRow,
971
+ children: (0, react_jsx_runtime.jsx)("span", {
972
+ className: MenuView_module_css_default.skeletonBar,
973
+ style: { width: "32%" }
974
+ })
975
+ }), (0, react_jsx_runtime.jsx)("div", {
976
+ className: MenuView_module_css_default.skeletonRow,
977
+ children: (0, react_jsx_runtime.jsx)("span", {
978
+ className: MenuView_module_css_default.skeletonBar,
979
+ style: { width: "48%" }
980
+ })
981
+ })]
801
982
  }) : group.items.map((item, index) => {
802
983
  const active = highlight !== null && highlight.source === group.source && highlight.index === index;
803
984
  return (0, react_jsx_runtime.jsxs)(react.Fragment, { children: [item.section !== void 0 && item.section !== group.items[index - 1]?.section ? (0, react_jsx_runtime.jsx)("div", {
@@ -814,11 +995,17 @@ window.__ModuleLoader__.load({
814
995
  ev.preventDefault();
815
996
  onPick(group.source, index);
816
997
  },
998
+ onMouseMove: active ? void 0 : () => {
999
+ onHover(group.source, index);
1000
+ },
817
1001
  children: [
818
1002
  item.icon !== void 0 && (0, react_jsx_runtime.jsx)("span", {
819
1003
  className: MenuView_module_css_default.itemIcon,
820
1004
  "aria-hidden": true,
821
- children: item.icon
1005
+ children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.ReferenceIcon, {
1006
+ kind: item.icon,
1007
+ size: 16
1008
+ })
822
1009
  }),
823
1010
  (0, react_jsx_runtime.jsx)("span", {
824
1011
  className: MenuView_module_css_default.itemName,
@@ -827,11 +1014,37 @@ window.__ModuleLoader__.load({
827
1014
  item.description !== void 0 && (0, react_jsx_runtime.jsx)("span", {
828
1015
  className: MenuView_module_css_default.itemDescription,
829
1016
  children: item.description
1017
+ }),
1018
+ item.drill === true && (0, react_jsx_runtime.jsxs)("span", {
1019
+ className: MenuView_module_css_default.trailing,
1020
+ children: [
1021
+ (0, react_jsx_runtime.jsx)("span", {
1022
+ className: MenuView_module_css_default.drillHintText,
1023
+ "aria-hidden": true,
1024
+ children: t("drill.hint")
1025
+ }),
1026
+ (0, react_jsx_runtime.jsx)("kbd", {
1027
+ className: MenuView_module_css_default.drillHint,
1028
+ "aria-hidden": true,
1029
+ children: t("drill.key")
1030
+ }),
1031
+ (0, react_jsx_runtime.jsx)("span", {
1032
+ role: "button",
1033
+ "aria-label": t("drill.aria"),
1034
+ className: MenuView_module_css_default.drill,
1035
+ onMouseDown: (ev) => {
1036
+ ev.preventDefault();
1037
+ ev.stopPropagation();
1038
+ onPick(group.source, index, "drill");
1039
+ },
1040
+ children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronRightOutline14, {})
1041
+ })
1042
+ ]
830
1043
  })
831
1044
  ]
832
1045
  })] }, optionId(group.source, index));
833
1046
  })] }, group.source))
834
- })
1047
+ })]
835
1048
  });
836
1049
  }
837
1050
  //#endregion
@@ -839,14 +1052,18 @@ window.__ModuleLoader__.load({
839
1052
  /**
840
1053
  * `slash.menu` namespace dictionaries: group titles keyed by source name
841
1054
  * (the lookup chain returns the key itself, so an unknown source shows its
842
- * raw name), the pending row, and the listbox aria label.
1055
+ * raw name), the pending row, and the listbox and header aria labels.
843
1056
  */
844
1057
  /** Simplified Chinese dictionary (the key-set source of truth). */
845
1058
  const zh = {
846
- "command": "命令",
1059
+ "command": "指令",
847
1060
  "skill": "技能",
848
1061
  "subagent": "子智能体",
849
1062
  "loading": "正在加载…",
1063
+ "drill.aria": "进入目录",
1064
+ "drill.hint": "进入目录",
1065
+ "drill.key": "Tab",
1066
+ "crumbs.aria": "目录导航",
850
1067
  "suggestions.aria": "触发候选建议"
851
1068
  };
852
1069
  /** English dictionary, checked complete against the zh key set. */
@@ -855,6 +1072,10 @@ window.__ModuleLoader__.load({
855
1072
  "skill": "Skills",
856
1073
  "subagent": "Subagents",
857
1074
  "loading": "Loading…",
1075
+ "drill.aria": "Browse folder",
1076
+ "drill.hint": "Browse folder",
1077
+ "drill.key": "Tab",
1078
+ "crumbs.aria": "Folder navigation",
858
1079
  "suggestions.aria": "Trigger suggestions"
859
1080
  };
860
1081
  //#endregion
@@ -892,8 +1113,15 @@ window.__ModuleLoader__.load({
892
1113
  const controller = inputTriggers.sessionOf(actx);
893
1114
  return {
894
1115
  menu: controller.menu,
895
- onPick: (source, index) => {
896
- controller.pick(source, index);
1116
+ headers: controller.headers,
1117
+ onPick: (source, index, action) => {
1118
+ controller.pick(source, index, action);
1119
+ },
1120
+ onCrumb: (source, index) => {
1121
+ controller.pickCrumb(source, index);
1122
+ },
1123
+ onHover: (source, index) => {
1124
+ controller.hover(source, index);
897
1125
  },
898
1126
  onDismiss: () => {
899
1127
  controller.dismiss();
@@ -8,7 +8,7 @@ window.__ModuleLoader__.load({
8
8
  let react = require("react");
9
9
  let _deepseek_ai_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
10
10
  //#region \0dsh-css:/home/runner/work/deepseek-harness/deepseek-harness/packages/client/ui-jobs/src/client/JobListAction.module.css.mjs
11
- const css = ".QsffPG_root{position:relative}.QsffPG_trigger{min-height:28px;color:var(--dsw-alias-label-tertiary);cursor:pointer;background:0 0;border:0;border-radius:6px;align-items:center;gap:3px;padding:3px 2px;font-size:12px;line-height:18px;display:inline-flex}.QsffPG_trigger:hover,.QsffPG_trigger:focus-visible{color:var(--dsw-alias-label-secondary)}.QsffPG_trigger svg{transition:transform .12s}.QsffPG_triggerOpen{transform:rotate(180deg)}.QsffPG_triggerDot{flex:none}.QsffPG_count{margin:0 5px}.QsffPG_menu{z-index:100;box-sizing:border-box;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-specific-menu);--dsh-scrollbar-thumb:var(--dsw-alias-scrollbar-bg-l2);--dsh-scrollbar-thumb-hover:var(--dsw-alias-scrollbar-hover-l2);width:336px;max-width:min(400px,100vw - 32px);max-height:min(420px,100vh - 140px);box-shadow:var(--dsw-shadow-lv3);border-radius:12px;flex-direction:column;gap:1px;margin:0;padding:4px;list-style:none;display:flex;position:absolute;top:calc(100% + 5px);left:0;overflow:auto}.QsffPG_row{box-sizing:border-box;width:100%;min-height:32px;color:var(--dsw-alias-label-primary);border-radius:8px;align-items:center;gap:8px;padding:6px 8px;font-size:13px;line-height:18px;display:flex}.QsffPG_rowSettled{color:var(--dsw-alias-label-tertiary)}.QsffPG_rowDot{flex:none}.QsffPG_kind{background:var(--dsw-alias-fill-l2);color:var(--dsw-alias-label-secondary);border-radius:5px;flex:none;padding:0 6px;font-size:11px;line-height:18px}.QsffPG_label{min-width:0;font-family:var(--dsw-font-mono);white-space:nowrap;text-overflow:ellipsis;flex:1;overflow:hidden}.QsffPG_status,.QsffPG_duration{color:var(--dsw-alias-label-tertiary);flex:none;font-size:11px;line-height:18px}.QsffPG_status{white-space:nowrap;text-overflow:ellipsis;max-width:40%;overflow:hidden}.QsffPG_duration{font-variant-numeric:tabular-nums}";
11
+ const css = ".QsffPG_root{position:relative}.QsffPG_trigger{min-height:28px;color:var(--dsw-alias-label-tertiary);cursor:pointer;background:0 0;border:0;border-radius:6px;align-items:center;gap:3px;padding:3px 2px;font-size:12px;line-height:18px;display:inline-flex}.QsffPG_trigger:hover,.QsffPG_trigger:focus-visible{color:var(--dsw-alias-label-secondary)}.QsffPG_trigger svg{transition:transform .12s}.QsffPG_triggerOpen{transform:rotate(180deg)}.QsffPG_triggerDot{flex:none}.QsffPG_count{margin:0 5px}.QsffPG_menu{z-index:100;box-sizing:border-box;background:var(--dsw-specific-menu);--dsh-scrollbar-thumb:var(--dsw-alias-scrollbar-bg-l2);--dsh-scrollbar-thumb-hover:var(--dsw-alias-scrollbar-hover-l2);--dsw-elevation-stroke-color:var(--dsw-alias-border-l1);width:336px;max-width:min(400px,100vw - 32px);max-height:min(420px,100vh - 140px);box-shadow:var(--dsw-elevation-prominent);border:0;border-radius:20px;flex-direction:column;gap:1px;margin:0;padding:4px;list-style:none;display:flex;position:absolute;top:calc(100% + 5px);left:0;overflow:auto}.QsffPG_row{box-sizing:border-box;width:100%;min-height:32px;color:var(--dsw-alias-label-primary);border-radius:8px;align-items:center;gap:8px;padding:6px 8px;font-size:13px;line-height:18px;display:flex}.QsffPG_rowSettled{color:var(--dsw-alias-label-tertiary)}.QsffPG_rowDot{flex:none}.QsffPG_kind{background:var(--dsw-alias-fill-l2);color:var(--dsw-alias-label-secondary);border-radius:5px;flex:none;padding:0 6px;font-size:11px;line-height:18px}.QsffPG_label{min-width:0;font-family:var(--dsw-font-mono);white-space:nowrap;text-overflow:ellipsis;flex:1;overflow:hidden}.QsffPG_status,.QsffPG_duration{color:var(--dsw-alias-label-tertiary);flex:none;font-size:11px;line-height:18px}.QsffPG_status{white-space:nowrap;text-overflow:ellipsis;max-width:40%;overflow:hidden}.QsffPG_duration{font-variant-numeric:tabular-nums}";
12
12
  const tagId = "@deepseek-ai/dsh-client-ui-jobs/JobListAction.module.css";
13
13
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
14
14
  const tag = document.createElement("style");