@dsh-workbench/core 0.2.15 → 0.3.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 (189) hide show
  1. package/client.js +320 -149
  2. package/dist/client/client.body.js +320 -149
  3. package/dist/client/index.js +321 -150
  4. package/dist/host/index.js +223 -61
  5. package/dist/types/app/client.d.ts +99 -45
  6. package/dist/types/app/layouts/rightbar/board-fact.d.ts +5 -0
  7. package/dist/types/app/layouts/sidebar/DebugFooterAction.d.ts +9 -5
  8. package/dist/types/modules/panels/model/diy-browser-act.d.ts +1 -1
  9. package/dist/types/modules/panels/model/diy-browser.d.ts +1 -0
  10. package/dist/types/modules/panels/model/diy-page.d.ts +5 -3
  11. package/dist/types/modules/panels/model/diy-scripts.d.ts +1 -1
  12. package/dist/types/shared/api/host/diy-debug-act.d.ts +31 -0
  13. package/dist/types/shared/api/host/host-args.d.ts +3 -0
  14. package/dist/types/shared/hooks/use-diy-debug.d.ts +4 -0
  15. package/docs/HANDOFF.md +32 -9
  16. package/docs/OPERATIONS.md +9 -0
  17. package/package.json +4 -3
  18. package/preset/diy.patch.yml +3 -0
  19. package/skills/workbench-module-diy/BUILD.md +5 -6
  20. package/skills/workbench-module-diy/DATASOURCE.md +3 -4
  21. package/skills/workbench-module-diy/DESIGN.md +3 -4
  22. package/skills/workbench-module-diy/KIT.md +11 -12
  23. package/skills/workbench-module-diy/LINKAGE.md +6 -7
  24. package/skills/workbench-module-diy/PANEL.md +9 -10
  25. package/skills/workbench-module-diy/REVIEW.md +2 -3
  26. package/skills/workbench-module-diy/SKILL.md +2 -3
  27. package/skills/workbench-module-diy/TOOLING.md +3 -8
  28. package/skills/workbench-module-diy/TOOLS.md +4 -9
  29. package/skills/workbench-module-diy/WIRING.md +3 -3
  30. package/dist/types/app/__tests__/workbench-styles.test.d.ts +0 -1
  31. package/dist/types/app/layouts/__tests__/async-feedback.test.d.ts +0 -1
  32. package/dist/types/app/layouts/__tests__/kit-preview-nav.test.d.ts +0 -1
  33. package/dist/types/app/layouts/__tests__/panel-hint.test.d.ts +0 -1
  34. package/dist/types/app/layouts/__tests__/project-selection.test.d.ts +0 -1
  35. package/dist/types/app/layouts/env-gate/__tests__/force-plan.test.d.ts +0 -1
  36. package/dist/types/app/layouts/env-gate/__tests__/gate-deadline.test.d.ts +0 -1
  37. package/dist/types/app/layouts/env-gate/__tests__/gate-hidden.test.d.ts +0 -1
  38. package/dist/types/app/layouts/env-gate/__tests__/gate-mocks.test.d.ts +0 -1
  39. package/dist/types/app/layouts/env-gate/gate-mock.d.ts +0 -18
  40. package/dist/types/app/layouts/market/__tests__/add-module-mock.test.d.ts +0 -1
  41. package/dist/types/app/layouts/market/__tests__/add-module-stages.test.d.ts +0 -1
  42. package/dist/types/app/layouts/market/__tests__/add-module-text.test.d.ts +0 -1
  43. package/dist/types/app/layouts/market/add-module-mock.d.ts +0 -14
  44. package/dist/types/app/layouts/rightbar/BoardMockStrip.d.ts +0 -5
  45. package/dist/types/app/layouts/rightbar/DebugStrip.d.ts +0 -11
  46. package/dist/types/app/layouts/rightbar/__tests__/board-mock.test.d.ts +0 -1
  47. package/dist/types/app/layouts/rightbar/__tests__/board-plan.test.d.ts +0 -1
  48. package/dist/types/app/layouts/rightbar/__tests__/board-selection.test.d.ts +0 -1
  49. package/dist/types/app/layouts/rightbar/__tests__/breadcrumbs.test.d.ts +0 -1
  50. package/dist/types/app/layouts/rightbar/__tests__/market-catalog.test.d.ts +0 -1
  51. package/dist/types/app/layouts/rightbar/__tests__/market-change.test.d.ts +0 -1
  52. package/dist/types/app/layouts/rightbar/__tests__/market-dots.test.d.ts +0 -1
  53. package/dist/types/app/layouts/rightbar/__tests__/market-freshness.test.d.ts +0 -1
  54. package/dist/types/app/layouts/rightbar/__tests__/market-hint-visible.test.d.ts +0 -1
  55. package/dist/types/app/layouts/rightbar/__tests__/market-installed.test.d.ts +0 -1
  56. package/dist/types/app/layouts/rightbar/__tests__/market-live.test.d.ts +0 -1
  57. package/dist/types/app/layouts/rightbar/__tests__/market-mock.test.d.ts +0 -1
  58. package/dist/types/app/layouts/rightbar/__tests__/market-order.test.d.ts +0 -1
  59. package/dist/types/app/layouts/rightbar/__tests__/market-row-icon.test.d.ts +0 -1
  60. package/dist/types/app/layouts/rightbar/__tests__/market-rows-libs.test.d.ts +0 -1
  61. package/dist/types/app/layouts/rightbar/__tests__/market-rows-plugins.test.d.ts +0 -1
  62. package/dist/types/app/layouts/rightbar/__tests__/market-rows.test.d.ts +0 -1
  63. package/dist/types/app/layouts/rightbar/__tests__/market-running-display.test.d.ts +0 -1
  64. package/dist/types/app/layouts/rightbar/__tests__/market-section-icon.test.d.ts +0 -1
  65. package/dist/types/app/layouts/rightbar/__tests__/market-settle.test.d.ts +0 -1
  66. package/dist/types/app/layouts/rightbar/__tests__/market-shared.test.d.ts +0 -1
  67. package/dist/types/app/layouts/rightbar/__tests__/market-state-rules.test.d.ts +0 -1
  68. package/dist/types/app/layouts/rightbar/__tests__/market-workbench-act.test.d.ts +0 -1
  69. package/dist/types/app/layouts/rightbar/__tests__/market-workbench.test.d.ts +0 -1
  70. package/dist/types/app/layouts/rightbar/__tests__/panel-dismiss.test.d.ts +0 -1
  71. package/dist/types/app/layouts/rightbar/__tests__/panel-drag-target.test.d.ts +0 -1
  72. package/dist/types/app/layouts/rightbar/__tests__/panel-mock.test.d.ts +0 -1
  73. package/dist/types/app/layouts/rightbar/__tests__/panel-plugin-rows.test.d.ts +0 -1
  74. package/dist/types/app/layouts/rightbar/__tests__/panel-scope-ui.test.d.ts +0 -1
  75. package/dist/types/app/layouts/rightbar/__tests__/panel-write.test.d.ts +0 -1
  76. package/dist/types/app/layouts/rightbar/__tests__/suite-world.test.d.ts +0 -1
  77. package/dist/types/app/layouts/rightbar/__tests__/use-panels.test.d.ts +0 -1
  78. package/dist/types/app/layouts/rightbar/board-mock.d.ts +0 -22
  79. package/dist/types/app/layouts/rightbar/kit-preview-controls.d.ts +0 -11
  80. package/dist/types/app/layouts/rightbar/kit-preview-frame.d.ts +0 -18
  81. package/dist/types/app/layouts/rightbar/kit-preview-hash.d.ts +0 -1
  82. package/dist/types/app/layouts/rightbar/kit-preview-rows.d.ts +0 -6
  83. package/dist/types/app/layouts/rightbar/kit-preview.d.ts +0 -3
  84. package/dist/types/app/layouts/rightbar/market-installed-mock.d.ts +0 -9
  85. package/dist/types/app/layouts/rightbar/market-mock-types.d.ts +0 -58
  86. package/dist/types/app/layouts/rightbar/market-mock.d.ts +0 -4
  87. package/dist/types/app/layouts/rightbar/panel-mock.d.ts +0 -27
  88. package/dist/types/app/layouts/sidebar/__tests__/current-workspace.test.d.ts +0 -1
  89. package/dist/types/app/layouts/sidebar/__tests__/debug-ui.test.d.ts +0 -1
  90. package/dist/types/app/layouts/sidebar/__tests__/session-pick.test.d.ts +0 -1
  91. package/dist/types/app/layouts/sidebar/__tests__/session-row-ui.test.d.ts +0 -1
  92. package/dist/types/app/layouts/sidebar/__tests__/workspace-groups.test.d.ts +0 -1
  93. package/dist/types/app/layouts/sidebar/__tests__/workspace-name.test.d.ts +0 -1
  94. package/dist/types/app/units/__tests__/fixture-unit-mock.test.d.ts +0 -1
  95. package/dist/types/app/units/__tests__/manifests.test.d.ts +0 -1
  96. package/dist/types/app/units/__tests__/registry.test.d.ts +0 -1
  97. package/dist/types/app/units/fixture-unit-mock.d.ts +0 -7
  98. package/dist/types/dev/MockStrip.d.ts +0 -15
  99. package/dist/types/dev/surface-types.d.ts +0 -53
  100. package/dist/types/dev/surface.d.ts +0 -2
  101. package/dist/types/dev/surface.stub.d.ts +0 -2
  102. package/dist/types/modules/panels/__tests__/approval.test.d.ts +0 -1
  103. package/dist/types/modules/panels/__tests__/config.test.d.ts +0 -1
  104. package/dist/types/modules/panels/__tests__/diy-harness.d.ts +0 -105
  105. package/dist/types/modules/panels/__tests__/diy-report.test.d.ts +0 -1
  106. package/dist/types/modules/panels/__tests__/diy-tools-health.test.d.ts +0 -1
  107. package/dist/types/modules/panels/__tests__/diy-tools-panel.test.d.ts +0 -1
  108. package/dist/types/modules/panels/__tests__/diy-tools-status.test.d.ts +0 -1
  109. package/dist/types/modules/panels/__tests__/diy-tools.test.d.ts +0 -1
  110. package/dist/types/modules/panels/__tests__/face.test.d.ts +0 -1
  111. package/dist/types/modules/panels/__tests__/market-bundle.test.d.ts +0 -1
  112. package/dist/types/modules/panels/__tests__/market-dependency.test.d.ts +0 -1
  113. package/dist/types/modules/panels/__tests__/market-dispatch.test.d.ts +0 -1
  114. package/dist/types/modules/panels/__tests__/market-env.test.d.ts +0 -1
  115. package/dist/types/modules/panels/__tests__/market-plugin.test.d.ts +0 -1
  116. package/dist/types/modules/panels/__tests__/market-registries.test.d.ts +0 -1
  117. package/dist/types/modules/panels/__tests__/market-route.test.d.ts +0 -1
  118. package/dist/types/modules/panels/__tests__/market-tools-harness.d.ts +0 -45
  119. package/dist/types/modules/panels/__tests__/market-tools.test.d.ts +0 -1
  120. package/dist/types/modules/panels/__tests__/market-update.test.d.ts +0 -1
  121. package/dist/types/modules/panels/__tests__/market-workbench-update.test.d.ts +0 -1
  122. package/dist/types/modules/panels/__tests__/market.test.d.ts +0 -1
  123. package/dist/types/modules/panels/__tests__/plugin-actions.test.d.ts +0 -1
  124. package/dist/types/modules/panels/__tests__/plugin-ledger.test.d.ts +0 -1
  125. package/dist/types/modules/panels/__tests__/plugin-panel-market-parity.test.d.ts +0 -1
  126. package/dist/types/modules/panels/__tests__/plugin-panel.test.d.ts +0 -1
  127. package/dist/types/modules/panels/__tests__/plugin-section.test.d.ts +0 -1
  128. package/dist/types/modules/panels/__tests__/plugin-tool-units-harness.d.ts +0 -69
  129. package/dist/types/modules/panels/__tests__/plugin-tool-units.test.d.ts +0 -1
  130. package/dist/types/modules/panels/__tests__/prefs.test.d.ts +0 -1
  131. package/dist/types/modules/panels/__tests__/routes.test.d.ts +0 -1
  132. package/dist/types/modules/panels/__tests__/scope-machine.test.d.ts +0 -1
  133. package/dist/types/modules/panels/__tests__/scope-support.d.ts +0 -51
  134. package/dist/types/modules/panels/__tests__/scope.test.d.ts +0 -1
  135. package/dist/types/modules/panels/__tests__/service-release.test.d.ts +0 -1
  136. package/dist/types/modules/panels/__tests__/service.test.d.ts +0 -1
  137. package/dist/types/modules/panels/__tests__/tools.test.d.ts +0 -1
  138. package/dist/types/shared/__tests__/i18n-keys.test.d.ts +0 -1
  139. package/dist/types/shared/api/__tests__/context-ref.test.d.ts +0 -1
  140. package/dist/types/shared/api/host/__tests__/approval-note-injection.test.d.ts +0 -1
  141. package/dist/types/shared/api/host/__tests__/capability-force.test.d.ts +0 -1
  142. package/dist/types/shared/api/host/__tests__/cli-error.test.d.ts +0 -1
  143. package/dist/types/shared/api/host/__tests__/config-sync.test.d.ts +0 -1
  144. package/dist/types/shared/api/host/__tests__/context-inject.test.d.ts +0 -1
  145. package/dist/types/shared/api/host/__tests__/data-root.test.d.ts +0 -1
  146. package/dist/types/shared/api/host/__tests__/events.test.d.ts +0 -1
  147. package/dist/types/shared/api/host/__tests__/fact-writes.test.d.ts +0 -1
  148. package/dist/types/shared/api/host/__tests__/facts.test.d.ts +0 -1
  149. package/dist/types/shared/api/host/__tests__/long-task.test.d.ts +0 -1
  150. package/dist/types/shared/api/host/__tests__/panel-state-route.test.d.ts +0 -1
  151. package/dist/types/shared/api/host/__tests__/plugin-catalog.test.d.ts +0 -1
  152. package/dist/types/shared/api/host/__tests__/plugin-login-hint.test.d.ts +0 -1
  153. package/dist/types/shared/api/host/__tests__/plugin-source.test.d.ts +0 -1
  154. package/dist/types/shared/api/host/__tests__/plugin-tools.test.d.ts +0 -1
  155. package/dist/types/shared/api/host/__tests__/png-fixtures.d.ts +0 -17
  156. package/dist/types/shared/api/host/__tests__/post-channels.test.d.ts +0 -1
  157. package/dist/types/shared/api/host/__tests__/preflight-fixtures.d.ts +0 -19
  158. package/dist/types/shared/api/host/__tests__/preflight-warm.test.d.ts +0 -1
  159. package/dist/types/shared/api/host/__tests__/preflight.test.d.ts +0 -1
  160. package/dist/types/shared/api/host/__tests__/probe-cache.test.d.ts +0 -1
  161. package/dist/types/shared/api/host/__tests__/probe-libs.test.d.ts +0 -1
  162. package/dist/types/shared/api/host/__tests__/probe-units-cache.test.d.ts +0 -1
  163. package/dist/types/shared/api/host/__tests__/probe-units-npm-source.test.d.ts +0 -1
  164. package/dist/types/shared/api/host/__tests__/probe-units-release.test.d.ts +0 -1
  165. package/dist/types/shared/api/host/__tests__/probe-units.test.d.ts +0 -1
  166. package/dist/types/shared/api/host/__tests__/probe-verdict.test.d.ts +0 -1
  167. package/dist/types/shared/api/host/__tests__/profile-registries.test.d.ts +0 -1
  168. package/dist/types/shared/api/host/__tests__/provision-dependency.test.d.ts +0 -1
  169. package/dist/types/shared/api/host/__tests__/registry-declaration.test.d.ts +0 -1
  170. package/dist/types/shared/api/host/__tests__/release.test.d.ts +0 -1
  171. package/dist/types/shared/api/host/__tests__/self-update.test.d.ts +0 -1
  172. package/dist/types/shared/api/host/__tests__/tool-approval.test.d.ts +0 -1
  173. package/dist/types/shared/api/host/__tests__/tool-kit.test.d.ts +0 -1
  174. package/dist/types/shared/api/host/__tests__/tool-scope.test.d.ts +0 -1
  175. package/dist/types/shared/api/host/__tests__/tool-surface.test.d.ts +0 -1
  176. package/dist/types/shared/api/host/__tests__/unit-face.test.d.ts +0 -1
  177. package/dist/types/shared/api/host/__tests__/unit-readiness.test.d.ts +0 -1
  178. package/dist/types/shared/api/host/__tests__/unit-registry.test.d.ts +0 -1
  179. package/dist/types/shared/api/host/__tests__/unit-roster-facts.test.d.ts +0 -1
  180. package/dist/types/shared/api/host/__tests__/value-handoff.test.d.ts +0 -1
  181. package/dist/types/shared/api/host/__tests__/version-range.test.d.ts +0 -1
  182. package/dist/types/shared/api/host/__tests__/workspace-store.test.d.ts +0 -1
  183. package/dist/types/shared/api/host/__tests__/write-result.test.d.ts +0 -1
  184. package/dist/types/shared/hooks/__tests__/mock-mode.test.d.ts +0 -1
  185. package/dist/types/shared/hooks/__tests__/use-api-resource.test.d.ts +0 -1
  186. package/dist/types/shared/hooks/__tests__/use-capabilities.test.d.ts +0 -1
  187. package/dist/types/shared/hooks/__tests__/use-visible-busy.test.d.ts +0 -1
  188. package/dist/types/shared/hooks/mock-mode.d.ts +0 -2
  189. package/dist/types/shared/hooks/use-fixture-pick.d.ts +0 -20
