weir-harness 1.2.3 → 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/cordis.patch.yml +7 -18
- 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-badge.js +307 -0
- package/lib/client.file-lease-tool-model.js +189 -0
- package/lib/client.file-lease-tool-view.js +434 -0
- package/lib/client.js +124 -36
- package/lib/client.mcp-manager.js +563 -0
- package/lib/client.settings-page.js +10 -34
- package/package.json +2 -2
- 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/capabilities/store/checked-contract.d.ts +2 -2
- package/src/capabilities/store/fs-adapter.js +2 -3
- package/src/context-guard/index.js +2 -2
- package/src/delegate/supervision-mount.js +5 -5
- package/src/delegate/tool.js +2 -10
- package/src/file-lease/client.js +1299 -0
- package/src/file-lease/index.js +34 -0
- package/src/file-lease/lineage.js +207 -0
- package/src/file-lease/node-contracts.d.ts +42 -0
- package/src/file-lease/plugin.js +1013 -0
- package/src/file-lease/singleton.js +155 -0
- package/src/file-lease/spawn.js +62 -0
- package/src/file-lease/tools.js +847 -0
- package/src/file-lease/view.js +144 -0
- package/src/file-lease/watch.js +473 -0
- package/src/hashline-edit/index.js +76 -42
- package/src/hashline-edit/write-tool.js +90 -0
- package/src/intent-gate/index.js +29 -12
- package/src/intent-gate/matcher.js +36 -2
- package/src/lease-broker/entry.js +98 -0
- package/src/lease-broker/node-contracts.d.ts +63 -0
- package/src/lease-broker/protocol.js +237 -0
- package/src/lease-broker/server.js +402 -0
- package/src/lease-broker/state.js +482 -0
- package/src/lsp/tools.js +137 -27
- package/src/process/index.js +4 -2
- package/src/settings/index.js +2 -44
- package/src/settings/sections.js +2 -24
- package/src/shared/audit.js +9 -1
- package/src/shared/child-scope.js +2 -0
- package/src/todo-driver/index.js +1 -6
- package/src/worktree/cards.js +6 -21
- package/src/worktree/lane-core.js +1 -19
- package/src/worktree/lane-workflows.js +11 -32
- package/src/worktree/rules.js +1 -1
- package/lib/client.edit-lock-maintenance.js +0 -592
- package/lib/client.edit-lock-panel.js +0 -405
- package/src/edit-lock/adapter.js +0 -57
- package/src/edit-lock/admin-ledger.js +0 -149
- package/src/edit-lock/admin-recovery.js +0 -151
- package/src/edit-lock/admission.js +0 -82
- package/src/edit-lock/binding-attestation.js +0 -29
- package/src/edit-lock/binding-guidance.js +0 -72
- package/src/edit-lock/binding-machine.js +0 -312
- package/src/edit-lock/call-context.js +0 -65
- package/src/edit-lock/derived-facts.js +0 -67
- package/src/edit-lock/domain.js +0 -165
- package/src/edit-lock/domains.js +0 -170
- package/src/edit-lock/host.js +0 -149
- package/src/edit-lock/incarnations.js +0 -150
- package/src/edit-lock/index.js +0 -1303
- package/src/edit-lock/inspect.js +0 -219
- package/src/edit-lock/lifecycle.js +0 -579
- package/src/edit-lock/limits.js +0 -61
- package/src/edit-lock/maintenance.js +0 -310
- package/src/edit-lock/manager.js +0 -875
- package/src/edit-lock/negotiation.js +0 -132
- package/src/edit-lock/operation-history.js +0 -214
- package/src/edit-lock/peer-client.js +0 -86
- package/src/edit-lock/peer-transport.js +0 -76
- package/src/edit-lock/peer.js +0 -87
- package/src/edit-lock/publisher.js +0 -191
- package/src/edit-lock/read-authority.js +0 -101
- package/src/edit-lock/recovery.js +0 -139
- package/src/edit-lock/remote.js +0 -362
- package/src/edit-lock/request-binding.js +0 -42
- package/src/edit-lock/request-data.js +0 -40
- package/src/edit-lock/reservation.js +0 -301
- package/src/edit-lock/reserved-runtime.js +0 -45
- package/src/edit-lock/resource-identity.js +0 -130
- package/src/edit-lock/runtime.js +0 -145
- package/src/edit-lock/settle.js +0 -144
- package/src/edit-lock/snapshot.js +0 -175
- package/src/edit-lock/stale-sweep.js +0 -120
- package/src/edit-lock/state.js +0 -462
- package/src/edit-lock/store.js +0 -327
- package/src/edit-lock/tool-scope.js +0 -29
- package/src/edit-lock/view.js +0 -170
- package/src/edit-lock/write-scopes.js +0 -48
- package/src/edit-lock/write-tool.js +0 -45
- package/src/shared/delegate-edit-lifecycle.js +0 -36
- package/src/worktree/authority.js +0 -56
|
@@ -0,0 +1,434 @@
|
|
|
1
|
+
window.__ModuleLoader__.load({
|
|
2
|
+
id: "weir-harness",
|
|
3
|
+
chunk: "client.file-lease-tool-view.js",
|
|
4
|
+
factory: (require) => {
|
|
5
|
+
var module = { exports: {} };
|
|
6
|
+
var exports = module.exports;
|
|
7
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
8
|
+
let react = require("react");
|
|
9
|
+
let react_jsx_runtime = require("react/jsx-runtime");
|
|
10
|
+
const jsx = react_jsx_runtime.jsx;
|
|
11
|
+
const jsxs = react_jsx_runtime.jsxs;
|
|
12
|
+
// Edit-lock conversation cards (openspec edit-lock-tool-cards, design D3).
|
|
13
|
+
// One read-only card per edit_lock_* call: a collapsed row (lock glyph,
|
|
14
|
+
// localized title, primary path, state badge) and an expandable body with
|
|
15
|
+
// the outcome's details. The ONLY control is the row's disclosure button:
|
|
16
|
+
// no verb, no command, no notice, nothing that writes to the conversation.
|
|
17
|
+
// Every visible string comes from the GUI-language dictionaries below;
|
|
18
|
+
// the model's English result text is only the row's hover title (and the
|
|
19
|
+
// raw text of a call that has no structured outcome). A card is the
|
|
20
|
+
// snapshot of its call — it never polls and never claims current
|
|
21
|
+
// ownership. The model helpers arrive through props.model (the entry
|
|
22
|
+
// composes lib/client.file-lease-tool-model.js); errors never throw out.
|
|
23
|
+
const MONO = "var(--dsw-font-markdown-code-block-font-family, ui-monospace, monospace)";
|
|
24
|
+
const TONES = {
|
|
25
|
+
success: "var(--dsw-alias-state-success-primary, #2f855a)",
|
|
26
|
+
wait: "var(--dsw-alias-state-business-primary)",
|
|
27
|
+
danger: "var(--dsw-alias-state-error-primary)",
|
|
28
|
+
warn: "var(--dsw-alias-state-warn-primary)",
|
|
29
|
+
neutral: "var(--dsw-alias-label-tertiary)"
|
|
30
|
+
};
|
|
31
|
+
const toneColor = (tone) => TONES[tone] ?? TONES.neutral;
|
|
32
|
+
const tint = (color, percent) => `color-mix(in srgb, ${color} ${percent}%, transparent)`;
|
|
33
|
+
const mono = { fontFamily: MONO, overflowWrap: "anywhere", wordBreak: "break-word" };
|
|
34
|
+
const text = {
|
|
35
|
+
title: { fontSize: "13px", lineHeight: "18px", fontWeight: 600, color: "var(--dsw-alias-label-primary)" },
|
|
36
|
+
body: { fontSize: "12px", lineHeight: "16px", color: "var(--dsw-alias-label-secondary)", overflowWrap: "anywhere" },
|
|
37
|
+
foot: { fontSize: "11px", lineHeight: "15px", color: "var(--dsw-alias-label-tertiary)", overflowWrap: "anywhere" }
|
|
38
|
+
};
|
|
39
|
+
const cardStyle = {
|
|
40
|
+
background: "var(--dsw-alias-bg-layer-1)", border: "1px solid var(--dsw-alias-border-l2)",
|
|
41
|
+
borderRadius: "var(--dsw-radius-md, 8px)", padding: "8px 10px",
|
|
42
|
+
minWidth: 0, maxWidth: "100%", overflow: "hidden"
|
|
43
|
+
};
|
|
44
|
+
const rowButtonStyle = {
|
|
45
|
+
display: "flex", alignItems: "center", gap: "8px", width: "100%", minWidth: 0,
|
|
46
|
+
padding: 0, margin: 0, border: "none", background: "none", cursor: "pointer",
|
|
47
|
+
textAlign: "left", font: "inherit", color: "inherit"
|
|
48
|
+
};
|
|
49
|
+
const calloutStyle = (color) => ({
|
|
50
|
+
padding: "5px 8px", fontSize: "12px", lineHeight: "16px",
|
|
51
|
+
color: "var(--dsw-alias-label-secondary)", background: tint(color, 8),
|
|
52
|
+
borderLeft: `2px solid ${color}`, borderRadius: "var(--dsw-radius-xs, 4px)",
|
|
53
|
+
overflowWrap: "anywhere"
|
|
54
|
+
});
|
|
55
|
+
const preStyle = {
|
|
56
|
+
margin: 0, padding: "6px 8px", fontFamily: MONO, fontSize: "11px", lineHeight: "16px",
|
|
57
|
+
whiteSpace: "pre-wrap", wordBreak: "break-word", overflowWrap: "anywhere", maxHeight: "240px", overflow: "auto",
|
|
58
|
+
boxSizing: "border-box", maxWidth: "100%", minWidth: 0,
|
|
59
|
+
border: "1px solid var(--dsw-alias-border-l2)", borderRadius: "var(--dsw-radius-md, 8px)",
|
|
60
|
+
background: "var(--dsw-alias-bg-base)", color: "var(--dsw-alias-label-secondary)"
|
|
61
|
+
};
|
|
62
|
+
/** `{name}` placeholders, substituted literally (no host interpolation assumed). */
|
|
63
|
+
const fill = (template, vars) => String(template).replace(/\{(\w+)\}/g, (whole, name) => (vars && Object.prototype.hasOwnProperty.call(vars, name) ? String(vars[name]) : whole));
|
|
64
|
+
/** Absolute local time of a call-time instant; ISO on hover. */
|
|
65
|
+
const timeOf = (ms) => {
|
|
66
|
+
try {
|
|
67
|
+
return new Date(ms).toLocaleString();
|
|
68
|
+
} catch {
|
|
69
|
+
return String(ms);
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
const isoOf = (ms) => {
|
|
73
|
+
try {
|
|
74
|
+
return new Date(ms).toISOString();
|
|
75
|
+
} catch {
|
|
76
|
+
return "";
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
/** 16x16 lock glyph, stroke currentColor. */
|
|
80
|
+
function LockGlyph(props) {
|
|
81
|
+
const size = props.size ?? 13;
|
|
82
|
+
return jsxs("svg", {
|
|
83
|
+
viewBox: "0 0 16 16", width: size, height: size, "aria-hidden": true,
|
|
84
|
+
fill: "none", stroke: "currentColor", strokeWidth: 1.4, strokeLinecap: "round", strokeLinejoin: "round",
|
|
85
|
+
style: { flex: "none", display: "inline-block", verticalAlign: "-2px" },
|
|
86
|
+
children: [
|
|
87
|
+
jsx("rect", { x: 3.2, y: 7, width: 9.6, height: 6.6, rx: 1.4 }, "body"),
|
|
88
|
+
jsx("path", { d: "M5.4 7V5.2a2.6 2.6 0 0 1 5.2 0V7" }, "shackle"),
|
|
89
|
+
jsx("path", { d: "M8 9.6v1.6" }, "keyhole")
|
|
90
|
+
]
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
function Chevron(props) {
|
|
94
|
+
return jsx("svg", {
|
|
95
|
+
viewBox: "0 0 16 16", width: 12, height: 12, "aria-hidden": true,
|
|
96
|
+
fill: "none", stroke: "currentColor", strokeWidth: 1.4, strokeLinecap: "round", strokeLinejoin: "round",
|
|
97
|
+
style: { flex: "none", display: "inline-block", transition: "transform 120ms ease", transform: props.open ? "rotate(90deg)" : "none" },
|
|
98
|
+
children: jsx("path", { d: "M6 3.5L10.5 8L6 12.5" })
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
/** State badge: dot + label on a soft tint of the tone colour. */
|
|
102
|
+
function Badge(props) {
|
|
103
|
+
return jsxs("span", {
|
|
104
|
+
"data-weir-lease-badge": props.state,
|
|
105
|
+
style: {
|
|
106
|
+
display: "inline-flex", alignItems: "center", gap: "5px", padding: "1px 7px",
|
|
107
|
+
fontSize: "11px", lineHeight: "16px", fontWeight: 600, color: props.color,
|
|
108
|
+
background: tint(props.color, 12), border: `1px solid ${props.color}`,
|
|
109
|
+
borderRadius: "var(--dsw-radius-sm)", flex: "none", whiteSpace: "nowrap"
|
|
110
|
+
},
|
|
111
|
+
children: [
|
|
112
|
+
jsx("span", { "aria-hidden": true, style: { display: "inline-block", width: "6px", height: "6px", borderRadius: "50%", background: props.color, flex: "none" } }, "dot"),
|
|
113
|
+
jsx("span", { children: props.label }, "label")
|
|
114
|
+
]
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
const line = (key, children, style) => jsx("div", { style: style ?? text.body, children }, key);
|
|
118
|
+
const pathChip = (path) => jsx("span", { style: { ...mono, fontSize: "11px", color: "var(--dsw-alias-label-primary)" }, children: path });
|
|
119
|
+
/** A labelled path list; each row may carry a trailing localized note. */
|
|
120
|
+
function pathList(key, label, rows) {
|
|
121
|
+
return jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "2px" }, children: [
|
|
122
|
+
label ? jsx("div", { style: text.foot, children: label }, "label") : null,
|
|
123
|
+
...rows.map((row, index) => jsxs("div", { style: { ...text.body, display: "flex", gap: "6px", flexWrap: "wrap", alignItems: "baseline" }, children: [
|
|
124
|
+
pathChip(row.path),
|
|
125
|
+
row.note ? jsx("span", { title: row.title, children: row.note }, "note") : null
|
|
126
|
+
] }, `${row.path}-${index}`))
|
|
127
|
+
] }, key);
|
|
128
|
+
}
|
|
129
|
+
const holderText = (t, holder) => (holder ? fill(t("leaseToolHolder"), { label: holder.label, session: holder.session }) : t("leaseToolHolderUnknown"));
|
|
130
|
+
/** Body rows for a call WITH a structured outcome. */
|
|
131
|
+
function outcomeRows(meta, t) {
|
|
132
|
+
const rows = [];
|
|
133
|
+
const path = meta.path ?? "";
|
|
134
|
+
const degradedCallout = (key) => {
|
|
135
|
+
rows.push(jsx("div", { style: calloutStyle(TONES.warn), children: t(key) }, "degraded"));
|
|
136
|
+
if (meta.code) rows.push(line("code", fill(t("leaseToolCode"), { code: meta.code }), text.foot));
|
|
137
|
+
};
|
|
138
|
+
if (meta.state === "degraded") {
|
|
139
|
+
degradedCallout("leaseToolDegraded");
|
|
140
|
+
const about = meta.path ? [meta.path] : meta.paths;
|
|
141
|
+
if (about.length) rows.push(pathList("about", t("leaseToolRequestedPaths"), about.map((p) => ({ path: p }))));
|
|
142
|
+
if (meta.requestId) rows.push(line("request", fill(t("leaseToolRequest"), { id: meta.requestId })));
|
|
143
|
+
return rows;
|
|
144
|
+
}
|
|
145
|
+
switch (meta.tool) {
|
|
146
|
+
case "edit_lock_acquire":
|
|
147
|
+
rows.push(meta.paths.length
|
|
148
|
+
? pathList("claimed", t("leaseToolClaimedPaths"), meta.paths.map((p) => ({ path: p })))
|
|
149
|
+
: line("nothing", t("leaseToolNothingClaimed")));
|
|
150
|
+
break;
|
|
151
|
+
case "edit_lock_release":
|
|
152
|
+
if (meta.released.length) rows.push(pathList("released", t("leaseToolReleasedPaths"), meta.released.map((p) => ({ path: p }))));
|
|
153
|
+
if (meta.notOwned.length) rows.push(pathList("not-owned", t("leaseToolNotOwnedPaths"), meta.notOwned.map((p) => ({ path: p }))));
|
|
154
|
+
if (!meta.released.length && !meta.notOwned.length) rows.push(line("nothing", t("leaseToolNothingReleased")));
|
|
155
|
+
break;
|
|
156
|
+
case "edit_lock_hold":
|
|
157
|
+
rows.push(meta.held.length
|
|
158
|
+
? pathList("held", null, meta.held.map((row) => ({ path: row.path, note: row.holdUntil !== null ? fill(t("leaseToolHeldUntil"), { time: timeOf(row.holdUntil) }) : null, title: row.holdUntil !== null ? isoOf(row.holdUntil) : undefined })))
|
|
159
|
+
: line("nothing", t("leaseToolNothingHeld")));
|
|
160
|
+
break;
|
|
161
|
+
case "edit_lock_status":
|
|
162
|
+
rows.push(meta.mine.length
|
|
163
|
+
? pathList("mine", fill(t("leaseToolMine"), { count: meta.mine.length }), meta.mine.map((row) => ({
|
|
164
|
+
path: row.path,
|
|
165
|
+
note: row.until === null ? null : fill(t(row.retained ? "leaseToolHeldUntil" : "leaseToolValidUntil"), { time: timeOf(row.until) }),
|
|
166
|
+
title: row.until === null ? undefined : isoOf(row.until)
|
|
167
|
+
})))
|
|
168
|
+
: line("mine-empty", t("leaseToolMineEmpty")));
|
|
169
|
+
if (meta.others.length) {
|
|
170
|
+
rows.push(pathList("others", fill(t("leaseToolOthers"), { count: meta.others.length }), meta.others.map((row) => ({
|
|
171
|
+
path: row.path,
|
|
172
|
+
note: [
|
|
173
|
+
row.label && row.session ? fill(t("leaseToolHolder"), { label: row.label, session: row.session }) : null,
|
|
174
|
+
row.lapsed ? t("leaseToolLapsed") : row.until !== null ? fill(t("leaseToolUntil"), { time: timeOf(row.until) }) : null
|
|
175
|
+
].filter(Boolean).join(" · "),
|
|
176
|
+
title: row.until !== null ? isoOf(row.until) : undefined
|
|
177
|
+
}))));
|
|
178
|
+
}
|
|
179
|
+
if (meta.at !== null) rows.push(jsx("div", { style: text.foot, title: isoOf(meta.at), children: fill(t("leaseToolReadAt"), { time: timeOf(meta.at) }) }, "read-at"));
|
|
180
|
+
break;
|
|
181
|
+
case "edit_lock_try_steal":
|
|
182
|
+
if (meta.state === "pending") {
|
|
183
|
+
rows.push(line("pending", fill(t("leaseToolPendingDetail"), { id: meta.requestId ?? "", holder: holderText(t, meta.holder), path })));
|
|
184
|
+
if (meta.expiresAt !== null) rows.push(jsx("div", { style: text.foot, title: isoOf(meta.expiresAt), children: fill(t("leaseToolPendingExpires"), { time: timeOf(meta.expiresAt) }) }, "expires"));
|
|
185
|
+
} else if (meta.state === "free") rows.push(line("free", fill(t("leaseToolStealFree"), { path })));
|
|
186
|
+
else rows.push(line("self", fill(t("leaseToolStealSelf"), { path })));
|
|
187
|
+
break;
|
|
188
|
+
case "edit_lock_reply":
|
|
189
|
+
rows.push(line("reply", fill(t(meta.state === "transferred" ? "leaseToolReplyTransferred" : "leaseToolReplyDeclined"), { id: meta.requestId ?? "" })));
|
|
190
|
+
break;
|
|
191
|
+
case "edit_lock_watch":
|
|
192
|
+
if (meta.state === "watching") {
|
|
193
|
+
rows.push(line("waiting", fill(t("leaseToolWatchWaiting"), { holder: holderText(t, meta.holder), path })));
|
|
194
|
+
} else if (meta.state === "free") rows.push(line("free", fill(t("leaseToolWatchFree"), { path })));
|
|
195
|
+
else if (meta.state === "self") rows.push(line("self", fill(t("leaseToolWatchSelf"), { path })));
|
|
196
|
+
else if (meta.state === "released") rows.push(line("released", fill(t("leaseToolWatchReleased"), { path })));
|
|
197
|
+
else if (meta.state === "reset") degradedCallout("leaseToolWatchReset");
|
|
198
|
+
else if (meta.state === "unsupported") degradedCallout("leaseToolWatchUnsupported");
|
|
199
|
+
else if (meta.state === "cancelled") degradedCallout("leaseToolWatchCancelled");
|
|
200
|
+
break;
|
|
201
|
+
default:
|
|
202
|
+
break;
|
|
203
|
+
}
|
|
204
|
+
return rows;
|
|
205
|
+
}
|
|
206
|
+
/** Body rows for a call WITHOUT a structured outcome (never empty). */
|
|
207
|
+
function fallbackRows(state, paths, requestId, block, model, t) {
|
|
208
|
+
const rows = [];
|
|
209
|
+
if (state === "running") rows.push(line("running", t("leaseToolRunning")));
|
|
210
|
+
if (state === "stopped") rows.push(line("stopped", t("leaseToolStoppedDetail")));
|
|
211
|
+
if (state === "failed") rows.push(line("failed", t("leaseToolFailedDetail")));
|
|
212
|
+
if (paths.length) rows.push(pathList("requested", t("leaseToolRequestedPaths"), paths.map((p) => ({ path: p }))));
|
|
213
|
+
if (requestId) rows.push(line("request", fill(t("leaseToolRequest"), { id: requestId })));
|
|
214
|
+
const raw = state === "failed" ? model.errorText(block) : state === "raw" || state === "stopped" ? model.resultText(block) : "";
|
|
215
|
+
if (raw !== "") {
|
|
216
|
+
rows.push(jsxs("div", { children: [
|
|
217
|
+
jsx("div", { style: { ...text.foot, marginBottom: "3px" }, children: t(state === "failed" ? "leaseToolErrorText" : "leaseToolRawOutput") }, "hint"),
|
|
218
|
+
jsx("pre", { style: preStyle, "data-weir-lease-raw": "", children: raw }, "pre")
|
|
219
|
+
] }, "raw"));
|
|
220
|
+
}
|
|
221
|
+
return rows;
|
|
222
|
+
}
|
|
223
|
+
/** The keyed conversation card for one edit_lock_* call. */
|
|
224
|
+
function FileLeaseToolRow(props) {
|
|
225
|
+
const model = props.model;
|
|
226
|
+
const block = props.block;
|
|
227
|
+
const t = typeof props.t === "function" ? props.t : (key) => key;
|
|
228
|
+
const [open, setOpen] = react.useState(false);
|
|
229
|
+
const meta = model.narrowLeaseMeta(block?.meta);
|
|
230
|
+
const tool = meta?.tool ?? (typeof props.toolName === "string" ? props.toolName : typeof block?.name === "string" ? block.name : typeof block?.call?.name === "string" ? block.call.name : "");
|
|
231
|
+
const state = meta ? meta.state : model.fallbackState(props.phase, block);
|
|
232
|
+
const color = toneColor(model.colorOf(tool, state));
|
|
233
|
+
const argsRaw = model.argsRawOf(block);
|
|
234
|
+
const paths = meta ? model.outcomePaths(meta) : model.argsPaths(tool, argsRaw).map((p) => model.shortPath(p, props.cwd));
|
|
235
|
+
const requestId = meta ? meta.requestId : tool === "edit_lock_reply" ? model.argsRequestId(argsRaw) : null;
|
|
236
|
+
const titleKey = model.LEASE_TOOLS.includes(tool) ? `leaseToolTitle_${tool}` : "leaseToolTitle_unknown";
|
|
237
|
+
// The primary subject of the row: a path (+N), the reply's request id,
|
|
238
|
+
// or the status counts. Never the model's text.
|
|
239
|
+
let subject = null;
|
|
240
|
+
if (meta && meta.tool === "edit_lock_status" && meta.state === "status") {
|
|
241
|
+
subject = jsx("span", { style: { ...text.body, flex: "0 1 auto", whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis", minWidth: 0 }, children: fill(t("leaseToolStatusSummary"), { mine: meta.mine.length, others: meta.others.length }) }, "subject");
|
|
242
|
+
} else if (paths.length) {
|
|
243
|
+
subject = jsxs("span", { style: { display: "inline-flex", alignItems: "baseline", gap: "4px", flex: "0 1 auto", minWidth: 0, overflow: "hidden" }, children: [
|
|
244
|
+
jsx("span", { "data-weir-lease-path": "", style: { ...mono, fontSize: "12px", color: "var(--dsw-alias-label-secondary)", whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis", minWidth: 0 }, children: paths[0] }, "path"),
|
|
245
|
+
paths.length > 1 ? jsx("span", { "data-weir-lease-more": "", style: { ...text.foot, flex: "none" }, children: `+${paths.length - 1}` }, "more") : null
|
|
246
|
+
] }, "subject");
|
|
247
|
+
} else if (requestId) {
|
|
248
|
+
subject = jsx("span", { style: { fontFamily: MONO, fontSize: "12px", color: "var(--dsw-alias-label-secondary)", flex: "0 1 auto", whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis", minWidth: 0 }, children: requestId }, "subject");
|
|
249
|
+
}
|
|
250
|
+
const hover = model.resultText(block);
|
|
251
|
+
const body = meta ? outcomeRows(meta, t) : fallbackRows(state, paths, requestId, block, model, t);
|
|
252
|
+
body.push(jsx("div", { style: text.foot, children: t("leaseToolSnapshot") }, "snapshot"));
|
|
253
|
+
const watching = meta?.tool === "edit_lock_watch" && meta.state === "watching";
|
|
254
|
+
return jsxs("div", {
|
|
255
|
+
"data-tool": tool,
|
|
256
|
+
"data-weir-lease-tool": tool,
|
|
257
|
+
"data-weir-lease-state": state,
|
|
258
|
+
style: cardStyle,
|
|
259
|
+
children: [
|
|
260
|
+
jsxs("button", {
|
|
261
|
+
type: "button",
|
|
262
|
+
"aria-expanded": open,
|
|
263
|
+
title: hover !== "" ? hover : undefined,
|
|
264
|
+
onClick: () => setOpen(!open),
|
|
265
|
+
style: rowButtonStyle,
|
|
266
|
+
children: [
|
|
267
|
+
jsx("span", { style: { color, display: "inline-flex", flex: "none" }, children: jsx(LockGlyph, { size: 13 }) }, "icon"),
|
|
268
|
+
jsx("span", { style: { ...text.title, flex: "0 1 auto", whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis", minWidth: 0 }, children: t(titleKey) }, "title"),
|
|
269
|
+
subject,
|
|
270
|
+
jsx("span", { style: { flex: 1, minWidth: 0 } }, "spacer"),
|
|
271
|
+
jsx(Badge, { state, label: t(model.stateKey(tool, state)), color }, "badge"),
|
|
272
|
+
jsx("span", { style: { color: "var(--dsw-alias-label-tertiary)", display: "inline-flex", flex: "none" }, children: jsx(Chevron, { open }) }, "chevron")
|
|
273
|
+
]
|
|
274
|
+
}, "row"),
|
|
275
|
+
// The wait's meaning is visible without expanding: a release
|
|
276
|
+
// produces a notice, and the notice is not an ownership grant.
|
|
277
|
+
watching ? jsx("div", { "data-weir-lease-watch-note": "", style: { ...calloutStyle(TONES.wait), marginTop: "6px" }, children: t("leaseToolWatchNote") }, "watch-note") : null,
|
|
278
|
+
open ? jsx("div", { "data-weir-lease-body": "", style: { display: "flex", flexDirection: "column", gap: "6px", marginTop: "8px", minWidth: 0 }, children: body }, "body") : null
|
|
279
|
+
]
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
// Locale data face (pure data, NO ctx calls — a chunk factory re-executes
|
|
283
|
+
// under HMR, so a chunk-local register would throw on the duplicate
|
|
284
|
+
// (namespace, locale) pair): the entry registers these under
|
|
285
|
+
// "settings.weir.file-lease-tools" when this chunk arrives (lib/client.js
|
|
286
|
+
// registerChunkDictionaries). Pinned by test/client.test.js's dictionary
|
|
287
|
+
// union pin and test/client-file-lease-tool-view.test.js's parity check.
|
|
288
|
+
const dictionaries = {
|
|
289
|
+
en: {
|
|
290
|
+
leaseToolTitle_edit_lock_acquire: "Claim edit lock",
|
|
291
|
+
leaseToolTitle_edit_lock_release: "Release edit lock",
|
|
292
|
+
leaseToolTitle_edit_lock_hold: "Keep edit lock",
|
|
293
|
+
leaseToolTitle_edit_lock_status: "Edit lock status",
|
|
294
|
+
leaseToolTitle_edit_lock_try_steal: "Request edit lock transfer",
|
|
295
|
+
leaseToolTitle_edit_lock_reply: "Answer transfer request",
|
|
296
|
+
leaseToolTitle_edit_lock_watch: "Watch for release",
|
|
297
|
+
leaseToolTitle_unknown: "Edit lock",
|
|
298
|
+
leaseToolState_claimed: "Claimed",
|
|
299
|
+
leaseToolState_released: "Released",
|
|
300
|
+
leaseToolState_held: "Kept",
|
|
301
|
+
leaseToolState_status: "Snapshot",
|
|
302
|
+
leaseToolState_pending: "Awaiting answer",
|
|
303
|
+
leaseToolState_free: "Not held",
|
|
304
|
+
leaseToolState_self: "Already yours",
|
|
305
|
+
leaseToolState_transferred: "Transferred",
|
|
306
|
+
leaseToolState_declined: "Declined",
|
|
307
|
+
leaseToolState_watching: "Waiting for release",
|
|
308
|
+
leaseToolState_watch_released: "Released meanwhile",
|
|
309
|
+
leaseToolState_reset: "Connection reset",
|
|
310
|
+
leaseToolState_unsupported: "Not supported",
|
|
311
|
+
leaseToolState_cancelled: "Cancelled",
|
|
312
|
+
leaseToolState_degraded: "Protection unavailable",
|
|
313
|
+
leaseToolState_running: "Running",
|
|
314
|
+
leaseToolState_failed: "Refused or failed",
|
|
315
|
+
leaseToolState_stopped: "Interrupted",
|
|
316
|
+
leaseToolState_raw: "Result",
|
|
317
|
+
leaseToolClaimedPaths: "Claimed for this turn",
|
|
318
|
+
leaseToolNothingClaimed: "Nothing was claimed.",
|
|
319
|
+
leaseToolReleasedPaths: "Released",
|
|
320
|
+
leaseToolNotOwnedPaths: "Not held by this session, so nothing to release",
|
|
321
|
+
leaseToolNothingReleased: "Nothing was released.",
|
|
322
|
+
leaseToolHeldUntil: "kept until {time}",
|
|
323
|
+
leaseToolValidUntil: "valid until {time}",
|
|
324
|
+
leaseToolUntil: "until {time}",
|
|
325
|
+
leaseToolNothingHeld: "Nothing was kept.",
|
|
326
|
+
leaseToolMine: "Held by this session ({count})",
|
|
327
|
+
leaseToolMineEmpty: "This session held nothing.",
|
|
328
|
+
leaseToolOthers: "Held by other sessions ({count})",
|
|
329
|
+
leaseToolHolder: "{label} (session {session})",
|
|
330
|
+
leaseToolHolderUnknown: "another session",
|
|
331
|
+
leaseToolLapsed: "lapsed, claimable",
|
|
332
|
+
leaseToolStatusSummary: "{mine} here · {others} elsewhere",
|
|
333
|
+
leaseToolReadAt: "Read at {time}",
|
|
334
|
+
leaseToolPendingDetail: "Request {id} for {path} is waiting for {holder} to answer.",
|
|
335
|
+
leaseToolPendingExpires: "If unanswered it expires at {time}, and ownership stays where it is.",
|
|
336
|
+
leaseToolStealFree: "Nobody held {path} at call time, so no transfer was requested.",
|
|
337
|
+
leaseToolStealSelf: "This session already held {path}; no transfer was needed.",
|
|
338
|
+
leaseToolReplyTransferred: "Request {id} was handed over: the requester holds the path now, this session no longer does.",
|
|
339
|
+
leaseToolReplyDeclined: "Request {id} was declined: ownership is unchanged and the path stays with this session.",
|
|
340
|
+
leaseToolWatchWaiting: "Waiting for {holder} to release {path}.",
|
|
341
|
+
leaseToolWatchNote: "A release arrives as a notice. The notice only means the path can be claimed again — it is not an ownership grant.",
|
|
342
|
+
leaseToolWatchFree: "Nobody held {path} at call time, so no subscription was kept.",
|
|
343
|
+
leaseToolWatchSelf: "This session already held {path}; there was nothing to wait for.",
|
|
344
|
+
leaseToolWatchReleased: "{path} was released while the subscription was being set up, so nothing is pending.",
|
|
345
|
+
leaseToolWatchReset: "The arbiter connection was reset while subscribing: nothing is pending and ownership is unknown.",
|
|
346
|
+
leaseToolWatchUnsupported: "The arbiter does not announce releases, so no subscription was created. Other edit-lock protection is unaffected.",
|
|
347
|
+
leaseToolWatchCancelled: "The subscription was cancelled before it was set up, so nothing is pending.",
|
|
348
|
+
leaseToolDegraded: "The ownership arbiter was unreachable, so edit protection was temporarily unavailable. This is not a conflict.",
|
|
349
|
+
leaseToolCode: "code: {code}",
|
|
350
|
+
leaseToolRequest: "Request {id}",
|
|
351
|
+
leaseToolRequestedPaths: "Requested paths",
|
|
352
|
+
leaseToolRunning: "Waiting for the result…",
|
|
353
|
+
leaseToolFailedDetail: "The call was refused or failed.",
|
|
354
|
+
leaseToolStoppedDetail: "The call was interrupted.",
|
|
355
|
+
leaseToolErrorText: "Error text",
|
|
356
|
+
leaseToolRawOutput: "Recorded output",
|
|
357
|
+
leaseToolSnapshot: "Outcome at call time; this card does not follow later changes."
|
|
358
|
+
},
|
|
359
|
+
zh: {
|
|
360
|
+
leaseToolTitle_edit_lock_acquire: "申请编辑锁",
|
|
361
|
+
leaseToolTitle_edit_lock_release: "释放编辑锁",
|
|
362
|
+
leaseToolTitle_edit_lock_hold: "保留编辑锁",
|
|
363
|
+
leaseToolTitle_edit_lock_status: "编辑锁状态",
|
|
364
|
+
leaseToolTitle_edit_lock_try_steal: "请求转交编辑锁",
|
|
365
|
+
leaseToolTitle_edit_lock_reply: "答复转交请求",
|
|
366
|
+
leaseToolTitle_edit_lock_watch: "订阅释放",
|
|
367
|
+
leaseToolTitle_unknown: "编辑锁",
|
|
368
|
+
leaseToolState_claimed: "已申请",
|
|
369
|
+
leaseToolState_released: "已释放",
|
|
370
|
+
leaseToolState_held: "已保留",
|
|
371
|
+
leaseToolState_status: "快照",
|
|
372
|
+
leaseToolState_pending: "等待答复",
|
|
373
|
+
leaseToolState_free: "无人持有",
|
|
374
|
+
leaseToolState_self: "本会话已持有",
|
|
375
|
+
leaseToolState_transferred: "已转交",
|
|
376
|
+
leaseToolState_declined: "已拒绝",
|
|
377
|
+
leaseToolState_watching: "等待释放",
|
|
378
|
+
leaseToolState_watch_released: "期间已释放",
|
|
379
|
+
leaseToolState_reset: "连接已重置",
|
|
380
|
+
leaseToolState_unsupported: "不支持",
|
|
381
|
+
leaseToolState_cancelled: "已取消",
|
|
382
|
+
leaseToolState_degraded: "保护暂不可用",
|
|
383
|
+
leaseToolState_running: "进行中",
|
|
384
|
+
leaseToolState_failed: "已拒绝或失败",
|
|
385
|
+
leaseToolState_stopped: "已中断",
|
|
386
|
+
leaseToolState_raw: "结果",
|
|
387
|
+
leaseToolClaimedPaths: "本轮已申请",
|
|
388
|
+
leaseToolNothingClaimed: "没有申请到任何路径。",
|
|
389
|
+
leaseToolReleasedPaths: "已释放",
|
|
390
|
+
leaseToolNotOwnedPaths: "本会话未持有,无需释放",
|
|
391
|
+
leaseToolNothingReleased: "没有释放任何路径。",
|
|
392
|
+
leaseToolHeldUntil: "保留至 {time}",
|
|
393
|
+
leaseToolValidUntil: "有效至 {time}",
|
|
394
|
+
leaseToolUntil: "至 {time}",
|
|
395
|
+
leaseToolNothingHeld: "没有保留任何路径。",
|
|
396
|
+
leaseToolMine: "本会话持有({count})",
|
|
397
|
+
leaseToolMineEmpty: "本会话未持有任何路径。",
|
|
398
|
+
leaseToolOthers: "其他会话持有({count})",
|
|
399
|
+
leaseToolHolder: "{label}(会话 {session})",
|
|
400
|
+
leaseToolHolderUnknown: "另一个会话",
|
|
401
|
+
leaseToolLapsed: "已过期,可申请",
|
|
402
|
+
leaseToolStatusSummary: "本会话 {mine} · 其他 {others}",
|
|
403
|
+
leaseToolReadAt: "读取于 {time}",
|
|
404
|
+
leaseToolPendingDetail: "关于 {path} 的请求 {id} 正等待 {holder}答复。",
|
|
405
|
+
leaseToolPendingExpires: "若无人答复,将于 {time} 过期,所有权保持不变。",
|
|
406
|
+
leaseToolStealFree: "调用时无人持有 {path},未发起转交请求。",
|
|
407
|
+
leaseToolStealSelf: "本会话已持有 {path},无需转交。",
|
|
408
|
+
leaseToolReplyTransferred: "请求 {id} 已转交:请求方现在持有该路径,本会话不再持有。",
|
|
409
|
+
leaseToolReplyDeclined: "请求 {id} 已拒绝:所有权不变,路径仍归本会话。",
|
|
410
|
+
leaseToolWatchWaiting: "正在等待 {holder}释放 {path}。",
|
|
411
|
+
leaseToolWatchNote: "释放后会收到一条通知;通知只代表可以重新争取,不代表已获得锁。",
|
|
412
|
+
leaseToolWatchFree: "调用时无人持有 {path},未保留订阅。",
|
|
413
|
+
leaseToolWatchSelf: "本会话已持有 {path},无需等待。",
|
|
414
|
+
leaseToolWatchReleased: "订阅建立期间 {path} 已被释放,没有待处理的等待。",
|
|
415
|
+
leaseToolWatchReset: "建立订阅时仲裁连接被重置:没有待处理的等待,所有权未知。",
|
|
416
|
+
leaseToolWatchUnsupported: "当前仲裁器不支持释放通知,未创建订阅;其他编辑锁保护不受影响。",
|
|
417
|
+
leaseToolWatchCancelled: "订阅在建立前已被取消,没有待处理的等待。",
|
|
418
|
+
leaseToolDegraded: "编辑锁仲裁器暂时无法连接,编辑保护暂不可用。这不是冲突。",
|
|
419
|
+
leaseToolCode: "代码:{code}",
|
|
420
|
+
leaseToolRequest: "请求 {id}",
|
|
421
|
+
leaseToolRequestedPaths: "请求的路径",
|
|
422
|
+
leaseToolRunning: "正在等待结果…",
|
|
423
|
+
leaseToolFailedDetail: "调用被拒绝或失败。",
|
|
424
|
+
leaseToolStoppedDetail: "调用已中断。",
|
|
425
|
+
leaseToolErrorText: "错误信息",
|
|
426
|
+
leaseToolRawOutput: "记录的输出",
|
|
427
|
+
leaseToolSnapshot: "以上是调用时的结果,不会随后续变化更新。"
|
|
428
|
+
}
|
|
429
|
+
};
|
|
430
|
+
exports.FileLeaseToolRow = FileLeaseToolRow;
|
|
431
|
+
exports.dictionaries = dictionaries;
|
|
432
|
+
return module.exports;
|
|
433
|
+
}
|
|
434
|
+
});
|