@yadsh/dsh-prompt-firewall 0.1.2 → 0.2.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/README.md +2 -2
- package/compatibility.json +16 -0
- package/lib/client/index.js +11 -71
- package/lib/client/index.js.map +1 -1
- package/lib/client/sections.js +75 -0
- package/lib/client/sections.js.map +1 -0
- package/lib/client/styles.js +2 -13
- package/lib/client/styles.js.map +1 -1
- package/lib/client.js +714 -571
- package/lib/client.js.map +1 -1
- package/lib/index.js +6 -5
- package/lib/index.js.map +1 -1
- package/lib/typert.host.js +2 -2
- package/lib/typert.remote-client.js +2 -2
- package/lib/types/audit.d.ts +1 -0
- package/lib/types/client/index.d.ts +1 -0
- package/lib/types/client/sections.d.ts +39 -0
- package/lib/types/client/styles.d.ts +1 -0
- package/lib/types/config.d.ts +1 -0
- package/lib/types/firewall.d.ts +1 -0
- package/lib/types/index.d.ts +2 -1
- package/lib/types/metrics.d.ts +1 -0
- package/lib/types/presets.d.ts +1 -0
- package/lib/types/rules.d.ts +1 -0
- package/lib/types/types.d.ts +1 -0
- package/package.json +32 -27
- package/lib/client/settings-store.js +0 -11
- package/lib/client/settings-store.js.map +0 -1
- package/lib/types/client/settings-store.d.ts +0 -11
package/lib/client.js
CHANGED
|
@@ -4,8 +4,8 @@ window.__ModuleLoader__.load({
|
|
|
4
4
|
var module = { exports: {} };
|
|
5
5
|
var exports = module.exports;
|
|
6
6
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
7
|
-
let react = require("react");
|
|
8
7
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
8
|
+
let react = require("react");
|
|
9
9
|
//#region ../../node_modules/.pnpm/zod@4.5.2/node_modules/zod/v4/core/util.js
|
|
10
10
|
function getEnumValues(entries) {
|
|
11
11
|
const numericValues = Object.values(entries).filter((v) => typeof v === "number");
|
|
@@ -5124,7 +5124,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
5124
5124
|
},
|
|
5125
5125
|
sourceLocation: {
|
|
5126
5126
|
"file": "packages/dsh-prompt-firewall/src/index.ts",
|
|
5127
|
-
"line":
|
|
5127
|
+
"line": 136,
|
|
5128
5128
|
"column": 3
|
|
5129
5129
|
}
|
|
5130
5130
|
}, {
|
|
@@ -5173,26 +5173,20 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
5173
5173
|
},
|
|
5174
5174
|
sourceLocation: {
|
|
5175
5175
|
"file": "packages/dsh-prompt-firewall/src/index.ts",
|
|
5176
|
-
"line":
|
|
5176
|
+
"line": 150,
|
|
5177
5177
|
"column": 9
|
|
5178
5178
|
}
|
|
5179
5179
|
}]
|
|
5180
5180
|
};
|
|
5181
5181
|
//#endregion
|
|
5182
|
-
//#region
|
|
5182
|
+
//#region ../../packages/plugin-kit/lib/client/plugin-card-css.js
|
|
5183
5183
|
/**
|
|
5184
|
-
*
|
|
5185
|
-
*
|
|
5184
|
+
* Canonical DSH settings-plugin card shell CSS — the single source of truth
|
|
5185
|
+
* for the shared `dsh-plugin-card` outer shell (see AGENTS.md). Plugins must
|
|
5186
|
+
* inject this CSS unchanged and may only append rules for their own controls
|
|
5187
|
+
* inside the card body; plugin-specific shell styling is forbidden.
|
|
5186
5188
|
*/
|
|
5187
|
-
|
|
5188
|
-
return {
|
|
5189
|
-
subscribe: (listener) => scope.subscribe(listener),
|
|
5190
|
-
getSnapshot: () => scope.getSnapshot()
|
|
5191
|
-
};
|
|
5192
|
-
}
|
|
5193
|
-
//#endregion
|
|
5194
|
-
//#region src/client/styles.ts
|
|
5195
|
-
const styles = `
|
|
5189
|
+
const PLUGIN_CARD_SHELL_CSS = `
|
|
5196
5190
|
.dsh-plugin-card{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:12px;list-style:none;transition:border-color .16s,background .16s}
|
|
5197
5191
|
.dsh-plugin-card:hover{border-color:var(--dsw-alias-label-dimmed)}
|
|
5198
5192
|
.dsh-plugin-card--open{background:var(--dsw-alias-bg-layer-2);border-color:var(--dsw-alias-label-dimmed)}
|
|
@@ -5205,6 +5199,153 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
5205
5199
|
.dsh-plugin-card__chevron{width:14px;height:14px;color:var(--dsw-alias-label-tertiary);flex:none;transition:transform .16s}
|
|
5206
5200
|
.dsh-plugin-card--open .dsh-plugin-card__chevron{transform:rotate(180deg)}
|
|
5207
5201
|
.dsh-plugin-card__body{border-top:1px solid var(--dsw-alias-border-l2);margin:0 16px;padding-bottom:8px}
|
|
5202
|
+
`;
|
|
5203
|
+
//#endregion
|
|
5204
|
+
//#region ../../packages/plugin-kit/lib/client/chevron.js
|
|
5205
|
+
/**
|
|
5206
|
+
* The standard disclosure chevron of the shared settings-card shell: a
|
|
5207
|
+
* 14x14 inline SVG stroked with `currentColor` (round caps and joins).
|
|
5208
|
+
* Font glyphs must not be used for this shape — their appearance and
|
|
5209
|
+
* baseline vary by font and encoding.
|
|
5210
|
+
*/
|
|
5211
|
+
function ChevronDown() {
|
|
5212
|
+
return (0, react_jsx_runtime.jsx)("svg", {
|
|
5213
|
+
className: "dsh-plugin-card__chevron",
|
|
5214
|
+
viewBox: "0 0 14 14",
|
|
5215
|
+
fill: "none",
|
|
5216
|
+
"aria-hidden": "true",
|
|
5217
|
+
children: (0, react_jsx_runtime.jsx)("path", {
|
|
5218
|
+
d: "m3.5 5.25 3.5 3.5 3.5-3.5",
|
|
5219
|
+
stroke: "currentColor",
|
|
5220
|
+
strokeLinecap: "round",
|
|
5221
|
+
strokeLinejoin: "round"
|
|
5222
|
+
})
|
|
5223
|
+
});
|
|
5224
|
+
}
|
|
5225
|
+
//#endregion
|
|
5226
|
+
//#region ../../packages/plugin-kit/lib/client/card-shell.js
|
|
5227
|
+
/**
|
|
5228
|
+
* Shared outer shell of a plugin configuration card (AGENTS.md contract): a
|
|
5229
|
+
* direct `<li>` child of the host list with a full-width header button
|
|
5230
|
+
* (`type="button"`, `aria-expanded`, accessible show/hide label, the
|
|
5231
|
+
* title/description stack, an optional status badge, then the chevron) and a
|
|
5232
|
+
* body rendered only while open. Plugin-specific controls belong inside the
|
|
5233
|
+
* body and must not restyle the shell.
|
|
5234
|
+
*/
|
|
5235
|
+
function CardShell(props) {
|
|
5236
|
+
const [open, setOpen] = (0, react.useState)(false);
|
|
5237
|
+
const body = props.bodyClassName === void 0 ? "dsh-plugin-card__body" : `dsh-plugin-card__body ${props.bodyClassName}`;
|
|
5238
|
+
return (0, react_jsx_runtime.jsxs)("li", {
|
|
5239
|
+
className: open ? "dsh-plugin-card dsh-plugin-card--open" : "dsh-plugin-card",
|
|
5240
|
+
children: [(0, react_jsx_runtime.jsxs)("button", {
|
|
5241
|
+
type: "button",
|
|
5242
|
+
className: "dsh-plugin-card__header",
|
|
5243
|
+
"aria-expanded": open,
|
|
5244
|
+
"aria-label": props.label(open),
|
|
5245
|
+
onClick: () => {
|
|
5246
|
+
setOpen(!open);
|
|
5247
|
+
},
|
|
5248
|
+
children: [
|
|
5249
|
+
(0, react_jsx_runtime.jsxs)("span", {
|
|
5250
|
+
className: "dsh-plugin-card__head-text",
|
|
5251
|
+
children: [(0, react_jsx_runtime.jsx)("span", {
|
|
5252
|
+
className: "dsh-plugin-card__name",
|
|
5253
|
+
children: props.title
|
|
5254
|
+
}), (0, react_jsx_runtime.jsx)("span", {
|
|
5255
|
+
className: "dsh-plugin-card__description",
|
|
5256
|
+
children: props.description
|
|
5257
|
+
})]
|
|
5258
|
+
}),
|
|
5259
|
+
props.badge ?? null,
|
|
5260
|
+
(0, react_jsx_runtime.jsx)(ChevronDown, {})
|
|
5261
|
+
]
|
|
5262
|
+
}), open ? (0, react_jsx_runtime.jsx)("div", {
|
|
5263
|
+
className: body,
|
|
5264
|
+
children: props.children
|
|
5265
|
+
}) : null]
|
|
5266
|
+
});
|
|
5267
|
+
}
|
|
5268
|
+
function noop() {}
|
|
5269
|
+
/**
|
|
5270
|
+
* Inject one stylesheet tag for the plugin's card CSS. The tag carries
|
|
5271
|
+
* `data-plugin="<pluginName>"` and is guarded against double injection; the
|
|
5272
|
+
* returned disposer removes the tag when this call created it. No-op in
|
|
5273
|
+
* non-DOM environments (headless bundles, module probes).
|
|
5274
|
+
*/
|
|
5275
|
+
function injectCardStyles(pluginName, css) {
|
|
5276
|
+
if (typeof document === "undefined") return noop;
|
|
5277
|
+
const selector = `style[data-plugin="${pluginName}"]`;
|
|
5278
|
+
if (typeof document.querySelector === "function" && document.querySelector(selector) !== null) return noop;
|
|
5279
|
+
const tag = document.createElement("style");
|
|
5280
|
+
tag.dataset.plugin = pluginName;
|
|
5281
|
+
tag.textContent = css;
|
|
5282
|
+
document.head.appendChild(tag);
|
|
5283
|
+
return () => {
|
|
5284
|
+
tag.remove();
|
|
5285
|
+
};
|
|
5286
|
+
}
|
|
5287
|
+
/**
|
|
5288
|
+
* Register the card component into the shared settings-plugins slot. Returns
|
|
5289
|
+
* the registration disposer. Use this variant when the plugin drives the
|
|
5290
|
+
* slot's inject-factory itself (e.g. to dispose a form controller alongside).
|
|
5291
|
+
*/
|
|
5292
|
+
function registerSettingsSlot(host, options) {
|
|
5293
|
+
const slotOptions = {
|
|
5294
|
+
name: options.slotName ?? "settings.plugin.item",
|
|
5295
|
+
key: options.key,
|
|
5296
|
+
...options.locale === void 0 ? {} : { locale: options.locale },
|
|
5297
|
+
...options.inject === void 0 ? {} : { inject: options.inject }
|
|
5298
|
+
};
|
|
5299
|
+
return host.slots.register(slotOptions, options.component);
|
|
5300
|
+
}
|
|
5301
|
+
/**
|
|
5302
|
+
* Full bootstrap: inject {@link options.styles} once (when provided), then
|
|
5303
|
+
* mount the card into the settings-plugins slot. Returns a disposer removing
|
|
5304
|
+
* the slot effect and the injected stylesheet.
|
|
5305
|
+
*/
|
|
5306
|
+
function registerSettingsCard(host, options) {
|
|
5307
|
+
const removeStyles = options.styles === void 0 || options.pluginName === void 0 ? void 0 : injectCardStyles(options.pluginName, options.styles);
|
|
5308
|
+
const slotName = options.slotName ?? "settings.plugin.item";
|
|
5309
|
+
const disposeEffect = host.slots.inject(slotName, () => registerSettingsSlot(host, options));
|
|
5310
|
+
return () => {
|
|
5311
|
+
disposeEffect();
|
|
5312
|
+
removeStyles?.();
|
|
5313
|
+
};
|
|
5314
|
+
}
|
|
5315
|
+
//#endregion
|
|
5316
|
+
//#region ../../packages/plugin-kit/lib/client/settings-store.js
|
|
5317
|
+
/**
|
|
5318
|
+
* React calls external-store callbacks as plain functions, while
|
|
5319
|
+
* SettingsScope's methods depend on their receiver. Forwarding the methods
|
|
5320
|
+
* directly loses `this` and crashes while reading the internal store, so
|
|
5321
|
+
* bind them through stable wrappers.
|
|
5322
|
+
*/
|
|
5323
|
+
function bindSettingsExternalStore(scope) {
|
|
5324
|
+
return {
|
|
5325
|
+
subscribe: (listener) => scope.subscribe(listener),
|
|
5326
|
+
getSnapshot: () => scope.getSnapshot()
|
|
5327
|
+
};
|
|
5328
|
+
}
|
|
5329
|
+
//#endregion
|
|
5330
|
+
//#region ../../packages/plugin-kit/lib/client/polling.js
|
|
5331
|
+
function startVisibilityAwarePolling(refresh, intervalMs, visibilityDocument = document, pollingWindow = window) {
|
|
5332
|
+
const refreshWhenVisible = () => {
|
|
5333
|
+
if (!visibilityDocument.hidden) refresh();
|
|
5334
|
+
};
|
|
5335
|
+
const handleVisibilityChange = () => {
|
|
5336
|
+
refreshWhenVisible();
|
|
5337
|
+
};
|
|
5338
|
+
refreshWhenVisible();
|
|
5339
|
+
const timer = pollingWindow.setInterval(refreshWhenVisible, intervalMs);
|
|
5340
|
+
visibilityDocument.addEventListener("visibilitychange", handleVisibilityChange);
|
|
5341
|
+
return () => {
|
|
5342
|
+
pollingWindow.clearInterval(timer);
|
|
5343
|
+
visibilityDocument.removeEventListener("visibilitychange", handleVisibilityChange);
|
|
5344
|
+
};
|
|
5345
|
+
}
|
|
5346
|
+
//#endregion
|
|
5347
|
+
//#region src/client/styles.ts
|
|
5348
|
+
const styles = `${PLUGIN_CARD_SHELL_CSS}
|
|
5208
5349
|
.pf-body,.pf-body *{box-sizing:border-box}
|
|
5209
5350
|
.pf-body{padding-top:16px;display:grid;gap:18px;color:var(--dsw-alias-label-primary)}
|
|
5210
5351
|
.pf-section{display:grid;gap:12px}.pf-section-title{display:flex;justify-content:space-between;align-items:center;gap:12px}.pf-section-title h3{font-size:13px;margin:0}.pf-muted{color:var(--dsw-alias-label-tertiary);font-size:12px;margin:0;line-height:1.5}
|
|
@@ -5221,32 +5362,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
5221
5362
|
@media(max-width:720px){.pf-grid{grid-template-columns:1fr}.pf-stats{grid-template-columns:repeat(2,minmax(0,1fr))}.pf-editor{grid-template-columns:1fr 1fr}.pf-editor input{grid-column:1/-1}.pf-rule{grid-template-columns:minmax(0,1fr) 58px auto}.pf-rule .pf-kind{display:none}}
|
|
5222
5363
|
`;
|
|
5223
5364
|
//#endregion
|
|
5224
|
-
//#region src/client/
|
|
5225
|
-
const SETTINGS_NAMESPACE = "prompt-firewall";
|
|
5226
|
-
const REFRESH_INTERVAL_MS = 3e3;
|
|
5365
|
+
//#region src/client/sections.tsx
|
|
5227
5366
|
const EMPTY_LIST = Object.freeze([]);
|
|
5228
5367
|
function list(config, field) {
|
|
5229
5368
|
return config?.[field] ?? EMPTY_LIST;
|
|
5230
5369
|
}
|
|
5231
|
-
function displayError(error) {
|
|
5232
|
-
if (error instanceof Error) return error.message;
|
|
5233
|
-
if (typeof error === "string") return error;
|
|
5234
|
-
return "Could not load Prompt Inspector data.";
|
|
5235
|
-
}
|
|
5236
|
-
function ChevronDown() {
|
|
5237
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
|
|
5238
|
-
className: "dsh-plugin-card__chevron",
|
|
5239
|
-
viewBox: "0 0 14 14",
|
|
5240
|
-
fill: "none",
|
|
5241
|
-
"aria-hidden": "true",
|
|
5242
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
|
|
5243
|
-
d: "m3.5 5.25 3.5 3.5 3.5-3.5",
|
|
5244
|
-
stroke: "currentColor",
|
|
5245
|
-
strokeLinecap: "round",
|
|
5246
|
-
strokeLinejoin: "round"
|
|
5247
|
-
})
|
|
5248
|
-
});
|
|
5249
|
-
}
|
|
5250
5370
|
function Toggle(props) {
|
|
5251
5371
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
5252
5372
|
className: "pf-toggle-row",
|
|
@@ -5264,68 +5384,163 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
5264
5384
|
})]
|
|
5265
5385
|
});
|
|
5266
5386
|
}
|
|
5267
|
-
function
|
|
5268
|
-
const
|
|
5269
|
-
const
|
|
5270
|
-
|
|
5271
|
-
|
|
5272
|
-
|
|
5273
|
-
|
|
5274
|
-
|
|
5275
|
-
|
|
5387
|
+
function PolicySection(props) {
|
|
5388
|
+
const { config, writable, setPath } = props;
|
|
5389
|
+
const configuredMode = config?.mode ?? (config?.preset === "strict" ? "allowlist" : config?.preset === "audit-only" ? "audit" : "blocklist");
|
|
5390
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
5391
|
+
className: "pf-section",
|
|
5392
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5393
|
+
className: "pf-section-title",
|
|
5394
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: "Policy" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5395
|
+
className: "pf-muted",
|
|
5396
|
+
children: "Changes apply live"
|
|
5397
|
+
})]
|
|
5398
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5399
|
+
className: "pf-grid",
|
|
5400
|
+
children: [
|
|
5401
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Toggle, {
|
|
5402
|
+
checked: config?.enabled ?? true,
|
|
5403
|
+
disabled: !writable,
|
|
5404
|
+
label: "Firewall enabled",
|
|
5405
|
+
hint: "Keep auditing available when policy is off.",
|
|
5406
|
+
onChange: (value) => {
|
|
5407
|
+
setPath(["enabled"], value);
|
|
5408
|
+
}
|
|
5409
|
+
}),
|
|
5410
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Toggle, {
|
|
5411
|
+
checked: config?.protectCoreSections ?? true,
|
|
5412
|
+
disabled: !writable,
|
|
5413
|
+
label: "Protect core sections",
|
|
5414
|
+
hint: "Prevents ordinary rules from removing Harness internals.",
|
|
5415
|
+
onChange: (value) => {
|
|
5416
|
+
setPath(["protectCoreSections"], value);
|
|
5417
|
+
}
|
|
5418
|
+
}),
|
|
5419
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
5420
|
+
className: "pf-field",
|
|
5421
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "Mode" }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
|
|
5422
|
+
className: "pf-control",
|
|
5423
|
+
value: configuredMode,
|
|
5424
|
+
disabled: !writable,
|
|
5425
|
+
onChange: (event) => {
|
|
5426
|
+
setPath(["mode"], event.currentTarget.value);
|
|
5427
|
+
},
|
|
5428
|
+
children: [
|
|
5429
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
5430
|
+
value: "off",
|
|
5431
|
+
children: "Off"
|
|
5432
|
+
}),
|
|
5433
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
5434
|
+
value: "audit",
|
|
5435
|
+
children: "Audit only"
|
|
5436
|
+
}),
|
|
5437
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
5438
|
+
value: "blocklist",
|
|
5439
|
+
children: "Blocklist"
|
|
5440
|
+
}),
|
|
5441
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
5442
|
+
value: "allowlist",
|
|
5443
|
+
children: "Allowlist"
|
|
5444
|
+
})
|
|
5445
|
+
]
|
|
5446
|
+
})]
|
|
5447
|
+
}),
|
|
5448
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
5449
|
+
className: "pf-field",
|
|
5450
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "Preset" }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
|
|
5451
|
+
className: "pf-control",
|
|
5452
|
+
value: config?.preset ?? "",
|
|
5453
|
+
disabled: !writable,
|
|
5454
|
+
onChange: (event) => {
|
|
5455
|
+
const value = event.currentTarget.value;
|
|
5456
|
+
if (value === "") props.unsetPreset();
|
|
5457
|
+
else setPath(["preset"], value);
|
|
5458
|
+
},
|
|
5459
|
+
children: [
|
|
5460
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
5461
|
+
value: "",
|
|
5462
|
+
children: "None"
|
|
5463
|
+
}),
|
|
5464
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
5465
|
+
value: "clean",
|
|
5466
|
+
children: "Clean"
|
|
5467
|
+
}),
|
|
5468
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
5469
|
+
value: "strict",
|
|
5470
|
+
children: "Strict"
|
|
5471
|
+
}),
|
|
5472
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
5473
|
+
value: "audit-only",
|
|
5474
|
+
children: "Audit only"
|
|
5475
|
+
})
|
|
5476
|
+
]
|
|
5477
|
+
})]
|
|
5478
|
+
}),
|
|
5479
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
5480
|
+
className: "pf-field",
|
|
5481
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "Unknown plugin sections" }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
|
|
5482
|
+
className: "pf-control",
|
|
5483
|
+
value: config?.unknownPluginPolicy ?? "allow",
|
|
5484
|
+
disabled: !writable,
|
|
5485
|
+
onChange: (event) => {
|
|
5486
|
+
setPath(["unknownPluginPolicy"], event.currentTarget.value);
|
|
5487
|
+
},
|
|
5488
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
5489
|
+
value: "allow",
|
|
5490
|
+
children: "Allow"
|
|
5491
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
5492
|
+
value: "block",
|
|
5493
|
+
children: "Block"
|
|
5494
|
+
})]
|
|
5495
|
+
})]
|
|
5496
|
+
})
|
|
5497
|
+
]
|
|
5498
|
+
})]
|
|
5499
|
+
});
|
|
5500
|
+
}
|
|
5501
|
+
function LastRequestSection(props) {
|
|
5502
|
+
const last = props.inspector?.last ?? null;
|
|
5503
|
+
const effectiveMode = props.inspector?.config.mode ?? props.config?.mode ?? "blocklist";
|
|
5504
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
5505
|
+
className: "pf-section",
|
|
5506
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5507
|
+
className: "pf-section-title",
|
|
5508
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: "Last request" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
5509
|
+
className: "pf-btn",
|
|
5510
|
+
disabled: props.refreshing,
|
|
5511
|
+
onClick: () => {
|
|
5512
|
+
props.onRefresh();
|
|
5513
|
+
},
|
|
5514
|
+
children: props.refreshing ? "Refreshing…" : "Refresh"
|
|
5515
|
+
})]
|
|
5516
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5517
|
+
className: "pf-stats",
|
|
5518
|
+
children: [
|
|
5519
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5520
|
+
className: "pf-stat",
|
|
5521
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("b", { children: last?.totalSections ?? "—" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "sections" })]
|
|
5522
|
+
}),
|
|
5523
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5524
|
+
className: "pf-stat",
|
|
5525
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("b", { children: last?.blockedSections ?? "—" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "blocked" })]
|
|
5526
|
+
}),
|
|
5527
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5528
|
+
className: "pf-stat",
|
|
5529
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("b", { children: last === null ? "—" : "~" + String(last.estimatedTokensRemoved) }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "tokens removed (estimate)" })]
|
|
5530
|
+
}),
|
|
5531
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5532
|
+
className: "pf-stat",
|
|
5533
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("b", { children: effectiveMode }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "effective mode" })]
|
|
5534
|
+
})
|
|
5535
|
+
]
|
|
5536
|
+
})]
|
|
5537
|
+
});
|
|
5538
|
+
}
|
|
5539
|
+
function RulesSection(props) {
|
|
5540
|
+
const { config, writable, setPath } = props;
|
|
5276
5541
|
const [rule, setRule] = (0, react.useState)("");
|
|
5277
5542
|
const [ruleKind, setRuleKind] = (0, react.useState)("exact");
|
|
5278
5543
|
const [ruleAction, setRuleAction] = (0, react.useState)("block");
|
|
5279
|
-
const activeRequest = (0, react.useRef)(0);
|
|
5280
|
-
const refresh = (0, react.useCallback)(async () => {
|
|
5281
|
-
const request = ++activeRequest.current;
|
|
5282
|
-
setRefreshing(true);
|
|
5283
|
-
try {
|
|
5284
|
-
const result = await inspect();
|
|
5285
|
-
if (request !== activeRequest.current) return;
|
|
5286
|
-
if (result.ok) {
|
|
5287
|
-
setInspector(result.value);
|
|
5288
|
-
setError(null);
|
|
5289
|
-
} else setError(displayError(result.error));
|
|
5290
|
-
} catch (cause) {
|
|
5291
|
-
if (request === activeRequest.current) setError(displayError(cause));
|
|
5292
|
-
} finally {
|
|
5293
|
-
if (request === activeRequest.current) setRefreshing(false);
|
|
5294
|
-
}
|
|
5295
|
-
}, [inspect]);
|
|
5296
|
-
(0, react.useEffect)(() => {
|
|
5297
|
-
refresh();
|
|
5298
|
-
const interval = window.setInterval(() => {
|
|
5299
|
-
refresh();
|
|
5300
|
-
}, REFRESH_INTERVAL_MS);
|
|
5301
|
-
return () => {
|
|
5302
|
-
window.clearInterval(interval);
|
|
5303
|
-
activeRequest.current += 1;
|
|
5304
|
-
};
|
|
5305
|
-
}, [refresh]);
|
|
5306
|
-
const setPath = (0, react.useCallback)((path, value) => {
|
|
5307
|
-
const [field, nested] = path;
|
|
5308
|
-
if (field === void 0) return;
|
|
5309
|
-
if (nested === void 0) {
|
|
5310
|
-
scope.set(field, value);
|
|
5311
|
-
return;
|
|
5312
|
-
}
|
|
5313
|
-
const current = scope.getSnapshot().value;
|
|
5314
|
-
const parent = field === "audit" ? current?.audit : current?.metrics;
|
|
5315
|
-
scope.set(field, {
|
|
5316
|
-
...parent,
|
|
5317
|
-
[nested]: value
|
|
5318
|
-
});
|
|
5319
|
-
}, [scope]);
|
|
5320
|
-
const setPolicy = (0, react.useCallback)(async (name, policy) => {
|
|
5321
|
-
const result = await setSectionPolicy(name, policy, scope.getSnapshot().revision);
|
|
5322
|
-
if (!result.ok) setError(displayError(result.error));
|
|
5323
|
-
await refresh();
|
|
5324
|
-
}, [
|
|
5325
|
-
refresh,
|
|
5326
|
-
scope,
|
|
5327
|
-
setSectionPolicy
|
|
5328
|
-
]);
|
|
5329
5544
|
const addRule = (event) => {
|
|
5330
5545
|
event.preventDefault();
|
|
5331
5546
|
const value = rule.trim();
|
|
@@ -5379,493 +5594,427 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
5379
5594
|
action: "block"
|
|
5380
5595
|
}))
|
|
5381
5596
|
];
|
|
5382
|
-
|
|
5383
|
-
|
|
5384
|
-
|
|
5385
|
-
|
|
5386
|
-
|
|
5387
|
-
|
|
5388
|
-
|
|
5389
|
-
|
|
5390
|
-
|
|
5391
|
-
|
|
5392
|
-
"
|
|
5393
|
-
|
|
5394
|
-
|
|
5395
|
-
|
|
5396
|
-
|
|
5397
|
-
|
|
5398
|
-
|
|
5399
|
-
|
|
5400
|
-
|
|
5401
|
-
|
|
5402
|
-
|
|
5403
|
-
|
|
5404
|
-
|
|
5405
|
-
|
|
5406
|
-
|
|
5407
|
-
|
|
5408
|
-
|
|
5409
|
-
|
|
5410
|
-
|
|
5411
|
-
|
|
5412
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ChevronDown, {})
|
|
5413
|
-
]
|
|
5414
|
-
}), open ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5415
|
-
className: "dsh-plugin-card__body pf-body",
|
|
5416
|
-
children: [
|
|
5417
|
-
error !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5418
|
-
className: "pf-error",
|
|
5419
|
-
children: error
|
|
5420
|
-
}),
|
|
5421
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
5422
|
-
className: "pf-section",
|
|
5423
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5424
|
-
className: "pf-section-title",
|
|
5425
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: "Policy" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5426
|
-
className: "pf-muted",
|
|
5427
|
-
children: "Changes apply live"
|
|
5428
|
-
})]
|
|
5429
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5430
|
-
className: "pf-grid",
|
|
5597
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
5598
|
+
className: "pf-section",
|
|
5599
|
+
children: [
|
|
5600
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5601
|
+
className: "pf-section-title",
|
|
5602
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: "Rules" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5603
|
+
className: "pf-muted",
|
|
5604
|
+
children: "Explicit rules; preset rules are applied in addition"
|
|
5605
|
+
})]
|
|
5606
|
+
}),
|
|
5607
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("form", {
|
|
5608
|
+
className: "pf-editor",
|
|
5609
|
+
onSubmit: addRule,
|
|
5610
|
+
children: [
|
|
5611
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
5612
|
+
className: "pf-control",
|
|
5613
|
+
value: rule,
|
|
5614
|
+
disabled: !writable,
|
|
5615
|
+
placeholder: "plugin:example or announcement:*",
|
|
5616
|
+
onChange: (event) => {
|
|
5617
|
+
setRule(event.currentTarget.value);
|
|
5618
|
+
}
|
|
5619
|
+
}),
|
|
5620
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
|
|
5621
|
+
className: "pf-control",
|
|
5622
|
+
value: ruleKind,
|
|
5623
|
+
disabled: !writable || ruleAction === "protect",
|
|
5624
|
+
onChange: (event) => {
|
|
5625
|
+
setRuleKind(event.currentTarget.value);
|
|
5626
|
+
},
|
|
5431
5627
|
children: [
|
|
5432
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
5433
|
-
|
|
5434
|
-
|
|
5435
|
-
label: "Firewall enabled",
|
|
5436
|
-
hint: "Keep auditing available when policy is off.",
|
|
5437
|
-
onChange: (value) => {
|
|
5438
|
-
setPath(["enabled"], value);
|
|
5439
|
-
}
|
|
5628
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
5629
|
+
value: "exact",
|
|
5630
|
+
children: "Exact"
|
|
5440
5631
|
}),
|
|
5441
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
5442
|
-
|
|
5443
|
-
|
|
5444
|
-
label: "Protect core sections",
|
|
5445
|
-
hint: "Prevents ordinary rules from removing Harness internals.",
|
|
5446
|
-
onChange: (value) => {
|
|
5447
|
-
setPath(["protectCoreSections"], value);
|
|
5448
|
-
}
|
|
5632
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
5633
|
+
value: "prefix",
|
|
5634
|
+
children: "Prefix"
|
|
5449
5635
|
}),
|
|
5450
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
5451
|
-
|
|
5452
|
-
children:
|
|
5453
|
-
className: "pf-control",
|
|
5454
|
-
value: configuredMode,
|
|
5455
|
-
disabled: !writable,
|
|
5456
|
-
onChange: (event) => {
|
|
5457
|
-
setPath(["mode"], event.currentTarget.value);
|
|
5458
|
-
},
|
|
5459
|
-
children: [
|
|
5460
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
5461
|
-
value: "off",
|
|
5462
|
-
children: "Off"
|
|
5463
|
-
}),
|
|
5464
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
5465
|
-
value: "audit",
|
|
5466
|
-
children: "Audit only"
|
|
5467
|
-
}),
|
|
5468
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
5469
|
-
value: "blocklist",
|
|
5470
|
-
children: "Blocklist"
|
|
5471
|
-
}),
|
|
5472
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
5473
|
-
value: "allowlist",
|
|
5474
|
-
children: "Allowlist"
|
|
5475
|
-
})
|
|
5476
|
-
]
|
|
5477
|
-
})]
|
|
5478
|
-
}),
|
|
5479
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
5480
|
-
className: "pf-field",
|
|
5481
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "Preset" }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
|
|
5482
|
-
className: "pf-control",
|
|
5483
|
-
value: config?.preset ?? "",
|
|
5484
|
-
disabled: !writable,
|
|
5485
|
-
onChange: (event) => {
|
|
5486
|
-
const value = event.currentTarget.value;
|
|
5487
|
-
if (value === "") scope.unset("preset");
|
|
5488
|
-
else setPath(["preset"], value);
|
|
5489
|
-
},
|
|
5490
|
-
children: [
|
|
5491
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
5492
|
-
value: "",
|
|
5493
|
-
children: "None"
|
|
5494
|
-
}),
|
|
5495
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
5496
|
-
value: "clean",
|
|
5497
|
-
children: "Clean"
|
|
5498
|
-
}),
|
|
5499
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
5500
|
-
value: "strict",
|
|
5501
|
-
children: "Strict"
|
|
5502
|
-
}),
|
|
5503
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
5504
|
-
value: "audit-only",
|
|
5505
|
-
children: "Audit only"
|
|
5506
|
-
})
|
|
5507
|
-
]
|
|
5508
|
-
})]
|
|
5509
|
-
}),
|
|
5510
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
5511
|
-
className: "pf-field",
|
|
5512
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "Unknown plugin sections" }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
|
|
5513
|
-
className: "pf-control",
|
|
5514
|
-
value: config?.unknownPluginPolicy ?? "allow",
|
|
5515
|
-
disabled: !writable,
|
|
5516
|
-
onChange: (event) => {
|
|
5517
|
-
setPath(["unknownPluginPolicy"], event.currentTarget.value);
|
|
5518
|
-
},
|
|
5519
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
5520
|
-
value: "allow",
|
|
5521
|
-
children: "Allow"
|
|
5522
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
5523
|
-
value: "block",
|
|
5524
|
-
children: "Block"
|
|
5525
|
-
})]
|
|
5526
|
-
})]
|
|
5636
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
5637
|
+
value: "glob",
|
|
5638
|
+
children: "Glob"
|
|
5527
5639
|
})
|
|
5528
5640
|
]
|
|
5529
|
-
})
|
|
5530
|
-
|
|
5531
|
-
|
|
5532
|
-
|
|
5533
|
-
|
|
5534
|
-
|
|
5535
|
-
|
|
5536
|
-
|
|
5537
|
-
|
|
5538
|
-
|
|
5539
|
-
refresh();
|
|
5540
|
-
},
|
|
5541
|
-
children: refreshing ? "Refreshing…" : "Refresh"
|
|
5542
|
-
})]
|
|
5543
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5544
|
-
className: "pf-stats",
|
|
5641
|
+
}),
|
|
5642
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
|
|
5643
|
+
className: "pf-control",
|
|
5644
|
+
value: ruleAction,
|
|
5645
|
+
disabled: !writable,
|
|
5646
|
+
onChange: (event) => {
|
|
5647
|
+
const action = event.currentTarget.value;
|
|
5648
|
+
setRuleAction(action);
|
|
5649
|
+
if (action === "protect") setRuleKind("exact");
|
|
5650
|
+
},
|
|
5545
5651
|
children: [
|
|
5546
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
5547
|
-
|
|
5548
|
-
children:
|
|
5549
|
-
}),
|
|
5550
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5551
|
-
className: "pf-stat",
|
|
5552
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("b", { children: last?.blockedSections ?? "—" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "blocked" })]
|
|
5652
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
5653
|
+
value: "block",
|
|
5654
|
+
children: "Block"
|
|
5553
5655
|
}),
|
|
5554
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
5555
|
-
|
|
5556
|
-
children:
|
|
5656
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
5657
|
+
value: "allow",
|
|
5658
|
+
children: "Allow"
|
|
5557
5659
|
}),
|
|
5558
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
5559
|
-
|
|
5560
|
-
children:
|
|
5660
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
5661
|
+
value: "protect",
|
|
5662
|
+
children: "Protect"
|
|
5561
5663
|
})
|
|
5562
5664
|
]
|
|
5665
|
+
}),
|
|
5666
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
5667
|
+
className: "pf-btn primary",
|
|
5668
|
+
type: "submit",
|
|
5669
|
+
disabled: !writable || rule.trim().length === 0,
|
|
5670
|
+
children: "Add rule"
|
|
5671
|
+
})
|
|
5672
|
+
]
|
|
5673
|
+
}),
|
|
5674
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5675
|
+
className: "pf-rules",
|
|
5676
|
+
children: [explicitRules.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5677
|
+
className: "pf-empty",
|
|
5678
|
+
children: "No explicit rules yet."
|
|
5679
|
+
}), explicitRules.map((item) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5680
|
+
className: "pf-rule",
|
|
5681
|
+
children: [
|
|
5682
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("code", {
|
|
5683
|
+
title: item.value,
|
|
5684
|
+
children: item.value
|
|
5685
|
+
}),
|
|
5686
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5687
|
+
className: "pf-pill pf-kind",
|
|
5688
|
+
children: item.kind
|
|
5689
|
+
}),
|
|
5690
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5691
|
+
className: `pf-pill ${item.action}`,
|
|
5692
|
+
children: item.action
|
|
5693
|
+
}),
|
|
5694
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
5695
|
+
className: "pf-btn link danger",
|
|
5696
|
+
disabled: !writable,
|
|
5697
|
+
onClick: () => {
|
|
5698
|
+
setPath([item.field], list(config, item.field).filter((value) => value !== item.value));
|
|
5699
|
+
},
|
|
5700
|
+
children: "Remove"
|
|
5701
|
+
})
|
|
5702
|
+
]
|
|
5703
|
+
}, `${item.field}:${item.value}`))]
|
|
5704
|
+
})
|
|
5705
|
+
]
|
|
5706
|
+
});
|
|
5707
|
+
}
|
|
5708
|
+
function AuditSection(props) {
|
|
5709
|
+
const { config, writable, setPath } = props;
|
|
5710
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("details", {
|
|
5711
|
+
className: "pf-advanced",
|
|
5712
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("summary", { children: "Audit & metrics" }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5713
|
+
className: "pf-advanced-content pf-grid",
|
|
5714
|
+
children: [
|
|
5715
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Toggle, {
|
|
5716
|
+
checked: config?.audit?.enabled ?? true,
|
|
5717
|
+
disabled: !writable,
|
|
5718
|
+
label: "Audit history",
|
|
5719
|
+
hint: "Keep recent assemblies in Host memory.",
|
|
5720
|
+
onChange: (value) => {
|
|
5721
|
+
setPath(["audit", "enabled"], value);
|
|
5722
|
+
}
|
|
5723
|
+
}),
|
|
5724
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Toggle, {
|
|
5725
|
+
checked: config?.audit?.includePreview ?? false,
|
|
5726
|
+
disabled: !writable,
|
|
5727
|
+
label: "Section preview",
|
|
5728
|
+
hint: "Expose only the configured prefix in Inspector.",
|
|
5729
|
+
onChange: (value) => {
|
|
5730
|
+
setPath(["audit", "includePreview"], value);
|
|
5731
|
+
}
|
|
5732
|
+
}),
|
|
5733
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Toggle, {
|
|
5734
|
+
checked: config?.audit?.logBlocked ?? true,
|
|
5735
|
+
disabled: !writable,
|
|
5736
|
+
label: "Log blocked sections",
|
|
5737
|
+
hint: "Names and sizes only unless preview is enabled.",
|
|
5738
|
+
onChange: (value) => {
|
|
5739
|
+
setPath(["audit", "logBlocked"], value);
|
|
5740
|
+
}
|
|
5741
|
+
}),
|
|
5742
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Toggle, {
|
|
5743
|
+
checked: config?.audit?.logAllowed ?? false,
|
|
5744
|
+
disabled: !writable,
|
|
5745
|
+
label: "Log allowed sections",
|
|
5746
|
+
hint: "Useful for initial policy discovery.",
|
|
5747
|
+
onChange: (value) => {
|
|
5748
|
+
setPath(["audit", "logAllowed"], value);
|
|
5749
|
+
}
|
|
5750
|
+
}),
|
|
5751
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Toggle, {
|
|
5752
|
+
checked: config?.audit?.highlightNewSections ?? true,
|
|
5753
|
+
disabled: !writable,
|
|
5754
|
+
label: "Highlight new plugin sections",
|
|
5755
|
+
hint: "Informational only; never blocks automatically.",
|
|
5756
|
+
onChange: (value) => {
|
|
5757
|
+
setPath(["audit", "highlightNewSections"], value);
|
|
5758
|
+
}
|
|
5759
|
+
}),
|
|
5760
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Toggle, {
|
|
5761
|
+
checked: config?.metrics?.enabled ?? true,
|
|
5762
|
+
disabled: !writable,
|
|
5763
|
+
label: "Aggregate metrics",
|
|
5764
|
+
hint: "No arbitrary section-name labels.",
|
|
5765
|
+
onChange: (value) => {
|
|
5766
|
+
setPath(["metrics", "enabled"], value);
|
|
5767
|
+
}
|
|
5768
|
+
}),
|
|
5769
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
5770
|
+
className: "pf-field",
|
|
5771
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "Preview characters" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
5772
|
+
className: "pf-control",
|
|
5773
|
+
type: "number",
|
|
5774
|
+
min: "0",
|
|
5775
|
+
step: "1",
|
|
5776
|
+
value: config?.audit?.previewChars ?? 160,
|
|
5777
|
+
disabled: !writable,
|
|
5778
|
+
onChange: (event) => {
|
|
5779
|
+
setPath(["audit", "previewChars"], Number(event.currentTarget.value));
|
|
5780
|
+
}
|
|
5563
5781
|
})]
|
|
5564
5782
|
}),
|
|
5565
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("
|
|
5566
|
-
className: "pf-
|
|
5567
|
-
children: [
|
|
5568
|
-
|
|
5569
|
-
|
|
5570
|
-
|
|
5783
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
5784
|
+
className: "pf-field",
|
|
5785
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "History size" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
5786
|
+
className: "pf-control",
|
|
5787
|
+
type: "number",
|
|
5788
|
+
min: "0",
|
|
5789
|
+
step: "1",
|
|
5790
|
+
value: config?.audit?.historySize ?? 100,
|
|
5791
|
+
disabled: !writable,
|
|
5792
|
+
onChange: (event) => {
|
|
5793
|
+
setPath(["audit", "historySize"], Number(event.currentTarget.value));
|
|
5794
|
+
}
|
|
5795
|
+
})]
|
|
5796
|
+
})
|
|
5797
|
+
]
|
|
5798
|
+
})]
|
|
5799
|
+
});
|
|
5800
|
+
}
|
|
5801
|
+
function InspectorSection(props) {
|
|
5802
|
+
const last = props.inspector?.last ?? null;
|
|
5803
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
5804
|
+
className: "pf-section",
|
|
5805
|
+
children: [
|
|
5806
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5807
|
+
className: "pf-section-title",
|
|
5808
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: "Prompt Inspector" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5809
|
+
className: "pf-muted",
|
|
5810
|
+
children: "Updates every 3 seconds"
|
|
5811
|
+
})]
|
|
5812
|
+
}),
|
|
5813
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5814
|
+
className: "pf-table-wrap",
|
|
5815
|
+
children: last === null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5816
|
+
className: "pf-empty",
|
|
5817
|
+
children: "No audited prompt assembly yet."
|
|
5818
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("table", {
|
|
5819
|
+
className: "pf-table",
|
|
5820
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("thead", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("tr", { children: [
|
|
5821
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", { children: "Section" }),
|
|
5822
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", { children: "Size" }),
|
|
5823
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", { children: "Decision" }),
|
|
5824
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", { children: "Reason" }),
|
|
5825
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", { children: "Policy" })
|
|
5826
|
+
] }) }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("tbody", { children: last.sections.map((section, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("tr", { children: [
|
|
5827
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("td", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5828
|
+
className: "pf-section-name",
|
|
5829
|
+
children: [
|
|
5830
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: section.name }),
|
|
5831
|
+
section.isNew && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5832
|
+
className: "pf-new",
|
|
5833
|
+
children: "NEW"
|
|
5834
|
+
}),
|
|
5835
|
+
section.suspicious && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5836
|
+
className: "pf-warn",
|
|
5837
|
+
children: "POSSIBLE ANNOUNCEMENT"
|
|
5838
|
+
})
|
|
5839
|
+
]
|
|
5840
|
+
}), section.preview !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5841
|
+
className: "pf-preview",
|
|
5842
|
+
children: section.preview
|
|
5843
|
+
})] }),
|
|
5844
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("td", { children: [
|
|
5845
|
+
"~",
|
|
5846
|
+
section.estimatedTokens,
|
|
5847
|
+
" t",
|
|
5848
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("br", {}),
|
|
5849
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
5571
5850
|
className: "pf-muted",
|
|
5572
|
-
children: "
|
|
5573
|
-
})
|
|
5574
|
-
}),
|
|
5575
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
5576
|
-
className:
|
|
5577
|
-
|
|
5851
|
+
children: [section.chars, " chars"]
|
|
5852
|
+
})
|
|
5853
|
+
] }),
|
|
5854
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5855
|
+
className: `pf-pill ${section.decision === "blocked" ? "block" : section.decision === "protected" ? "protect" : "allow"}`,
|
|
5856
|
+
children: section.decision
|
|
5857
|
+
}) }),
|
|
5858
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", { children: section.reason }),
|
|
5859
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5860
|
+
className: "pf-actions",
|
|
5578
5861
|
children: [
|
|
5579
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("
|
|
5580
|
-
className: "pf-
|
|
5581
|
-
|
|
5582
|
-
|
|
5583
|
-
|
|
5584
|
-
|
|
5585
|
-
|
|
5586
|
-
}
|
|
5862
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
5863
|
+
className: "pf-btn link",
|
|
5864
|
+
disabled: !props.writable,
|
|
5865
|
+
onClick: () => {
|
|
5866
|
+
props.setPolicy(section.name, "allow");
|
|
5867
|
+
},
|
|
5868
|
+
children: "Allow"
|
|
5587
5869
|
}),
|
|
5588
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
5589
|
-
className: "pf-
|
|
5590
|
-
|
|
5591
|
-
|
|
5592
|
-
|
|
5593
|
-
setRuleKind(event.currentTarget.value);
|
|
5870
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
5871
|
+
className: "pf-btn link danger",
|
|
5872
|
+
disabled: !props.writable,
|
|
5873
|
+
onClick: () => {
|
|
5874
|
+
props.setPolicy(section.name, "block");
|
|
5594
5875
|
},
|
|
5595
|
-
children:
|
|
5596
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
5597
|
-
value: "exact",
|
|
5598
|
-
children: "Exact"
|
|
5599
|
-
}),
|
|
5600
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
5601
|
-
value: "prefix",
|
|
5602
|
-
children: "Prefix"
|
|
5603
|
-
}),
|
|
5604
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
5605
|
-
value: "glob",
|
|
5606
|
-
children: "Glob"
|
|
5607
|
-
})
|
|
5608
|
-
]
|
|
5876
|
+
children: "Block"
|
|
5609
5877
|
}),
|
|
5610
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
5611
|
-
className: "pf-
|
|
5612
|
-
|
|
5613
|
-
|
|
5614
|
-
|
|
5615
|
-
const action = event.currentTarget.value;
|
|
5616
|
-
setRuleAction(action);
|
|
5617
|
-
if (action === "protect") setRuleKind("exact");
|
|
5878
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
5879
|
+
className: "pf-btn link",
|
|
5880
|
+
disabled: !props.writable,
|
|
5881
|
+
onClick: () => {
|
|
5882
|
+
props.setPolicy(section.name, "protect");
|
|
5618
5883
|
},
|
|
5619
|
-
children:
|
|
5620
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
5621
|
-
value: "block",
|
|
5622
|
-
children: "Block"
|
|
5623
|
-
}),
|
|
5624
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
5625
|
-
value: "allow",
|
|
5626
|
-
children: "Allow"
|
|
5627
|
-
}),
|
|
5628
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
5629
|
-
value: "protect",
|
|
5630
|
-
children: "Protect"
|
|
5631
|
-
})
|
|
5632
|
-
]
|
|
5884
|
+
children: "Protect"
|
|
5633
5885
|
}),
|
|
5634
5886
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
5635
|
-
className: "pf-btn
|
|
5636
|
-
|
|
5637
|
-
|
|
5638
|
-
|
|
5887
|
+
className: "pf-btn link",
|
|
5888
|
+
disabled: !props.writable,
|
|
5889
|
+
onClick: () => {
|
|
5890
|
+
props.setPolicy(section.name, "clear");
|
|
5891
|
+
},
|
|
5892
|
+
children: "Clear"
|
|
5639
5893
|
})
|
|
5640
5894
|
]
|
|
5641
|
-
})
|
|
5642
|
-
|
|
5643
|
-
className: "pf-rules",
|
|
5644
|
-
children: [explicitRules.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5645
|
-
className: "pf-empty",
|
|
5646
|
-
children: "No explicit rules yet."
|
|
5647
|
-
}), explicitRules.map((item) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5648
|
-
className: "pf-rule",
|
|
5649
|
-
children: [
|
|
5650
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("code", {
|
|
5651
|
-
title: item.value,
|
|
5652
|
-
children: item.value
|
|
5653
|
-
}),
|
|
5654
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5655
|
-
className: "pf-pill pf-kind",
|
|
5656
|
-
children: item.kind
|
|
5657
|
-
}),
|
|
5658
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5659
|
-
className: `pf-pill ${item.action}`,
|
|
5660
|
-
children: item.action
|
|
5661
|
-
}),
|
|
5662
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
5663
|
-
className: "pf-btn link danger",
|
|
5664
|
-
disabled: !writable,
|
|
5665
|
-
onClick: () => {
|
|
5666
|
-
setPath([item.field], list(config, item.field).filter((value) => value !== item.value));
|
|
5667
|
-
},
|
|
5668
|
-
children: "Remove"
|
|
5669
|
-
})
|
|
5670
|
-
]
|
|
5671
|
-
}, `${item.field}:${item.value}`))]
|
|
5672
|
-
})
|
|
5673
|
-
]
|
|
5674
|
-
}),
|
|
5675
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("details", {
|
|
5676
|
-
className: "pf-advanced",
|
|
5677
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("summary", { children: "Audit & metrics" }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5678
|
-
className: "pf-advanced-content pf-grid",
|
|
5679
|
-
children: [
|
|
5680
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Toggle, {
|
|
5681
|
-
checked: config?.audit?.enabled ?? true,
|
|
5682
|
-
disabled: !writable,
|
|
5683
|
-
label: "Audit history",
|
|
5684
|
-
hint: "Keep recent assemblies in Host memory.",
|
|
5685
|
-
onChange: (value) => {
|
|
5686
|
-
setPath(["audit", "enabled"], value);
|
|
5687
|
-
}
|
|
5688
|
-
}),
|
|
5689
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Toggle, {
|
|
5690
|
-
checked: config?.audit?.includePreview ?? false,
|
|
5691
|
-
disabled: !writable,
|
|
5692
|
-
label: "Section preview",
|
|
5693
|
-
hint: "Expose only the configured prefix in Inspector.",
|
|
5694
|
-
onChange: (value) => {
|
|
5695
|
-
setPath(["audit", "includePreview"], value);
|
|
5696
|
-
}
|
|
5697
|
-
}),
|
|
5698
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Toggle, {
|
|
5699
|
-
checked: config?.audit?.logBlocked ?? true,
|
|
5700
|
-
disabled: !writable,
|
|
5701
|
-
label: "Log blocked sections",
|
|
5702
|
-
hint: "Names and sizes only unless preview is enabled.",
|
|
5703
|
-
onChange: (value) => {
|
|
5704
|
-
setPath(["audit", "logBlocked"], value);
|
|
5705
|
-
}
|
|
5706
|
-
}),
|
|
5707
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Toggle, {
|
|
5708
|
-
checked: config?.audit?.logAllowed ?? false,
|
|
5709
|
-
disabled: !writable,
|
|
5710
|
-
label: "Log allowed sections",
|
|
5711
|
-
hint: "Useful for initial policy discovery.",
|
|
5712
|
-
onChange: (value) => {
|
|
5713
|
-
setPath(["audit", "logAllowed"], value);
|
|
5714
|
-
}
|
|
5715
|
-
}),
|
|
5716
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Toggle, {
|
|
5717
|
-
checked: config?.audit?.highlightNewSections ?? true,
|
|
5718
|
-
disabled: !writable,
|
|
5719
|
-
label: "Highlight new plugin sections",
|
|
5720
|
-
hint: "Informational only; never blocks automatically.",
|
|
5721
|
-
onChange: (value) => {
|
|
5722
|
-
setPath(["audit", "highlightNewSections"], value);
|
|
5723
|
-
}
|
|
5724
|
-
}),
|
|
5725
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Toggle, {
|
|
5726
|
-
checked: config?.metrics?.enabled ?? true,
|
|
5727
|
-
disabled: !writable,
|
|
5728
|
-
label: "Aggregate metrics",
|
|
5729
|
-
hint: "No arbitrary section-name labels.",
|
|
5730
|
-
onChange: (value) => {
|
|
5731
|
-
setPath(["metrics", "enabled"], value);
|
|
5732
|
-
}
|
|
5733
|
-
}),
|
|
5734
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
5735
|
-
className: "pf-field",
|
|
5736
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "Preview characters" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
5737
|
-
className: "pf-control",
|
|
5738
|
-
type: "number",
|
|
5739
|
-
min: "0",
|
|
5740
|
-
step: "1",
|
|
5741
|
-
value: config?.audit?.previewChars ?? 160,
|
|
5742
|
-
disabled: !writable,
|
|
5743
|
-
onChange: (event) => {
|
|
5744
|
-
setPath(["audit", "previewChars"], Number(event.currentTarget.value));
|
|
5745
|
-
}
|
|
5746
|
-
})]
|
|
5747
|
-
}),
|
|
5748
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
5749
|
-
className: "pf-field",
|
|
5750
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "History size" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
5751
|
-
className: "pf-control",
|
|
5752
|
-
type: "number",
|
|
5753
|
-
min: "0",
|
|
5754
|
-
step: "1",
|
|
5755
|
-
value: config?.audit?.historySize ?? 100,
|
|
5756
|
-
disabled: !writable,
|
|
5757
|
-
onChange: (event) => {
|
|
5758
|
-
setPath(["audit", "historySize"], Number(event.currentTarget.value));
|
|
5759
|
-
}
|
|
5760
|
-
})]
|
|
5761
|
-
})
|
|
5762
|
-
]
|
|
5763
|
-
})]
|
|
5764
|
-
}),
|
|
5765
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
5766
|
-
className: "pf-section",
|
|
5767
|
-
children: [
|
|
5768
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5769
|
-
className: "pf-section-title",
|
|
5770
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: "Prompt Inspector" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5771
|
-
className: "pf-muted",
|
|
5772
|
-
children: "Updates every 3 seconds"
|
|
5773
|
-
})]
|
|
5774
|
-
}),
|
|
5775
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5776
|
-
className: "pf-table-wrap",
|
|
5777
|
-
children: last === null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5778
|
-
className: "pf-empty",
|
|
5779
|
-
children: "No audited prompt assembly yet."
|
|
5780
|
-
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("table", {
|
|
5781
|
-
className: "pf-table",
|
|
5782
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("thead", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("tr", { children: [
|
|
5783
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", { children: "Section" }),
|
|
5784
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", { children: "Size" }),
|
|
5785
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", { children: "Decision" }),
|
|
5786
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", { children: "Reason" }),
|
|
5787
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", { children: "Policy" })
|
|
5788
|
-
] }) }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("tbody", { children: last.sections.map((section, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("tr", { children: [
|
|
5789
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("td", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5790
|
-
className: "pf-section-name",
|
|
5791
|
-
children: [
|
|
5792
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: section.name }),
|
|
5793
|
-
section.isNew && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5794
|
-
className: "pf-new",
|
|
5795
|
-
children: "NEW"
|
|
5796
|
-
}),
|
|
5797
|
-
section.suspicious && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5798
|
-
className: "pf-warn",
|
|
5799
|
-
children: "POSSIBLE ANNOUNCEMENT"
|
|
5800
|
-
})
|
|
5801
|
-
]
|
|
5802
|
-
}), section.preview !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5803
|
-
className: "pf-preview",
|
|
5804
|
-
children: section.preview
|
|
5805
|
-
})] }),
|
|
5806
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("td", { children: [
|
|
5807
|
-
"~",
|
|
5808
|
-
section.estimatedTokens,
|
|
5809
|
-
" t",
|
|
5810
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("br", {}),
|
|
5811
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
5812
|
-
className: "pf-muted",
|
|
5813
|
-
children: [section.chars, " chars"]
|
|
5814
|
-
})
|
|
5815
|
-
] }),
|
|
5816
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5817
|
-
className: `pf-pill ${section.decision === "blocked" ? "block" : section.decision === "protected" ? "protect" : "allow"}`,
|
|
5818
|
-
children: section.decision
|
|
5819
|
-
}) }),
|
|
5820
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", { children: section.reason }),
|
|
5821
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5822
|
-
className: "pf-actions",
|
|
5823
|
-
children: [
|
|
5824
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
5825
|
-
className: "pf-btn link",
|
|
5826
|
-
disabled: !writable,
|
|
5827
|
-
onClick: () => {
|
|
5828
|
-
setPolicy(section.name, "allow");
|
|
5829
|
-
},
|
|
5830
|
-
children: "Allow"
|
|
5831
|
-
}),
|
|
5832
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
5833
|
-
className: "pf-btn link danger",
|
|
5834
|
-
disabled: !writable,
|
|
5835
|
-
onClick: () => {
|
|
5836
|
-
setPolicy(section.name, "block");
|
|
5837
|
-
},
|
|
5838
|
-
children: "Block"
|
|
5839
|
-
}),
|
|
5840
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
5841
|
-
className: "pf-btn link",
|
|
5842
|
-
disabled: !writable,
|
|
5843
|
-
onClick: () => {
|
|
5844
|
-
setPolicy(section.name, "protect");
|
|
5845
|
-
},
|
|
5846
|
-
children: "Protect"
|
|
5847
|
-
}),
|
|
5848
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
5849
|
-
className: "pf-btn link",
|
|
5850
|
-
disabled: !writable,
|
|
5851
|
-
onClick: () => {
|
|
5852
|
-
setPolicy(section.name, "clear");
|
|
5853
|
-
},
|
|
5854
|
-
children: "Clear"
|
|
5855
|
-
})
|
|
5856
|
-
]
|
|
5857
|
-
}) })
|
|
5858
|
-
] }, `${section.name}:${index}`)) })]
|
|
5859
|
-
})
|
|
5860
|
-
}),
|
|
5861
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
5862
|
-
className: "pf-footer-note",
|
|
5863
|
-
children: "Token counts are estimates. Prompt Firewall is a hygiene and observability layer, not a security boundary."
|
|
5864
|
-
})
|
|
5865
|
-
]
|
|
5895
|
+
}) })
|
|
5896
|
+
] }, `${section.name}:${index}`)) })]
|
|
5866
5897
|
})
|
|
5867
|
-
|
|
5868
|
-
|
|
5898
|
+
}),
|
|
5899
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
5900
|
+
className: "pf-footer-note",
|
|
5901
|
+
children: "Token counts are estimates. Prompt Firewall is a hygiene and observability layer, not a security boundary."
|
|
5902
|
+
})
|
|
5903
|
+
]
|
|
5904
|
+
});
|
|
5905
|
+
}
|
|
5906
|
+
//#endregion
|
|
5907
|
+
//#region src/client/index.tsx
|
|
5908
|
+
const SETTINGS_NAMESPACE = "prompt-firewall";
|
|
5909
|
+
const REFRESH_INTERVAL_MS = 3e3;
|
|
5910
|
+
function displayError(error) {
|
|
5911
|
+
if (error instanceof Error) return error.message;
|
|
5912
|
+
if (typeof error === "string") return error;
|
|
5913
|
+
return "Could not load Prompt Inspector data.";
|
|
5914
|
+
}
|
|
5915
|
+
function PromptFirewallCard({ scope, inspect, setSectionPolicy }) {
|
|
5916
|
+
const settingsStore = (0, react.useMemo)(() => bindSettingsExternalStore(scope), [scope]);
|
|
5917
|
+
const settings = (0, react.useSyncExternalStore)(settingsStore.subscribe, settingsStore.getSnapshot, settingsStore.getSnapshot);
|
|
5918
|
+
const config = settings.value;
|
|
5919
|
+
const writable = settings.status === "ready" && settings.writable;
|
|
5920
|
+
const [inspector, setInspector] = (0, react.useState)(null);
|
|
5921
|
+
const [error, setError] = (0, react.useState)(null);
|
|
5922
|
+
const [refreshing, setRefreshing] = (0, react.useState)(false);
|
|
5923
|
+
const activeRequest = (0, react.useRef)(0);
|
|
5924
|
+
const refresh = (0, react.useCallback)(async () => {
|
|
5925
|
+
const request = ++activeRequest.current;
|
|
5926
|
+
setRefreshing(true);
|
|
5927
|
+
try {
|
|
5928
|
+
const result = await inspect();
|
|
5929
|
+
if (request !== activeRequest.current) return;
|
|
5930
|
+
if (result.ok) {
|
|
5931
|
+
setInspector(result.value);
|
|
5932
|
+
setError(null);
|
|
5933
|
+
} else setError(displayError(result.error));
|
|
5934
|
+
} catch (cause) {
|
|
5935
|
+
if (request === activeRequest.current) setError(displayError(cause));
|
|
5936
|
+
} finally {
|
|
5937
|
+
if (request === activeRequest.current) setRefreshing(false);
|
|
5938
|
+
}
|
|
5939
|
+
}, [inspect]);
|
|
5940
|
+
(0, react.useEffect)(() => {
|
|
5941
|
+
const stopPolling = startVisibilityAwarePolling(refresh, REFRESH_INTERVAL_MS);
|
|
5942
|
+
return () => {
|
|
5943
|
+
stopPolling();
|
|
5944
|
+
activeRequest.current += 1;
|
|
5945
|
+
};
|
|
5946
|
+
}, [refresh]);
|
|
5947
|
+
const setPath = (0, react.useCallback)((path, value) => {
|
|
5948
|
+
const [field, nested] = path;
|
|
5949
|
+
if (field === void 0) return;
|
|
5950
|
+
if (nested === void 0) {
|
|
5951
|
+
scope.set(field, value);
|
|
5952
|
+
return;
|
|
5953
|
+
}
|
|
5954
|
+
const current = scope.getSnapshot().value;
|
|
5955
|
+
const parent = field === "audit" ? current?.audit : current?.metrics;
|
|
5956
|
+
scope.set(field, {
|
|
5957
|
+
...parent,
|
|
5958
|
+
[nested]: value
|
|
5959
|
+
});
|
|
5960
|
+
}, [scope]);
|
|
5961
|
+
const setPolicy = (0, react.useCallback)(async (name, policy) => {
|
|
5962
|
+
const result = await setSectionPolicy(name, policy, scope.getSnapshot().revision);
|
|
5963
|
+
if (!result.ok) setError(displayError(result.error));
|
|
5964
|
+
await refresh();
|
|
5965
|
+
}, [
|
|
5966
|
+
refresh,
|
|
5967
|
+
scope,
|
|
5968
|
+
setSectionPolicy
|
|
5969
|
+
]);
|
|
5970
|
+
const enabled = config?.enabled ?? true;
|
|
5971
|
+
if (settings.status === "unavailable") return null;
|
|
5972
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(CardShell, {
|
|
5973
|
+
title: "Prompt Firewall",
|
|
5974
|
+
description: "Prompt hygiene, section policy, and request-level observability.",
|
|
5975
|
+
badge: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5976
|
+
className: "dsh-plugin-card__badge",
|
|
5977
|
+
children: enabled ? "Enabled" : "Disabled"
|
|
5978
|
+
}),
|
|
5979
|
+
label: (open) => `${open ? "Hide" : "Show"} settings: Prompt Firewall`,
|
|
5980
|
+
bodyClassName: "pf-body",
|
|
5981
|
+
children: [
|
|
5982
|
+
error !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5983
|
+
className: "pf-error",
|
|
5984
|
+
children: error
|
|
5985
|
+
}),
|
|
5986
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(PolicySection, {
|
|
5987
|
+
config,
|
|
5988
|
+
writable,
|
|
5989
|
+
setPath,
|
|
5990
|
+
unsetPreset: () => {
|
|
5991
|
+
scope.unset("preset");
|
|
5992
|
+
}
|
|
5993
|
+
}),
|
|
5994
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(LastRequestSection, {
|
|
5995
|
+
config,
|
|
5996
|
+
inspector,
|
|
5997
|
+
refreshing,
|
|
5998
|
+
onRefresh: () => {
|
|
5999
|
+
refresh();
|
|
6000
|
+
}
|
|
6001
|
+
}),
|
|
6002
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(RulesSection, {
|
|
6003
|
+
config,
|
|
6004
|
+
writable,
|
|
6005
|
+
setPath
|
|
6006
|
+
}),
|
|
6007
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(AuditSection, {
|
|
6008
|
+
config,
|
|
6009
|
+
writable,
|
|
6010
|
+
setPath
|
|
6011
|
+
}),
|
|
6012
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(InspectorSection, {
|
|
6013
|
+
inspector,
|
|
6014
|
+
writable,
|
|
6015
|
+
setPolicy
|
|
6016
|
+
})
|
|
6017
|
+
]
|
|
5869
6018
|
});
|
|
5870
6019
|
}
|
|
5871
6020
|
const inject = [
|
|
@@ -5884,19 +6033,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
5884
6033
|
inspect: () => injectedRemote.promptFirewall.inspect(),
|
|
5885
6034
|
setSectionPolicy: (section, policy, revision) => injectedRemote.promptFirewall.setSectionPolicy(section, policy, revision)
|
|
5886
6035
|
};
|
|
5887
|
-
|
|
5888
|
-
style.dataset.plugin = "dsh-prompt-firewall";
|
|
5889
|
-
style.textContent = styles;
|
|
5890
|
-
document.head.appendChild(style);
|
|
5891
|
-
const disposeSlot = remoteCtx.slots.inject("settings.plugin.item", () => remoteCtx.slots.register({
|
|
5892
|
-
name: "settings.plugin.item",
|
|
6036
|
+
return registerSettingsCard(remoteCtx, {
|
|
5893
6037
|
key: SETTINGS_NAMESPACE,
|
|
6038
|
+
pluginName: "dsh-prompt-firewall",
|
|
6039
|
+
styles,
|
|
6040
|
+
component: PromptFirewallCard,
|
|
5894
6041
|
inject: () => face
|
|
5895
|
-
}
|
|
5896
|
-
return () => {
|
|
5897
|
-
disposeSlot();
|
|
5898
|
-
style.remove();
|
|
5899
|
-
};
|
|
6042
|
+
});
|
|
5900
6043
|
});
|
|
5901
6044
|
} catch (cause) {
|
|
5902
6045
|
await disposeRemote();
|