@@ -13,7 +13,10 @@ var PREFS_PREFIX = `${API_PREFIX}/prefs`;
13
13
  var EVENTS_PATH = "/workbench/events";
14
14
  var ACTIONS_PREFIX = `${API_PREFIX}/actions`;
15
15
  var PROVISION_PREFIX = `${API_PREFIX}/provision`;
16
- var PANEL_STATE_PREFIX = `${API_PREFIX}/panel-state`;
16
+ var PANEL_STATE_PATH = "panel-state";
17
+ var DIY_DEBUG_PATH = "diy-debug";
18
+ `${DIY_DEBUG_PATH}`;
19
+ var PANEL_STATE_PREFIX = `${API_PREFIX}/${PANEL_STATE_PATH}`;
17
20
  var OPENCLI_PIN = "1.8.8";
18
21
  var PANELS_SERVICE = "workbenchPanels";
19
22
  var UNITS_SERVICE = "workbenchUnits";
@@ -435,6 +438,33 @@ function createPanelStateStore() {
435
438
  }
436
439
  };
437
440
  }
441
+ //#endregion
442
+ //#region ../shared/dist/lib/board-fact.js
443
+ function insideWorkshop$1(root, target) {
444
+ if (target === root) return true;
445
+ const base = root.endsWith("/") ? root : `${root}/`;
446
+ return target.startsWith(base);
447
+ }
448
+ function boardFactOf(probe, workshop) {
449
+ if (!probe.workbench) return "unknown";
450
+ if (!probe.bar || !probe.open || !probe.drawn) return "hidden";
451
+ if (probe.board === "" || workshop === null) return "unknown";
452
+ return insideWorkshop$1(workshop, probe.board) ? "workshop" : "other";
453
+ }
454
+ function boardSituation(probe, workshop) {
455
+ if (!probe.workbench || workshop === null) return "unknown";
456
+ if (probe.bar && probe.open && probe.drawn) {
457
+ if (probe.board === "") return "unknown";
458
+ return insideWorkshop$1(workshop, probe.board) ? "ok" : "other-board";
459
+ }
460
+ if (probe.where !== "" && !insideWorkshop$1(workshop, probe.where)) return "off-workspace";
461
+ return "panel-closed";
462
+ }
463
+ //#endregion
464
+ //#region ../shared/dist/lib/diy-debug.js
465
+ function parseDebugIntent(value) {
466
+ return value === "pause" || value === "resume" || value === "stop" ? value : null;
467
+ }
438
468
  function alive(state, now) {
439
469
  if (state === null) return null;
440
470
  return now - state.at <= 144e5 ? state : null;
@@ -471,27 +501,6 @@ function createDebugStore() {
471
501
  state
472
502
  };
473
503
  },
