@dsh-workbench/core 0.2.13 → 0.2.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/client.js +700 -124
- package/dist/client/client.body.js +700 -124
- package/dist/client/index.js +701 -125
- package/dist/host/index.js +387 -22
- package/dist/types/app/client.d.ts +124 -6
- package/dist/types/app/layouts/rightbar/DebugStrip.d.ts +11 -0
- package/dist/types/app/layouts/rightbar/kit-preview-controls.d.ts +1 -0
- package/dist/types/app/layouts/sidebar/DebugFooterAction.d.ts +13 -0
- package/dist/types/app/layouts/sidebar/ProjectSwitcher.d.ts +4 -1
- package/dist/types/app/layouts/sidebar/SidebarHeader.d.ts +12 -0
- package/dist/types/app/layouts/sidebar/WorkspaceAttentionDot.d.ts +9 -0
- package/dist/types/app/layouts/sidebar/WorkspaceAttentionTag.d.ts +7 -0
- package/dist/types/app/layouts/sidebar/__tests__/current-workspace.test.d.ts +1 -0
- package/dist/types/app/layouts/sidebar/__tests__/debug-ui.test.d.ts +1 -0
- package/dist/types/app/layouts/sidebar/current-workspace.d.ts +8 -0
- package/dist/types/app/layouts/sidebar/debug-footer.d.ts +4 -0
- package/dist/types/app/layouts/sidebar/session-pick.d.ts +2 -1
- package/dist/types/app/layouts/sidebar/use-attention.d.ts +16 -0
- package/dist/types/app/layouts/sidebar/workspace-items.d.ts +2 -0
- package/dist/types/modules/panels/__tests__/diy-harness.d.ts +6 -3
- package/dist/types/modules/panels/model/diy-browser.d.ts +3 -0
- package/dist/types/modules/panels/model/diy-debug-routes.d.ts +2 -0
- package/dist/types/modules/panels/model/diy-debug-routes.test.d.ts +1 -0
- package/dist/types/modules/panels/model/diy-debug-tools.d.ts +8 -0
- package/dist/types/modules/panels/model/diy-debug-tools.test.d.ts +1 -0
- package/dist/types/modules/panels/model/diy-look.d.ts +2 -1
- package/dist/types/modules/panels/model/diy-page.d.ts +12 -0
- package/dist/types/modules/panels/model/diy-scripts.d.ts +2 -1
- package/dist/types/modules/panels/model/diy-tools.d.ts +2 -1
- package/dist/types/modules/panels/model/handoff.d.ts +1 -0
- package/dist/types/modules/panels/unit.d.ts +7 -2
- package/dist/types/modules/sessions/index.d.ts +1 -0
- package/dist/types/modules/sessions/model/attention.d.ts +29 -0
- package/dist/types/modules/sessions/model/attention.test.d.ts +1 -0
- package/dist/types/shared/hooks/use-api-resource.d.ts +1 -0
- package/dist/types/shared/hooks/use-diy-debug.d.ts +4 -0
- package/package.json +2 -2
- package/skills/workbench-module-diy/BUILD.md +1 -1
- package/skills/workbench-module-diy/DATASOURCE.md +1 -1
- package/skills/workbench-module-diy/KIT.md +22 -5
- package/skills/workbench-module-diy/PANEL.md +1 -1
- package/skills/workbench-module-diy/REVIEW.md +1 -1
package/dist/host/index.js
CHANGED
|
@@ -18,6 +18,7 @@ var OPENCLI_PIN = "1.8.8";
|
|
|
18
18
|
var PANELS_SERVICE = "workbenchPanels";
|
|
19
19
|
var UNITS_SERVICE = "workbenchUnits";
|
|
20
20
|
var PANEL_STATE_SERVICE = "workbenchPanelState";
|
|
21
|
+
var DIY_DEBUG_SERVICE = "workbenchDiyDebug";
|
|
21
22
|
var OPENCLI_TIMEOUT_MS = 12e4;
|
|
22
23
|
var WARM_TIMEOUT_MS = 2e4;
|
|
23
24
|
var INSTALL_TIMEOUT_MS = 3e5;
|
|
@@ -434,6 +435,119 @@ function createPanelStateStore() {
|
|
|
434
435
|
}
|
|
435
436
|
};
|
|
436
437
|
}
|
|
438
|
+
function alive(state, now) {
|
|
439
|
+
if (state === null) return null;
|
|
440
|
+
return now - state.at <= 144e5 ? state : null;
|
|
441
|
+
}
|
|
442
|
+
function ownerOf(state, sessionId, now) {
|
|
443
|
+
const held = alive(state, now);
|
|
444
|
+
if (held === null) return "none";
|
|
445
|
+
return held.sessionId === sessionId ? held : "not-owner";
|
|
446
|
+
}
|
|
447
|
+
function createDebugStore() {
|
|
448
|
+
let held = null;
|
|
449
|
+
const live = (now) => alive(held, now);
|
|
450
|
+
return {
|
|
451
|
+
live,
|
|
452
|
+
begin(pact) {
|
|
453
|
+
const current = alive(held, pact.now);
|
|
454
|
+
if (current !== null) return {
|
|
455
|
+
ok: false,
|
|
456
|
+
code: current.sessionId === pact.sessionId ? "already-held" : "held-by-other"
|
|
457
|
+
};
|
|
458
|
+
const state = {
|
|
459
|
+
phase: "debugging",
|
|
460
|
+
sessionId: pact.sessionId,
|
|
461
|
+
workspace: pact.workspace,
|
|
462
|
+
board: pact.board,
|
|
463
|
+
unit: pact.unit,
|
|
464
|
+
name: pact.name,
|
|
465
|
+
startedAt: pact.now,
|
|
466
|
+
at: pact.now
|
|
467
|
+
};
|
|
468
|
+
held = state;
|
|
469
|
+
return {
|
|
470
|
+
ok: true,
|
|
471
|
+
state
|
|
472
|
+
};
|
|
473
|
+
},
|
|
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
|
+
pause(sessionId, now) {
|
|
496
|
+
const found = ownerOf(held, sessionId, now);
|
|
497
|
+
if (typeof found === "string") return {
|
|
498
|
+
ok: false,
|
|
499
|
+
code: found
|
|
500
|
+
};
|
|
501
|
+
if (found.phase === "paused") return {
|
|
502
|
+
ok: false,
|
|
503
|
+
code: "already-paused"
|
|
504
|
+
};
|
|
505
|
+
const state = {
|
|
506
|
+
...found,
|
|
507
|
+
phase: "paused",
|
|
508
|
+
at: now
|
|
509
|
+
};
|
|
510
|
+
held = state;
|
|
511
|
+
return {
|
|
512
|
+
ok: true,
|
|
513
|
+
state
|
|
514
|
+
};
|
|
515
|
+
},
|
|
516
|
+
resume(sessionId, now) {
|
|
517
|
+
const found = ownerOf(held, sessionId, now);
|
|
518
|
+
if (typeof found === "string") return {
|
|
519
|
+
ok: false,
|
|
520
|
+
code: found
|
|
521
|
+
};
|
|
522
|
+
if (found.phase === "debugging") return {
|
|
523
|
+
ok: false,
|
|
524
|
+
code: "already-debugging"
|
|
525
|
+
};
|
|
526
|
+
const state = {
|
|
527
|
+
...found,
|
|
528
|
+
phase: "debugging",
|
|
529
|
+
at: now
|
|
530
|
+
};
|
|
531
|
+
held = state;
|
|
532
|
+
return {
|
|
533
|
+
ok: true,
|
|
534
|
+
state
|
|
535
|
+
};
|
|
536
|
+
},
|
|
537
|
+
stop(sessionId, now) {
|
|
538
|
+
const found = ownerOf(held, sessionId, now);
|
|
539
|
+
if (typeof found === "string") return {
|
|
540
|
+
ok: false,
|
|
541
|
+
code: found
|
|
542
|
+
};
|
|
543
|
+
held = null;
|
|
544
|
+
return {
|
|
545
|
+
ok: true,
|
|
546
|
+
state: found
|
|
547
|
+
};
|
|
548
|
+
}
|
|
549
|
+
};
|
|
550
|
+
}
|
|
437
551
|
//#endregion
|
|
438
552
|
//#region ../shared/dist/host/opencli-window.js
|
|
439
553
|
var OPENCLI_WINDOW_ENV = "OPENCLI_WINDOW=background";
|
|
@@ -2138,6 +2252,10 @@ function sessionWorkspace(exec) {
|
|
|
2138
2252
|
const cwd = exec?.agent?.session?.header?.cwd;
|
|
2139
2253
|
return typeof cwd === "string" && cwd.trim() !== "" ? cwd.trim() : null;
|
|
2140
2254
|
}
|
|
2255
|
+
function sessionIdOf(exec) {
|
|
2256
|
+
const id = exec?.agent?.session?.id;
|
|
2257
|
+
return typeof id === "string" && id.trim() !== "" ? id.trim() : null;
|
|
2258
|
+
}
|
|
2141
2259
|
function textOutput(text) {
|
|
2142
2260
|
return [{
|
|
2143
2261
|
type: "text",
|
|
@@ -2871,6 +2989,10 @@ var DIY_NET_STOP_TOOL = "workbench_diy_net_stop";
|
|
|
2871
2989
|
var DIY_LOGS_WATCH_TOOL = "workbench_diy_logs_watch";
|
|
2872
2990
|
var DIY_LOGS_READ_TOOL = "workbench_diy_logs_read";
|
|
2873
2991
|
var DIY_LOGS_STOP_TOOL = "workbench_diy_logs_stop";
|
|
2992
|
+
var DIY_DEBUG_START_TOOL = "workbench_diy_debug_start";
|
|
2993
|
+
var DIY_DEBUG_PAUSE_TOOL = "workbench_diy_debug_pause";
|
|
2994
|
+
var DIY_DEBUG_RESUME_TOOL = "workbench_diy_debug_resume";
|
|
2995
|
+
var DIY_DEBUG_STOP_TOOL = "workbench_diy_debug_stop";
|
|
2874
2996
|
var READ_TOOLS = [
|
|
2875
2997
|
PANELS_LIST_TOOL,
|
|
2876
2998
|
MODULES_LIST_TOOL,
|
|
@@ -2911,7 +3033,11 @@ var WRITE_TOOLS = [
|
|
|
2911
3033
|
MODULES_UNINSTALL_PLUGIN_TOOL,
|
|
2912
3034
|
MODULES_UPDATE_WORKBENCH_TOOL,
|
|
2913
3035
|
DIY_INSTALL_TOOL,
|
|
2914
|
-
DIY_SHOW_TOOL
|
|
3036
|
+
DIY_SHOW_TOOL,
|
|
3037
|
+
DIY_DEBUG_START_TOOL,
|
|
3038
|
+
DIY_DEBUG_PAUSE_TOOL,
|
|
3039
|
+
DIY_DEBUG_RESUME_TOOL,
|
|
3040
|
+
DIY_DEBUG_STOP_TOOL
|
|
2915
3041
|
];
|
|
2916
3042
|
var DIY_TOOLS = [
|
|
2917
3043
|
DIY_LIST_TOOL,
|
|
@@ -2938,6 +3064,12 @@ var DIY_TOOLS = [
|
|
|
2938
3064
|
DIY_LOGS_READ_TOOL,
|
|
2939
3065
|
DIY_LOGS_STOP_TOOL
|
|
2940
3066
|
];
|
|
3067
|
+
var DIY_DEBUG_TOOLS = [
|
|
3068
|
+
DIY_DEBUG_START_TOOL,
|
|
3069
|
+
DIY_DEBUG_PAUSE_TOOL,
|
|
3070
|
+
DIY_DEBUG_RESUME_TOOL,
|
|
3071
|
+
DIY_DEBUG_STOP_TOOL
|
|
3072
|
+
];
|
|
2941
3073
|
var panelsUnit = {
|
|
2942
3074
|
id: "panels",
|
|
2943
3075
|
card: null,
|
|
@@ -3031,6 +3163,13 @@ function askOf(reason, question, fallback) {
|
|
|
3031
3163
|
};
|
|
3032
3164
|
}
|
|
3033
3165
|
var panelsApproval = (call) => {
|
|
3166
|
+
if (call.name === "workbench_diy_debug_start" || call.name === "workbench_diy_debug_resume") {
|
|
3167
|
+
const starting = call.name === DIY_DEBUG_START_TOOL;
|
|
3168
|
+
const unit = argsOf$1(call)["unit"];
|
|
3169
|
+
const target = typeof unit === "string" && unit !== "" ? ` [${unit}]` : "";
|
|
3170
|
+
return askOf(`${call.name}${target} takes over the user's screen to debug a workbench module`, pair(starting ? "要在「工作台DIY」那块板上开始调试 —— 调试中请留在那一屏,允许吗?" : "要接着调试 —— 请回到「工作台DIY」那一屏,允许吗?", starting ? "it takes over your screen to debug on the workshop board — please stay on that screen. Allow?" : "it needs your screen again to keep debugging — please go back to the workshop board. Allow?"), pair(starting ? "agent 要占用你的屏幕开始调试工作台模块,允许吗?" : "agent 要接着占用你的屏幕调试,允许吗?", starting ? "The agent wants to take over your screen to start debugging a workbench module. Allow?" : "The agent wants your screen again to keep debugging. Allow?"));
|
|
3171
|
+
}
|
|
3172
|
+
if (call.name === "workbench_diy_debug_pause" || call.name === "workbench_diy_debug_stop") return { kind: "allow" };
|
|
3034
3173
|
if (call.name !== void 0 && DIY_TOOLS.includes(call.name)) return { kind: "allow" };
|
|
3035
3174
|
const raw = argsOf$1(call);
|
|
3036
3175
|
const text = (key) => {
|
|
@@ -3591,11 +3730,18 @@ function numberIn$1(value, fallback) {
|
|
|
3591
3730
|
}
|
|
3592
3731
|
var PAGE_PROBE = `(async () => {
|
|
3593
3732
|
const answer = await fetch('/workbench/api/health').then((one) => one.json()).catch(() => null);
|
|
3733
|
+
const bar = document.querySelector('.wb-rightbar');
|
|
3734
|
+
const board = bar === null ? '' : (bar.getAttribute('data-wb-board') ?? '');
|
|
3735
|
+
const open = bar === null ? null : bar.hasAttribute('data-wb-open');
|
|
3736
|
+
const shown = bar === null ? false : getComputedStyle(bar).visibility !== 'hidden';
|
|
3594
3737
|
return JSON.stringify({
|
|
3595
3738
|
plugin: answer === null ? null : answer.plugin,
|
|
3596
3739
|
pid: answer === null ? null : answer.pid,
|
|
3597
3740
|
url: location.href,
|
|
3598
3741
|
title: document.title,
|
|
3742
|
+
board,
|
|
3743
|
+
open,
|
|
3744
|
+
shown,
|
|
3599
3745
|
});
|
|
3600
3746
|
})()`;
|
|
3601
3747
|
function cardSelectorOf(unit) {
|
|
@@ -3657,6 +3803,7 @@ var NO_PICK = {
|
|
|
3657
3803
|
var EMPTY_CARD = {
|
|
3658
3804
|
ok: false,
|
|
3659
3805
|
anchored: false,
|
|
3806
|
+
visible: false,
|
|
3660
3807
|
width: 0,
|
|
3661
3808
|
height: 0,
|
|
3662
3809
|
head: "",
|
|
@@ -3703,10 +3850,13 @@ function measureScriptOf(unit, pick) {
|
|
|
3703
3850
|
};
|
|
3704
3851
|
const anchor = document.querySelector(${JSON.stringify(cardSelectorOf(unit))});
|
|
3705
3852
|
const all = [...document.querySelectorAll('.wb-card')];
|
|
3706
|
-
if (anchor === null) return JSON.stringify({ ok: false, cards: all.length, anchored: false });
|
|
3853
|
+
if (anchor === null) return JSON.stringify({ ok: false, cards: all.length, anchored: false, visible: false });
|
|
3707
3854
|
const card = anchor.classList.contains('wb-card') ? anchor : anchor.querySelector('.wb-card');
|
|
3708
|
-
if (card === null) return JSON.stringify({ ok: false, cards: all.length, anchored: true });
|
|
3855
|
+
if (card === null) return JSON.stringify({ ok: false, cards: all.length, anchored: true, visible: false });
|
|
3709
3856
|
const box = card.getBoundingClientRect();
|
|
3857
|
+
const painted = getComputedStyle(card);
|
|
3858
|
+
const visible =
|
|
3859
|
+
painted.visibility !== 'hidden' && painted.display !== 'none' && box.width > 0 && box.height > 0;
|
|
3710
3860
|
const head = card.querySelector('.wb-cardTitle');
|
|
3711
3861
|
const text = scrub(card.textContent);
|
|
3712
3862
|
const shown = scrub(card.innerText);
|
|
@@ -3749,6 +3899,7 @@ function measureScriptOf(unit, pick) {
|
|
|
3749
3899
|
return JSON.stringify({
|
|
3750
3900
|
ok: true,
|
|
3751
3901
|
cards: all.length,
|
|
3902
|
+
visible,
|
|
3752
3903
|
width: Math.ceil(box.width),
|
|
3753
3904
|
height: Math.ceil(box.height),
|
|
3754
3905
|
x: Math.round(box.x),
|
|
@@ -3900,12 +4051,19 @@ async function workbenchPageOf(shell, command, session) {
|
|
|
3900
4051
|
if (parsed === void 0) return {
|
|
3901
4052
|
ok: false,
|
|
3902
4053
|
url: "",
|
|
3903
|
-
title: ""
|
|
4054
|
+
title: "",
|
|
4055
|
+
board: "",
|
|
4056
|
+
open: null,
|
|
4057
|
+
shown: false
|
|
3904
4058
|
};
|
|
4059
|
+
const raw = parsed["open"];
|
|
3905
4060
|
return {
|
|
3906
4061
|
ok: textOf$4(parsed["plugin"]) === "@dsh-workbench/core",
|
|
3907
4062
|
url: textOf$4(parsed["url"]),
|
|
3908
|
-
title: textOf$4(parsed["title"])
|
|
4063
|
+
title: textOf$4(parsed["title"]),
|
|
4064
|
+
board: textOf$4(parsed["board"]),
|
|
4065
|
+
open: typeof raw === "boolean" ? raw : null,
|
|
4066
|
+
shown: parsed["shown"] === true
|
|
3909
4067
|
};
|
|
3910
4068
|
}
|
|
3911
4069
|
async function writeShotsDir(shell, dir) {
|
|
@@ -3951,13 +4109,15 @@ async function measureCard(shell, command, session, unit, pick) {
|
|
|
3951
4109
|
if (parsed === void 0 || parsed["ok"] !== true) return {
|
|
3952
4110
|
...EMPTY_CARD,
|
|
3953
4111
|
cards: numberIn(parsed?.["cards"], 0),
|
|
3954
|
-
anchored: parsed?.["anchored"] === true
|
|
4112
|
+
anchored: parsed?.["anchored"] === true,
|
|
4113
|
+
visible: parsed?.["visible"] === true
|
|
3955
4114
|
};
|
|
3956
4115
|
const width = numberIn(parsed["width"], 0);
|
|
3957
4116
|
const height = numberIn(parsed["height"], 0);
|
|
3958
4117
|
return {
|
|
3959
4118
|
ok: true,
|
|
3960
4119
|
anchored: true,
|
|
4120
|
+
visible: parsed["visible"] === true,
|
|
3961
4121
|
width,
|
|
3962
4122
|
height,
|
|
3963
4123
|
head: textOf$4(parsed["head"]),
|
|
@@ -4036,6 +4196,25 @@ async function shootCard(shell, command, session, unit, file, view) {
|
|
|
4036
4196
|
}
|
|
4037
4197
|
//#endregion
|
|
4038
4198
|
//#region src/modules/panels/model/diy-page.ts
|
|
4199
|
+
function debugPausedText(held) {
|
|
4200
|
+
return `调试已暂停(${held.unit})—— 动作族关闸,不再拿屏当目标。要接着看先 workbench_diy_debug_resume(会再要用户点头一次);这之前可以改源码 / build / 跑门禁。`;
|
|
4201
|
+
}
|
|
4202
|
+
function debugForeignPactText(held) {
|
|
4203
|
+
return `另一场调试正占着那块屏(${held.sessionId} 在调试 ${held.unit})—— 一台机器同时只允许一场:让它先 workbench_diy_debug_stop,或等它收工。`;
|
|
4204
|
+
}
|
|
4205
|
+
function debugStalledText(held) {
|
|
4206
|
+
return `你现在这一页画的不是工坊那块板 —— ${held.unit} 这场调试算**搁置**(已自动落 paused):说好别离开那一屏。请用户在左栏切回「工作台DIY」;回到那一屏之后再 workbench_diy_debug_resume 接着看。`;
|
|
4207
|
+
}
|
|
4208
|
+
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";
|
|
4213
|
+
}
|
|
4214
|
+
function boardGateText(board, unit, page, workshop) {
|
|
4215
|
+
if (board === "hidden") return `右栏收着 —— 面板没画在屏上(锚点还在页面里,但看不见它)。让用户把面板展开、或切回「工作台DIY」,我再接着看 ${unit}。`;
|
|
4216
|
+
return `你现在这一页画的是 ${page.board || "(不知道哪一块)"} 的面板,工坊那块板(${workshop ?? "(不知道)"})没在这一屏 —— ${unit} 的这张卡不在屏上,我不拿别的板当目标。请用户在左栏切回「工作台DIY」;这之前我可以继续改源码 / build / 跑门禁。`;
|
|
4217
|
+
}
|
|
4039
4218
|
async function pageAt(ctx, exec, raw, options = {}) {
|
|
4040
4219
|
const { packagesDir } = workshopOf(ctx, exec);
|
|
4041
4220
|
const args = asRecord$3(raw);
|
|
@@ -4053,6 +4232,20 @@ async function pageAt(ctx, exec, raw, options = {}) {
|
|
|
4053
4232
|
const { page } = handshake;
|
|
4054
4233
|
throw new Error(`你现在这一页不是工作台(${page.title || "(没有标题)"} ${page.url})—— 把工作台那一页切到前台,再喊我一次。我只看用户正在看的那一页。`);
|
|
4055
4234
|
}
|
|
4235
|
+
const workshop = workshopPathOf(ctx);
|
|
4236
|
+
const board = boardStateOf(handshake.page, workshop);
|
|
4237
|
+
const store = ctx.get(DIY_DEBUG_SERVICE);
|
|
4238
|
+
const held = store?.live(Date.now()) ?? null;
|
|
4239
|
+
const sessionId = sessionIdOf(exec);
|
|
4240
|
+
if (options.requirePact !== false && held !== null) {
|
|
4241
|
+
if (held.sessionId !== sessionId) throw new Error(debugForeignPactText(held));
|
|
4242
|
+
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
|
+
}
|
|
4247
|
+
}
|
|
4248
|
+
if (options.requireBoard !== false && (board === "other" || board === "hidden")) throw new Error(boardGateText(board, wanted, handshake.page, workshop));
|
|
4056
4249
|
return {
|
|
4057
4250
|
packagesDir,
|
|
4058
4251
|
unit: wanted,
|
|
@@ -4060,10 +4253,155 @@ async function pageAt(ctx, exec, raw, options = {}) {
|
|
|
4060
4253
|
shell,
|
|
4061
4254
|
command,
|
|
4062
4255
|
session,
|
|
4063
|
-
bound: handshake.bound
|
|
4256
|
+
bound: handshake.bound,
|
|
4257
|
+
board,
|
|
4258
|
+
boardPath: handshake.page.board
|
|
4064
4259
|
};
|
|
4065
4260
|
}
|
|
4066
4261
|
//#endregion
|
|
4262
|
+
//#region src/modules/panels/model/diy-debug-tools.ts
|
|
4263
|
+
var EMPTY = {
|
|
4264
|
+
type: "object",
|
|
4265
|
+
properties: {},
|
|
4266
|
+
additionalProperties: false
|
|
4267
|
+
};
|
|
4268
|
+
function debugRefusalText(code, held) {
|
|
4269
|
+
switch (code) {
|
|
4270
|
+
case "held-by-other": return `另一场调试还占着那块屏(${held === void 0 ? "另一个会话" : held.sessionId})—— 一台机器同时只允许一场:让它先 workbench_diy_debug_stop,或等它收工。`;
|
|
4271
|
+
case "already-held": return `你这个会话已经持有一场调试(${held === void 0 ? "" : `${held.unit},${held.phase}`})—— 要换目标先 workbench_diy_debug_stop;暂停着要接着看用 workbench_diy_debug_resume。`;
|
|
4272
|
+
case "not-owner": return "这个调试态不是你这个会话的 —— 谁开始的谁收工。";
|
|
4273
|
+
case "none": return "现在没有调试态。";
|
|
4274
|
+
case "already-paused": return "已经暂停了 —— 要接着看用 workbench_diy_debug_resume(会再要用户点头)。";
|
|
4275
|
+
case "already-debugging": return "正在调试中,不用再开一次。";
|
|
4276
|
+
}
|
|
4277
|
+
}
|
|
4278
|
+
function renderDebugStart(state) {
|
|
4279
|
+
return [`开始调试 ${state.unit}(声明的目标:${state.board === "" ? "用户那一屏" : state.board})。`, "现在看 / 动 / 网络那一族才把屏当目标 —— 收工前记得 workbench_diy_debug_stop。"].join("\n");
|
|
4280
|
+
}
|
|
4281
|
+
function renderDebugPause(state) {
|
|
4282
|
+
return [`调试暂停了(${state.unit})—— 动作族关闸,不再拿屏当目标。`, "改源码 / build / 跑门禁照常;要看屏再 workbench_diy_debug_resume(会再要用户点头一次)。"].join("\n");
|
|
4283
|
+
}
|
|
4284
|
+
function renderDebugResume(state) {
|
|
4285
|
+
return [`继续调试 ${state.unit} —— 请用户回到「工作台DIY」那一屏。`, "卡不在屏上时我会当场拒(不拿别的板当目标)。"].join("\n");
|
|
4286
|
+
}
|
|
4287
|
+
function renderDebugStop(state) {
|
|
4288
|
+
return `收工了:${state.unit} 的调试态清掉了(占用解除)。`;
|
|
4289
|
+
}
|
|
4290
|
+
function moveOrThrow(move, held) {
|
|
4291
|
+
if (move.ok) return move.state;
|
|
4292
|
+
throw new Error(debugRefusalText(move.code, held ?? void 0));
|
|
4293
|
+
}
|
|
4294
|
+
function registerDebugTools(ctx, tools, store) {
|
|
4295
|
+
const startTool = {
|
|
4296
|
+
name: DIY_DEBUG_START_TOOL,
|
|
4297
|
+
description: "开始调试:占用用户那一屏(要点头一次)。声明 unit 之后,看 / 动那一族才把屏当目标。",
|
|
4298
|
+
parameters: withApprovalNote({
|
|
4299
|
+
type: "object",
|
|
4300
|
+
properties: { unit: {
|
|
4301
|
+
type: "string",
|
|
4302
|
+
description: "工坊里的 unit(workbench_diy_list 会给)。"
|
|
4303
|
+
} },
|
|
4304
|
+
required: ["unit"],
|
|
4305
|
+
additionalProperties: false
|
|
4306
|
+
}, { required: true }),
|
|
4307
|
+
output: OUTPUT$2,
|
|
4308
|
+
async execute(raw, exec) {
|
|
4309
|
+
const { packagesDir, workspace } = workshopOf(ctx, exec);
|
|
4310
|
+
const unit = asText$1(asRecord$3(raw)["unit"]);
|
|
4311
|
+
if (unit === "") {
|
|
4312
|
+
const { modules } = modulesOf(ctx, packagesDir);
|
|
4313
|
+
throw new Error(`要一个 unit(工坊里:${modules.map((one) => one.unit).join(", ") || "(空)"})`);
|
|
4314
|
+
}
|
|
4315
|
+
const held = store.live(Date.now());
|
|
4316
|
+
const page = await pageAt(ctx, exec, raw, {
|
|
4317
|
+
requireBoard: false,
|
|
4318
|
+
requirePact: false
|
|
4319
|
+
});
|
|
4320
|
+
const state = moveOrThrow(store.begin({
|
|
4321
|
+
sessionId: sessionIdOf(exec) ?? "",
|
|
4322
|
+
workspace: workspace ?? "",
|
|
4323
|
+
board: page.boardPath,
|
|
4324
|
+
unit,
|
|
4325
|
+
name: modulesOf(ctx, packagesDir).modules.find((one) => one.unit === unit)?.name ?? unit,
|
|
4326
|
+
now: Date.now()
|
|
4327
|
+
}), held);
|
|
4328
|
+
return plainJson({
|
|
4329
|
+
workshop: packagesDir,
|
|
4330
|
+
unit,
|
|
4331
|
+
board: state.board,
|
|
4332
|
+
phase: state.phase,
|
|
4333
|
+
state,
|
|
4334
|
+
text: renderDebugStart(state)
|
|
4335
|
+
});
|
|
4336
|
+
}
|
|
4337
|
+
};
|
|
4338
|
+
const pauseTool = {
|
|
4339
|
+
name: DIY_DEBUG_PAUSE_TOOL,
|
|
4340
|
+
description: "暂停调试(不审批):动作族关闸,不再拿屏当目标。要看屏再 debug_resume。",
|
|
4341
|
+
parameters: EMPTY,
|
|
4342
|
+
output: OUTPUT$2,
|
|
4343
|
+
async execute(_raw, exec) {
|
|
4344
|
+
const { packagesDir } = workshopOf(ctx, exec);
|
|
4345
|
+
const held = store.live(Date.now());
|
|
4346
|
+
const state = moveOrThrow(store.pause(sessionIdOf(exec) ?? "", Date.now()), held);
|
|
4347
|
+
return plainJson({
|
|
4348
|
+
workshop: packagesDir,
|
|
4349
|
+
unit: state.unit,
|
|
4350
|
+
phase: state.phase,
|
|
4351
|
+
state,
|
|
4352
|
+
text: renderDebugPause(state)
|
|
4353
|
+
});
|
|
4354
|
+
}
|
|
4355
|
+
};
|
|
4356
|
+
const resumeTool = {
|
|
4357
|
+
name: DIY_DEBUG_RESUME_TOOL,
|
|
4358
|
+
description: "继续调试(要点头一次):请用户回到「工作台DIY」那一屏。",
|
|
4359
|
+
parameters: withApprovalNote(EMPTY, { required: true }),
|
|
4360
|
+
output: OUTPUT$2,
|
|
4361
|
+
async execute(_raw, exec) {
|
|
4362
|
+
const { packagesDir } = workshopOf(ctx, exec);
|
|
4363
|
+
const held = store.live(Date.now());
|
|
4364
|
+
const page = await pageAt(ctx, exec, { unit: held?.unit ?? "" }, {
|
|
4365
|
+
requireBoard: false,
|
|
4366
|
+
requirePact: false,
|
|
4367
|
+
requireUnit: false
|
|
4368
|
+
});
|
|
4369
|
+
const state = moveOrThrow(store.resume(sessionIdOf(exec) ?? "", Date.now()), held);
|
|
4370
|
+
return plainJson({
|
|
4371
|
+
workshop: packagesDir,
|
|
4372
|
+
unit: state.unit,
|
|
4373
|
+
board: page.boardPath,
|
|
4374
|
+
phase: state.phase,
|
|
4375
|
+
state,
|
|
4376
|
+
text: renderDebugResume(state)
|
|
4377
|
+
});
|
|
4378
|
+
}
|
|
4379
|
+
};
|
|
4380
|
+
const stopTool = {
|
|
4381
|
+
name: DIY_DEBUG_STOP_TOOL,
|
|
4382
|
+
description: "结束调试(不审批):清掉\"占用用户那一屏\"这件事。收工用它。",
|
|
4383
|
+
parameters: EMPTY,
|
|
4384
|
+
output: OUTPUT$2,
|
|
4385
|
+
async execute(_raw, exec) {
|
|
4386
|
+
const { packagesDir } = workshopOf(ctx, exec);
|
|
4387
|
+
const held = store.live(Date.now());
|
|
4388
|
+
const state = moveOrThrow(store.stop(sessionIdOf(exec) ?? "", Date.now()), held);
|
|
4389
|
+
return plainJson({
|
|
4390
|
+
workshop: packagesDir,
|
|
4391
|
+
unit: state.unit,
|
|
4392
|
+
phase: "idle",
|
|
4393
|
+
text: renderDebugStop(state)
|
|
4394
|
+
});
|
|
4395
|
+
}
|
|
4396
|
+
};
|
|
4397
|
+
return [
|
|
4398
|
+
tools.register(startTool),
|
|
4399
|
+
tools.register(pauseTool),
|
|
4400
|
+
tools.register(resumeTool),
|
|
4401
|
+
tools.register(stopTool)
|
|
4402
|
+
];
|
|
4403
|
+
}
|
|
4404
|
+
//#endregion
|
|
4067
4405
|
//#region src/modules/panels/model/diy-browser-act.ts
|
|
4068
4406
|
var ACT_TIMEOUT_MS = 15e3;
|
|
4069
4407
|
function actTargetOf(raw) {
|
|
@@ -4321,16 +4659,20 @@ function registerLookTools(ctx, tools) {
|
|
|
4321
4659
|
},
|
|
4322
4660
|
output: OUTPUT$2,
|
|
4323
4661
|
async execute(raw, exec) {
|
|
4324
|
-
const { packagesDir, unit, shell, command, session } = await pageAt(ctx, exec, raw);
|
|
4662
|
+
const { packagesDir, unit, shell, command, session, board } = await pageAt(ctx, exec, raw);
|
|
4325
4663
|
const pick = pickOf(asRecord$3(raw));
|
|
4326
4664
|
let view = await measureCard(shell, command, session, unit, pick);
|
|
4327
|
-
if (!view.ok)
|
|
4328
|
-
|
|
4329
|
-
|
|
4330
|
-
|
|
4331
|
-
|
|
4332
|
-
|
|
4333
|
-
|
|
4665
|
+
if (!view.ok || !view.visible) {
|
|
4666
|
+
const state = view.ok ? "hidden" : board;
|
|
4667
|
+
return plainJson({
|
|
4668
|
+
workshop: packagesDir,
|
|
4669
|
+
unit,
|
|
4670
|
+
ok: false,
|
|
4671
|
+
board: state,
|
|
4672
|
+
cards: view.cards,
|
|
4673
|
+
text: renderMissingCard(unit, view, state)
|
|
4674
|
+
});
|
|
4675
|
+
}
|
|
4334
4676
|
if (!insideViewportOf(view)) {
|
|
4335
4677
|
await scrollIntoView(shell, command, session, unit, "");
|
|
4336
4678
|
view = await measureCard(shell, command, session, unit, pick);
|
|
@@ -4431,9 +4773,12 @@ function renderLook(unit, view, shot, pick) {
|
|
|
4431
4773
|
...view.clipped ? ["有内容被裁掉了(某一格比它自己的宽度还宽)—— 这是要改的信号"] : []
|
|
4432
4774
|
].join("\n");
|
|
4433
4775
|
}
|
|
4434
|
-
function renderMissingCard(unit,
|
|
4435
|
-
if (
|
|
4436
|
-
|
|
4776
|
+
function renderMissingCard(unit, view, board) {
|
|
4777
|
+
if (board === "other") return `你现在这一页画的是别的工作区的面板,工坊那块板没在这一屏 —— ${unit} 的卡不在屏上,我不拿别的板当目标。请用户在左栏切回「工作台DIY」,或把这张卡上到他正看着的那块板上。`;
|
|
4778
|
+
if (board === "hidden") return `右栏收着 —— 面板没画在屏上(锚点还在页面里,但看不见它),量不到也不该拍 ${unit}。让用户把面板展开、或切回「工作台DIY」,我再接着看。`;
|
|
4779
|
+
if (view.anchored) return `面板里给 ${unit} 留了位置(锚点在),但里面没有卡片 —— 它的 View 没画出来:要么渲染时抛了(看 workbench_diy_panel 的运行态上报与 workbench_diy_status),要么它返回了空 / 没套卡壳。你现在这一页面板里一共 ${String(view.cards)} 张卡。`;
|
|
4780
|
+
const stale = board === "unknown" ? "③ 页面上跑的外壳可能还是旧的一份(锚点由外壳盖)—— 让用户刷新一次页面。" : "";
|
|
4781
|
+
return `你现在这一页的面板里没有 ${unit} 这张卡(面板里现在有 ${String(view.cards)} 张卡)。按顺序试:① workbench_diy_show(unit=${unit})把它上板;② 右栏可能没停在「工作台面板」那一列 —— 让用户切回来。${stale}`;
|
|
4437
4782
|
}
|
|
4438
4783
|
//#endregion
|
|
4439
4784
|
//#region src/modules/panels/model/diy-logs.ts
|
|
@@ -5483,7 +5828,7 @@ function renderList(packagesDir, modules) {
|
|
|
5483
5828
|
}
|
|
5484
5829
|
//#endregion
|
|
5485
5830
|
//#region src/modules/panels/model/diy-tools.ts
|
|
5486
|
-
function registerDiyTools(ctx, market, panels) {
|
|
5831
|
+
function registerDiyTools(ctx, market, panels, debug) {
|
|
5487
5832
|
const tools = ctx.get("tools");
|
|
5488
5833
|
if (tools === void 0) {
|
|
5489
5834
|
ctx.logger?.info?.("[dsh-workbench] 没有 tools 服务,跳过 DIY 工坊工具注册");
|
|
@@ -5831,11 +6176,20 @@ function registerDiyTools(ctx, market, panels) {
|
|
|
5831
6176
|
...registerLogTools(ctx, tools),
|
|
5832
6177
|
...registerNetTools(ctx, tools),
|
|
5833
6178
|
...registerActTools(ctx, tools),
|
|
6179
|
+
...registerDebugTools(ctx, tools, debug),
|
|
5834
6180
|
tools.register(showTool),
|
|
5835
6181
|
tools.register(installTool)
|
|
5836
6182
|
];
|
|
5837
6183
|
}
|
|
5838
6184
|
//#endregion
|
|
6185
|
+
//#region src/modules/panels/model/diy-debug-routes.ts
|
|
6186
|
+
function diyDebugRoutes(store) {
|
|
6187
|
+
return { "panels/diy-debug": () => ({
|
|
6188
|
+
ok: true,
|
|
6189
|
+
state: store.live(Date.now())
|
|
6190
|
+
}) };
|
|
6191
|
+
}
|
|
6192
|
+
//#endregion
|
|
5839
6193
|
//#region src/shared/api/host/release.ts
|
|
5840
6194
|
function parseLedgerVersion(stdout, name) {
|
|
5841
6195
|
const parsed = parseJsonLoose(stdout);
|
|
@@ -7869,7 +8223,14 @@ function applyPanelsPref(panels, payload) {
|
|
|
7869
8223
|
//#endregion
|
|
7870
8224
|
//#region src/modules/panels/model/handoff.ts
|
|
7871
8225
|
var PANELS_FACT = "panels";
|
|
8226
|
+
var DIY_DEBUG_FACT = "diy-debug";
|
|
7872
8227
|
var CAPABILITY_FACT = "capability";
|
|
8228
|
+
var DEBUG_TOOLS = [
|
|
8229
|
+
DIY_DEBUG_START_TOOL,
|
|
8230
|
+
DIY_DEBUG_PAUSE_TOOL,
|
|
8231
|
+
DIY_DEBUG_RESUME_TOOL,
|
|
8232
|
+
DIY_DEBUG_STOP_TOOL
|
|
8233
|
+
];
|
|
7873
8234
|
var PROVISION_TOOLS = {
|
|
7874
8235
|
[MODULES_INSTALL_TOOL]: "install",
|
|
7875
8236
|
[MODULES_UPDATE_TOOL]: "update",
|
|
@@ -7905,6 +8266,7 @@ function panelsFactsOf(call, manifests) {
|
|
|
7905
8266
|
if (call.source === "workbench_modules_list") return [PANELS_FACT, CAPABILITY_FACT];
|
|
7906
8267
|
if (call.source === "workbench_modules_update_workbench") return [PANELS_FACT, CAPABILITY_FACT];
|
|
7907
8268
|
if (call.source === "workbench_diy_list") return [PANELS_FACT];
|
|
8269
|
+
if (DEBUG_TOOLS.includes(call.source)) return [DIY_DEBUG_FACT];
|
|
7908
8270
|
const request = requestOf(call);
|
|
7909
8271
|
if (request === void 0) return void 0;
|
|
7910
8272
|
return [
|
|
@@ -8479,6 +8841,8 @@ var OWNED = [{
|
|
|
8479
8841
|
logger
|
|
8480
8842
|
});
|
|
8481
8843
|
ctx.provide(PANELS_SERVICE, panels);
|
|
8844
|
+
const debug = createDebugStore();
|
|
8845
|
+
ctx.provide(DIY_DEBUG_SERVICE, debug);
|
|
8482
8846
|
const profileDir = profileDirOf(ctx);
|
|
8483
8847
|
const shell = ctx.get("shell");
|
|
8484
8848
|
const moduleManifests = () => {
|
|
@@ -8526,12 +8890,13 @@ var OWNED = [{
|
|
|
8526
8890
|
...pluginRoutes({
|
|
8527
8891
|
ledger,
|
|
8528
8892
|
...shell === void 0 ? {} : { shell }
|
|
8529
|
-
})
|
|
8893
|
+
}),
|
|
8894
|
+
...diyDebugRoutes(debug)
|
|
8530
8895
|
},
|
|
8531
8896
|
registerTools: () => [
|
|
8532
8897
|
...registerPanelTools(ctx, panels, values),
|
|
8533
8898
|
...registerMarketTools(ctx, market),
|
|
8534
|
-
...registerDiyTools(ctx, market, panels)
|
|
8899
|
+
...registerDiyTools(ctx, market, panels, debug)
|
|
8535
8900
|
],
|
|
8536
8901
|
factsOf: (call) => panelsFactsOf(call, manifests()),
|
|
8537
8902
|
needsApproval: panelsApproval,
|
|
@@ -8542,7 +8907,7 @@ var OWNED = [{
|
|
|
8542
8907
|
return [...manifests().flatMap((manifest) => owned.has(manifest.id) || resolveScope({
|
|
8543
8908
|
id: manifest.id,
|
|
8544
8909
|
boards
|
|
8545
|
-
}) ? [] : manifest.tools.map((tool) => tool.name)), ...inWorkshopSession(ctx, workspace) ? [] : [...DIY_TOOLS]];
|
|
8910
|
+
}) ? [] : manifest.tools.map((tool) => tool.name)), ...inWorkshopSession(ctx, workspace) ? [] : [...DIY_TOOLS, ...DIY_DEBUG_TOOLS]];
|
|
8546
8911
|
},
|
|
8547
8912
|
subscribe: (listener) => panels.subscribe(listener)
|
|
8548
8913
|
},
|