dsh-ptc-plus 0.5.0 → 0.5.1

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.cjs CHANGED
@@ -1494,6 +1494,15 @@ var CONFIG_FIELDS = Object.freeze([
1494
1494
  description: "worker \u91CD\u542F\u540E\u4ECE session journal \u91CD\u5EFA\u53EF\u6062\u590D\u7684 REPL \u72B6\u6001\u3002",
1495
1495
  descriptionEn: "Rebuilds recoverable REPL state from the session journal after a worker restart."
1496
1496
  },
1497
+ {
1498
+ key: "officialReplPriority",
1499
+ type: "boolean",
1500
+ default: false,
1501
+ label: "\u5B98\u65B9 REPL \u6A21\u5F0F\u4F18\u5148",
1502
+ labelEn: "Prioritize the official REPL mode",
1503
+ description: "\u68C0\u6D4B\u5230\u5B98\u65B9\u6301\u4E45 REPL \u6A21\u5F0F\u65F6\u7531\u5B98\u65B9\u8FD0\u884C\u65F6\u63A5\u7BA1 PTC \u4F1A\u8BDD\u6267\u884C\uFF1BPTC Plus \u8BA9\u51FA run_code \u53CA\u5176\u8FDB\u7A0B\u5185\u4F1A\u8BDD\u72B6\u6001\u8BED\u4E49\uFF0C\u5173\u95ED\u65F6\u59CB\u7EC8\u7531 PTC Plus \u63A5\u7BA1\u3002",
1504
+ descriptionEn: "Lets the official runtime own PTC session execution when the official persistent REPL mode is active; PTC Plus then leaves run_code and its in-process session-state semantics to DSH. Disabled keeps PTC Plus in charge."
1505
+ },
1497
1506
  {
1498
1507
  key: "tipsEnabled",
1499
1508
  type: "boolean",
@@ -1644,7 +1653,7 @@ var CONFIG_GROUPS = Object.freeze([
1644
1653
  key: "recovery",
1645
1654
  label: "\u72B6\u6001\u4E0E\u6062\u590D",
1646
1655
  labelEn: "State and recovery",
1647
- fields: Object.freeze(["durableReplay", "tipsEnabled", "tipCooldownMessages", "tipEscalationFailures"])
1656
+ fields: Object.freeze(["durableReplay", "officialReplPriority", "tipsEnabled", "tipCooldownMessages", "tipEscalationFailures"])
1648
1657
  },
1649
1658
  {
1650
1659
  key: "extensions",
@@ -2214,11 +2223,12 @@ function derivePtcToolView(block, toolName = void 0) {
2214
2223
  const explicitDescription = typeof args?.description === "string" && args.description.length > 0 ? args.description : void 0;
2215
2224
  const generatedDescription = settled && isRecord2(block.meta) && typeof block.meta[GENERATED_RUN_CODE_DESCRIPTION_KEY] === "string" && block.meta[GENERATED_RUN_CODE_DESCRIPTION_KEY].length > 0 ? block.meta[GENERATED_RUN_CODE_DESCRIPTION_KEY] : void 0;
2216
2225
  const description = (explicitDescription ?? generatedDescription)?.split(/\r?\n/, 1)[0] ?? "";
2226
+ const descriptionGenerated = explicitDescription === void 0 && generatedDescription !== void 0;
2217
2227
  const output = settled ? resultText(block) : "";
2218
2228
  const state = !settled ? "running" : block.error?.code === "interrupted" ? "stopped" : block.isError === true ? "error" : "ok";
2219
2229
  const journal = settled && isRecord2(block.meta) && isCountableJournal(block.meta.dshPtcPlus) ? block.meta.dshPtcPlus : void 0;
2220
2230
  if (journal === void 0) {
2221
- return Object.freeze({ state, description, code: code2, output, ptc: false, features: Object.freeze([]) });
2231
+ return Object.freeze({ state, description, descriptionGenerated, code: code2, output, ptc: false, features: Object.freeze([]) });
2222
2232
  }
2223
2233
  const rewrites = isValidRewrites(block.meta.dshPtcPlusRewrites, journal) ? block.meta.dshPtcPlusRewrites : [];
2224
2234
  const resolvedToolName = typeof toolName === "string" ? toolName : typeof block.call?.name === "string" ? block.call.name : "";
@@ -2233,7 +2243,7 @@ function derivePtcToolView(block, toolName = void 0) {
2233
2243
  journal.diagnostics.some(isDurableRecoveryDiagnostic) ? { key: "durableReplay.label", detail: "" } : void 0,
2234
2244
  ...operationFeatures(journal.operations)
2235
2245
  ]);
2236
- return Object.freeze({ state, description, code: code2, output, ptc: true, features: Object.freeze(features) });
2246
+ return Object.freeze({ state, description, descriptionGenerated, code: code2, output, ptc: true, features: Object.freeze(features) });
2237
2247
  }
2238
2248
 
2239
2249
  // src/client-host-compat.js
@@ -2572,12 +2582,17 @@ function createPtcToolView(React32, deps) {
2572
2582
  if (expandable) setOpen((current) => !current);
2573
2583
  };
2574
2584
  const summaryText = summary === "" ? null : summary;
2585
+ const generatedSummary = view.descriptionGenerated && outputSummary === "";
2575
2586
  const summaryLine = stateText === null && summaryText === null ? null : h(
2576
2587
  "div",
2577
2588
  { className: "ptcPlusToolSummaryLine", "data-state": view.state, role: "status" },
2578
2589
  stateText === null ? null : h("span", { className: "ptcPlusToolState" }, stateText),
2579
2590
  summaryText === null ? null : h("span", { className: "ptcPlusToolSep", "aria-hidden": true }),
2580
- summaryText === null ? null : h("span", { className: "ptcPlusToolDescription" }, summaryText)
2591
+ summaryText === null ? null : h("span", {
2592
+ className: "ptcPlusToolDescription",
2593
+ "data-generated": generatedSummary ? "true" : void 0,
2594
+ title: generatedSummary ? t2("tool.descriptionGenerated") : void 0
2595
+ }, summaryText)
2581
2596
  );
2582
2597
  const renderBody = (withInspect) => h(
2583
2598
  "div",
@@ -2646,7 +2661,11 @@ function createPtcToolView(React32, deps) {
2646
2661
  h(
2647
2662
  "div",
2648
2663
  { className: "ptcPlusToolHoverContent" },
2649
- view.description === "" ? null : h("div", { className: "ptcPlusToolHoverDescription" }, view.description),
2664
+ view.description === "" ? null : h("div", {
2665
+ className: "ptcPlusToolHoverDescription",
2666
+ "data-generated": view.descriptionGenerated ? "true" : void 0,
2667
+ title: view.descriptionGenerated ? t2("tool.descriptionGenerated") : void 0
2668
+ }, view.description),
2650
2669
  view.code === "" ? null : h(
2651
2670
  "div",
2652
2671
  { className: "ptcPlusToolHoverSection" },
@@ -2900,9 +2919,11 @@ var FALLBACKS = Object.freeze({
2900
2919
  recorded: "Capabilities updated for session",
2901
2920
  pending: "Capabilities prepared; they take effect at the first accepted model step for session",
2902
2921
  unavailable: "Select an active PTC session; the command did not update session",
2903
- usage: "Use /capabilities to inspect or /capabilities refresh to apply saved settings for session"
2922
+ usage: "Use /capabilities to inspect or /capabilities refresh to apply saved settings for session",
2923
+ paused: "Capabilities and context are off; the session stays with the Host capabilities for session",
2924
+ off: "Capability management is off; the session stays with the Host capabilities for session"
2904
2925
  });
2905
- var STATES = /* @__PURE__ */ new Set(["recorded", "pending", "unavailable", "usage", "saved-only"]);
2926
+ var STATES = /* @__PURE__ */ new Set(["recorded", "pending", "unavailable", "usage", "saved-only", "paused", "off"]);
2906
2927
  function capabilityCommandReceipt(state, sessionId, error, proposal) {
2907
2928
  if (!STATES.has(state) || typeof sessionId !== "string" || !sessionId) throw new TypeError("invalid capability command receipt");
2908
2929
  if (error !== void 0 && (state !== "saved-only" || typeof error !== "string" || !error)) throw new TypeError("invalid capability command error");
@@ -8862,7 +8883,6 @@ function createCapabilitySettingsViews(React32, { SearchIcon, Select: Select2, M
8862
8883
  "div",
8863
8884
  { className: "ptcPlusCapabilityBatchBody" },
8864
8885
  h("p", { className: "ptcPlusDetail", role: "status" }, t2("capabilities.batch.targets", { count: operation.targets.length })),
8865
- h("p", { className: "ptcPlusDetail" }, t2("capabilities.batch.scope", { scope: operation.scope })),
8866
8886
  operation.excluded ? h("p", { className: "ptcPlusDetail" }, t2("capabilities.batch.excluded", { count: operation.excluded })) : null,
8867
8887
  operation.targets.length ? h(
8868
8888
  "ul",
@@ -8878,7 +8898,7 @@ function createCapabilitySettingsViews(React32, { SearchIcon, Select: Select2, M
8878
8898
  disabled: blocked || !operation.targets.length,
8879
8899
  label: t2(`capabilities.batch.${dimension}`),
8880
8900
  onChange: (choice) => setChoices((current) => ({ ...current, [dimension]: choice })),
8881
- options: ["keep", "automatic", ...dimension === "availability" ? ["enabled", "closed"] : CAPABILITY_DISCLOSURES].map((choice) => ({ value: choice, label: t2(choice === "keep" ? "capabilities.batch.keep" : choice === "automatic" ? "capabilities.policy.inheritRule" : choice === "enabled" ? "capabilities.quick.enabled" : `capabilities.${choice}`) }))
8901
+ options: ["keep", "automatic", ...dimension === "availability" ? ["enabled", "closed"] : CAPABILITY_DISCLOSURES].map((choice) => ({ value: choice, label: t2(choice === "keep" ? "capabilities.batch.keep" : choice === "automatic" ? "capabilities.policy.inheritRule" : choice === "enabled" ? "capabilities.action.enable" : choice === "closed" ? "capabilities.action.close" : `capabilities.${choice}`) }))
8882
8902
  })
8883
8903
  ))),
8884
8904
  h("p", { className: "ptcPlusDetail" }, t2("capabilities.batch.effect")),
@@ -8915,6 +8935,7 @@ function createCapabilitySettingsViews(React32, { SearchIcon, Select: Select2, M
8915
8935
  const [availability, setAvailability] = React32.useState("all");
8916
8936
  const [sort2, setSort] = React32.useState(null);
8917
8937
  const [selected, setSelected] = React32.useState(null);
8938
+ const [picked, setPicked] = React32.useState([]);
8918
8939
  const [filtersOpen, setFiltersOpen] = React32.useState(false);
8919
8940
  const [batchOperation, setBatchOperation] = React32.useState(null);
8920
8941
  const [inheritedRulesOpen, setInheritedRulesOpen] = React32.useState(false);
@@ -8968,6 +8989,13 @@ function createCapabilitySettingsViews(React32, { SearchIcon, Select: Select2, M
8968
8989
  const groupOrder = ["tool", ...[...groups.keys()].filter((key) => key.startsWith("mcp:")).sort(compare), "skill", "resource", "other", "unavailable"];
8969
8990
  const defaultEntries = groupOrder.flatMap((group) => (groups.get(group) ?? []).sort(defaultOrder));
8970
8991
  const visible = sortCapabilityEntries(defaultEntries, sort2, (item, column) => column === "name" ? item.name : column === "type" ? t2(`capabilities.type.${type(item)}`) : column === "source" ? displayedSource(item) : column === "availability" ? t2(`capabilities.rowState.${state(item)}`) : t2(`capabilities.${item.resolvedRule.disclosure}`));
8992
+ const pickedIds = picked.filter((id2) => entries.some((item) => item.id === id2));
8993
+ const pickedEntries = pickedIds.map((id2) => entries.find((item) => item.id === id2)).filter(Boolean);
8994
+ const pickedTargets = pickedEntries.filter((item) => item.availability === "available");
8995
+ const allVisiblePicked = visible.length > 0 && visible.every((item) => pickedIds.includes(item.id));
8996
+ const someVisiblePicked = visible.some((item) => pickedIds.includes(item.id));
8997
+ const togglePick = (id2) => setPicked((current) => current.includes(id2) ? current.filter((item) => item !== id2) : [...current, id2]);
8998
+ const toggleAllVisible = () => setPicked((current) => allVisiblePicked ? current.filter((id2) => !visible.some((item) => item.id === id2)) : [.../* @__PURE__ */ new Set([...current, ...visible.map((item) => item.id)])]);
8971
8999
  const entry = visible.find((item) => item.id === selected);
8972
9000
  const plan = sessionId ? plans?.find((item) => item.sessionId === sessionId) : void 0;
8973
9001
  const effective = plan?.effective.entries.find((item) => item.id === entry?.id);
@@ -9080,17 +9108,30 @@ function createCapabilitySettingsViews(React32, { SearchIcon, Select: Select2, M
9080
9108
  "aria-haspopup": "dialog",
9081
9109
  onClick: () => setFiltersOpen(true)
9082
9110
  }, t2("capabilities.filterAction")),
9083
- h("button", {
9084
- type: "button",
9085
- className: "ptcPlusButton",
9086
- "aria-haspopup": "dialog",
9087
- disabled: disabled("capabilityPolicy"),
9088
- onClick: () => setBatchOperation({
9089
- targets: visible.filter((item) => item.availability === "available").map((item) => ({ id: item.id, name: item.name })),
9090
- excluded: visible.filter((item) => item.availability !== "available").length,
9091
- scope: [...filterLabels, ...query.trim() ? [t2("capabilities.batch.search", { query: query.trim() })] : []].join(" \xB7 ") || t2("capabilities.batch.all")
9092
- })
9093
- }, t2("capabilities.batchSettings")),
9111
+ h(
9112
+ "button",
9113
+ {
9114
+ type: "button",
9115
+ className: "ptcPlusButton",
9116
+ "aria-haspopup": "dialog",
9117
+ "aria-label": t2("capabilities.batchSettings"),
9118
+ disabled: disabled("capabilityPolicy") || pickedTargets.length === 0,
9119
+ onClick: () => setBatchOperation({
9120
+ targets: pickedTargets.map((item) => ({ id: item.id, name: item.name })),
9121
+ excluded: pickedIds.length - pickedTargets.length
9122
+ })
9123
+ },
9124
+ t2("capabilities.batchSettings"),
9125
+ pickedIds.length ? h(
9126
+ "span",
9127
+ {
9128
+ className: "ptcPlusCapabilityBatchCount",
9129
+ "aria-hidden": true,
9130
+ title: t2("capabilities.selectionCount", { count: pickedIds.length })
9131
+ },
9132
+ String(pickedIds.length)
9133
+ ) : null
9134
+ ),
9094
9135
  h("button", {
9095
9136
  type: "button",
9096
9137
  className: "ptcPlusButton",
@@ -9194,8 +9235,20 @@ function createCapabilitySettingsViews(React32, { SearchIcon, Select: Select2, M
9194
9235
  {
9195
9236
  key: column.key,
9196
9237
  role: "columnheader",
9197
- "aria-sort": capabilitySortDirection(sort2, column.key)
9238
+ "aria-sort": capabilitySortDirection(sort2, column.key),
9239
+ ...column.key === "name" ? { "aria-label": t2("capabilities.member"), className: "ptcPlusCapabilityPickHead" } : {}
9198
9240
  },
9241
+ ...column.key === "name" ? [h("input", {
9242
+ type: "checkbox",
9243
+ className: "ptcPlusPick",
9244
+ checked: allVisiblePicked,
9245
+ ref: (node) => {
9246
+ if (node) node.indeterminate = someVisiblePicked && !allVisiblePicked;
9247
+ },
9248
+ disabled: visible.length === 0,
9249
+ "aria-label": t2("capabilities.selectAllVisible"),
9250
+ onChange: toggleAllVisible
9251
+ })] : [],
9199
9252
  h(
9200
9253
  "button",
9201
9254
  {
@@ -9223,7 +9276,24 @@ function createCapabilitySettingsViews(React32, { SearchIcon, Select: Select2, M
9223
9276
  "data-availability": item.availability,
9224
9277
  onClick: () => setSelected(item.id)
9225
9278
  },
9226
- h("div", { className: "ptcPlusCapabilityIdentity", role: "cell" }, h("span", { className: "ptcPlusCapabilityName" }, item.name), h("code", null, item.id)),
9279
+ h(
9280
+ "div",
9281
+ { className: "ptcPlusCapabilityIdentity", role: "cell" },
9282
+ h("input", {
9283
+ type: "checkbox",
9284
+ className: "ptcPlusPick",
9285
+ checked: pickedIds.includes(item.id),
9286
+ "aria-label": t2("capabilities.selectForBatch", { name: item.name ?? item.id }),
9287
+ onClick: (event) => event.stopPropagation(),
9288
+ onChange: () => togglePick(item.id)
9289
+ }),
9290
+ h(
9291
+ "div",
9292
+ { className: "ptcPlusCapabilityIdentityText" },
9293
+ h("span", { className: "ptcPlusCapabilityName" }, item.name),
9294
+ h("code", null, item.id)
9295
+ )
9296
+ ),
9227
9297
  h("span", { className: "ptcPlusCapabilityBadge", role: "cell", "data-kind": type(item) }, t2(`capabilities.type.${type(item)}`)),
9228
9298
  h("span", { className: "ptcPlusCapabilitySource", role: "cell" }, displayedSource(item)),
9229
9299
  // The cell stays a plain cell so its empty area selects the row; only the switch and
@@ -10180,9 +10250,13 @@ function createSessionCapabilityControlsView(React32, { commands, Modal, Select:
10180
10250
  const available = React32.useSyncExternalStore(source.subscribe, source.getSnapshot);
10181
10251
  const [catalog, setCatalog] = React32.useState([]);
10182
10252
  const [management, setManagement] = React32.useState("unknown");
10253
+ const [savedSettings, setSavedSettings] = React32.useState(null);
10183
10254
  const [loading, setLoading] = React32.useState(false);
10184
10255
  const [error, setError] = React32.useState(null);
10185
10256
  const [drafts, setDrafts] = React32.useState(emptyDrafts);
10257
+ const [picked, setPicked] = React32.useState([]);
10258
+ const [batchOpen, setBatchOpen] = React32.useState(false);
10259
+ const [batchChoices, setBatchChoices] = React32.useState({ availability: "keep", disclosure: "keep" });
10186
10260
  const [selectedId, setSelectedId] = React32.useState(null);
10187
10261
  const [pane, setPane] = React32.useState("list");
10188
10262
  const [query, setQuery] = React32.useState("");
@@ -10218,7 +10292,10 @@ function createSessionCapabilityControlsView(React32, { commands, Modal, Select:
10218
10292
  applying.current = false;
10219
10293
  setCatalog([]);
10220
10294
  setManagement("unknown");
10295
+ setSavedSettings(null);
10221
10296
  setDrafts(emptyDrafts());
10297
+ setPicked([]);
10298
+ setBatchOpen(false);
10222
10299
  setSelectedId(null);
10223
10300
  setPane("list");
10224
10301
  setFocusDimension(null);
@@ -10235,7 +10312,9 @@ function createSessionCapabilityControlsView(React32, { commands, Modal, Select:
10235
10312
  throw new Error("Invalid capability catalog");
10236
10313
  }
10237
10314
  setCatalog(payload.entries);
10315
+ setPicked((current) => current.filter((id2) => payload.entries.some((entry) => entry.id === id2)));
10238
10316
  setManagement(["managed", "paused", "off", "unknown"].includes(payload.management) ? payload.management : "unknown");
10317
+ setSavedSettings(payload.savedSettings !== null && typeof payload.savedSettings === "object" && !Array.isArray(payload.savedSettings) ? payload.savedSettings : null);
10239
10318
  setError(null);
10240
10319
  return payload.entries;
10241
10320
  } catch (failure) {
@@ -10246,11 +10325,14 @@ function createSessionCapabilityControlsView(React32, { commands, Modal, Select:
10246
10325
  }, [sessionId]);
10247
10326
  React32.useEffect(() => {
10248
10327
  if (!open || !enabled || !available) {
10249
- request.current?.abort();
10250
- request.current = null;
10328
+ if (!applying.current) {
10329
+ request.current?.abort();
10330
+ request.current = null;
10331
+ }
10251
10332
  setLoading(false);
10252
10333
  return;
10253
10334
  }
10335
+ if (applying.current) return;
10254
10336
  const controller = new AbortController();
10255
10337
  request.current = controller;
10256
10338
  void load(controller.signal);
@@ -10259,17 +10341,10 @@ function createSessionCapabilityControlsView(React32, { commands, Modal, Select:
10259
10341
  if (request.current === controller) request.current = null;
10260
10342
  };
10261
10343
  }, [open, enabled, available, load]);
10262
- React32.useEffect(() => {
10263
- if (!enabled || !available) {
10264
- request.current?.abort();
10265
- request.current = null;
10266
- applying.current = false;
10267
- setPending(false);
10268
- }
10269
- }, [enabled, available]);
10270
10344
  const choices = drafts;
10271
10345
  const choiceFor = (entry) => choices[entry.id] ?? entry.temporary ?? "inherit";
10272
- const writesBlocked = management === "paused" || management === "off";
10346
+ const savedBlocks = savedSettings !== null && (savedSettings.enabled === false || savedSettings.contextEnabled === false);
10347
+ const writesBlocked = management === "paused" || management === "off" || savedBlocks;
10273
10348
  const sourceKey = (entry) => entry.source?.kind === "mcp" ? "mcp:" + (entry.source.server ?? "") : entry.source?.kind === "skill" ? "skill:" + (entry.source.bucket ?? "") : entry.source?.kind ?? "unknown";
10274
10349
  const sourceLabel = (entry) => entry.source?.kind === "mcp" ? `MCP \xB7 ${entry.source.server ?? ""}` : entry.source?.kind === "skill" ? `Skill \xB7 ${entry.source.bucket ? t2(`capabilities.source.${entry.source.bucket}`) : t2("capabilities.source.unknown")}` : t2(`capabilities.source.${entry.source?.kind === "host" ? "host" : "unknown"}`);
10275
10350
  const category = (entry) => entry.category === "skill" ? "skills" : ["server", "resource"].includes(entry.category) ? "mcp" : entry.source?.kind === "mcp" ? "mcp_tools" : "tools";
@@ -10295,29 +10370,45 @@ function createSessionCapabilityControlsView(React32, { commands, Modal, Select:
10295
10370
  const matches = sortCapabilityEntries(defaultOrder, sort2, (entry, column) => column === "name" ? entry.name ?? entry.id : column === "type" ? t2(`capabilities.type.${type(entry)}`) : column === "source" ? displayedSource(entry) : column === "availability" ? capabilityChoiceLabel(t2, effectiveAvailability(entry)) : capabilityChoiceLabel(t2, effectiveContext(entry)));
10296
10371
  const selected = matches.find((entry) => entry.id === selectedId) ?? ["tools", "skills", "mcp", "mcp_tools"].map((group) => matches.find((entry) => category(entry) === group)).find(Boolean);
10297
10372
  const staged = Object.entries(choices).flatMap(([id2, choice]) => typeof choice === "object" ? Object.entries(choice).map(([dimension, selection]) => [id2, selection, dimension]) : [[id2, choice]]);
10298
- const chooseDimension = (id2, dimension, choice) => {
10299
- setDrafts((current) => {
10300
- const patch = typeof current[id2] === "object" ? { ...current[id2] } : {};
10301
- const original = catalog.find((entry) => entry.id === id2)?.temporaryRule?.[dimension] ?? "inherit";
10302
- if (choice === original && choice === "inherit") delete patch[dimension];
10373
+ const pickedRows = picked.map((id2) => catalog.find((entry) => entry.id === id2)).filter(Boolean);
10374
+ const allMatchesPicked = matches.length > 0 && matches.every((entry) => picked.includes(entry.id));
10375
+ const someMatchesPicked = matches.some((entry) => picked.includes(entry.id));
10376
+ const togglePick = (id2) => setPicked((current) => current.includes(id2) ? current.filter((item) => item !== id2) : [...current, id2]);
10377
+ const toggleAllMatches = () => setPicked((current) => allMatchesPicked ? current.filter((id2) => !matches.some((entry) => entry.id === id2)) : [.../* @__PURE__ */ new Set([...current, ...matches.map((entry) => entry.id)])]);
10378
+ const stageDimension = (current, entry, dimension, choice) => {
10379
+ const next = { ...current };
10380
+ const patch = typeof next[entry.id] === "object" && next[entry.id] !== null ? { ...next[entry.id] } : {};
10381
+ const original = storedDimension(entry, dimension) ?? "inherit";
10382
+ const selectedChoice = patch[dimension] ?? original;
10383
+ if (choice !== selectedChoice) {
10384
+ if (choice === original) delete patch[dimension];
10303
10385
  else patch[dimension] = choice;
10304
- const next = { ...current };
10305
- if (Object.keys(patch).length) next[id2] = patch;
10306
- else delete next[id2];
10307
- return next;
10308
- });
10386
+ }
10387
+ if (Object.keys(patch).length) next[entry.id] = patch;
10388
+ else delete next[entry.id];
10389
+ return next;
10390
+ };
10391
+ const chooseDimension = (id2, dimension, choice) => {
10392
+ const entry = catalog.find((item) => item.id === id2);
10393
+ if (entry) setDrafts((current) => stageDimension(current, entry, dimension, choice));
10309
10394
  };
10310
10395
  const choose = (id2, next) => {
10311
10396
  const entry = catalog.find((item) => item.id === id2);
10312
10397
  if (!entry) return;
10313
10398
  const original = entry.temporary ?? "inherit";
10399
+ if (next === (choices[id2] ?? original)) return;
10314
10400
  setDrafts((current) => {
10315
10401
  const nextChoices = { ...current };
10316
- if (next === original && next === "inherit") delete nextChoices[id2];
10402
+ if (next === original) delete nextChoices[id2];
10317
10403
  else nextChoices[id2] = next;
10318
10404
  return nextChoices;
10319
10405
  });
10320
10406
  };
10407
+ const stageBatch = (ids, selections2) => setDrafts((current) => ids.reduce((draft, id2) => {
10408
+ const entry = catalog.find((item) => item.id === id2);
10409
+ if (!entry) return draft;
10410
+ return ["availability", "disclosure"].reduce((next, dimension) => selections2[dimension] === void 0 || selections2[dimension] === "keep" ? next : stageDimension(next, entry, dimension, selections2[dimension]), draft);
10411
+ }, current));
10321
10412
  const hasInheritanceReset = staged.some(([, selection]) => selection === "inherit");
10322
10413
  const apply = async (targetScope) => {
10323
10414
  if (applying.current || !enabled || !available || writesBlocked || staged.length === 0) return;
@@ -10329,58 +10420,62 @@ function createSessionCapabilityControlsView(React32, { commands, Modal, Select:
10329
10420
  const controller = new AbortController();
10330
10421
  request.current?.abort();
10331
10422
  request.current = controller;
10332
- let completed = 0;
10333
- let pendingCount = 0;
10334
- let failure = null;
10335
- let savedOnly = null;
10336
- for (const [id2, selection, dimension] of staged) {
10337
- if (controller.signal.aborted) break;
10338
- try {
10339
- const result = await commands.run(sessionId, `set ${targetScope} ${encodeURIComponent(id2)} ${dimension ? dimension + " " : ""}${selection}`, controller.signal);
10340
- const receipt = readCapabilityCommandReceipt(result.text);
10341
- if (!receipt || receipt.sessionId !== sessionId || !["recorded", "pending"].includes(receipt.state)) {
10342
- throw new Error(receipt ? capabilityCommandText(t2, result.text) : t2("capabilities.quick.unknownReceipt"));
10423
+ const finish = () => {
10424
+ if (request.current === controller) request.current = null;
10425
+ applying.current = false;
10426
+ if (mounted.current) setPending(false);
10427
+ };
10428
+ try {
10429
+ let completed = 0;
10430
+ let pendingCount = 0;
10431
+ let failure = null;
10432
+ let savedOnly = null;
10433
+ for (const [id2, selection, dimension] of staged) {
10434
+ if (controller.signal.aborted) break;
10435
+ try {
10436
+ const result = await commands.run(sessionId, `set ${targetScope} ${encodeURIComponent(id2)} ${dimension ? dimension + " " : ""}${selection}`, controller.signal);
10437
+ const receipt = readCapabilityCommandReceipt(result.text);
10438
+ if (!receipt || receipt.sessionId !== sessionId || !["recorded", "pending"].includes(receipt.state)) {
10439
+ throw new Error(receipt ? capabilityCommandText(t2, result.text) : t2("capabilities.quick.unknownReceipt"));
10440
+ }
10441
+ if (receipt?.state === "pending") pendingCount += 1;
10442
+ completed += 1;
10443
+ } catch (cause) {
10444
+ failure = String(cause?.message ?? cause);
10445
+ savedOnly = readCapabilityCommandReceipt(failure)?.state === "saved-only" ? readCapabilityCommandReceipt(failure) : null;
10446
+ break;
10343
10447
  }
10344
- if (receipt?.state === "pending") pendingCount += 1;
10345
- completed += 1;
10346
- } catch (cause) {
10347
- failure = String(cause?.message ?? cause);
10348
- savedOnly = readCapabilityCommandReceipt(failure)?.state === "saved-only" ? readCapabilityCommandReceipt(failure) : null;
10349
- break;
10350
10448
  }
10351
- }
10352
- if (request.current !== controller || controller.signal.aborted || !mounted.current) return;
10353
- const refreshed = await load(controller.signal);
10354
- if (request.current !== controller || controller.signal.aborted || !mounted.current) return;
10355
- const confirmed = refreshed ? staged.slice(0, completed).filter(([id2, selection, dimension]) => {
10356
- const entry = refreshed.find((item) => item.id === id2);
10357
- if (dimension) return entry && (targetScope === "session" ? (entry.temporaryRule?.[dimension] ?? "inherit") === selection : (entry.savedRule?.[dimension] ?? "automatic") === selection && entry.temporaryRule?.[dimension] === void 0);
10358
- return entry && (targetScope === "session" ? entry.temporary === selection : entry.saved === selection && entry.temporary === "inherit");
10359
- }) : [];
10360
- setDrafts((current) => {
10361
- const nextChoices = { ...current };
10362
- for (const [id2, selection, dimension] of confirmed) {
10363
- if (savedOnly && id2 === staged[completed]?.[0] && dimension === staged[completed]?.[2]) continue;
10364
- if (dimension) {
10365
- if (nextChoices[id2]?.[dimension] !== submitted[id2]?.[dimension]) continue;
10366
- const patch = { ...nextChoices[id2] };
10367
- delete patch[dimension];
10368
- if (Object.keys(patch).length) nextChoices[id2] = patch;
10369
- else delete nextChoices[id2];
10370
- } else if (nextChoices[id2] === submitted[id2]) delete nextChoices[id2];
10371
- }
10372
- return nextChoices;
10373
- });
10374
- if (savedOnly) setStatus({ key: "capabilities.quick.savedOnly", params: { count: completed, error: savedOnly.error ?? "" } });
10375
- else if (failure || !refreshed || confirmed.length < completed) setStatus({
10376
- key: "capabilities.quick.partial",
10377
- params: { count: confirmed.length, error: failure ?? t2("capabilities.quick.confirmationUnavailable") }
10378
- });
10379
- else setStatus({ key: pendingCount ? "capabilities.quick.pendingApplied" : "capabilities.quick.applied", params: { count: completed } });
10380
- if (request.current === controller) {
10381
- request.current = null;
10382
- applying.current = false;
10383
- setPending(false);
10449
+ if (request.current !== controller || controller.signal.aborted || !mounted.current) return;
10450
+ const refreshed = await load(controller.signal);
10451
+ if (request.current !== controller || controller.signal.aborted || !mounted.current) return;
10452
+ const confirmed = refreshed ? staged.slice(0, completed).filter(([id2, selection, dimension]) => {
10453
+ const entry = refreshed.find((item) => item.id === id2);
10454
+ if (dimension) return entry && (targetScope === "session" ? (entry.temporaryRule?.[dimension] ?? "inherit") === selection : (entry.savedRule?.[dimension] ?? "automatic") === selection && entry.temporaryRule?.[dimension] === void 0);
10455
+ return entry && (targetScope === "session" ? entry.temporary === selection : entry.saved === selection && entry.temporary === "inherit");
10456
+ }) : [];
10457
+ setDrafts((current) => {
10458
+ const nextChoices = { ...current };
10459
+ for (const [id2, selection, dimension] of confirmed) {
10460
+ if (savedOnly && id2 === staged[completed]?.[0] && dimension === staged[completed]?.[2]) continue;
10461
+ if (dimension) {
10462
+ if (nextChoices[id2]?.[dimension] !== submitted[id2]?.[dimension]) continue;
10463
+ const patch = { ...nextChoices[id2] };
10464
+ delete patch[dimension];
10465
+ if (Object.keys(patch).length) nextChoices[id2] = patch;
10466
+ else delete nextChoices[id2];
10467
+ } else if (nextChoices[id2] === submitted[id2]) delete nextChoices[id2];
10468
+ }
10469
+ return nextChoices;
10470
+ });
10471
+ if (savedOnly) setStatus({ key: "capabilities.quick.savedOnly", params: { count: completed, error: savedOnly.error ?? "" } });
10472
+ else if (failure || !refreshed || confirmed.length < completed) setStatus({
10473
+ key: "capabilities.quick.partial",
10474
+ params: { count: confirmed.length, error: failure ?? t2("capabilities.quick.confirmationUnavailable") }
10475
+ });
10476
+ else setStatus({ key: pendingCount ? "capabilities.quick.pendingApplied" : "capabilities.quick.applied", params: { count: completed } });
10477
+ } finally {
10478
+ finish();
10384
10479
  }
10385
10480
  };
10386
10481
  const discard = () => {
@@ -10388,6 +10483,7 @@ function createSessionCapabilityControlsView(React32, { commands, Modal, Select:
10388
10483
  setStatus(null);
10389
10484
  };
10390
10485
  const close = () => {
10486
+ if (applying.current) return;
10391
10487
  request.current?.abort();
10392
10488
  request.current = null;
10393
10489
  applying.current = false;
@@ -10408,15 +10504,82 @@ function createSessionCapabilityControlsView(React32, { commands, Modal, Select:
10408
10504
  options: options2.map(([key, text]) => ({ value: key, label: text }))
10409
10505
  })
10410
10506
  );
10507
+ const ruleLabel = (rule, empty2) => capabilityRuleLabel(t2, rule, empty2);
10508
+ const statusLabel = (value) => value && typeof value === "object" ? ruleLabel(value) : capabilityChoiceLabel(t2, value);
10509
+ const storedDimension = (entry, dimension) => {
10510
+ const rule = entry.temporaryRule !== null && typeof entry.temporaryRule === "object" && !Array.isArray(entry.temporaryRule) ? entry.temporaryRule : void 0;
10511
+ const override = rule?.[dimension];
10512
+ if (override !== void 0) return override;
10513
+ if (entry.temporary === "automatic") return "automatic";
10514
+ if (typeof entry.temporary === "string" && !["inherit", "automatic", "unknown", "pending"].includes(entry.temporary)) {
10515
+ return dimension === "availability" ? entry.temporary === "closed" ? "closed" : "enabled" : CAPABILITY_DISCLOSURES.includes(entry.temporary) ? entry.temporary : void 0;
10516
+ }
10517
+ return void 0;
10518
+ };
10519
+ const frozenDimension = (entry, dimension) => {
10520
+ const source2 = entry.sourceDimensions?.[dimension];
10521
+ if (typeof source2 === "string") return source2;
10522
+ const effective = entry.effectiveDimensions?.[dimension];
10523
+ if (typeof effective === "string" && storedDimension(entry, dimension) === void 0) return effective;
10524
+ if (dimension === "availability") return entry.effective === "closed" ? "closed" : ["full", "on-demand", "host", "enabled"].includes(entry.effective) ? "enabled" : void 0;
10525
+ return ["full", "on-demand", "host"].includes(entry.effective) ? entry.effective : void 0;
10526
+ };
10527
+ const stateText = (value) => value === void 0 ? t2("capabilities.quick.unknown") : statusLabel(value);
10528
+ const dimensionCurrent = (entry, dimension) => choices[entry.id]?.[dimension] ?? storedDimension(entry, dimension) ?? "inherit";
10529
+ const dimensionImpact = (entry, dimension) => {
10530
+ const draft = choices[entry.id]?.[dimension];
10531
+ const choice = draft ?? storedDimension(entry, dimension) ?? "inherit";
10532
+ const stagedChange = draft !== void 0;
10533
+ if (choice === "inherit") return { state: frozenDimension(entry, dimension), origin: "capabilities.quick.originPlan", staged: stagedChange };
10534
+ if (choice === "automatic") return { upper: true, staged: stagedChange };
10535
+ return { state: choice, origin: "capabilities.quick.originSession", staged: stagedChange };
10536
+ };
10537
+ const impactLine = (impact) => impact.upper ? t2(impact.staged ? "capabilities.quick.impactUpperPending" : "capabilities.quick.impactUpper") : t2(
10538
+ impact.staged ? "capabilities.quick.impactPending" : "capabilities.quick.impact",
10539
+ { state: stateText(impact.state), source: t2(impact.origin) }
10540
+ );
10541
+ const dimensionOptions = (entry, dimension) => {
10542
+ const restore = stateText(frozenDimension(entry, dimension));
10543
+ const inherit = storedDimension(entry, dimension) === void 0 ? t2("capabilities.quick.noChange", { state: restore }) : t2("capabilities.quick.undoTemp", { state: restore });
10544
+ const sourceDimension = entry.sourceRule?.[dimension];
10545
+ const distinctRule = sourceDimension !== void 0 && sourceDimension !== "automatic";
10546
+ return [
10547
+ "inherit",
10548
+ ...distinctRule || dimensionCurrent(entry, dimension) === "automatic" ? ["automatic"] : [],
10549
+ ...dimension === "availability" ? ["enabled", "closed"] : CAPABILITY_DISCLOSURES
10550
+ ].map((choice) => ({ value: choice, label: choice === "inherit" ? inherit : choice === "automatic" ? t2("capabilities.quick.upperRule") : t2(choice === "enabled" ? "capabilities.action.enable" : choice === "closed" ? "capabilities.action.close" : `capabilities.${choice}`) }));
10551
+ };
10552
+ const legacyFrozenState = (entry) => {
10553
+ const stored = typeof entry.temporary === "string" && !["inherit", "automatic", "unknown", "pending"].includes(entry.temporary);
10554
+ if (stored) return ["full", "on-demand", "closed"].includes(entry.sessionSourceSelection) ? entry.sessionSourceSelection : void 0;
10555
+ return ["full", "on-demand", "closed", "host"].includes(entry.effective) ? entry.effective : void 0;
10556
+ };
10557
+ const choiceCurrent = (entry) => choices[entry.id] ?? entry.temporary ?? "inherit";
10558
+ const choiceImpact = (entry) => {
10559
+ const draft = choices[entry.id];
10560
+ const choice = draft ?? entry.temporary ?? "inherit";
10561
+ const stagedChange = draft !== void 0;
10562
+ if (choice === "inherit") return { state: legacyFrozenState(entry), origin: "capabilities.quick.originPlan", staged: stagedChange };
10563
+ if (choice === "automatic") return { upper: true, staged: stagedChange };
10564
+ return { state: choice, origin: "capabilities.quick.originSession", staged: stagedChange };
10565
+ };
10411
10566
  const choiceOptions = selected ? [
10412
10567
  "inherit",
10413
10568
  "automatic",
10414
10569
  ...selected.category === "server" ? [] : ["full", "on-demand"],
10415
10570
  "closed"
10416
- ].map((choice) => ({ value: choice, label: t2(choice === "inherit" ? "capabilities.quick.inherit" : `capabilities.${choice}`) })) : [];
10417
- const ruleLabel = (rule, empty2) => capabilityRuleLabel(t2, rule, empty2);
10571
+ ].map((choice) => ({ value: choice, label: choice === "inherit" ? t2(selected.temporary !== void 0 && selected.temporary !== "inherit" ? "capabilities.quick.undoChange" : "capabilities.quick.keepUnchanged") : choice === "automatic" ? t2("capabilities.quick.upperRule") : t2(`capabilities.${choice}`) })) : [];
10418
10572
  const dimensionFacts = (dimensions) => ["availability", "disclosure"].map((dimension) => `${t2(`capabilities.policy.${dimension}`)}: ${statusLabel(dimensions[dimension])} (${dimensions[`${dimension}Source`] ?? t2("capabilities.quick.unknown")})`).join(" \xB7 ");
10419
- const statusLabel = (value) => value && typeof value === "object" ? ruleLabel(value) : capabilityChoiceLabel(t2, value);
10573
+ const temporaryDimension = (entry, dimension) => {
10574
+ const rule = entry.temporaryRule !== null && typeof entry.temporaryRule === "object" && !Array.isArray(entry.temporaryRule) ? entry.temporaryRule : void 0;
10575
+ const override = rule?.[dimension];
10576
+ if (override !== void 0 && override !== "automatic") return override;
10577
+ if (typeof entry.temporary === "string" && !["inherit", "automatic"].includes(entry.temporary)) {
10578
+ return dimension === "availability" ? entry.temporary === "closed" ? "closed" : "enabled" : entry.temporary;
10579
+ }
10580
+ return void 0;
10581
+ };
10582
+ const dimensionCell = (entry, dimension, value) => temporaryDimension(entry, dimension) === value ? t2("capabilities.quick.temporaryState", { state: statusLabel(value) }) : statusLabel(value);
10420
10583
  const openEditor = (entry, dimension = "availability") => {
10421
10584
  setSelectedId(entry.id);
10422
10585
  setPane("detail");
@@ -10435,16 +10598,29 @@ function createSessionCapabilityControlsView(React32, { commands, Modal, Select:
10435
10598
  h(
10436
10599
  "div",
10437
10600
  { role: "cell", className: "ptcPlusCapabilityIdentity" },
10438
- h("button", {
10439
- type: "button",
10440
- className: "ptcPlusSessionCapabilityName ptcPlusCapabilityName",
10441
- "aria-current": selected?.id === entry.id ? "true" : void 0,
10442
- onClick: (event) => {
10443
- event.stopPropagation();
10444
- openEditor(entry);
10445
- }
10446
- }, entry.name ?? entry.id),
10447
- entry.name && entry.name !== entry.id ? h("code", null, entry.id) : null
10601
+ h("input", {
10602
+ type: "checkbox",
10603
+ className: "ptcPlusPick",
10604
+ checked: picked.includes(entry.id),
10605
+ disabled: writesBlocked,
10606
+ "aria-label": t2("capabilities.selectForBatch", { name: entry.name ?? entry.id }),
10607
+ onClick: (event) => event.stopPropagation(),
10608
+ onChange: () => togglePick(entry.id)
10609
+ }),
10610
+ h(
10611
+ "div",
10612
+ { className: "ptcPlusCapabilityIdentityText" },
10613
+ h("button", {
10614
+ type: "button",
10615
+ className: "ptcPlusSessionCapabilityName ptcPlusCapabilityName",
10616
+ "aria-current": selected?.id === entry.id ? "true" : void 0,
10617
+ onClick: (event) => {
10618
+ event.stopPropagation();
10619
+ openEditor(entry);
10620
+ }
10621
+ }, entry.name ?? entry.id),
10622
+ entry.name && entry.name !== entry.id ? h("code", null, entry.id) : null
10623
+ )
10448
10624
  ),
10449
10625
  h("span", { role: "cell", className: "ptcPlusCapabilityBadge", "data-kind": type(entry) }, t2(`capabilities.type.${type(entry)}`)),
10450
10626
  h("span", { role: "cell", className: "ptcPlusCapabilitySource" }, displayedSource(entry)),
@@ -10460,7 +10636,7 @@ function createSessionCapabilityControlsView(React32, { commands, Modal, Select:
10460
10636
  event.stopPropagation();
10461
10637
  openEditor(entry, "availability");
10462
10638
  }
10463
- }, statusLabel(effectiveAvailability(entry)))
10639
+ }, dimensionCell(entry, "availability", effectiveAvailability(entry)))
10464
10640
  ),
10465
10641
  h(
10466
10642
  "div",
@@ -10474,7 +10650,7 @@ function createSessionCapabilityControlsView(React32, { commands, Modal, Select:
10474
10650
  event.stopPropagation();
10475
10651
  openEditor(entry, "disclosure");
10476
10652
  }
10477
- }, statusLabel(effectiveContext(entry)))
10653
+ }, dimensionCell(entry, "disclosure", effectiveContext(entry)))
10478
10654
  ),
10479
10655
  h(
10480
10656
  "span",
@@ -10506,7 +10682,7 @@ function createSessionCapabilityControlsView(React32, { commands, Modal, Select:
10506
10682
  h("h2", null, t2("capabilities.quick.modalTitle")),
10507
10683
  h("p", null, t2("capabilities.quick.sessionIdentity", { session: sessionId }))
10508
10684
  ),
10509
- h("button", { type: "button", className: "ptcPlusDialogClose", "aria-label": t2("settings.close"), onClick: close }, "\xD7")
10685
+ h("button", { type: "button", className: "ptcPlusDialogClose", "aria-label": t2("settings.close"), disabled: pending, onClick: close }, "\xD7")
10510
10686
  ),
10511
10687
  h(
10512
10688
  "div",
@@ -10554,10 +10730,25 @@ function createSessionCapabilityControlsView(React32, { commands, Modal, Select:
10554
10730
  ]
10555
10731
  )
10556
10732
  ),
10733
+ // A blocked workbench states why writes are off and how to restore them; the banner styling
10734
+ // keeps that condition from reading as an incidental list message.
10557
10735
  writesBlocked ? h(
10558
10736
  "p",
10559
- { className: "ptcPlusCapabilityNotice", role: "status" },
10560
- t2(management === "paused" ? "capabilities.quick.sessionPaused" : "capabilities.quick.sessionManagementOff")
10737
+ { className: "ptcPlusCapabilityNotice ptcPlusCapabilityBlocked", role: "status" },
10738
+ h(
10739
+ "svg",
10740
+ {
10741
+ className: "ptcPlusCapabilityBlockedIcon",
10742
+ viewBox: "0 0 16 16",
10743
+ width: 14,
10744
+ height: 14,
10745
+ "aria-hidden": true,
10746
+ fill: "none"
10747
+ },
10748
+ h("path", { d: "M8 2.3 14.7 13.5H1.3L8 2.3Z", stroke: "currentColor", strokeWidth: 1.3, strokeLinejoin: "round" }),
10749
+ h("path", { d: "M8 6.4v3M8 11.2v.7", stroke: "currentColor", strokeWidth: 1.3, strokeLinecap: "round" })
10750
+ ),
10751
+ t2(management === "paused" ? "capabilities.quick.sessionPaused" : management === "off" ? "capabilities.quick.sessionManagementOff" : savedSettings?.contextEnabled === false ? "capabilities.quick.savedPaused" : "capabilities.quick.savedManagementOff")
10561
10752
  ) : null,
10562
10753
  h(
10563
10754
  "div",
@@ -10573,8 +10764,20 @@ function createSessionCapabilityControlsView(React32, { commands, Modal, Select:
10573
10764
  {
10574
10765
  key: column.key,
10575
10766
  role: "columnheader",
10576
- "aria-sort": capabilitySortDirection(sort2, column.key)
10767
+ "aria-sort": capabilitySortDirection(sort2, column.key),
10768
+ ...column.key === "name" ? { "aria-label": t2("capabilities.member"), className: "ptcPlusCapabilityPickHead" } : {}
10577
10769
  },
10770
+ ...column.key === "name" ? [h("input", {
10771
+ type: "checkbox",
10772
+ className: "ptcPlusPick",
10773
+ checked: allMatchesPicked,
10774
+ ref: (node) => {
10775
+ if (node) node.indeterminate = someMatchesPicked && !allMatchesPicked;
10776
+ },
10777
+ disabled: writesBlocked || matches.length === 0,
10778
+ "aria-label": t2("capabilities.selectAllVisible"),
10779
+ onChange: toggleAllMatches
10780
+ })] : [],
10578
10781
  h(
10579
10782
  "button",
10580
10783
  {
@@ -10654,29 +10857,47 @@ function createSessionCapabilityControlsView(React32, { commands, Modal, Select:
10654
10857
  h("ul", null, ...catalog.filter((entry) => entry.id !== selected.id && entry.source?.kind === "mcp" && entry.source.server === selected.source?.server).map((entry) => h("li", { key: entry.id }, entry.name ?? entry.id)))
10655
10858
  ) : null,
10656
10859
  selected.savedRule ? h(React32.Fragment, null, ...["availability", "disclosure"].map((dimension) => h(
10657
- "div",
10658
- { className: "ptcPlusCapabilityFilter", key: dimension, "data-capability-dimension": dimension },
10659
- h("span", null, t2(`capabilities.policy.${dimension}`)),
10660
- h(Select2, {
10661
- label: t2(`capabilities.policy.${dimension}`),
10662
- disabled: !enabled || !available || pending || writesBlocked,
10663
- value: choices[selected.id]?.[dimension] ?? selected.temporaryRule?.[dimension] ?? "inherit",
10664
- onChange: (next) => chooseDimension(selected.id, dimension, next),
10665
- options: ["inherit", "automatic", ...dimension === "availability" ? ["enabled", "closed"] : CAPABILITY_DISCLOSURES].map((choice) => ({ value: choice, label: t2(choice === "inherit" ? "capabilities.quick.inherit" : choice === "automatic" ? "capabilities.policy.inheritRule" : choice === "enabled" ? "capabilities.quick.enabled" : `capabilities.${choice}`) }))
10666
- })
10860
+ React32.Fragment,
10861
+ { key: dimension },
10862
+ h(
10863
+ "div",
10864
+ { className: "ptcPlusCapabilityFilter", "data-capability-dimension": dimension },
10865
+ h("span", null, t2(`capabilities.policy.${dimension}`)),
10866
+ h(Select2, {
10867
+ label: t2(`capabilities.policy.${dimension}`),
10868
+ disabled: !enabled || !available || pending || writesBlocked,
10869
+ value: dimensionCurrent(selected, dimension),
10870
+ onChange: (next) => chooseDimension(selected.id, dimension, next),
10871
+ options: dimensionOptions(selected, dimension)
10872
+ })
10873
+ ),
10874
+ h(
10875
+ "p",
10876
+ { className: "ptcPlusDetail ptcPlusCapabilityImpact", "data-impact-dimension": dimension },
10877
+ impactLine(dimensionImpact(selected, dimension))
10878
+ )
10667
10879
  ))) : h(
10668
- "div",
10669
- { className: "ptcPlusCapabilityFilter" },
10670
- h("span", null, t2("capabilities.quick.choice")),
10671
- h(Select2, {
10672
- label: t2("capabilities.quick.choice"),
10673
- value: choiceFor(selected),
10674
- disabled: !enabled || !available || pending || writesBlocked,
10675
- options: choiceOptions,
10676
- onChange: (next) => choose(selected.id, next)
10677
- })
10880
+ React32.Fragment,
10881
+ null,
10882
+ h(
10883
+ "div",
10884
+ { className: "ptcPlusCapabilityFilter" },
10885
+ h("span", null, t2("capabilities.quick.choice")),
10886
+ h(Select2, {
10887
+ label: t2("capabilities.quick.choice"),
10888
+ value: choiceCurrent(selected),
10889
+ disabled: !enabled || !available || pending || writesBlocked,
10890
+ options: choiceOptions,
10891
+ onChange: (next) => choose(selected.id, next)
10892
+ })
10893
+ ),
10894
+ h(
10895
+ "p",
10896
+ { className: "ptcPlusDetail ptcPlusCapabilityImpact", "data-impact-dimension": "selection" },
10897
+ impactLine(choiceImpact(selected))
10898
+ )
10678
10899
  ),
10679
- choices[selected.id] === "inherit" ? h(
10900
+ (typeof choices[selected.id] === "string" ? choices[selected.id] === "inherit" : Object.values(choices[selected.id] ?? {}).includes("inherit")) ? h(
10680
10901
  "p",
10681
10902
  { className: "ptcPlusDetail" },
10682
10903
  t2("capabilities.quick.inheritSessionOnly")
@@ -10684,6 +10905,69 @@ function createSessionCapabilityControlsView(React32, { commands, Modal, Select:
10684
10905
  ) : h("p", null, t2("capabilities.noMatches"))
10685
10906
  )
10686
10907
  ),
10908
+ batchOpen ? h(
10909
+ Modal,
10910
+ {
10911
+ open: true,
10912
+ onClose: () => setBatchOpen(false),
10913
+ title: t2("capabilities.batchSettings"),
10914
+ closeLabel: t2("capabilities.batch.cancel"),
10915
+ headless: true,
10916
+ className: "ptcPlusCapabilityBatchModal"
10917
+ },
10918
+ h(
10919
+ "div",
10920
+ { className: "ptcPlusCapabilityBatchHead" },
10921
+ h("h2", null, t2("capabilities.batchSettings")),
10922
+ h("button", {
10923
+ type: "button",
10924
+ className: "ptcPlusDialogClose",
10925
+ "aria-label": t2("capabilities.batch.cancel"),
10926
+ onClick: () => setBatchOpen(false)
10927
+ }, "\xD7")
10928
+ ),
10929
+ h(
10930
+ "div",
10931
+ { className: "ptcPlusCapabilityBatchBody" },
10932
+ h("p", { className: "ptcPlusDetail", role: "status" }, t2("capabilities.batch.selected", { count: pickedRows.length })),
10933
+ h(
10934
+ "ul",
10935
+ { className: "ptcPlusCapabilityBatchTargets", "aria-label": t2("capabilities.batch.targetList") },
10936
+ ...pickedRows.map((entry) => h("li", { key: entry.id }, h("span", null, entry.name ?? entry.id), h("code", null, entry.id)))
10937
+ ),
10938
+ h("div", { className: "ptcPlusCapabilityBatchFields" }, ...["availability", "disclosure"].map((dimension) => h(
10939
+ "div",
10940
+ { key: dimension, className: "ptcPlusCapabilityFilter" },
10941
+ h("span", null, t2(`capabilities.policy.${dimension}`)),
10942
+ h(Select2, {
10943
+ value: batchChoices[dimension],
10944
+ label: t2(`capabilities.batch.${dimension}`),
10945
+ onChange: (choice) => setBatchChoices((current) => ({ ...current, [dimension]: choice })),
10946
+ options: ["keep", "inherit", ...dimension === "availability" ? ["enabled", "closed"] : CAPABILITY_DISCLOSURES].map((choice) => ({ value: choice, label: choice === "keep" ? t2("capabilities.batch.keep") : choice === "inherit" ? t2("capabilities.batch.sessionInherit") : choice === "enabled" ? t2("capabilities.action.enable") : choice === "closed" ? t2("capabilities.action.close") : t2(`capabilities.${choice}`) }))
10947
+ })
10948
+ ))),
10949
+ h("p", { className: "ptcPlusDetail" }, t2("capabilities.batch.sessionStage"))
10950
+ ),
10951
+ h(
10952
+ "div",
10953
+ { className: "ptcPlusCapabilityBatchFooter" },
10954
+ h("button", { type: "button", className: "ptcPlusButton", onClick: () => setBatchOpen(false) }, t2("capabilities.batch.cancel")),
10955
+ h(
10956
+ "button",
10957
+ {
10958
+ type: "button",
10959
+ className: "ptcPlusButton",
10960
+ "data-kind": "primary",
10961
+ disabled: pickedRows.length === 0 || !["availability", "disclosure"].some((dimension) => batchChoices[dimension] !== "keep"),
10962
+ onClick: () => {
10963
+ stageBatch(pickedRows.map((entry) => entry.id), batchChoices);
10964
+ setBatchOpen(false);
10965
+ }
10966
+ },
10967
+ t2("capabilities.batch.stage", { count: pickedRows.length })
10968
+ )
10969
+ )
10970
+ ) : null,
10687
10971
  h(
10688
10972
  "div",
10689
10973
  { className: "ptcPlusSessionCapabilityFooter" },
@@ -10693,11 +10977,14 @@ function createSessionCapabilityControlsView(React32, { commands, Modal, Select:
10693
10977
  { type: "button", className: "ptcPlusButton", disabled: pending || staged.length === 0, onClick: discard },
10694
10978
  t2("capabilities.quick.discard")
10695
10979
  ),
10980
+ // Session-scoped temporary application stays the footer's primary action; saving global
10981
+ // defaults is an explicit secondary choice, so no default-looking control changes global state.
10696
10982
  h(
10697
10983
  "button",
10698
10984
  {
10699
10985
  type: "button",
10700
10986
  className: "ptcPlusButton",
10987
+ "data-kind": "primary",
10701
10988
  title: t2("capabilities.quick.sessionHint"),
10702
10989
  disabled: pending || !enabled || !available || writesBlocked || staged.length === 0,
10703
10990
  onClick: () => void apply("session")
@@ -10709,12 +10996,35 @@ function createSessionCapabilityControlsView(React32, { commands, Modal, Select:
10709
10996
  {
10710
10997
  type: "button",
10711
10998
  className: "ptcPlusButton",
10712
- "data-kind": "primary",
10713
10999
  title: t2(hasInheritanceReset ? "capabilities.quick.inheritSessionOnly" : "capabilities.quick.globalHint"),
10714
11000
  disabled: pending || !enabled || !available || writesBlocked || staged.length === 0 || hasInheritanceReset,
10715
11001
  onClick: () => void apply("global")
10716
11002
  },
10717
11003
  t2("capabilities.quick.applyGlobal")
11004
+ ),
11005
+ h(
11006
+ "button",
11007
+ {
11008
+ type: "button",
11009
+ className: "ptcPlusButton",
11010
+ "aria-haspopup": "dialog",
11011
+ "aria-label": t2("capabilities.batchSettings"),
11012
+ disabled: pending || writesBlocked || picked.length === 0,
11013
+ onClick: () => {
11014
+ setBatchChoices({ availability: "keep", disclosure: "keep" });
11015
+ setBatchOpen(true);
11016
+ }
11017
+ },
11018
+ t2("capabilities.batchSettings"),
11019
+ picked.length ? h(
11020
+ "span",
11021
+ {
11022
+ className: "ptcPlusCapabilityBatchCount",
11023
+ "aria-hidden": true,
11024
+ title: t2("capabilities.selectionCount", { count: picked.length })
11025
+ },
11026
+ String(picked.length)
11027
+ ) : null
10718
11028
  )
10719
11029
  )
10720
11030
  );
@@ -39276,6 +39586,10 @@ var REPL_CONSOLE_CSS = `
39276
39586
  @media(max-width:560px){.ptcPlusConsole{padding:14px 12px}.ptcPlusBindingsModal.ptcPlusBindingsModal{width:calc(100vw - 16px);max-height:calc(100dvh - 16px)}.ptcPlusBindingsDialog{padding:16px;max-height:calc(100dvh - 16px)}.ptcPlusObservationFilters>.ptcPlusSelectTrigger{width:105px}.ptcPlusObservationTable th,.ptcPlusObservationTable td{padding:0 6px}.ptcPlusObservationValue{gap:3px}.ptcPlusObservationState{font-size:10px}.ptcPlusEditorHead{align-items:flex-start}.ptcPlusEditorHead>.ptcPlusBindingLifecycle{margin-left:auto}.ptcPlusSourceBody .cm-editor{height:300px}}
39277
39587
  .ptcPlusReplIdentity{grid-column:1}.ptcPlusReplReuse{flex:none;padding:0 5px;border-radius:999px;background:var(--dsw-alias-bg-layer-2,rgba(38,49,72,.06));color:var(--dsw-alias-label-tertiary,#74777d);font:500 10px/15px system-ui,sans-serif;white-space:nowrap}
39278
39588
  .ptcPlusObservationReuseTotal{font-size:13px;color:var(--dsw-alias-label-tertiary)}.ptcPlusObservationReuse{color:var(--dsw-alias-label-tertiary);white-space:nowrap;font-variant-numeric:tabular-nums}
39589
+ .ptcPlusCapabilityIdentity{display:grid;grid-template-columns:auto minmax(0,1fr);align-items:center;gap:3px 8px;min-width:0}.ptcPlusCapabilityIdentityText{display:flex;flex-direction:column;gap:3px;min-width:0}.ptcPlusCapabilityPickHead{display:grid;grid-template-columns:auto minmax(0,1fr);align-items:center;gap:6px}.ptcPlusCapabilityPickHead .ptcPlusCapabilitySort{min-width:0}.ptcPlusPick{appearance:none;position:relative;flex:none;box-sizing:border-box;width:16px;height:16px;margin:0;border:1px solid var(--dsw-alias-border-l4);border-radius:4px;background:var(--dsw-alias-bg-layer-3);cursor:pointer}.ptcPlusPick:checked,.ptcPlusPick:indeterminate{border-color:var(--dsw-alias-brand-primary);background:var(--dsw-alias-brand-primary)}.ptcPlusPick:checked::after{position:absolute;left:4px;top:1px;width:5px;height:9px;border:solid var(--dsw-alias-label-primary-foreground);border-width:0 2px 2px 0;content:'';transform:rotate(45deg)}.ptcPlusPick:indeterminate::after{position:absolute;left:3px;top:6px;width:8px;height:2px;border-radius:1px;background:var(--dsw-alias-label-primary-foreground);content:''}.ptcPlusPick:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#4d6bfe);outline-offset:2px}.ptcPlusPick:disabled{cursor:not-allowed;opacity:.4}.ptcPlusCapabilityBatchCount{display:inline-flex;align-items:center;justify-content:center;min-width:16px;height:16px;padding:0 5px;border-radius:999px;background:var(--dsw-alias-state-business-primary,#4d6bfe);color:#fff;font-size:10px;line-height:16px}.ptcPlusCapabilityBlocked{display:flex;gap:8px;align-items:flex-start;margin:10px 24px 0;border:1px solid color-mix(in srgb,var(--dsw-alias-state-warn-primary,#a15c00) 30%,transparent);background:color-mix(in srgb,var(--dsw-alias-state-warn-primary,#a15c00) 8%,var(--dsw-alias-bg-layer-2));color:var(--dsw-alias-label-primary);font-weight:500}.ptcPlusCapabilityBlockedIcon{flex:none;margin-top:2px;color:var(--dsw-alias-state-warn-primary,#a15c00)}.ptcPlusSessionCapabilityDetail .ptcPlusCapabilityImpact{margin:6px 0 14px;font-size:12px;line-height:18px}
39590
+ @media(max-width:650px){.ptcPlusCapabilityBlocked{margin-inline:14px}}@media(max-width:650px) and (max-height:480px){.ptcPlusCapabilityBlocked{margin:4px 6px 0;font-size:11px}}
39591
+ @media(max-width:650px){.ptcPlusSessionCapabilityFooter button{font-size:11px;line-height:14px}}
39592
+ @media(max-width:650px) and (max-height:480px){.ptcPlusSessionCapabilityFooter{grid-template-columns:repeat(4,minmax(0,1fr));gap:3px;padding:3px 6px}.ptcPlusSessionCapabilityFooter [role=status]{line-height:11px}.ptcPlusSessionCapabilityFooter button{font-size:10px;line-height:12px;padding:1px 10px}}
39279
39593
  `;
39280
39594
  var CLIENT_PLUGIN_ID = true ? "dsh-ptc-plus" : "dsh-ptc-plus";
39281
39595
  var CLIENT_STYLE_TAG = `${CLIENT_PLUGIN_ID}/client.css`;
@@ -39723,7 +40037,6 @@ var CHROME_COPY = Object.freeze({
39723
40037
  "capabilities.inheritedRules": "\u7EE7\u627F\u89C4\u5219",
39724
40038
  "capabilities.inheritedRulesHelp": "\u8BBE\u7F6E\u9ED8\u8BA4\u3001\u7C7B\u522B\u548C MCP \u6765\u6E90\u7684\u6301\u7EED\u89C4\u5219\uFF0C\u66F4\u6539\u5373\u4FDD\u5B58\u3002\u89C4\u5219\u72EC\u7ACB\u4E8E\u5F53\u524D\u7B5B\u9009\uFF0C\u5355\u9879\u8BBE\u7F6E\u6309\u7EF4\u5EA6\u8986\u76D6\uFF1BMCP \u6765\u6E90\u505C\u7528\u4F18\u5148\u3002",
39725
40039
  "capabilities.batch.targets": "\u4E00\u6B21\u6027\u4FEE\u6539 {count} \u9879\u771F\u5B9E\u80FD\u529B",
39726
- "capabilities.batch.scope": "\u76EE\u6807\u8303\u56F4\uFF1A{scope}",
39727
40040
  "capabilities.batch.excluded": "\u5DF2\u6392\u9664 {count} \u9879\u5F53\u524D\u4E0D\u53EF\u7528\u6216\u672A\u786E\u8BA4\u7684\u6761\u76EE\u3002",
39728
40041
  "capabilities.batch.targetList": "\u672C\u6B21\u6279\u91CF\u76EE\u6807",
39729
40042
  "capabilities.batch.empty": "\u5F53\u524D\u7B5B\u9009\u4E2D\u6CA1\u6709\u53EF\u6279\u91CF\u4FEE\u6539\u7684\u771F\u5B9E\u80FD\u529B\u3002",
@@ -39735,8 +40048,14 @@ var CHROME_COPY = Object.freeze({
39735
40048
  "capabilities.batch.changedTargets": "{count} \u9879\u76EE\u6807\u5DF2\u4E0D\u5728\u6700\u65B0\u5B8C\u6574\u76EE\u5F55\u4E2D\u6216\u53EF\u7528\u6027\u672A\u786E\u8BA4\uFF1B\u8BF7\u53D6\u6D88\u5E76\u91CD\u65B0\u68C0\u67E5\u76EE\u6807\u3002",
39736
40049
  "capabilities.batch.failed": "\u4FDD\u5B58\u672A\u6210\u529F\uFF0C\u76EE\u6807\u548C\u9009\u62E9\u5DF2\u4FDD\u7559\uFF0C\u53EF\u518D\u6B21\u786E\u8BA4\u91CD\u8BD5\u3002",
39737
40050
  "capabilities.batch.confirm": "\u786E\u8BA4\u4FEE\u6539 {count} \u9879",
39738
- "capabilities.batch.search": "\u641C\u7D22\u201C{query}\u201D",
39739
40051
  "capabilities.batch.all": "\u5F53\u524D\u5B8C\u6574\u80FD\u529B\u76EE\u5F55",
40052
+ "capabilities.batch.selected": "\u5DF2\u9009\u62E9 {count} \u9879\u80FD\u529B",
40053
+ "capabilities.batch.stage": "\u6682\u5B58\u4FEE\u6539\uFF08{count} \u9879\uFF09",
40054
+ "capabilities.batch.sessionStage": "\u786E\u8BA4\u540E\u5199\u5165\u5F85\u5E94\u7528\u66F4\u6539\uFF1B\u7531\u5E95\u90E8\u6309\u94AE\u51B3\u5B9A\u5E94\u7528\u5230\u4F1A\u8BDD\u6216\u4FDD\u5B58\u4E3A\u5168\u5C40\u9ED8\u8BA4\u3002",
40055
+ "capabilities.batch.sessionInherit": "\u4E0D\u6539\u52A8\uFF08\u6E05\u9664\u672C\u4F1A\u8BDD\u4FEE\u6539\uFF09",
40056
+ "capabilities.selectForBatch": "\u9009\u62E9 {name}",
40057
+ "capabilities.selectAllVisible": "\u9009\u62E9\u5F53\u524D\u7B5B\u9009\u7ED3\u679C",
40058
+ "capabilities.selectionCount": "\u5DF2\u9009 {count} \u9879",
39740
40059
  "capabilities.typesColumn": "\u7C7B\u578B",
39741
40060
  "capabilities.sourceColumn": "\u6765\u6E90",
39742
40061
  "capabilities.enabledColumn": "\u662F\u5426\u542F\u7528",
@@ -39757,7 +40076,7 @@ var CHROME_COPY = Object.freeze({
39757
40076
  "capabilities.eligibleFamilies": "\u53EF\u7528\u5BB6\u65CF\u6570",
39758
40077
  "capabilities.coverageColumn": "\u8986\u76D6\u7387",
39759
40078
  "capabilities.coverageFor": "{name} \u7684\u8986\u76D6\u7387",
39760
- "capabilities.familyHint": "\u4F1A\u8BDD\u5BB6\u65CF\uFF1A\u4E00\u4E2A\u4E3B\u4F1A\u8BDD\u53CA\u5176\u5B50\u4EE3\u7406\u5408\u8BA1\u4E00\u6B21\u3002\u5173\u95ED\u91C7\u96C6\u4ECD\u53EF\u67E5\u770B\u5DF2\u6709\u8BB0\u5F55\u3002",
40079
+ "capabilities.familyHint": "\u4F1A\u8BDD\u5BB6\u65CF\uFF1A\u4E00\u4E2A\u4E3B\u4F1A\u8BDD\u53CA\u5176\u5B50\u4EE3\u7406\u5408\u8BA1\u4E00\u6B21\uFF0C\u53EA\u6709\u5B8C\u6210\u7ED3\u7B97\u7684\u5BB6\u65CF\u8BA1\u5165\u7EDF\u8BA1\u3002\u5173\u95ED\u91C7\u96C6\u4ECD\u53EF\u67E5\u770B\u5DF2\u6709\u8BB0\u5F55\u3002",
39761
40080
  "capabilities.contextNavigation": "\u4E0A\u4E0B\u6587\u529F\u80FD",
39762
40081
  "capabilities.context.description": "\u521D\u59CB\u63D0\u793A",
39763
40082
  "capabilities.context.recovery": "\u63D0\u793A\u6062\u590D",
@@ -39805,7 +40124,7 @@ var CHROME_COPY = Object.freeze({
39805
40124
  "capabilities.observedUsage": "\u5B9E\u9645\u4F7F\u7528\u7EDF\u8BA1",
39806
40125
  "capabilities.budgetPreview": "\u5F53\u524D\u80FD\u529B\u5206\u914D\u9884\u89C8",
39807
40126
  "capabilities.observationUnavailable": "\u65E0\u6CD5\u8BFB\u53D6\u80FD\u529B\u9884\u89C8\uFF0C\u8BF7\u91CD\u65B0\u8BFB\u53D6\u3002",
39808
- "capabilities.selectObservation": "\u9009\u62E9\u4E00\u4E2A\u6D3B\u8DC3 PTC \u4F1A\u8BDD\uFF0C\u67E5\u770B\u5176\u5DE5\u4F5C\u533A\u7EDF\u8BA1\u548C\u5F53\u524D\u914D\u7F6E\u7684\u9884\u7B97\u9884\u89C8\u3002",
40127
+ "capabilities.selectObservation": "\u9009\u62E9\u4E00\u4E2A\u6D3B\u8DC3 PTC \u4F1A\u8BDD\u4F5C\u4E3A\u89C2\u5BDF\u951A\u70B9\uFF1B\u7EDF\u8BA1\u548C\u9884\u7B97\u9884\u89C8\u90FD\u6309\u5B83\u7684\u80FD\u529B\u6E05\u5355\u5C55\u793A\uFF0C\u7EDF\u8BA1\u8303\u56F4\u53EF\u5207\u6362\u5F53\u524D\u5DE5\u4F5C\u533A\u6216\u5168\u90E8\u5DE5\u4F5C\u533A\u3002",
39809
40128
  "capabilities.quick.title": "\u4F1A\u8BDD\u80FD\u529B\u63A7\u5236",
39810
40129
  "capabilities.quick.modalTitle": "\u7BA1\u7406\u4F1A\u8BDD\u80FD\u529B",
39811
40130
  "capabilities.quick.sessionIdentity": "\u5F53\u524D\u4F1A\u8BDD\uFF1A{session}",
@@ -39824,7 +40143,7 @@ var CHROME_COPY = Object.freeze({
39824
40143
  "capabilities.quick.applySession": "\u5E94\u7528\u5230\u4F1A\u8BDD",
39825
40144
  "capabilities.quick.applyGlobal": "\u5E94\u7528\u5230\u5168\u5C40",
39826
40145
  "capabilities.quick.noOverride": "\u65E0\u8986\u76D6",
39827
- "capabilities.quick.inheritSessionOnly": "\u64A4\u9500\u4E34\u65F6\u8986\u76D6\u53EA\u9002\u7528\u4E8E\u672C\u4F1A\u8BDD\u3002\u8BF7\u7528\u201C\u5E94\u7528\u5230\u4F1A\u8BDD\u201D\u63D0\u4EA4\u3002",
40146
+ "capabilities.quick.inheritSessionOnly": "\u64A4\u9500\u4E34\u65F6\u4FEE\u6539\u53EA\u9002\u7528\u4E8E\u672C\u4F1A\u8BDD\u3002\u8BF7\u7528\u201C\u5E94\u7528\u5230\u4F1A\u8BDD\u201D\u63D0\u4EA4\u3002",
39828
40147
  "capabilities.quick.discard": "\u653E\u5F03\u66F4\u6539",
39829
40148
  "capabilities.quick.applying": "\u6B63\u5728\u5E94\u7528\u2026",
39830
40149
  "capabilities.quick.applied": "{count} \u9879\u4F1A\u8BDD\u80FD\u529B\u5DF2\u66F4\u65B0\u3002",
@@ -39840,8 +40159,11 @@ var CHROME_COPY = Object.freeze({
39840
40159
  "capabilities.quick.pendingServerClose": "MCP \u670D\u52A1 {server} \u6709\u5F85\u751F\u6548\u7684\u5173\u95ED\u9009\u62E9\uFF1B\u5B50\u9879\u9009\u62E9\u4ECD\u4FDD\u7559\u3002",
39841
40160
  "capabilities.quick.enabled": "\u5DF2\u542F\u7528",
39842
40161
  "capabilities.quick.pending": "\u5F85\u751F\u6548",
40162
+ "capabilities.quick.temporaryState": "{state}\uFF08\u4E34\u65F6\uFF09",
39843
40163
  "capabilities.quick.sessionPaused": "\u672C\u4F1A\u8BDD\u7684\u80FD\u529B\u4E0E\u4E0A\u4E0B\u6587\u5DF2\u6682\u505C\uFF1B\u6E05\u5355\u663E\u793A\u5BBF\u4E3B\u9ED8\u8BA4\uFF0C\u9700\u5728\u8BBE\u7F6E\u4E2D\u91CD\u65B0\u5F00\u542F\u5E76\u5237\u65B0\u540E\u624D\u4F1A\u5E94\u7528\u65B0\u7684\u66F4\u6539\u3002",
39844
- "capabilities.quick.sessionManagementOff": "\u672C\u4F1A\u8BDD\u672A\u542F\u7528\u80FD\u529B\u7BA1\u7406\uFF1B\u80FD\u529B\u6CBF\u7528\u5BBF\u4E3B\u914D\u7F6E\u3002",
40164
+ "capabilities.quick.sessionManagementOff": "\u672C\u4F1A\u8BDD\u672A\u542F\u7528\u80FD\u529B\u7BA1\u7406\uFF1B\u80FD\u529B\u6CBF\u7528\u5BBF\u4E3B\u914D\u7F6E\u3002\u5728\u8BBE\u7F6E\u7684\u201C\u80FD\u529B\u4E0E\u4E0A\u4E0B\u6587\u201D\u4E2D\u5F00\u542F\u80FD\u529B\u7BA1\u7406\u5E76\u5237\u65B0\u540E\u53EF\u4FEE\u6539\u672C\u4F1A\u8BDD\u9009\u62E9\u3002",
40165
+ "capabilities.quick.savedPaused": "\u80FD\u529B\u4E0E\u4E0A\u4E0B\u6587\u5DF2\u5728\u8BBE\u7F6E\u4E2D\u5173\u95ED\uFF1B\u91CD\u65B0\u5F00\u542F\u5E76\u5237\u65B0\u540E\u53EF\u4FEE\u6539\u672C\u4F1A\u8BDD\u9009\u62E9\u3002",
40166
+ "capabilities.quick.savedManagementOff": "\u80FD\u529B\u7BA1\u7406\u5DF2\u5728\u8BBE\u7F6E\u4E2D\u5173\u95ED\uFF1B\u91CD\u65B0\u5F00\u542F\u5E76\u5237\u65B0\u540E\u53EF\u4FEE\u6539\u672C\u4F1A\u8BDD\u9009\u62E9\u3002",
39845
40167
  "capabilities.quick.scope": "\u751F\u6548\u8303\u56F4",
39846
40168
  "capabilities.quick.session": "\u4EC5\u672C\u4F1A\u8BDD",
39847
40169
  "capabilities.quick.global": "\u5168\u5C40\u4FDD\u5B58\u5E76\u66F4\u65B0\u672C\u4F1A\u8BDD",
@@ -39853,12 +40175,26 @@ var CHROME_COPY = Object.freeze({
39853
40175
  "capabilities.quick.tools": "\u57FA\u7840\u5DE5\u5177",
39854
40176
  "capabilities.quick.mcp": "MCP \u670D\u52A1\u4E0E\u8D44\u6E90",
39855
40177
  "capabilities.quick.mcp_tools": "MCP Tools",
39856
- "capabilities.quick.inherit": "\u7EE7\u627F\u4F1A\u8BDD\u8BBE\u7F6E",
40178
+ "capabilities.quick.noChange": "\u4E0D\u6539\u52A8\uFF08\u5F53\u524D\uFF1A{state}\uFF09",
40179
+ "capabilities.quick.undoTemp": "\u64A4\u9500\u672C\u4F1A\u8BDD\u4FEE\u6539\uFF08\u6062\u590D\u4E3A\uFF1A{state}\uFF09",
40180
+ "capabilities.quick.keepUnchanged": "\u4E0D\u6539\u52A8",
40181
+ "capabilities.quick.undoChange": "\u64A4\u9500\u672C\u4F1A\u8BDD\u4FEE\u6539",
40182
+ "capabilities.quick.upperRule": "\u7531\u4E0A\u4E00\u7EA7\u89C4\u5219\u51B3\u5B9A",
40183
+ "capabilities.quick.impact": "\u672C\u4F1A\u8BDD\u751F\u6548\uFF1A{state} \xB7 \u6765\u6E90\uFF1A{source}",
40184
+ "capabilities.quick.impactPending": "\u672C\u4F1A\u8BDD\u751F\u6548\uFF1A{state} \xB7 \u6765\u6E90\uFF1A{source} \xB7 \u5F85\u5E94\u7528",
40185
+ "capabilities.quick.impactUpper": "\u672C\u4F1A\u8BDD\u751F\u6548\uFF1A\u6309\u4E0A\u4E00\u7EA7\u89C4\u5219\u51B3\u5B9A",
40186
+ "capabilities.quick.impactUpperPending": "\u672C\u4F1A\u8BDD\u751F\u6548\uFF1A\u6309\u4E0A\u4E00\u7EA7\u89C4\u5219\u51B3\u5B9A \xB7 \u5F85\u5E94\u7528",
40187
+ "capabilities.quick.originPlan": "\u4F1A\u8BDD\u65B9\u6848",
40188
+ "capabilities.quick.originSession": "\u672C\u4F1A\u8BDD\u4E34\u65F6\u4FEE\u6539",
40189
+ "capabilities.action.enable": "\u542F\u7528",
40190
+ "capabilities.action.close": "\u5173\u95ED",
39857
40191
  "capabilities.quick.states": "\u5DF2\u4FDD\u5B58\uFF1A{saved} \xB7 \u4E34\u65F6\uFF1A{temporary} \xB7 \u751F\u6548\uFF1A{effective}",
39858
40192
  "capabilities.quick.apply": "\u63D0\u4EA4\u5E76\u751F\u6548",
39859
40193
  "capabilities.quick.prefill": "\u586B\u5165\u547D\u4EE4\u8349\u7A3F",
39860
40194
  "capabilities.card.recorded": "\u4F1A\u8BDD\u80FD\u529B\u5DF2\u66F4\u65B0\u3002",
39861
40195
  "capabilities.card.pending": "\u80FD\u529B\u5DF2\u51C6\u5907\uFF0C\u5C06\u5728\u4E0B\u4E00\u6B21\u83B7\u51C6\u7684\u6A21\u578B\u6B65\u9AA4\u751F\u6548\u3002",
40196
+ "capabilities.card.paused": "\u80FD\u529B\u4E0E\u4E0A\u4E0B\u6587\u5DF2\u5173\u95ED\uFF1B\u672C\u4F1A\u8BDD\u6CBF\u7528\u5BBF\u4E3B\u80FD\u529B\u3002",
40197
+ "capabilities.card.off": "\u80FD\u529B\u7BA1\u7406\u5DF2\u5173\u95ED\uFF1B\u672C\u4F1A\u8BDD\u6CBF\u7528\u5BBF\u4E3B\u80FD\u529B\u3002",
39862
40198
  "capabilities.card.saved-only": "\u5168\u5C40\u8BBE\u7F6E\u5DF2\u4FDD\u5B58\uFF0C\u4F1A\u8BDD\u66F4\u65B0\u5931\u8D25\u3002{error}",
39863
40199
  "capabilities.card.unavailable": "\u4F1A\u8BDD\u4E0D\u53EF\u7528\uFF0C\u672A\u5E94\u7528\u66F4\u6539\u3002",
39864
40200
  "capabilities.card.usage": "\u547D\u4EE4\u672A\u6267\u884C\uFF0C\u8BF7\u68C0\u67E5\u53C2\u6570\u3002",
@@ -39874,6 +40210,8 @@ var CHROME_COPY = Object.freeze({
39874
40210
  "capabilities.receipt.saved-only": "\u5168\u5C40\u9009\u62E9\u5DF2\u4FDD\u5B58\uFF0C\u4F46\u4F1A\u8BDD {session} \u66F4\u65B0\u5931\u8D25\uFF1B\u8BF7\u8BFB\u53D6\u5F53\u524D\u65B9\u6848\u5E76\u91CD\u8BD5\u3002{error}",
39875
40211
  "capabilities.receipt.recorded": "\u4F1A\u8BDD {session} \u7684\u80FD\u529B\u5DF2\u66F4\u65B0\u3002",
39876
40212
  "capabilities.receipt.pending": "\u4F1A\u8BDD {session} \u7684\u80FD\u529B\u5DF2\u51C6\u5907\uFF0C\u5C06\u5728\u9996\u6B21\u63A5\u53D7\u7684\u6A21\u578B\u6B65\u9AA4\u751F\u6548\u3002",
40213
+ "capabilities.receipt.paused": "\u80FD\u529B\u4E0E\u4E0A\u4E0B\u6587\u5DF2\u5173\u95ED\uFF1B\u4F1A\u8BDD {session} \u6CBF\u7528\u5BBF\u4E3B\u80FD\u529B\u3002",
40214
+ "capabilities.receipt.off": "\u80FD\u529B\u7BA1\u7406\u5DF2\u5173\u95ED\uFF1B\u4F1A\u8BDD {session} \u6CBF\u7528\u5BBF\u4E3B\u80FD\u529B\u3002",
39877
40215
  "capabilities.receipt.unavailable": "\u8BF7\u9009\u62E9\u4ECD\u6D3B\u8DC3\u7684 PTC \u4F1A\u8BDD\u3002",
39878
40216
  "capabilities.receipt.usage": "\u4F7F\u7528 /capabilities \u67E5\u770B\uFF0C\u6216 /capabilities refresh \u540C\u6B65\u5DF2\u4FDD\u5B58\u8BBE\u7F6E\u3002",
39879
40217
  "bindings.toggleEnabled": "\u5DF2\u4FDD\u5B58\u201C{name}\u201D\u7684\u542F\u7528\u9009\u62E9\uFF1B\u6A21\u578B\u76EE\u5F55\u5728\u4E0B\u4E00\u6B21\u83B7\u51C6\u6B65\u9AA4\u66F4\u65B0\uFF0C\u7A0B\u5E8F\u503C\u5C1A\u672A\u8BC1\u660E\u521D\u59CB\u5316\u3002",
@@ -39896,6 +40234,7 @@ var CHROME_COPY = Object.freeze({
39896
40234
  "capabilities.directoryUsage": "\u5BFC\u822A\u8BF4\u660E\uFF1A{bytes} / {budget} UTF-8 bytes",
39897
40235
  "capabilities.statStatus.unavailable": "\u7EDF\u8BA1\u4E0D\u53EF\u7528",
39898
40236
  "capabilities.statStatus.no-samples": "\u6682\u65E0\u6837\u672C",
40237
+ "capabilities.statStatus.pending-settlement": "\u5DF2\u6709\u8BB0\u5F55\u5F85\u7ED3\u7B97",
39899
40238
  "capabilities.statStatus.incomplete-window": "\u7A97\u53E3\u8BC1\u636E\u4E0D\u5B8C\u6574",
39900
40239
  "capabilities.statStatus.capacity-exceeded": "\u7EDF\u8BA1\u5BB9\u91CF\u5DF2\u8D85\u9650",
39901
40240
  "capabilities.savedConfigurations": "\u5DF2\u4FDD\u5B58\u914D\u7F6E",
@@ -39941,7 +40280,7 @@ var CHROME_COPY = Object.freeze({
39941
40280
  "capabilities.reason.workspace": "\u5DE5\u4F5C\u533A\u7EDF\u8BA1",
39942
40281
  "capabilities.reason.global": "\u5168\u5C40\u7EDF\u8BA1\u53C2\u8003",
39943
40282
  "capabilities.host": "\u6CBF\u7528 DSH",
39944
- "capabilities.policy.inheritRule": "\u6CBF\u7528\u4E0A\u5C42\u89C4\u5219",
40283
+ "capabilities.policy.inheritRule": "\u4E0D\u5355\u72EC\u8BBE\u7F6E",
39945
40284
  "capabilities.policy.availabilityFilter": "\u5DF2\u4FDD\u5B58\u7684\u53EF\u7528\u6027",
39946
40285
  "capabilities.policy.disclosureFilter": "\u5DF2\u4FDD\u5B58\u7684\u8BF4\u660E\u65B9\u5F0F",
39947
40286
  "capabilities.policy.frozenSource": "\u51BB\u7ED3\u6765\u6E90\u7684\u89C4\u5219\u7ED3\u679C",
@@ -40257,6 +40596,7 @@ var CHROME_COPY = Object.freeze({
40257
40596
  "tool.stopped": "\u6267\u884C\u5DF2\u4E2D\u65AD",
40258
40597
  "tool.source": "\u6E90\u7801",
40259
40598
  "tool.result": "\u7ED3\u679C",
40599
+ "tool.descriptionGenerated": "\u81EA\u52A8\u6458\u8981\uFF1A\u6A21\u578B\u672A\u63D0\u4F9B\u6458\u8981\uFF0C\u7531\u63D2\u4EF6\u751F\u6210",
40260
40600
  "tool.copy": "\u590D\u5236\u4EE3\u7801",
40261
40601
  "tool.copied": "\u5DF2\u590D\u5236",
40262
40602
  "tool.inspect": "\u68C0\u67E5\u8C03\u7528",
@@ -40328,7 +40668,6 @@ var CHROME_COPY = Object.freeze({
40328
40668
  "capabilities.inheritedRules": "Inherited rules",
40329
40669
  "capabilities.inheritedRulesHelp": "Set persistent defaults, category and MCP source rules. Changes save immediately and are independent of current filters. Item preferences override each dimension; MCP source closure takes precedence.",
40330
40670
  "capabilities.batch.targets": "One-time change to {count} catalog capabilities",
40331
- "capabilities.batch.scope": "Target scope: {scope}",
40332
40671
  "capabilities.batch.excluded": "Excluded {count} unavailable or unconfirmed entries.",
40333
40672
  "capabilities.batch.targetList": "Targets for this batch",
40334
40673
  "capabilities.batch.empty": "There are no confirmed catalog capabilities in the current filters.",
@@ -40340,8 +40679,14 @@ var CHROME_COPY = Object.freeze({
40340
40679
  "capabilities.batch.changedTargets": "{count} targets are absent from the latest complete catalog or unconfirmed. Cancel and review the targets again.",
40341
40680
  "capabilities.batch.failed": "Save was not confirmed. Targets and choices are retained; confirm again to retry.",
40342
40681
  "capabilities.batch.confirm": "Confirm {count} changes",
40343
- "capabilities.batch.search": "Search \u201C{query}\u201D",
40344
40682
  "capabilities.batch.all": "Current complete capability catalog",
40683
+ "capabilities.batch.selected": "Selected {count} capabilities",
40684
+ "capabilities.batch.stage": "Stage changes ({count})",
40685
+ "capabilities.batch.sessionStage": "Confirm stages these changes; the footer decides whether they apply to this session or become global defaults.",
40686
+ "capabilities.batch.sessionInherit": "No change (clears this session\u2019s change)",
40687
+ "capabilities.selectForBatch": "Select {name}",
40688
+ "capabilities.selectAllVisible": "Select all visible results",
40689
+ "capabilities.selectionCount": "{count} selected",
40345
40690
  "capabilities.typesColumn": "Type",
40346
40691
  "capabilities.sourceColumn": "Source",
40347
40692
  "capabilities.enabledColumn": "Enabled",
@@ -40362,7 +40707,7 @@ var CHROME_COPY = Object.freeze({
40362
40707
  "capabilities.eligibleFamilies": "Eligible families",
40363
40708
  "capabilities.coverageColumn": "Coverage",
40364
40709
  "capabilities.coverageFor": "Coverage for {name}",
40365
- "capabilities.familyHint": "A family counts one main session and its subagents together. Existing records remain available when collection is off.",
40710
+ "capabilities.familyHint": "A family counts one main session and its subagents together; only settled families count toward statistics. Existing records remain available when collection is off.",
40366
40711
  "capabilities.contextNavigation": "Context features",
40367
40712
  "capabilities.context.description": "Initial prompt",
40368
40713
  "capabilities.context.recovery": "Prompt recovery",
@@ -40410,7 +40755,7 @@ var CHROME_COPY = Object.freeze({
40410
40755
  "capabilities.observedUsage": "Observed usage",
40411
40756
  "capabilities.budgetPreview": "Current allocation preview",
40412
40757
  "capabilities.observationUnavailable": "Capability preview is unavailable; reload the observation.",
40413
- "capabilities.selectObservation": "Select an active PTC session to view its workspace statistics and allocation preview for the current configuration.",
40758
+ "capabilities.selectObservation": "Select an active PTC session as the observation anchor; statistics and budget preview follow its capability inventory, and the scope switches between its workspace and all workspaces.",
40414
40759
  "capabilities.quick.title": "Session capability controls",
40415
40760
  "capabilities.quick.modalTitle": "Manage session capabilities",
40416
40761
  "capabilities.quick.sessionIdentity": "Current session: {session}",
@@ -40429,7 +40774,7 @@ var CHROME_COPY = Object.freeze({
40429
40774
  "capabilities.quick.applySession": "Apply to session",
40430
40775
  "capabilities.quick.applyGlobal": "Apply to global",
40431
40776
  "capabilities.quick.noOverride": "None",
40432
- "capabilities.quick.inheritSessionOnly": "Clearing a temporary override applies only to this session. Use Apply to session.",
40777
+ "capabilities.quick.inheritSessionOnly": "Clearing a temporary change applies only to this session. Use Apply to session.",
40433
40778
  "capabilities.quick.discard": "Discard changes",
40434
40779
  "capabilities.quick.applying": "Applying\u2026",
40435
40780
  "capabilities.quick.applied": "{count} session capabilities updated.",
@@ -40445,8 +40790,11 @@ var CHROME_COPY = Object.freeze({
40445
40790
  "capabilities.quick.pendingServerClose": "MCP server {server} has a close choice awaiting effect; child choices are retained.",
40446
40791
  "capabilities.quick.enabled": "Enabled",
40447
40792
  "capabilities.quick.pending": "Pending",
40793
+ "capabilities.quick.temporaryState": "{state} (temporary)",
40448
40794
  "capabilities.quick.sessionPaused": "Capabilities and context are paused for this session; the list shows Host defaults. Re-enable them in settings and refresh before changes can apply.",
40449
- "capabilities.quick.sessionManagementOff": "Capability management is off for this session; capabilities stay with the Host.",
40795
+ "capabilities.quick.sessionManagementOff": "Capability management is off for this session; capabilities stay with the Host. Enable it under Capabilities & Context in settings and refresh before changing this session's choices.",
40796
+ "capabilities.quick.savedPaused": "Capabilities and context are off in settings; re-enable them and refresh before changing this session's choices.",
40797
+ "capabilities.quick.savedManagementOff": "Capability management is off in settings; re-enable it and refresh before changing this session's choices.",
40450
40798
  "capabilities.quick.scope": "Apply to",
40451
40799
  "capabilities.quick.session": "This session only",
40452
40800
  "capabilities.quick.global": "Save globally and update this session",
@@ -40458,12 +40806,26 @@ var CHROME_COPY = Object.freeze({
40458
40806
  "capabilities.quick.tools": "Ordinary tools",
40459
40807
  "capabilities.quick.mcp": "MCP servers and resources",
40460
40808
  "capabilities.quick.mcp_tools": "MCP tools",
40461
- "capabilities.quick.inherit": "Inherit session settings",
40809
+ "capabilities.quick.noChange": "No change (currently: {state})",
40810
+ "capabilities.quick.undoTemp": "Undo this session\u2019s change (restores {state})",
40811
+ "capabilities.quick.keepUnchanged": "No change",
40812
+ "capabilities.quick.undoChange": "Undo this session\u2019s change",
40813
+ "capabilities.quick.upperRule": "Let the level above decide",
40814
+ "capabilities.quick.impact": "Effective in this session: {state} \xB7 From: {source}",
40815
+ "capabilities.quick.impactPending": "Effective in this session: {state} \xB7 From: {source} \xB7 Pending apply",
40816
+ "capabilities.quick.impactUpper": "Effective in this session: decided by the level above",
40817
+ "capabilities.quick.impactUpperPending": "Effective in this session: decided by the level above \xB7 Pending apply",
40818
+ "capabilities.quick.originPlan": "the session plan",
40819
+ "capabilities.quick.originSession": "this session\u2019s change",
40820
+ "capabilities.action.enable": "Enable",
40821
+ "capabilities.action.close": "Close",
40462
40822
  "capabilities.quick.states": "Saved: {saved} \xB7 Temporary: {temporary} \xB7 Effective: {effective}",
40463
40823
  "capabilities.quick.apply": "Submit and apply",
40464
40824
  "capabilities.quick.prefill": "Fill command draft",
40465
40825
  "capabilities.card.recorded": "Session capabilities updated.",
40466
40826
  "capabilities.card.pending": "Capabilities prepared; they take effect at the next accepted model step.",
40827
+ "capabilities.card.paused": "Capabilities and context are off; this session stays with the Host capabilities.",
40828
+ "capabilities.card.off": "Capability management is off; this session stays with the Host capabilities.",
40467
40829
  "capabilities.card.saved-only": "Global settings saved; session update failed. {error}",
40468
40830
  "capabilities.card.unavailable": "Session unavailable; changes were not applied.",
40469
40831
  "capabilities.card.usage": "Command not executed; check its arguments.",
@@ -40479,6 +40841,8 @@ var CHROME_COPY = Object.freeze({
40479
40841
  "capabilities.receipt.saved-only": "Global choice saved, but session {session} could not be updated. Inspect its plan and retry. {error}",
40480
40842
  "capabilities.receipt.recorded": "Capabilities updated for session {session}.",
40481
40843
  "capabilities.receipt.pending": "Capabilities prepared for session {session}; they take effect at its first accepted model step.",
40844
+ "capabilities.receipt.paused": "Capabilities and context are off; session {session} stays with the Host capabilities.",
40845
+ "capabilities.receipt.off": "Capability management is off; session {session} stays with the Host capabilities.",
40482
40846
  "capabilities.receipt.unavailable": "Select an active PTC session.",
40483
40847
  "capabilities.receipt.usage": "Use /capabilities to inspect or /capabilities refresh to apply saved settings.",
40484
40848
  "bindings.toggleEnabled": "Enabled \u201C{name}\u201D in saved configuration. The model catalog updates at the next accepted step; worker initialization is not yet established.",
@@ -40501,6 +40865,7 @@ var CHROME_COPY = Object.freeze({
40501
40865
  "capabilities.directoryUsage": "Navigation: {bytes} / {budget} UTF-8 bytes",
40502
40866
  "capabilities.statStatus.unavailable": "Statistics unavailable",
40503
40867
  "capabilities.statStatus.no-samples": "No samples yet",
40868
+ "capabilities.statStatus.pending-settlement": "Recorded, awaiting settlement",
40504
40869
  "capabilities.statStatus.incomplete-window": "Incomplete window evidence",
40505
40870
  "capabilities.statStatus.capacity-exceeded": "Statistics capacity exceeded",
40506
40871
  "capabilities.savedConfigurations": "Saved configurations",
@@ -40546,7 +40911,7 @@ var CHROME_COPY = Object.freeze({
40546
40911
  "capabilities.reason.workspace": "Workspace statistics",
40547
40912
  "capabilities.reason.global": "Global statistics fallback",
40548
40913
  "capabilities.host": "Host defaults",
40549
- "capabilities.policy.inheritRule": "Use parent rules",
40914
+ "capabilities.policy.inheritRule": "Not set here",
40550
40915
  "capabilities.policy.availabilityFilter": "Saved availability",
40551
40916
  "capabilities.policy.disclosureFilter": "Saved disclosure",
40552
40917
  "capabilities.policy.frozenSource": "Frozen source rule result",
@@ -40863,6 +41228,7 @@ var CHROME_COPY = Object.freeze({
40863
41228
  "tool.stopped": "Stopped",
40864
41229
  "tool.source": "Source",
40865
41230
  "tool.result": "Result",
41231
+ "tool.descriptionGenerated": "Auto summary: generated because the model provided none",
40866
41232
  "tool.inspect": "Inspect call",
40867
41233
  "feature.safeEdit": "Safe edit execution",
40868
41234
  "feature.codeRun": "Isolated code.run execution",