474
- stall(sessionId, now) {
475
- const found = ownerOf(held, sessionId, now);
476
- if (typeof found === "string") return {
477
- ok: false,
478
- code: found
479
- };
480
- if (found.phase === "paused") return {
481
- ok: false,
482
- code: "already-paused"
483
- };
484
- const state = {
485
- ...found,
486
- phase: "paused",
487
- at: now
488
- };
489
- held = state;
490
- return {
491
- ok: true,
492
- state
493
- };
494
- },
495
504
  pause(sessionId, now) {
496
505
  const found = ownerOf(held, sessionId, now);
497
506
  if (typeof found === "string") return {
@@ -1775,6 +1784,15 @@ function registerPanelState(ctx, store) {
1775
1784
  }]
1776
1785
  });
1777
1786
  }
1787
+ function registerDiyDebugAct(ctx, resource, log) {
1788
+ return registerPost(ctx, {
1789
+ prefix: `${API_PREFIX}/${DIY_DEBUG_PATH}`,
1790
+ what: "工作台 DIY 调试动作",
1791
+ refusedCode: "action-refused",
1792
+ resources: [resource],
1793
+ wrote: () => log?.bump(["diy-debug"])
1794
+ });
1795
+ }
1778
1796
  //#endregion
1779
1797
  //#region ../shared/dist/host/long-task.js
