weir-harness 2.0.0 → 2.1.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.
- package/lib/client.capability-badge.js +2 -0
- package/lib/client.capability-manager.js +46 -179
- package/lib/client.capability-model.js +428 -3
- package/lib/client.file-lease-tool-model.js +189 -0
- package/lib/client.file-lease-tool-view.js +434 -0
- package/lib/client.js +105 -7
- package/lib/client.mcp-manager.js +563 -0
- package/package.json +1 -1
- package/skills/mcp-server-setup/SKILL.md +124 -0
- package/src/capabilities/apply-engine.js +18 -4
- package/src/capabilities/capability-remote.js +296 -45
- package/src/capabilities/initial-selection.js +3 -2
- package/src/capabilities/lifecycle-preload.js +69 -11
- package/src/capabilities/lifecycle-snapshot.js +127 -39
- package/src/capabilities/mcp-admission.js +2 -2
- package/src/capabilities/mcp-config.js +344 -0
- package/src/capabilities/mcp-credentials.js +180 -0
- package/src/capabilities/mcp-diagnostics.js +169 -0
- package/src/capabilities/mcp-drain.js +18 -4
- package/src/capabilities/mcp-facade.js +3 -3
- package/src/capabilities/mcp-gate.js +51 -52
- package/src/capabilities/mcp-install-tool.js +276 -0
- package/src/capabilities/mcp-manager.js +368 -142
- package/src/capabilities/mcp-mount.js +219 -79
- package/src/capabilities/mcp-operations.js +359 -0
- package/src/capabilities/mcp-process.js +43 -0
- package/src/capabilities/mcp-registry.js +74 -60
- package/src/capabilities/mcp-runtime.js +103 -0
- package/src/capabilities/read-payloads.js +8 -3
- package/src/capabilities/skill-applicability.js +185 -0
- package/src/capabilities/skill-builtin-migration.js +2 -1
- package/src/capabilities/skill-selection-plugin.js +161 -56
- package/src/file-lease/client.js +268 -35
- package/src/file-lease/index.js +4 -0
- package/src/file-lease/plugin.js +239 -15
- package/src/file-lease/tools.js +426 -38
- package/src/file-lease/watch.js +473 -0
- package/src/intent-gate/index.js +29 -12
- package/src/intent-gate/matcher.js +36 -2
- package/src/lease-broker/protocol.js +3 -2
- package/src/lease-broker/server.js +6 -3
- package/src/lease-broker/state.js +68 -11
- package/src/process/index.js +4 -2
- package/src/shared/audit.js +3 -0
- package/src/shared/child-scope.js +2 -0
- package/src/worktree/rules.js +1 -1
package/lib/client.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Weir client chunks: {"client.blackboard-model.js":"2e5abdd44edb599d10d9d547fa07133e84250d6007161c2c8704b58151896f93","client.blackboard-panel.js":"c9d6a0f02623075fc884f3519f982574ad33ad871f7bcd7e8c36f12512f0de39","client.capability-badge.js":"
|
|
1
|
+
// Weir client chunks: {"client.blackboard-model.js":"2e5abdd44edb599d10d9d547fa07133e84250d6007161c2c8704b58151896f93","client.blackboard-panel.js":"c9d6a0f02623075fc884f3519f982574ad33ad871f7bcd7e8c36f12512f0de39","client.capability-badge.js":"f5c5d21293360d00815446beb8455794a1778ae033e270af37e436329ac09185","client.capability-manager.js":"f02e08174487f2f70e90a5c50a4a44cbeb4d462f115a2d2ab8a52ed8b4e70aee","client.capability-model.js":"57127dc5ea7ca6aa70c619480684f4de84fcbff4922f70df9886f55fad66abbf","client.capability-presets.js":"12ac8da3568d013abd76b67cfe473a329f4af2feaac9cd55a82d8881e5bc1017","client.chain-editor.js":"1e9a33bc68cabc43bc27b91ef83eab5028a33256596c147e15722d684687765b","client.chain-model.js":"2e885922cf8c2972725c6eef8bf20c7d1202d961edfb8ad41574dac062d74371","client.disabled-categories-editor.js":"f9103fd2e2691eda9afd199e1a5462189097a9f3dee0518be5fa3587d896e033","client.file-lease-badge.js":"cd30546307c91c94fe05484557e46f58c53fe55657f62b0a0415a072dfb3b582","client.file-lease-tool-model.js":"f72d87b049454ec489b4dffac1f32dabc273947b8a4c55fe07c91ddf320bd899","client.file-lease-tool-view.js":"7004caa06b36d8497a1d2e448b6ce5e4c8efd22ad903d8b39e26220de64bb1fe","client.hash-edit-model.js":"71727d47a6ef32ebd2abfb063fa93499a5e607d6716e3ec8983ae056c4fb317f","client.hash-edit-view.js":"fc0f4dabddab9a48527553ad4232b3715e46e6863aab75e02ae2dcd6687265c2","client.lsp-model.js":"30943ed1ed11c1f2770a724da855ea2417c11566c2778c79e17cfc2de499cd80","client.lsp-panel.js":"61629a4d317dae9ed01c1cc0355632fb752788dc23f7606257188050734cd030","client.lsp-toggle.js":"d6af81be5e5b854e98563bbb9349a6db89834a9d7dee9cf0e97759ecb32090e8","client.mcp-manager.js":"cfcd4792251fcca8bfa6a2c35b80881ab6f6480cf2ebce24a8ce304cddf940a7","client.model-picker.js":"57f96826e00b37ae6d6474a6750f31b4e128e5fdb37e302875a41cdb2e18f14a","client.notify-permissions.js":"2be9bdbeffef96baa3cbe4ce430ab30a1d1bf797782453d287d54602ea47db8e","client.notify-web.js":"0943f67d5526ff0fb7cb4f69580e0a9ea54ed06465c513afc51a5a7fb1c55ccf","client.robash-editor.js":"cd6a283b72cb02598e32ca4ce03a1b8de5f328ecdd1f5f920377524f3bdcbe1c","client.robash-model.js":"f4395338a773e8bb48e4f96aeb737cd634edcca0b90af992a7dbbe47be42e451","client.settings-page.js":"f3c04a5b33cdb963357bc653f7050e598f19efc4cc833694379a4ba055e949d3","client.worktree-model.js":"8bfbaaa080f20e90a0128afccb9b4e232514615a8f2fee3a32a42dde78b34a8f","client.worktree-view.js":"356c3f5f683b8509ae8679243a6460ca02957fd15e057a629b2ac4fdd12ed057"}
|
|
2
2
|
window.__ModuleLoader__.load({
|
|
3
3
|
id: "weir-harness",
|
|
4
4
|
factory: (require) => {
|
|
@@ -49,6 +49,17 @@ window.__ModuleLoader__.load({
|
|
|
49
49
|
worktreeLoading: "Loading lanes…",
|
|
50
50
|
hashEditInput: "Input",
|
|
51
51
|
hashEditOutput: "Output",
|
|
52
|
+
// Edit-lock conversation cards: the seven tool titles the pre-arrival
|
|
53
|
+
// placeholder reads synchronously. Byte-identical to the view chunk's
|
|
54
|
+
// data face ("settings.weir.file-lease-tools") — a documented
|
|
55
|
+
// cross-namespace duplicate pinned by test/client.test.js.
|
|
56
|
+
leaseToolTitle_edit_lock_acquire: "Claim edit lock",
|
|
57
|
+
leaseToolTitle_edit_lock_release: "Release edit lock",
|
|
58
|
+
leaseToolTitle_edit_lock_hold: "Keep edit lock",
|
|
59
|
+
leaseToolTitle_edit_lock_status: "Edit lock status",
|
|
60
|
+
leaseToolTitle_edit_lock_try_steal: "Request edit lock transfer",
|
|
61
|
+
leaseToolTitle_edit_lock_reply: "Answer transfer request",
|
|
62
|
+
leaseToolTitle_edit_lock_watch: "Watch for release",
|
|
52
63
|
// Session capability Badge + manager (12.x, D3/D4): the chunks carry
|
|
53
64
|
// the same strings as in-code fallbacks; these rows translate them.
|
|
54
65
|
capabilityTabLabel: "Capabilities",
|
|
@@ -84,6 +95,13 @@ window.__ModuleLoader__.load({
|
|
|
84
95
|
worktreeLoading: "正在加载车道…",
|
|
85
96
|
hashEditInput: "输入",
|
|
86
97
|
hashEditOutput: "输出",
|
|
98
|
+
leaseToolTitle_edit_lock_acquire: "申请编辑锁",
|
|
99
|
+
leaseToolTitle_edit_lock_release: "释放编辑锁",
|
|
100
|
+
leaseToolTitle_edit_lock_hold: "保留编辑锁",
|
|
101
|
+
leaseToolTitle_edit_lock_status: "编辑锁状态",
|
|
102
|
+
leaseToolTitle_edit_lock_try_steal: "请求转交编辑锁",
|
|
103
|
+
leaseToolTitle_edit_lock_reply: "答复转交请求",
|
|
104
|
+
leaseToolTitle_edit_lock_watch: "订阅释放",
|
|
87
105
|
capabilityTabLabel: "能力",
|
|
88
106
|
capabilityGuideTitle: "能力",
|
|
89
107
|
capabilityGuideDescription: "此会话的技能、MCP server 与预设。",
|
|
@@ -123,6 +141,7 @@ window.__ModuleLoader__.load({
|
|
|
123
141
|
lspToggle: null,
|
|
124
142
|
hashEdit: null,
|
|
125
143
|
fileLease: null,
|
|
144
|
+
fileLeaseTools: null,
|
|
126
145
|
worktree: null,
|
|
127
146
|
};
|
|
128
147
|
// ---- Package-local chunk wiring (composition root) ----
|
|
@@ -228,6 +247,59 @@ window.__ModuleLoader__.load({
|
|
|
228
247
|
if (!arrival?.chunks) return null;
|
|
229
248
|
return react_jsx_runtime.jsx(arrival.chunks.FileLeaseBadge, { ...props, t: chunkDictionaries.fileLease ?? props.t });
|
|
230
249
|
}
|
|
250
|
+
// ---- Edit-lock conversation cards (edit-lock-tool-cards D2) ----
|
|
251
|
+
// One view chunk plus one model chunk carry the seven keyed tool cards;
|
|
252
|
+
// the dictionaries ride the view chunk and register under their own
|
|
253
|
+
// namespace (the composer badge already owns "settings.weir.file-lease",
|
|
254
|
+
// and a namespace registers once per apply).
|
|
255
|
+
const FILE_LEASE_TOOL_NAMES = ["edit_lock_acquire", "edit_lock_release", "edit_lock_hold", "edit_lock_status", "edit_lock_try_steal", "edit_lock_reply", "edit_lock_watch"];
|
|
256
|
+
const loadFileLeaseToolChunks = lazyChunks(() => Promise.all([
|
|
257
|
+
require.async("./client.file-lease-tool-view.js"),
|
|
258
|
+
require.async("./client.file-lease-tool-model.js")
|
|
259
|
+
]).then((chunks) => {
|
|
260
|
+
chunkDictionaries.register?.("settings.weir.file-lease-tools", chunks[0].dictionaries);
|
|
261
|
+
return chunks;
|
|
262
|
+
}));
|
|
263
|
+
// Pre-arrival (or failed-load) placeholder: the localized title and the
|
|
264
|
+
// requested paths from the call arguments, so a card is never blank. The
|
|
265
|
+
// argument read mirrors the model chunk's argsPaths (same-package sync
|
|
266
|
+
// require is impossible, so the tiny parse is mirrored here, not shared).
|
|
267
|
+
const fileLeasePlaceholderStyle = { display: "flex", alignItems: "baseline", gap: "8px", minWidth: 0, padding: "8px 10px", border: "1px solid var(--dsw-alias-border-l2)", borderRadius: "var(--dsw-radius-md, 8px)", background: "var(--dsw-alias-bg-layer-1)" };
|
|
268
|
+
const fileLeasePlaceholderTitleStyle = { fontSize: "13px", lineHeight: "18px", fontWeight: 600, color: "var(--dsw-alias-label-primary)", whiteSpace: "nowrap" };
|
|
269
|
+
const fileLeasePlaceholderPathStyle = { fontSize: "12px", lineHeight: "16px", color: "var(--dsw-alias-label-secondary)", fontFamily: "var(--dsw-font-markdown-code-block-font-family, ui-monospace, monospace)", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", minWidth: 0 };
|
|
270
|
+
const fileLeaseArgsPaths = (block) => {
|
|
271
|
+
const raw = typeof block?.argsRaw === "string" ? block.argsRaw : typeof block?.call?.argsRaw === "string" ? block.call.argsRaw : null;
|
|
272
|
+
if (raw === null) return [];
|
|
273
|
+
let args;
|
|
274
|
+
try {
|
|
275
|
+
args = JSON.parse(raw);
|
|
276
|
+
} catch {
|
|
277
|
+
return [];
|
|
278
|
+
}
|
|
279
|
+
if (Array.isArray(args?.paths)) return args.paths.filter((path) => typeof path === "string" && path !== "");
|
|
280
|
+
return typeof args?.file_path === "string" && args.file_path !== "" ? [args.file_path] : [];
|
|
281
|
+
};
|
|
282
|
+
function FileLeaseToolPlaceholder(props) {
|
|
283
|
+
const paths = fileLeaseArgsPaths(props.block);
|
|
284
|
+
const title = typeof props.t === "function" ? props.t(`leaseToolTitle_${props.toolName}`) : props.toolName;
|
|
285
|
+
return react_jsx_runtime.jsxs("div", { "data-tool": props.toolName, "data-weir-lease-placeholder": "", style: fileLeasePlaceholderStyle, children: [
|
|
286
|
+
react_jsx_runtime.jsx("span", { style: fileLeasePlaceholderTitleStyle, children: title }, "title"),
|
|
287
|
+
paths.length > 0 ? react_jsx_runtime.jsx("span", { style: fileLeasePlaceholderPathStyle, children: paths.length > 1 ? `${paths[0]} +${paths.length - 1}` : paths[0] }, "path") : null
|
|
288
|
+
] });
|
|
289
|
+
}
|
|
290
|
+
/** Keyed toolview wrapper for one edit_lock_* tool: the placeholder until
|
|
291
|
+
* the view+model chunks arrive, then the read-only card. */
|
|
292
|
+
const fileLeaseToolView = (toolName) => {
|
|
293
|
+
function FileLeaseToolViewWrapper(props) {
|
|
294
|
+
const arrival = useChunkArrival(loadFileLeaseToolChunks);
|
|
295
|
+
if (arrival?.chunks) {
|
|
296
|
+
const [view, model] = arrival.chunks;
|
|
297
|
+
return react_jsx_runtime.jsx(view.FileLeaseToolRow, { ...props, toolName, t: chunkDictionaries.fileLeaseTools ?? props.t, model });
|
|
298
|
+
}
|
|
299
|
+
return react_jsx_runtime.jsx(FileLeaseToolPlaceholder, { ...props, toolName });
|
|
300
|
+
}
|
|
301
|
+
return FileLeaseToolViewWrapper;
|
|
302
|
+
};
|
|
231
303
|
// ---- Tab glyphs (ui-entries-and-icons) ----
|
|
232
304
|
// Three 16x16 stroke glyphs drawn in currentColor, matching the host
|
|
233
305
|
// CompassGlyph/CubeGlyph style (no strokeWidth, rounded caps/joins).
|
|
@@ -428,6 +500,7 @@ window.__ModuleLoader__.load({
|
|
|
428
500
|
chunkDictionaries.lspToggle = ctx.locale.bind("settings.weir.lsp-toggle");
|
|
429
501
|
chunkDictionaries.hashEdit = ctx.locale.bind("settings.weir.hash-edit");
|
|
430
502
|
chunkDictionaries.fileLease = ctx.locale.bind("settings.weir.file-lease");
|
|
503
|
+
chunkDictionaries.fileLeaseTools = ctx.locale.bind("settings.weir.file-lease-tools");
|
|
431
504
|
chunkDictionaries.worktree = ctx.locale.bind("settings.weir.worktree");
|
|
432
505
|
const pageT = ctx.locale.bind("settings.weir.page");
|
|
433
506
|
const capabilityT = ctx.locale.bind("settings.weir.capability");
|
|
@@ -802,6 +875,11 @@ window.__ModuleLoader__.load({
|
|
|
802
875
|
const result = await capabilityChannel(`weirCapabilities/${method}`, { args: { sessionId: sid } });
|
|
803
876
|
return result.ok === true ? result.value : fallback;
|
|
804
877
|
};
|
|
878
|
+
const capabilityMutation = async (method, sid, request) => {
|
|
879
|
+
const result = await capabilityChannel(`weirCapabilityMutations/${method}`, { args: { sessionId: sid, request } });
|
|
880
|
+
if (result.ok === true) return result.value;
|
|
881
|
+
return { status: result.error?.code ?? "call-failed", saved: false, error: result.error ?? { code: "call-failed", message: "MCP mutation failed" } };
|
|
882
|
+
};
|
|
805
883
|
// The presets & workspace-default view is its own chunk, pulled only
|
|
806
884
|
// when the Presets view is first selected (D3) — the composition root
|
|
807
885
|
// owns every require.async specifier (no chunk-to-chunk waterfall).
|
|
@@ -829,6 +907,9 @@ window.__ModuleLoader__.load({
|
|
|
829
907
|
// (explicit error surface) — a null payload maps to the error state.
|
|
830
908
|
applySelection: (sid, draft) => capabilityPayload(sid, `/capabilities apply ${JSON.stringify(draft)}`, true),
|
|
831
909
|
mcpAdd: (sid, spec) => capabilityPayload(sid, `/capabilities mcp-add ${JSON.stringify(spec)}`),
|
|
910
|
+
mcpPreview: (sid, request) => capabilityMutation("mutate", sid, request),
|
|
911
|
+
mcpMutate: (sid, request) => capabilityMutation("mutate", sid, request),
|
|
912
|
+
mcpBatch: (sid, request) => capabilityMutation("batch", sid, request),
|
|
832
913
|
fetchListing: (sid) => capabilityRead("list", sid, { error: true }),
|
|
833
914
|
fetchConditions: (sid) => capabilityRead("conditions", sid, { error: true }),
|
|
834
915
|
// The manager forwards only its established props. Adapt the lazy view
|
|
@@ -859,14 +940,19 @@ window.__ModuleLoader__.load({
|
|
|
859
940
|
const [impl, setImpl] = react.useState(null);
|
|
860
941
|
react.useEffect(() => {
|
|
861
942
|
let alive = true;
|
|
862
|
-
Promise.all([
|
|
943
|
+
Promise.all([
|
|
944
|
+
require.async("./client.capability-badge.js"),
|
|
945
|
+
require.async("./client.capability-model.js"),
|
|
946
|
+
require.async("./client.capability-manager.js"),
|
|
947
|
+
require.async("./client.mcp-manager.js").catch(() => null),
|
|
948
|
+
]).then(([badge, model, panel, mcp]) => {
|
|
863
949
|
registerChunkDictionaries("settings.weir.capability", model.dictionaries);
|
|
864
|
-
if (alive) setImpl(() => ({ Badge: badge.CapabilityBadge, model, Panel: panel.CapabilityManagerPanel }));
|
|
950
|
+
if (alive) setImpl(() => ({ Badge: badge.CapabilityBadge, model, Panel: panel.CapabilityManagerPanel, McpManagerView: mcp?.McpManagerView, McpManagerBoundary: mcp?.McpManagerBoundary }));
|
|
865
951
|
});
|
|
866
952
|
return () => { alive = false; };
|
|
867
953
|
}, [props.sessionId]);
|
|
868
954
|
if (!impl) return null;
|
|
869
|
-
return react_jsx_runtime.jsx(impl.Badge, { ...props, t: capabilityT, model: impl.model, ManagerPanel: impl.Panel });
|
|
955
|
+
return react_jsx_runtime.jsx(impl.Badge, { ...props, t: capabilityT, model: impl.model, ManagerPanel: impl.Panel, McpManagerView: impl.McpManagerView, McpManagerBoundary: impl.McpManagerBoundary });
|
|
870
956
|
};
|
|
871
957
|
ctx.effect(() => ctx.slots.inject("conversation.input.right", () => ctx.slots.register({
|
|
872
958
|
name: "conversation.input.right",
|
|
@@ -895,7 +981,8 @@ window.__ModuleLoader__.load({
|
|
|
895
981
|
// view tree.
|
|
896
982
|
const loadCapabilityPanelChunks = lazyChunks(() => Promise.all([
|
|
897
983
|
require.async("./client.capability-model.js"),
|
|
898
|
-
require.async("./client.capability-manager.js")
|
|
984
|
+
require.async("./client.capability-manager.js"),
|
|
985
|
+
require.async("./client.mcp-manager.js").catch(() => null),
|
|
899
986
|
]).then((chunks) => {
|
|
900
987
|
registerChunkDictionaries("settings.weir.capability", chunks[0].dictionaries);
|
|
901
988
|
return chunks;
|
|
@@ -903,10 +990,10 @@ window.__ModuleLoader__.load({
|
|
|
903
990
|
function CapabilityPanelWrapper(props) {
|
|
904
991
|
const arrival = useChunkArrival(loadCapabilityPanelChunks, typeof props.sessionId === "string" && props.sessionId !== "");
|
|
905
992
|
if (!arrival?.chunks) return react_jsx_runtime.jsx("div", { style: settingsLoadingStyle, children: typeof props.t === "function" ? props.t("capability.loading") : "" });
|
|
906
|
-
const [model, panel] = arrival.chunks;
|
|
993
|
+
const [model, panel, mcp] = arrival.chunks;
|
|
907
994
|
// The same view tree the composer popover renders — the sidebar is
|
|
908
995
|
// just the outer frame (D1). No onClose: the pane chrome owns closing.
|
|
909
|
-
return react_jsx_runtime.jsx(panel.CapabilityManagerPanel, { ...props, t: capabilityT, model, shell: "sidebar" });
|
|
996
|
+
return react_jsx_runtime.jsx(panel.CapabilityManagerPanel, { ...props, t: capabilityT, model, shell: "sidebar", McpManagerView: mcp?.McpManagerView, McpManagerBoundary: mcp?.McpManagerBoundary });
|
|
910
997
|
}
|
|
911
998
|
ctx.inject?.(["sidebarRightTabs"], (sidebarScope) => {
|
|
912
999
|
capabilitySidebarTab = true;
|
|
@@ -1005,6 +1092,17 @@ window.__ModuleLoader__.load({
|
|
|
1005
1092
|
}
|
|
1006
1093
|
} : {})
|
|
1007
1094
|
}, BlackboardPill)), "ui-weir-settings: blackboard header pill");
|
|
1095
|
+
// Edit-lock conversation cards (edit-lock-tool-cards D2): one keyed,
|
|
1096
|
+
// read-only tool view per edit_lock_* tool, each in its own effect so
|
|
1097
|
+
// one registration failure cannot take down the others. Registration
|
|
1098
|
+
// pulls no chunk; the wrapper renders a title+paths placeholder first.
|
|
1099
|
+
for (const toolName of FILE_LEASE_TOOL_NAMES) {
|
|
1100
|
+
ctx.effect(() => ctx.slots.inject("tool.call.toolview", () => ctx.slots.register({
|
|
1101
|
+
name: "tool.call.toolview",
|
|
1102
|
+
key: toolName,
|
|
1103
|
+
locale: NS
|
|
1104
|
+
}, fileLeaseToolView(toolName))), `ui-weir-settings: ${toolName} toolview`);
|
|
1105
|
+
}
|
|
1008
1106
|
// Top-level Settings section (same place as dsh-web-kimi and the
|
|
1009
1107
|
// built-in General/Models sections), with a nested item slot
|
|
1010
1108
|
// hosting the form — the single Weir settings entry.
|