1780
1798
  var LIVE = /* @__PURE__ */ new Set(["running", "needs-login"]);
@@ -2917,9 +2935,7 @@ function workshopPackagesDir(ctx) {
2917
2935
  return root === null ? null : join(root, "packages");
2918
2936
  }
2919
2937
  function insideWorkshop(root, target) {
2920
- const base = existsSync(root) ? realpathSync(root) : resolve(root);
2921
- const real = existsSync(target) ? realpathSync(target) : resolve(target);
2922
- return real === base || real.startsWith(base + sep);
2938
+ return insideWorkshop$1(existsSync(root) ? realpathSync(root) : resolve(root), existsSync(target) ? realpathSync(target) : resolve(target));
2923
2939
  }
2924
2940
  function workshopModules(packagesDir, installed = []) {
2925
2941
  if (!existsSync(packagesDir)) return [];
@@ -3730,18 +3746,28 @@ function numberIn$1(value, fallback) {
3730
3746
  }
3731
3747
  var PAGE_PROBE = `(async () => {
3732
3748
  const answer = await fetch('/workbench/api/health').then((one) => one.json()).catch(() => null);
3749
+ const root = document.querySelector('.wb-root');
3750
+ const where = root === null ? '' : (root.getAttribute('data-wb-where') ?? '');
3733
3751
  const bar = document.querySelector('.wb-rightbar');
3734
3752
  const board = bar === null ? '' : (bar.getAttribute('data-wb-board') ?? '');
3735
3753
  const open = bar === null ? null : bar.hasAttribute('data-wb-open');
3736
- const shown = bar === null ? false : getComputedStyle(bar).visibility !== 'hidden';
3754
+ const style = bar === null ? null : getComputedStyle(bar);
3755
+ const box = bar === null ? null : bar.getBoundingClientRect();
3756
+ const drawn =
3757
+ bar !== null &&
3758
+ style.visibility !== 'hidden' &&
3759
+ style.display !== 'none' &&
3760
+ box.width > 0 &&
3761
+ box.height > 0;
3737
3762
  return JSON.stringify({
3738
3763
  plugin: answer === null ? null : answer.plugin,
3739
3764
  pid: answer === null ? null : answer.pid,
3740
3765
  url: location.href,
3741
3766
  title: document.title,
3767
+ where,
3742
3768
  board,
3743
3769
  open,
3744
- shown,
3770
+ shown: drawn,
3745
3771
  });
3746
3772
  })()`;
3747
3773
  function cardSelectorOf(unit) {
@@ -4052,6 +4078,7 @@ async function workbenchPageOf(shell, command, session) {
4052
4078
  ok: false,
4053
4079
  url: "",
4054
4080
  title: "",
4081
+ where: "",
4055
4082
  board: "",
4056
4083
  open: null,
4057
4084
  shown: false
@@ -4061,6 +4088,7 @@ async function workbenchPageOf(shell, command, session) {
4061
4088
  ok: textOf$4(parsed["plugin"]) === "@dsh-workbench/core",
4062
4089
  url: textOf$4(parsed["url"]),
4063
4090
  title: textOf$4(parsed["title"]),
4091
+ where: textOf$4(parsed["where"]),
4064
4092
  board: textOf$4(parsed["board"]),
4065
4093
  open: typeof raw === "boolean" ? raw : null,
4066
4094
  shown: parsed["shown"] === true
@@ -4202,18 +4230,28 @@ function debugPausedText(held) {
4202
4230
  function debugForeignPactText(held) {
4203
4231
  return `另一场调试正占着那块屏(${held.sessionId} 在调试 ${held.unit})—— 一台机器同时只允许一场:让它先 workbench_diy_debug_stop,或等它收工。`;
4204
4232
  }
4205
- function debugStalledText(held) {
4206
- return `你现在这一页画的不是工坊那块板 —— ${held.unit} 这场调试算**搁置**(已自动落 paused):说好别离开那一屏。请用户在左栏切回「工作台DIY」;回到那一屏之后再 workbench_diy_debug_resume 接着看。`;
4233
+ function debugOffBoardText(held, situation = "other-board") {
4234
+ const what = situation === "off-workspace" ? "用户现在不在 DIY 工作区(外壳选中的是别的工作区)" : situation === "panel-closed" ? "工作台面板没画在屏上(右栏收着,或那一列让给了别的面板)" : "你现在这一页画的不是工坊那块板";
4235
+ const next = situation === "off-workspace" ? "让用户在左栏切回「工作台DIY」那个工作区" : situation === "panel-closed" ? "让用户把「工作台面板」切回来(或把右栏展开)" : "让用户把那一页切回「工作台DIY」";
4236
+ return `${what} —— 看 / 动 / 网络这一族现在发不出去,我不拿别的板当目标。${held.unit} 这场调试仍然**进行中**(我没有自动替你落 paused):${next};要停下来就自己 workbench_diy_debug_pause(不问审批),页面切回来了就接着看。`;
4237
+ }
4238
+ function boardProbeOf(page) {
4239
+ return {
4240
+ workbench: page.ok,
4241
+ where: page.where,
4242
+ bar: page.open !== null,
4243
+ board: page.board,
4244
+ open: page.open === true,
4245
+ drawn: page.shown
4246
+ };
4207
4247
  }
4208
4248
  function boardStateOf(page, workshop) {
4209
- if (page.open === null) return "unknown";
4210
- if (!page.open || !page.shown) return "hidden";
4211
- if (page.board === "" || workshop === null) return "unknown";
4212
- return insideWorkshop(workshop, page.board) ? "workshop" : "other";
4249
+ return boardFactOf(boardProbeOf(page), workshop);
4213
4250
  }
4214
- function boardGateText(board, unit, page, workshop) {
4215
- if (board === "hidden") return `右栏收着 —— 面板没画在屏上(锚点还在页面里,但看不见它)。让用户把面板展开、或切回「工作台DIY」,我再接着看 ${unit}。`;
4216
- return `你现在这一页画的是 ${page.board || "(不知道哪一块)"} 的面板,工坊那块板(${workshop ?? "(不知道)"})没在这一屏 —— ${unit} 的这张卡不在屏上,我不拿别的板当目标。请用户在左栏切回「工作台DIY」;这之前我可以继续改源码 / build / 跑门禁。`;
4251
+ function boardGateText(situation, unit, page) {
4252
+ if (situation === "off-workspace") return `用户现在不在 DIY 工作区 —— 外壳选中的是 ${page.where || "(问不出来是哪一块)"}。工坊那块板没在屏上,${unit} 的这张卡我看不到,也不拿别的板当目标。让用户在左栏切回「工作台DIY」;这之前我可以继续改源码 / build / 跑门禁。`;
4253
+ if (situation === "panel-closed") return `工作台面板没画在屏上(右栏收着,或者这一页让给了别的面板:文件预览、模块市场等)。让用户把「工作台面板」切回来(或把右栏展开),我再接着看 ${unit}。`;
4254
+ return `你现在这一页画的是 ${page.board || "(不知道哪一块)"} 的面板,工坊那块板没在这一屏 —— ${unit} 的这张卡不在屏上,我不拿别的板当目标。请用户在左栏切回「工作台DIY」;这之前我可以继续改源码 / build / 跑门禁。`;
4217
4255
  }
4218
4256
  async function pageAt(ctx, exec, raw, options = {}) {
4219
4257
  const { packagesDir } = workshopOf(ctx, exec);
@@ -4234,18 +4272,15 @@ async function pageAt(ctx, exec, raw, options = {}) {
4234
4272
  }
4235
4273
  const workshop = workshopPathOf(ctx);
4236
4274
  const board = boardStateOf(handshake.page, workshop);
4237
- const store = ctx.get(DIY_DEBUG_SERVICE);
4238
- const held = store?.live(Date.now()) ?? null;
4275
+ const situation = boardSituation(boardProbeOf(handshake.page), workshop);
4276
+ const held = ctx.get("workbenchDiyDebug")?.live(Date.now()) ?? null;
4239
4277
  const sessionId = sessionIdOf(exec);
4240
4278
  if (options.requirePact !== false && held !== null) {
4241
4279
  if (held.sessionId !== sessionId) throw new Error(debugForeignPactText(held));
4242
4280
  if (held.phase === "paused") throw new Error(debugPausedText(held));
4243
- if (board === "other" || board === "hidden") {
4244
- store?.stall(sessionId ?? "", Date.now());
4245
- throw new Error(debugStalledText(held));
4246
- }
4281
+ if (board === "other" || board === "hidden") throw new Error(debugOffBoardText(held, situation));
4247
4282
  }
4248
- if (options.requireBoard !== false && (board === "other" || board === "hidden")) throw new Error(boardGateText(board, wanted, handshake.page, workshop));
4283
+ if (options.requireBoard !== false && (board === "other" || board === "hidden")) throw new Error(boardGateText(situation, wanted, handshake.page));
4249
4284
  return {
4250
4285
  packagesDir,
4251
4286
  unit: wanted,
@@ -4518,12 +4553,11 @@ async function scrollIntoView(shell, command, session, unit, selector) {
4518
4553
  async function reloadPage(shell, command, session) {
4519
4554
  return actBrowser(shell, command, session, ["eval", `(() => { setTimeout(() => location.reload(), 30); return JSON.stringify({ ok: true }); })()`]);
4520
4555
  }
4521
- async function shootAtWidth(shell, command, session, file, width, height) {
4556
+ async function shootAtWidth(shell, command, session, file, width = 0, height = 0) {
4522
4557
  const step = await actBrowser(shell, command, session, [
4523
4558
  "screenshot",
4524
4559
  file,
4525
- "--width",
4526
- String(width),
4560
+ ...width > 0 ? ["--width", String(width)] : [],
4527
4561
  ...height > 0 ? ["--height", String(height)] : []
4528
4562
  ], LOOK_TIMEOUT_MS);
4529
4563
  return {
@@ -5434,24 +5468,26 @@ function registerActTools(ctx, tools) {
5434
5468
  };
5435
5469
  const viewportTool = {
5436
5470
  name: DIY_VIEWPORT_TOOL,
5437
- description: "按某个宽度重拍一张整屏图(看窄屏/宽屏下这张卡挤不挤)—— 只在这一拍里换视口。",
5471
+ description: "拍整屏图。不给宽高 = 按用户当前窗口拍;给了才换视口 —— 会回流一次。",
5438
5472
  parameters: pageSchema({
5439
5473
  width: {
5440
5474
  type: "number",
5441
- description: "视口宽度(CSS px,例如 390)。"
5475
+ description: "视口宽度(CSS px,如 390);不填按当前窗口。"
5442
5476
  },
5443
5477
  height: {
5444
5478
  type: "number",
5445
5479
  description: "视口高度(可不要)。"
5446
5480
  }
5447
- }, ["width"]),
5481
+ }, []),
5448
5482
  output: OUTPUT$2,
5449
5483
  async execute(raw, exec) {
5450
5484
  const page = await pageAt(ctx, exec, raw, { requireUnit: false });
5451
- const width = asNumber(page.args["width"]);
5452
- if (width === void 0 || width <= 0) throw new Error("多宽?给 width(CSS px)。");
5485
+ const width = asNumber(page.args["width"]) ?? 0;
5486
+ if (width < 0) throw new Error("width 得是正的 CSS px;不给就按用户当前窗口拍。");
5453
5487
  const height = asNumber(page.args["height"]) ?? 0;
5454
- const file = join(dirname(page.packagesDir), "shots", `${page.unit || "page"}-${String(width)}-${String(Date.now())}.png`);
5488
+ const overrode = width > 0 || height > 0;
5489
+ const stamp = overrode ? `${String(width)}x${String(height)}` : "now";
5490
+ const file = join(dirname(page.packagesDir), "shots", `${page.unit || "page"}-${stamp}-${String(Date.now())}.png`);
5455
5491
  await writeShotsDir(page.shell, dirname(file));
5456
5492
  const shot = await shootAtWidth(page.shell, page.command, page.session, file, width, height);
5457
5493
  return plainJson({
@@ -5459,12 +5495,13 @@ function registerActTools(ctx, tools) {
5459
5495
  unit: page.unit,
5460
5496
  ok: shot.ok,
5461
5497
  file: shot.file,
5462
- width,
5463
- viewport: {
5498
+ overrode,
5499
+ width: overrode ? width : null,
5500
+ viewport: overrode ? {
5464
5501
  width,
5465
5502
  height
5466
- },
5467
- text: shot.ok ? `按 ${String(width)}px 宽重拍了一张:${shot.file}(页面按新视口回流,只在这一拍里生效)。` : `没拍成:${shot.reason}`
5503
+ } : null,
5504
+ text: shot.ok ? overrode ? `重拍了一张:${shot.file}(临时换了视口${width > 0 ? ` 宽 ${String(width)}px` : ""}${height > 0 ? ` 高 ${String(height)}px` : ""},你那一屏会回流一次、拍完就恢复)。` : `按你当前窗口拍了一张:${shot.file}(没动你的视口)。` : `没拍成:${shot.reason}`
5468
5505
  });
5469
5506
  }
5470
5507
  };
@@ -9240,6 +9277,122 @@ function createPostChannels(deps) {
9240
9277
  };
9241
9278
  }
9242
9279
  //#endregion
9280
+ //#region src/shared/api/host/diy-debug-act.ts
9281
+ var DEBUG_NOTICE_KIND = "workbench-diy";
9282
+ var INTENT_WORD = {
9283
+ pause: "暂停",
9284
+ resume: "继续",
9285
+ stop: "结束"
9286
+ };
9287
+ function debugNoticeText(intent, state) {
9288
+ const head = `[工作台 DIY]用户按了「${INTENT_WORD[intent]}」:`;
9289
+ if (intent === "pause") return `${head}${state.unit} 这场调试暂停了 —— 现在别再把那一屏当目标(看 / 动 / 网络那一族发不出去)。要接着看屏就等用户按「继续」;在那之前照常改源码 / build / 跑门禁。`;
9290
+ if (intent === "resume") return `${head}${state.unit} 这场调试重新开始了 —— 那一屏又归你看。屏 / 板不对的话照旧会被拒,拒了就照实说清是哪种不对。`;
9291
+ return `${head}${state.unit} 这场调试收工了(占用解除)。要再调试就重新 start 一场。`;
9292
+ }
9293
+ function debugNoticeSummary(intent, state) {
9294
+ return `工作台 DIY:用户按了${INTENT_WORD[intent]}(${state.unit})`;
9295
+ }
9296
+ function debugNotice(intent, state) {
9297
+ const summary = debugNoticeSummary(intent, state);
9298
+ return {
9299
+ summary,
9300
+ message: {
9301
+ role: "user",
9302
+ id: randomUUID(),
9303
+ content: [{
9304
+ type: "text",
9305
+ text: debugNoticeText(intent, state)
9306
+ }],
9307
+ source: {
9308
+ kind: DEBUG_NOTICE_KIND,
9309
+ form: "notice",
9310
+ summary
9311
+ }
9312
+ }
9313
+ };
9314
+ }
9315
+ var NOTICE_MODE = {
9316
+ resume: "wake",
9317
+ pause: "hold",
9318
+ stop: "drop"
9319
+ };
9320
+ var held = /* @__PURE__ */ new Map();
9321
+ function holdNotice(sessionId, message) {
9322
+ const list = held.get(sessionId);
9323
+ if (list === void 0) held.set(sessionId, [message]);
9324
+ else list.push(message);
9325
+ }
9326
+ function takeHeldNotices(sessionId) {
9327
+ const list = held.get(sessionId) ?? [];
9328
+ held.delete(sessionId);
9329
+ return list;
9330
+ }
9331
+ function deliverDebugNotice(agents, sessionId, message, mode = "wake") {
9332
+ const agent = agents?.get(sessionId);
9333
+ if (agent === void 0) {
9334
+ if (mode === "drop") return "none";
9335
+ holdNotice(sessionId, message);
9336
+ return "held";
9337
+ }
9338
+ if (agent.status !== "idle") {
9339
+ agent.inject(message);
9340
+ return "inject";
9341
+ }
9342
+ if (mode === "wake") {
9343
+ agent.followup(message);
9344
+ return "followup";
9345
+ }
9346
+ if (mode === "hold") {
9347
+ holdNotice(sessionId, message);
9348
+ return "held";
9349
+ }
9350
+ return "skipped-idle";
9351
+ }
9352
+ var REFUSAL = {
9353
+ "already-paused": "这一场已经是暂停态了",
9354
+ "already-debugging": "这一场本来就在调试中",
9355
+ none: "现在没有调试态",
9356
+ "not-owner": "这场调试不是这个会话的"
9357
+ };
9358
+ function debugActResource(deps) {
9359
+ const now = () => deps.now?.() ?? Date.now();
9360
+ return {
9361
+ resource: "act",
9362
+ handle(payload) {
9363
+ const intent = parseDebugIntent(payload?.intent);
9364
+ if (intent === null) return {
9365
+ ok: false,
9366
+ text: "不认识的意图(只认 pause / resume / stop)"
9367
+ };
9368
+ const store = deps.store();
9369
+ if (store === void 0) return {
9370
+ ok: false,
9371
+ text: "现在没有调试态 —— 没什么可暂停 / 继续 / 结束的"
9372
+ };
9373
+ const at = now();
9374
+ const held = store.live(at);
9375
+ if (held === null) return {
9376
+ ok: false,
9377
+ text: "现在没有调试态 —— 没什么可暂停 / 继续 / 结束的"
9378
+ };
9379
+ const move = intent === "pause" ? store.pause(held.sessionId, at) : intent === "resume" ? store.resume(held.sessionId, at) : store.stop(held.sessionId, at);
9380
+ if (!move.ok) return {
9381
+ ok: false,
9382
+ text: REFUSAL[move.code] ?? `按不动:${move.code}`
9383
+ };
9384
+ const notice = deps.notice?.(intent, move.state) ?? debugNotice(intent, move.state);
9385
+ return {
9386
+ ok: true,
9387
+ intent,
9388
+ delivered: deliverDebugNotice(deps.agents(), held.sessionId, notice.message, NOTICE_MODE[intent]),
9389
+ summary: notice.summary,
9390
+ state: store.live(now())
9391
+ };
9392
+ }
9393
+ };
9394
+ }
9395
+ //#endregion
9243
9396
  //#region src/shared/api/host/events.ts
9244
9397
  var HEARTBEAT_MS = 25e3;
9245
9398
  function frame(payload) {
@@ -11369,15 +11522,17 @@ function createToolScope(options) {
11369
11522
  };
11370
11523
  }
11371
11524
  //#endregion
11372
- //#region src/app/host.ts
11373
- var name = "dsh-workbench";
11374
- var inject = ["webServer"];
11525
+ //#region src/shared/api/host/host-args.ts
11375
11526
  function asArgs(value) {
11376
11527
  return typeof value === "object" && value !== null ? value : {};
11377
11528
  }
11378
11529
  function warn(ctx, message) {
11379
11530
  ctx.logger?.warn?.(`[dsh-workbench] ${message}`);
11380
11531
  }
11532
+ //#endregion
11533
+ //#region src/app/host.ts
11534
+ var name = "dsh-workbench";
11535
+ var inject = ["webServer"];
11381
11536
  function seedWorkbenchRuntime(ctx) {
11382
11537
  const root = runtimeSeedRootOf(ctx);
11383
11538
  if (root === null) return;
@@ -11749,9 +11904,10 @@ function apply(ctx) {
11749
11904
  if (decision.kind === "reject") return decision;
11750
11905
  try {
11751
11906
  const message = await injector.inject(decision.messages ?? [], payload?.agent);
11752
- return message === void 0 ? decision : {
11907
+ const extra = [...takeHeldNotices(String((payload?.agent)?.id ?? "")), ...message === void 0 ? [] : [message]];
11908
+ return extra.length === 0 ? decision : {
11753
11909
  ...decision,
11754
- messages: [...decision.messages ?? [], message]
11910
+ messages: [...decision.messages ?? [], ...extra]
11755
11911
  };
11756
11912
  } catch (error) {
11757
11913
  ctx.logger?.warn?.(`[dsh-workbench] 对话引用注入失败:${String(error)}`);
@@ -11762,6 +11918,12 @@ function apply(ctx) {
11762
11918
  }, `${PLUGIN_ID}: 对话引用注入`);
11763
11919
  ctx.effect(() => registerFactStream(ctx, facts), `${PLUGIN_ID}: 变更流`);
11764
11920
  ctx.effect(() => registerPanelState(ctx, panelState), `${PLUGIN_ID}: 面板运行态上报(浏览器半侧报自己的取数与渲染收尾)`);
11921
+ ctx.effect(() => {
11922
+ return registerDiyDebugAct(ctx, debugActResource({
11923
+ store: () => ctx.get(DIY_DEBUG_SERVICE),
11924
+ agents: () => ctx.get("agents")
11925
+ }), { bump: (names) => facts.bump(names) });
11926
+ }, `${PLUGIN_ID}: DIY 调试的三个键(用户按的)`);
11765
11927
  ctx.effect(() => registerApi(ctx, routes), `${PLUGIN_ID}: HTTP 投影`);
11766
11928
  }
11767
11929
  //#endregion